├── .browserslistrc ├── .editorconfig ├── .env.development ├── .env.preview ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .stylelintrc.js ├── LICENSE ├── README.md ├── babel.config.js ├── cypress.json ├── example ├── 2021-09-12_112646.png ├── 2021-09-12_113236.png ├── 2021-09-12_113312.png ├── 2021-09-12_113341.png ├── 2021-09-12_113612.png ├── 2021-09-12_113839.png ├── 2021-09-12_114307.png ├── 2021-09-12_115100.png ├── 2021-09-12_115127.png ├── 2021-09-12_115228.png ├── 2021-09-13_021734.png ├── Beehive-data-model.jpg ├── Beehive功能设计.jpg ├── Beehive后端设计.jpg └── home-page.gif ├── jest.config.js ├── package.json ├── prettier.config.js ├── public ├── favicon.ico ├── index.html └── static │ ├── css │ └── loading.css │ └── img │ ├── dragChipImgs │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ ├── 6.jpg │ ├── 7.jpg │ ├── 8.jpg │ └── 9.jpg │ ├── github.png │ └── logo.png ├── src ├── App.vue ├── api │ ├── departmentManagement.js │ ├── inviteManagement.js │ ├── menuManagement.js │ ├── messageManagement.js │ ├── operationLogManagement.js │ ├── permissionManagement.js │ ├── projectFileManagement.js │ ├── projectManagement.js │ ├── projectTemplateManagement.js │ ├── projectTemplateTaskManagement.js │ ├── publicKey.js │ ├── roleManagement.js │ ├── roleMenuManagement.js │ ├── rolePermissionManagement.js │ ├── router.js │ ├── taskListManagement.js │ ├── taskLogManagement.js │ ├── taskManagement.js │ ├── taskPriorityManagement.js │ ├── taskStateManagement.js │ ├── taskTagManagement.js │ ├── taskTaskTagManagement.js │ ├── taskTypeManagement.js │ ├── taskWorkingHourManagement.js │ ├── upload.js │ ├── user.js │ ├── userProjectCollectManagement.js │ ├── userProjectManagement.js │ ├── userRoleManagement.js │ ├── userTaskLikeManagement.js │ ├── userTaskManagement.js │ └── verification_code.js ├── assets │ ├── error_images │ │ ├── 401.png │ │ ├── 403.png │ │ ├── 404.png │ │ └── cloud.png │ ├── iconfonts │ │ ├── iconfont.css │ │ ├── iconfont.eot │ │ ├── iconfont.json │ │ ├── iconfont.svg │ │ ├── iconfont.ttf │ │ ├── iconfont.woff │ │ └── iconfont.woff2 │ ├── imgs │ │ ├── empty.png │ │ └── invite │ │ │ └── new-message.png │ ├── login_images │ │ └── background.jpg │ └── logo.png ├── components │ ├── B-image │ │ └── index.vue │ ├── Btn-tooltip │ │ └── index.vue │ ├── Cover-image │ │ └── index.vue │ ├── Cropper │ │ └── index.vue │ ├── Dj-tag │ │ └── index.vue │ ├── DragCerifyImgChip │ │ └── index.vue │ ├── Dropdown │ │ └── index.vue │ ├── EmptyImage │ │ └── index.vue │ ├── ExecutorSelect │ │ └── index.vue │ ├── FileTypeIcon │ │ └── index.vue │ ├── GithubPath │ │ └── index.vue │ ├── ShapeShifter │ │ ├── index.vue │ │ └── shape-shifter.js │ ├── Upload │ │ └── index.vue │ ├── UserInfoDialog │ │ └── index.vue │ └── VabQueryForm │ │ ├── VabQueryFormBottomPanel.vue │ │ ├── VabQueryFormLeftPanel.vue │ │ ├── VabQueryFormRightPanel.vue │ │ ├── VabQueryFormTopPanel.vue │ │ ├── export.js │ │ └── index.vue ├── config │ ├── permission.js │ └── settings.js ├── layouts │ ├── EmptyLayout.vue │ ├── components │ │ ├── Header.vue │ │ ├── Menu.vue │ │ ├── MessageBox │ │ │ ├── components │ │ │ │ └── InformList.vue │ │ │ └── index.vue │ │ ├── SideBar │ │ │ ├── components │ │ │ │ ├── MenuItem.vue │ │ │ │ ├── SideBarItem.vue │ │ │ │ └── Submenu.vue │ │ │ └── index.vue │ │ └── UserOperation.vue │ └── index.vue ├── main.js ├── mixins │ └── index.js ├── plugins │ ├── echarts.js │ ├── element.js │ └── index.js ├── router │ └── index.js ├── store │ ├── index.js │ └── modules │ │ ├── errorLog.js │ │ ├── project.js │ │ ├── routes.js │ │ ├── settings.js │ │ ├── table.js │ │ ├── tagsBar.js │ │ └── user.js ├── styles │ ├── custom.scss │ ├── element-variables.scss │ ├── loading.scss │ ├── normalize.scss │ ├── spinner │ │ ├── dots.css │ │ ├── gauge.css │ │ ├── inner-circles.css │ │ └── plus.css │ ├── transition.scss │ ├── vab.scss │ ├── variables.scss │ └── wangEditor.scss ├── utils │ ├── accessToken.js │ ├── encrypt.js │ ├── errorLog.js │ ├── handleRoutes.js │ ├── index.js │ ├── pageTitle.js │ ├── request.js │ ├── vab.js │ ├── validate-rule-el-form.js │ └── validate.js └── views │ ├── 401.vue │ ├── 403.vue │ ├── 404.vue │ ├── departmentManagement │ ├── components │ │ ├── AddMemberToDepartmentDialog.vue │ │ ├── DepartmentManagementEdit.vue │ │ ├── DepartmentOperation.vue │ │ └── UserContent.vue │ └── index.vue │ ├── index │ ├── components │ │ ├── MyProject │ │ │ └── index.vue │ │ ├── MyTask │ │ │ └── index.vue │ │ └── UserInfo │ │ │ └── index.vue │ └── index.vue │ ├── invite │ └── ProjectInvite.vue │ ├── login │ ├── components │ │ ├── LoginForm │ │ │ └── index.vue │ │ ├── RegisterForm │ │ │ └── index.vue │ │ └── RetrievePasswordForm │ │ │ └── index.vue │ └── index.vue │ ├── personalCenter │ ├── components │ │ ├── BaseSetting.vue │ │ └── Cropper.vue │ └── index.vue │ ├── personnelManagement │ ├── menuManagement │ │ ├── components │ │ │ └── MenuManagementEdit.vue │ │ └── index.vue │ ├── operationLogManagement │ │ └── index.vue │ ├── permissionManagement │ │ ├── components │ │ │ └── PermissionManagementEdit.vue │ │ └── index.vue │ ├── roleManagement │ │ ├── components │ │ │ ├── RoleManagementEdit.vue │ │ │ ├── RoleMenuManagementEdit.vue │ │ │ └── RolePermissionManagementEdit.vue │ │ └── index.vue │ └── userManagement │ │ ├── components │ │ ├── UserManagementEdit.vue │ │ └── UserRoleManagementEdit.vue │ │ └── index.vue │ ├── projectManagement │ ├── messageManagement │ │ └── index.vue │ ├── project │ │ ├── components │ │ │ ├── Events │ │ │ │ └── index.vue │ │ │ ├── File │ │ │ │ └── index.vue │ │ │ ├── Overview │ │ │ │ ├── components │ │ │ │ │ ├── ProjectInfo │ │ │ │ │ │ └── index.vue │ │ │ │ │ ├── ProjectLog.vue │ │ │ │ │ └── TaskStatisticsEcharts │ │ │ │ │ │ └── index.vue │ │ │ │ └── index.vue │ │ │ ├── Version │ │ │ │ └── index.vue │ │ │ └── task │ │ │ │ ├── TaskList.vue │ │ │ │ └── components │ │ │ │ ├── CreateTask.vue │ │ │ │ ├── CreateTaskList.vue │ │ │ │ ├── EditorTaskListDialog.vue │ │ │ │ ├── Participator.vue │ │ │ │ ├── ProjectSetting │ │ │ │ ├── components │ │ │ │ │ └── RecycleDialog.vue │ │ │ │ └── index.vue │ │ │ │ ├── RichText.vue │ │ │ │ ├── TaskDialog │ │ │ │ ├── components │ │ │ │ │ └── TaskController.vue │ │ │ │ └── index.vue │ │ │ │ ├── TaskDraggableItem │ │ │ │ └── index.vue │ │ │ │ ├── TaskFile │ │ │ │ └── index.vue │ │ │ │ ├── TaskFilter.vue │ │ │ │ ├── TaskLog │ │ │ │ ├── components │ │ │ │ │ └── LogComment.vue │ │ │ │ └── index.vue │ │ │ │ ├── TaskTag.vue │ │ │ │ └── WorkingHour │ │ │ │ ├── components │ │ │ │ └── EditorWorkingHourDialog.vue │ │ │ │ └── index.vue │ │ └── index.vue │ ├── projectList │ │ ├── components │ │ │ ├── AddMemberToProjectDialog.vue │ │ │ ├── ProjectCreate.vue │ │ │ └── ProjectEdit.vue │ │ └── index.vue │ ├── projectTemplate │ │ ├── components │ │ │ └── ProjectTemplateEdit.vue │ │ └── index.vue │ └── projectTemplateTask │ │ ├── components │ │ └── ProjectTemplateTaskEdit.vue │ │ └── index.vue │ └── retrievePassword │ └── index.vue ├── tests ├── e2e │ ├── .eslintrc.js │ ├── plugins │ │ └── index.js │ ├── specs │ │ └── test.js │ └── support │ │ ├── commands.js │ │ └── index.js └── unit │ └── example.spec.js ├── upload-qiniu.js ├── vue.config.js └── yarn.lock /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | not dead 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 2 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | NODE_ENV = development 2 | VUE_CLI_BABEL_TRANSPILE_MODULES = true 3 | -------------------------------------------------------------------------------- /.env.preview: -------------------------------------------------------------------------------- 1 | NODE_ENV = preview 2 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | src/assets 2 | src/icons 3 | public 4 | dist 5 | node_modules 6 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | node: true, 5 | }, 6 | extends: ['plugin:vue/essential', 'eslint:recommended', '@vue/prettier'], 7 | parserOptions: { 8 | parser: 'babel-eslint', 9 | }, 10 | rules: { 11 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 12 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off', 13 | 'vue/no-v-html': 'off', 14 | 'prettier/prettier': 'off', 15 | 'vue/attribute-hyphenation': 'off', 16 | 'rule-empty-line-before': 'off', 17 | 'no-unused': 'off', 18 | 'no-unused-vars': 'off', 19 | }, 20 | overrides: [ 21 | { 22 | files: ['**/__tests__/*.{j,t}s?(x)', '**/tests/unit/**/*.spec.{j,t}s?(x)'], 23 | env: { 24 | jest: true, 25 | }, 26 | }, 27 | ], 28 | }; 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | /tests/e2e/videos/ 6 | /tests/e2e/screenshots/ 7 | 8 | 9 | # local env files 10 | .env.local 11 | .env.*.local 12 | 13 | # Log files 14 | npm-debug.log* 15 | yarn-debug.log* 16 | yarn-error.log* 17 | pnpm-debug.log* 18 | 19 | # Editor directories and files 20 | .idea 21 | .vscode 22 | *.suo 23 | *.ntvs* 24 | *.njsproj 25 | *.sln 26 | *.sw? 27 | -------------------------------------------------------------------------------- /.stylelintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["stylelint-config-standard", "stylelint-config-recess-order"], 3 | rules: { 4 | "at-rule-no-unknown": [ 5 | true, 6 | { 7 | ignoreAtRules: [ 8 | "mixin", 9 | "extend", 10 | "content", 11 | "include", 12 | "for", 13 | "function", 14 | "return", 15 | ], 16 | }, 17 | ], 18 | "selector-pseudo-element-no-unknown": [ 19 | true, 20 | { 21 | ignorePseudoElements: ["v-deep"], 22 | }, 23 | ], 24 | "selector-pseudo-class-no-unknown": [ 25 | true, 26 | { 27 | ignorePseudoClasses: ["export"], 28 | }, 29 | ], 30 | indentation: 2, 31 | "no-descending-specificity": null, 32 | "declaration-colon-newline-after": null, 33 | }, 34 | ignoreFiles: ["**/*.js", "dist/*.*", "node_modules", "**/*.ts"], 35 | }; 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Imfdj 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 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@vue/cli-plugin-babel/preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "pluginsFile": "tests/e2e/plugins/index.js" 3 | } 4 | -------------------------------------------------------------------------------- /example/2021-09-12_112646.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_112646.png -------------------------------------------------------------------------------- /example/2021-09-12_113236.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_113236.png -------------------------------------------------------------------------------- /example/2021-09-12_113312.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_113312.png -------------------------------------------------------------------------------- /example/2021-09-12_113341.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_113341.png -------------------------------------------------------------------------------- /example/2021-09-12_113612.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_113612.png -------------------------------------------------------------------------------- /example/2021-09-12_113839.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_113839.png -------------------------------------------------------------------------------- /example/2021-09-12_114307.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_114307.png -------------------------------------------------------------------------------- /example/2021-09-12_115100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_115100.png -------------------------------------------------------------------------------- /example/2021-09-12_115127.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_115127.png -------------------------------------------------------------------------------- /example/2021-09-12_115228.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-12_115228.png -------------------------------------------------------------------------------- /example/2021-09-13_021734.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/2021-09-13_021734.png -------------------------------------------------------------------------------- /example/Beehive-data-model.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/Beehive-data-model.jpg -------------------------------------------------------------------------------- /example/Beehive功能设计.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/Beehive功能设计.jpg -------------------------------------------------------------------------------- /example/Beehive后端设计.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/Beehive后端设计.jpg -------------------------------------------------------------------------------- /example/home-page.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/example/home-page.gif -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: '@vue/cli-plugin-unit-jest', 3 | }; 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-beehive", 3 | "version": "0.1.0", 4 | "author": "Imfdj", 5 | "private": true, 6 | "homepage": "https://github.com/Imfdj/vue-beehive", 7 | "publishConfig": { 8 | "registry": "https://npm.pkg.github.com/" 9 | }, 10 | "scripts": { 11 | "serve": "vue-cli-service serve", 12 | "build": "vue-cli-service build", 13 | "build:qiniu:preview": "cross-env BUILD_TARGET=qiniu VUE_APP_PREVIEW=true vue-cli-service build", 14 | "build:qiniu": "cross-env BUILD_TARGET=qiniu vue-cli-service build", 15 | "test:unit": "vue-cli-service test:unit", 16 | "test:e2e": "vue-cli-service test:e2e", 17 | "lint": "vue-cli-service lint --fix", 18 | "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,md}\"" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/Imfdj/vue-beehive.git" 23 | }, 24 | "husky": { 25 | "hooks": { 26 | "pre-commit": "lint-staged" 27 | } 28 | }, 29 | "lint-staged": { 30 | "src/**/*.{js,vue}": [ 31 | "pretty-quick --staged", 32 | "eslint --fix" 33 | ] 34 | }, 35 | "dependencies": { 36 | "@sentry/browser": "^5.29.0", 37 | "@sentry/integrations": "^5.29.0", 38 | "@wcjiang/notify": "^2.0.12", 39 | "axios": "^0.21.1", 40 | "core-js": "^3.6.5", 41 | "dayjs": "^1.10.4", 42 | "echarts": "^5.1.1", 43 | "element-ui": "^2.15.1", 44 | "js-cookie": "^2.2.1", 45 | "jsencrypt": "^3.0.0-rc.1", 46 | "lodash": "^4.17.21", 47 | "multi-download": "^3.0.0", 48 | "node-rsa": "^1.1.1", 49 | "nprogress": "^0.2.0", 50 | "qs": "^6.10.1", 51 | "vue": "^2.6.11", 52 | "vue-cropper": "^0.5.5", 53 | "vue-drag-verify-img-chip": "^1.1.1", 54 | "vue-echarts": "^6.0.0-rc.5", 55 | "vue-router": "^3.2.0", 56 | "vue-socket.io": "^3.0.10", 57 | "vuedraggable": "^2.24.3", 58 | "vuex": "^3.4.0", 59 | "wangeditor": "^4.6.6" 60 | }, 61 | "devDependencies": { 62 | "@vue/cli-plugin-babel": "~4.5.0", 63 | "@vue/cli-plugin-e2e-cypress": "~4.5.0", 64 | "@vue/cli-plugin-eslint": "~4.5.0", 65 | "@vue/cli-plugin-router": "~4.5.0", 66 | "@vue/cli-plugin-unit-jest": "~4.5.0", 67 | "@vue/cli-plugin-vuex": "~4.5.0", 68 | "@vue/cli-service": "~4.5.0", 69 | "@vue/composition-api": "^1.0.0-rc.8", 70 | "@vue/eslint-config-prettier": "^6.0.0", 71 | "@vue/test-utils": "^1.0.3", 72 | "babel-eslint": "^10.1.0", 73 | "compression-webpack-plugin": "^4.0.0", 74 | "cross-env": "^7.0.3", 75 | "eslint": "^6.7.2", 76 | "eslint-plugin-prettier": "^3.3.1", 77 | "eslint-plugin-vue": "^6.2.2", 78 | "filemanager-webpack-plugin": "^2.0.5", 79 | "husky": "^4.2.5", 80 | "image-webpack-loader": "^6.0.0", 81 | "lint-staged": "^10.2.11", 82 | "prettier": "^2.2.1", 83 | "pretty-quick": "^3.1.0", 84 | "qiniu": "^7.3.2", 85 | "sass": "^1.26.10", 86 | "sass-loader": "^9.0.2", 87 | "vue-template-compiler": "^2.6.11", 88 | "webpackbar": "^5.0.0-3" 89 | }, 90 | "keywords": [ 91 | "vue", 92 | "admin", 93 | "dashboard", 94 | "element-ui", 95 | "vue-admin", 96 | "element-admin", 97 | "boilerplate", 98 | "admin-template", 99 | "management-system", 100 | "beehive" 101 | ], 102 | "engines": { 103 | "node": ">=8.9", 104 | "npm": ">= 3.0.0" 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | printWidth: 120, 3 | tabWidth: 2, 4 | useTabs: false, 5 | semi: true, 6 | vueIndentScriptAndStyle: true, 7 | singleQuote: true, 8 | quoteProps: 'as-needed', 9 | bracketSpacing: true, 10 | trailingComma: 'es5', 11 | jsxBracketSameLine: false, 12 | jsxSingleQuote: false, 13 | arrowParens: 'avoid', 14 | endOfLine: 'lf', 15 | insertPragma: false, 16 | requirePragma: false, 17 | proseWrap: 'never', 18 | htmlWhitespaceSensitivity: 'strict', 19 | rangeStart: 0, 20 | overrides: [ 21 | { 22 | files: '*.md', 23 | options: { 24 | tabWidth: 2, 25 | }, 26 | }, 27 | ], 28 | }; 29 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%= VUE_APP_TITLE %> 9 | 10 | 11 | <% for(var css of htmlWebpackPlugin.options.cdn.css) { %> 12 | 13 | <% } %> <% for(var js of htmlWebpackPlugin.options.cdn.js) { %> 14 | 15 | <% } %> 16 | 32 | 33 | 34 | 35 |
36 |
37 |
38 | 39 |
40 |

<%= VUE_APP_TITLE %>

41 |
42 |
43 | 44 | 45 | -------------------------------------------------------------------------------- /public/static/css/loading.css: -------------------------------------------------------------------------------- 1 | .first-loading-wrp { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: center; 6 | height: 90vh; 7 | min-height: 90vh; 8 | } 9 | 10 | .first-loading-wrp > h1 { 11 | font-size: 30px; 12 | font-weight: bolder; 13 | } 14 | 15 | .first-loading-wrp .loading-wrp { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | padding: 98px; 20 | } 21 | 22 | .dot { 23 | position: relative; 24 | box-sizing: border-box; 25 | display: inline-block; 26 | width: 64px; 27 | height: 64px; 28 | font-size: 64px; 29 | transform: rotate(45deg); 30 | animation: antRotate 1.2s infinite linear; 31 | } 32 | 33 | .dot i { 34 | position: absolute; 35 | display: block; 36 | width: 28px; 37 | height: 28px; 38 | background-color: #f5ae16; 39 | border-radius: 100%; 40 | opacity: 0.3; 41 | transform: scale(0.75); 42 | transform-origin: 50% 50%; 43 | animation: antSpinMove 1s infinite linear alternate; 44 | } 45 | 46 | .dot i:nth-child(1) { 47 | top: 0; 48 | left: 0; 49 | } 50 | 51 | .dot i:nth-child(2) { 52 | top: 0; 53 | right: 0; 54 | -webkit-animation-delay: 0.4s; 55 | animation-delay: 0.4s; 56 | } 57 | 58 | .dot i:nth-child(3) { 59 | right: 0; 60 | bottom: 0; 61 | -webkit-animation-delay: 0.8s; 62 | animation-delay: 0.8s; 63 | } 64 | 65 | .dot i:nth-child(4) { 66 | bottom: 0; 67 | left: 0; 68 | -webkit-animation-delay: 1.2s; 69 | animation-delay: 1.2s; 70 | } 71 | 72 | @keyframes antRotate { 73 | to { 74 | -webkit-transform: rotate(405deg); 75 | transform: rotate(405deg); 76 | } 77 | } 78 | 79 | @-webkit-keyframes antRotate { 80 | to { 81 | -webkit-transform: rotate(405deg); 82 | transform: rotate(405deg); 83 | } 84 | } 85 | 86 | @keyframes antSpinMove { 87 | to { 88 | opacity: 1; 89 | } 90 | } 91 | 92 | @-webkit-keyframes antSpinMove { 93 | to { 94 | opacity: 1; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/1.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/2.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/3.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/4.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/5.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/6.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/7.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/8.jpg -------------------------------------------------------------------------------- /public/static/img/dragChipImgs/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/dragChipImgs/9.jpg -------------------------------------------------------------------------------- /public/static/img/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/github.png -------------------------------------------------------------------------------- /public/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/public/static/img/logo.png -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 9 | -------------------------------------------------------------------------------- /src/api/departmentManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/departments/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/departments', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/departments', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/departments', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/inviteManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/invites/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/invites', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/invites', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/invites', 19 | method: 'delete', 20 | }, 21 | getValid: { 22 | url: '/v1/invites/valid', 23 | method: 'get', 24 | }, 25 | getInfoByUUID: { 26 | url: '/v1/invites/uuid', 27 | method: 'get', 28 | }, 29 | doAcceptInvite: { 30 | url: '/v1/invites/accept', 31 | method: 'put', 32 | }, 33 | }; 34 | 35 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 36 | 37 | export function getList(params) { 38 | return request({ 39 | ...methodUrl.getList, 40 | params, 41 | }); 42 | } 43 | 44 | export function doCreate(data) { 45 | return request({ 46 | ...methodUrl.doCreate, 47 | data, 48 | }); 49 | } 50 | 51 | export function doEdit(data) { 52 | return request({ 53 | ...methodUrl.doEdit, 54 | data, 55 | }); 56 | } 57 | 58 | export function doDelete(data) { 59 | return request({ 60 | ...methodUrl.doDelete, 61 | data, 62 | }); 63 | } 64 | 65 | export function getValid(params) { 66 | return request({ 67 | ...methodUrl.getValid, 68 | params, 69 | }); 70 | } 71 | 72 | export function getInfoByUUID(params) { 73 | return request({ 74 | ...methodUrl.getInfoByUUID, 75 | params, 76 | }); 77 | } 78 | 79 | export function doAcceptInvite(data) { 80 | return request({ 81 | ...methodUrl.doAcceptInvite, 82 | data, 83 | }); 84 | } 85 | -------------------------------------------------------------------------------- /src/api/menuManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/menus/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/menus', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/menus', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/menus', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/messageManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/messages/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/messages', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/messages', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/messages', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/operationLogManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/operation_logs/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/operation_logs', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/operation_logs', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/operation_logs', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/permissionManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/permissions/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/permissions', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/permissions', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/permissions', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/projectFileManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/project_files/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/project_files', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/project_files', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/project_files', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/projectManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/projects/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/projects', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/projects', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/projects', 19 | method: 'delete', 20 | }, 21 | getInfo: { 22 | url: '/v1/projects', 23 | method: 'get', 24 | }, 25 | getStatistics: { 26 | url: '/v1/projects/statistics', 27 | method: 'get', 28 | }, 29 | }; 30 | 31 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 32 | 33 | export function getList(params) { 34 | return request({ 35 | ...methodUrl.getList, 36 | params, 37 | }); 38 | } 39 | 40 | export function doCreate(data) { 41 | return request({ 42 | ...methodUrl.doCreate, 43 | data, 44 | }); 45 | } 46 | 47 | export function doEdit(data) { 48 | return request({ 49 | ...methodUrl.doEdit, 50 | data, 51 | }); 52 | } 53 | 54 | export function doDelete(data) { 55 | return request({ 56 | ...methodUrl.doDelete, 57 | data, 58 | }); 59 | } 60 | 61 | export function getInfo(params) { 62 | return request({ 63 | ...methodUrl.getInfo, 64 | params, 65 | }); 66 | } 67 | 68 | export function getStatistics(params) { 69 | return request({ 70 | ...methodUrl.getStatistics, 71 | params, 72 | }); 73 | } 74 | -------------------------------------------------------------------------------- /src/api/projectTemplateManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/project_templates/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/project_templates', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/project_templates', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/project_templates', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/projectTemplateTaskManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/project_template_tasks/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/project_template_tasks', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/project_template_tasks', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/project_template_tasks', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/publicKey.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | 3 | export function getPublicKey(data) { 4 | return request({ 5 | url: '/v1/configurations/public_key', 6 | method: 'get', 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /src/api/roleManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/roles/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/roles', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/roles', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/roles', 19 | method: 'delete', 20 | }, 21 | doSetDefault: { 22 | url: '/v1/roles/is_default', 23 | method: 'put', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doSetDefault(data) { 58 | return request({ 59 | ...methodUrl.doSetDefault, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/roleMenuManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/role_menus/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/role_menus', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/role_menus', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/role_menus', 19 | method: 'delete', 20 | }, 21 | doBulkMenuCreate: { 22 | url: '/v1/role_menus/bulk_menu', 23 | method: 'post', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doBulkMenuCreate(data) { 58 | return request({ 59 | ...methodUrl.doBulkMenuCreate, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/rolePermissionManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/role_permissions/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/role_permissions', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/role_permissions', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/role_permissions', 19 | method: 'delete', 20 | }, 21 | doBulkPermissionCreate: { 22 | url: '/v1/role_permissions/bulk_permission', 23 | method: 'post', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doBulkPermissionCreate(data) { 58 | return request({ 59 | ...methodUrl.doBulkPermissionCreate, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/router.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getRouterList: { 6 | url: '/v1/menus/user_menus', 7 | method: 'get', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export function getRouterList(params) { 14 | return request({ 15 | ...methodUrl.getRouterList, 16 | params, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/api/taskListManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_lists/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_lists', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_lists', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_lists', 19 | method: 'delete', 20 | }, 21 | doEditSort: { 22 | url: '/v1/task_lists/sort', 23 | method: 'put', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doEditSort(data) { 58 | return request({ 59 | ...methodUrl.doEditSort, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/taskLogManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_logs/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_logs', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_logs', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_logs', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/taskManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/tasks/list', 7 | method: 'get', 8 | }, 9 | getInfo: { 10 | url: '/v1/tasks', 11 | method: 'get', 12 | }, 13 | doCreate: { 14 | url: '/v1/tasks', 15 | method: 'post', 16 | }, 17 | doEdit: { 18 | url: '/v1/tasks', 19 | method: 'put', 20 | }, 21 | doDelete: { 22 | url: '/v1/tasks', 23 | method: 'delete', 24 | }, 25 | doEditSort: { 26 | url: '/v1/tasks/sort', 27 | method: 'put', 28 | }, 29 | doRecycleAllTaskOfTaskList: { 30 | url: '/v1/tasks/recycle_all_task_of_taskList', 31 | method: 'put', 32 | }, 33 | }; 34 | 35 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 36 | 37 | export function getList(params) { 38 | return request({ 39 | ...methodUrl.getList, 40 | params, 41 | }); 42 | } 43 | 44 | export function getInfo(params) { 45 | return request({ 46 | ...methodUrl.getInfo, 47 | params, 48 | }); 49 | } 50 | 51 | export function doCreate(data) { 52 | return request({ 53 | ...methodUrl.doCreate, 54 | data, 55 | }); 56 | } 57 | 58 | export function doEdit(data) { 59 | return request({ 60 | ...methodUrl.doEdit, 61 | data, 62 | }); 63 | } 64 | 65 | export function doDelete(data) { 66 | return request({ 67 | ...methodUrl.doDelete, 68 | data, 69 | }); 70 | } 71 | 72 | export function doEditSort(data) { 73 | return request({ 74 | ...methodUrl.doEditSort, 75 | data, 76 | }); 77 | } 78 | 79 | export function doRecycleAllTaskOfTaskList(data) { 80 | return request({ 81 | ...methodUrl.doRecycleAllTaskOfTaskList, 82 | data, 83 | }); 84 | } 85 | -------------------------------------------------------------------------------- /src/api/taskPriorityManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_prioritys/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_prioritys', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_prioritys', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_prioritys', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/taskStateManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_states/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_states', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_states', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_states', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/taskTagManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_tags/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_tags', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_tags', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_tags', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/taskTaskTagManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_task_tags/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_task_tags', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_task_tags', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_task_tags', 19 | method: 'delete', 20 | }, 21 | doChange: { 22 | url: '/v1/task_task_tags/change', 23 | method: 'post', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doChange(data) { 58 | return request({ 59 | ...methodUrl.doChange, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/taskTypeManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_types/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_types', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_types', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_types', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/taskWorkingHourManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/task_working_hours/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/task_working_hours', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/task_working_hours', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/task_working_hours', 19 | method: 'delete', 20 | }, 21 | }; 22 | 23 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 24 | 25 | export function getList(params) { 26 | return request({ 27 | ...methodUrl.getList, 28 | params, 29 | }); 30 | } 31 | 32 | export function doCreate(data) { 33 | return request({ 34 | ...methodUrl.doCreate, 35 | data, 36 | }); 37 | } 38 | 39 | export function doEdit(data) { 40 | return request({ 41 | ...methodUrl.doEdit, 42 | data, 43 | }); 44 | } 45 | 46 | export function doDelete(data) { 47 | return request({ 48 | ...methodUrl.doDelete, 49 | data, 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/api/upload.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | upload: { 6 | url: '/v1/uploads', 7 | method: 'post', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export function upload(data) { 14 | return request({ 15 | ...methodUrl.upload, 16 | data, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/api/user.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { encryptedData } from '@/utils/encrypt'; 3 | import { loginRSA } from '@/config/settings'; 4 | import { getPermissionStr } from '@/utils'; 5 | 6 | const methodUrl = { 7 | getList: { 8 | url: '/v1/users/list', 9 | method: 'get', 10 | }, 11 | doEdit: { 12 | url: '/v1/users', 13 | method: 'put', 14 | }, 15 | doDelete: { 16 | url: '/v1/users', 17 | method: 'delete', 18 | }, 19 | login: { 20 | url: '/v1/users/login', 21 | method: 'post', 22 | }, 23 | getInfo: { 24 | url: '/v1/users/user_info', 25 | method: 'get', 26 | }, 27 | logout: { 28 | url: '/v1/users/logout', 29 | method: 'post', 30 | }, 31 | register: { 32 | url: '/v1/users', 33 | method: 'post', 34 | }, 35 | usersPassword: { 36 | url: '/v1/users/password', 37 | method: 'put', 38 | }, 39 | doRefreshToken: { 40 | url: '/v1/users/refreshToken', 41 | method: 'post', 42 | }, 43 | githubLogin: { 44 | url: '/v1/users/github/login', 45 | method: 'post', 46 | }, 47 | getOne: { 48 | url: '/v1/users', 49 | method: 'get', 50 | }, 51 | updateUserDepartment: { 52 | url: '/v1/users/department', 53 | method: 'put', 54 | }, 55 | getExistsUserUniqueFields: { 56 | url: '/v1/users/exists_user_unique_fields', 57 | method: 'get', 58 | }, 59 | }; 60 | 61 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 62 | 63 | export function getList(params) { 64 | return request({ 65 | ...methodUrl.getList, 66 | params, 67 | }); 68 | } 69 | 70 | export function doEdit(data) { 71 | return request({ 72 | ...methodUrl.doEdit, 73 | data, 74 | }); 75 | } 76 | 77 | export function doDelete(data) { 78 | return request({ 79 | ...methodUrl.doDelete, 80 | data, 81 | }); 82 | } 83 | 84 | export async function login(data) { 85 | let password = data.password; 86 | if (loginRSA) { 87 | password = await encryptedData(data.password); 88 | } 89 | return request({ 90 | ...methodUrl.login, 91 | data: { 92 | ...data, 93 | password, 94 | }, 95 | }); 96 | } 97 | 98 | export function getInfo() { 99 | return request({ 100 | ...methodUrl.getInfo, 101 | }); 102 | } 103 | 104 | export function logout() { 105 | return request({ 106 | ...methodUrl.logout, 107 | }); 108 | } 109 | 110 | export function register(data) { 111 | return request({ 112 | ...methodUrl.register, 113 | data, 114 | }); 115 | } 116 | 117 | export function usersPassword(data) { 118 | return request({ 119 | ...methodUrl.usersPassword, 120 | data, 121 | }); 122 | } 123 | 124 | export function doRefreshToken(data) { 125 | return request({ 126 | ...methodUrl.doRefreshToken, 127 | data, 128 | }); 129 | } 130 | 131 | export function githubLogin(data) { 132 | return request({ 133 | ...methodUrl.githubLogin, 134 | data, 135 | }); 136 | } 137 | 138 | export function getOne(params) { 139 | return request({ 140 | ...methodUrl.getOne, 141 | params, 142 | }); 143 | } 144 | 145 | export function updateUserDepartment(data) { 146 | return request({ 147 | ...methodUrl.updateUserDepartment, 148 | data, 149 | }); 150 | } 151 | 152 | export function getExistsUserUniqueFields(params) { 153 | return request({ 154 | ...methodUrl.getExistsUserUniqueFields, 155 | params, 156 | }); 157 | } 158 | -------------------------------------------------------------------------------- /src/api/userProjectCollectManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | doChange: { 6 | url: '/v1/user_project_collects/change', 7 | method: 'post', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export function doChange(data) { 14 | return request({ 15 | ...methodUrl.doChange, 16 | data, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/api/userProjectManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/user_projects/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/user_projects', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/user_projects', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/user_projects', 19 | method: 'delete', 20 | }, 21 | doQuit: { 22 | url: '/v1/user_projects/quit', 23 | method: 'delete', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doQuit(data) { 58 | return request({ 59 | ...methodUrl.doQuit, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/userRoleManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | getList: { 6 | url: '/v1/user_roles/list', 7 | method: 'get', 8 | }, 9 | doCreate: { 10 | url: '/v1/user_roles', 11 | method: 'post', 12 | }, 13 | doEdit: { 14 | url: '/v1/user_roles', 15 | method: 'put', 16 | }, 17 | doDelete: { 18 | url: '/v1/user_roles', 19 | method: 'delete', 20 | }, 21 | doBulkRoleCreate: { 22 | url: '/v1/user_roles/bulk_role', 23 | method: 'post', 24 | }, 25 | }; 26 | 27 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 28 | 29 | export function getList(params) { 30 | return request({ 31 | ...methodUrl.getList, 32 | params, 33 | }); 34 | } 35 | 36 | export function doCreate(data) { 37 | return request({ 38 | ...methodUrl.doCreate, 39 | data, 40 | }); 41 | } 42 | 43 | export function doEdit(data) { 44 | return request({ 45 | ...methodUrl.doEdit, 46 | data, 47 | }); 48 | } 49 | 50 | export function doDelete(data) { 51 | return request({ 52 | ...methodUrl.doDelete, 53 | data, 54 | }); 55 | } 56 | 57 | export function doBulkRoleCreate(data) { 58 | return request({ 59 | ...methodUrl.doBulkRoleCreate, 60 | data, 61 | }); 62 | } 63 | -------------------------------------------------------------------------------- /src/api/userTaskLikeManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | doChange: { 6 | url: '/v1/user_task_likes/change', 7 | method: 'post', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export function doChange(data) { 14 | return request({ 15 | ...methodUrl.doChange, 16 | data, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/api/userTaskManagement.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | doChange: { 6 | url: '/v1/user_tasks/change', 7 | method: 'post', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export function doChange(data) { 14 | return request({ 15 | ...methodUrl.doChange, 16 | data, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/api/verification_code.js: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request'; 2 | import { getPermissionStr } from '@/utils'; 3 | 4 | const methodUrl = { 5 | create: { 6 | url: '/v1/verification_codes', 7 | method: 'post', 8 | }, 9 | }; 10 | 11 | export const permissions = Object.assign({}, methodUrl, { ...getPermissionStr(methodUrl) }); 12 | 13 | export async function create(data) { 14 | return request({ 15 | ...methodUrl.create, 16 | data, 17 | }); 18 | } 19 | -------------------------------------------------------------------------------- /src/assets/error_images/401.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/error_images/401.png -------------------------------------------------------------------------------- /src/assets/error_images/403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/error_images/403.png -------------------------------------------------------------------------------- /src/assets/error_images/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/error_images/404.png -------------------------------------------------------------------------------- /src/assets/error_images/cloud.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/error_images/cloud.png -------------------------------------------------------------------------------- /src/assets/iconfonts/iconfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/iconfonts/iconfont.eot -------------------------------------------------------------------------------- /src/assets/iconfonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/iconfonts/iconfont.ttf -------------------------------------------------------------------------------- /src/assets/iconfonts/iconfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/iconfonts/iconfont.woff -------------------------------------------------------------------------------- /src/assets/iconfonts/iconfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/iconfonts/iconfont.woff2 -------------------------------------------------------------------------------- /src/assets/imgs/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/imgs/empty.png -------------------------------------------------------------------------------- /src/assets/imgs/invite/new-message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/imgs/invite/new-message.png -------------------------------------------------------------------------------- /src/assets/login_images/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/login_images/background.jpg -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/B-image/index.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 44 | 45 | 56 | -------------------------------------------------------------------------------- /src/components/Btn-tooltip/index.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 57 | 58 | 62 | -------------------------------------------------------------------------------- /src/components/Cover-image/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 75 | 76 | 119 | 120 | 133 | -------------------------------------------------------------------------------- /src/components/Dj-tag/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 18 | 19 | 44 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.vue: -------------------------------------------------------------------------------- 1 | 23 | 24 | 47 | 48 | 63 | -------------------------------------------------------------------------------- /src/components/EmptyImage/index.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 36 | 37 | 52 | -------------------------------------------------------------------------------- /src/components/FileTypeIcon/index.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 52 | 53 | 70 | -------------------------------------------------------------------------------- /src/components/GithubPath/index.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 21 | 22 | 35 | -------------------------------------------------------------------------------- /src/components/ShapeShifter/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/components/Upload/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 42 | -------------------------------------------------------------------------------- /src/components/UserInfoDialog/index.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 85 | 86 | 141 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/VabQueryFormBottomPanel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/VabQueryFormLeftPanel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/VabQueryFormRightPanel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/VabQueryFormTopPanel.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 21 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/export.js: -------------------------------------------------------------------------------- 1 | import VabQueryForm from './index'; 2 | import VabQueryFormTopPanel from './VabQueryFormTopPanel'; 3 | import VabQueryFormBottomPanel from './VabQueryFormBottomPanel'; 4 | import VabQueryFormLeftPanel from './VabQueryFormLeftPanel'; 5 | import VabQueryFormRightPanel from './VabQueryFormRightPanel'; 6 | export default { 7 | install(Vue) { 8 | Vue.component('vab-query-form', VabQueryForm); 9 | Vue.component('vab-query-form-left-panel', VabQueryFormLeftPanel); 10 | Vue.component('vab-query-form-right-panel', VabQueryFormRightPanel); 11 | Vue.component('vab-query-form-top-panel', VabQueryFormTopPanel); 12 | Vue.component('vab-query-form-bottom-panel', VabQueryFormBottomPanel); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /src/components/VabQueryForm/index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 19 | 20 | 67 | -------------------------------------------------------------------------------- /src/config/permission.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 路由守卫,目前两种模式:all模式与intelligence模式 3 | */ 4 | import router from '@/router'; 5 | import store from '@/store'; 6 | import VabProgress from 'nprogress'; 7 | import 'nprogress/nprogress.css'; 8 | import getPageTitle from '@/utils/pageTitle'; 9 | import { routesWhiteList, progressBar, recordRoute } from './settings'; 10 | 11 | VabProgress.configure({ 12 | easing: 'ease', 13 | speed: 500, 14 | trickleSpeed: 200, 15 | showSpinner: false, 16 | }); 17 | router.beforeResolve(async (to, from, next) => { 18 | if (progressBar) VabProgress.start(); 19 | let hasToken = store.getters['user/accessToken']; 20 | if (hasToken) { 21 | if (to.path === '/login') { 22 | next({ path: '/' }); 23 | if (progressBar) VabProgress.done(); 24 | } else { 25 | const hasPermissions = store.getters['user/permissions'] && store.getters['user/permissions'].length > 0; 26 | if (hasPermissions) { 27 | next(); 28 | } else { 29 | try { 30 | await store.dispatch('user/getInfo'); 31 | let accessRoutes = (await store.dispatch('routes/setAllRoutes')) || []; 32 | router.addRoutes(accessRoutes); 33 | next({ ...to, replace: true }); 34 | } catch { 35 | await store.dispatch('user/resetAccessToken'); 36 | if (progressBar) VabProgress.done(); 37 | } 38 | } 39 | } 40 | } else { 41 | if (routesWhiteList.indexOf(to.path) !== -1) { 42 | next(); 43 | } else { 44 | if (recordRoute) { 45 | next(`/login?redirect=${to.path}`); 46 | } else { 47 | next('/login'); 48 | } 49 | 50 | if (progressBar) VabProgress.done(); 51 | } 52 | } 53 | document.title = getPageTitle(to.meta.title); 54 | }); 55 | router.afterEach(() => { 56 | if (progressBar) VabProgress.done(); 57 | }); 58 | -------------------------------------------------------------------------------- /src/config/settings.js: -------------------------------------------------------------------------------- 1 | const { BUILD_TARGET, NODE_ENV, VUE_APP_PREVIEW } = process.env; 2 | const isProdQiniu = BUILD_TARGET && BUILD_TARGET.trim() == 'qiniu'; 3 | const dayjs = require('dayjs'); 4 | const path = require('path'); 5 | const fs = require('fs'); 6 | const prefix = `vue-beehive/${dayjs().format('YYYYMMDD-HHmmss')}`; 7 | // 打包时,供七牛cdn上传使用 8 | if (isProdQiniu) fs.writeFileSync(path.resolve(__dirname, './prefix'), prefix, 'utf-8'); 9 | 10 | module.exports = { 11 | // 开发以及部署时的URL 12 | publicPath: isProdQiniu ? `https://qiniucdn.imfdj.top/${prefix}/` : '/', 13 | // 生产环境构建文件的目录名 14 | outputDir: 'dist', 15 | // 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。 16 | assetsDir: 'static', 17 | // 开发环境每次保存时是否输出为eslint编译警告 18 | lintOnSave: true, 19 | // 默认的接口地址 20 | baseURL: NODE_ENV === 'development' || NODE_ENV === 'preview' ? '/api' : '/api', 21 | //标题 (包括初次加载雪花屏的标题 页面的标题 浏览器的标题) 22 | title: 'beehive', 23 | //简写 24 | //开发环境端口号 25 | devPort: '80', 26 | //版本号 27 | version: process.env.VUE_APP_VERSION, 28 | //是否显示顶部进度条 29 | progressBar: true, 30 | // 路由模式,可选值为 history 或 hash 31 | routerMode: 'history', 32 | //不经过token校验的路由 33 | routesWhiteList: ['/login', '/register', '/retrieve_password', '/404', '/401'], 34 | //加载时显示文字 35 | loadingText: '正在加载中...', 36 | //token名称 37 | tokenName: 'Authorization', 38 | //token在localStorage、sessionStorage、cookie存储的key的名称 39 | tokenTableName: 'vue-beehive', 40 | //token存储位置localStorage sessionStorage cookie 41 | storage: 'localStorage', 42 | //token失效回退到登录页时是否记录本次的路由 43 | recordRoute: true, 44 | //是否显示logo,不显示时设置false,显示时请填写remixIcon图标名称,暂时只支持设置remixIcon 45 | logo: 'beehive', 46 | //是否国定头部 固定fixed 不固定noFixed 47 | header: 'fixed', 48 | //横纵布局 horizontal vertical 49 | layout: 'horizontal', 50 | //是否开启主题配置按钮 51 | themeBar: false, 52 | //是否显示多标签页 53 | tagsBar: false, 54 | //是否显示骨架屏 55 | skeleton: false, 56 | //配后端数据的接收方式application/json;charset=UTF-8或者application/x-www-form-urlencoded;charset=UTF-8 57 | contentType: 'application/json;charset=UTF-8', 58 | //消息框消失时间 59 | messageDuration: 3000, 60 | //最长请求时间 61 | requestTimeout: 10000, 62 | //操作正常code,支持String、Array两种方式 63 | successCode: [200, 201, 204, 0], 64 | //参数错误code 65 | invalidRequestCode: 400, 66 | //登录失效code 67 | invalidCode: 402, 68 | //无权限code 69 | noPermissionCode: 403, 70 | //没有找到code 71 | noFoundCode: 404, 72 | //无认证code 73 | noAuthenticationCode: 401, 74 | //是否显示在页面高亮错误 75 | errorLog: ['development', 'test', 'production'], 76 | //是否开启登录RSA加密 77 | loginRSA: NODE_ENV === 'production' && true, 78 | //vertical布局时是否只保持一个子菜单的展开 79 | uniqueOpened: true, 80 | //vertical布局时默认展开的菜单path,使用逗号隔开建议只展开一个 81 | defaultOopeneds: ['/vab'], 82 | //需要加loading层的请求,防止重复提交 83 | debounce: ['doEdit'], 84 | //需要自动注入并加载的模块 85 | providePlugin: {}, 86 | //npm run build时是否自动生成7z压缩包 87 | build7z: false, 88 | //github授权登录authorize请求地址 89 | github_auth_authorize_url: 'https://github.com/login/oauth/authorize', 90 | //github授权登录client_id 91 | github_auth_client_id: 92 | NODE_ENV === 'production' 93 | ? VUE_APP_PREVIEW && VUE_APP_PREVIEW.trim() == 'true' 94 | ? '4827d5eb3fec86a9d541' 95 | : 'd347423472204bea6caf' 96 | : '7191c2792ca23d773c32', 97 | //github授权登录重定向地址 98 | github_auth_redirect_uri: 99 | NODE_ENV === 'production' 100 | ? `https://${VUE_APP_PREVIEW && VUE_APP_PREVIEW.trim() == 'true' ? 'beehives' : 'beehive'}.imfdj.top/login` 101 | : 'http://localhost/login', 102 | // 项目列表路径 103 | project_list_path: '/projectManagement/ProjectLists', 104 | // 项目路径 105 | project_path: '/projectManagement/Project', 106 | }; 107 | -------------------------------------------------------------------------------- /src/layouts/EmptyLayout.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /src/layouts/components/Menu.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 89 | 90 | 143 | -------------------------------------------------------------------------------- /src/layouts/components/MessageBox/components/InformList.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 52 | 53 | 132 | -------------------------------------------------------------------------------- /src/layouts/components/SideBar/components/MenuItem.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 77 | -------------------------------------------------------------------------------- /src/layouts/components/SideBar/components/SideBarItem.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 87 | 88 | 105 | -------------------------------------------------------------------------------- /src/layouts/components/SideBar/components/Submenu.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 53 | -------------------------------------------------------------------------------- /src/layouts/components/SideBar/index.vue: -------------------------------------------------------------------------------- 1 | 21 | 60 | 141 | -------------------------------------------------------------------------------- /src/layouts/components/UserOperation.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 36 | 37 | 62 | -------------------------------------------------------------------------------- /src/layouts/index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 36 | 37 | 51 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | import './plugins'; 6 | import * as Sentry from '@sentry/browser'; 7 | import * as Integrations from '@sentry/integrations'; 8 | 9 | if (process.env.NODE_ENV === 'production') { 10 | Sentry.init({ 11 | dsn: 'https://725db29937f546b887c32c3334062f9a@sentry.imfdj.top/3', 12 | integrations: [new Integrations.Vue({ Vue, attachProps: true })], 13 | }); 14 | // 生产环境不打印console.log 15 | console.log = () => {}; 16 | } 17 | 18 | Vue.config.productionTip = false; 19 | 20 | // 注册一个全局自定义指令,验证资源权限 `v-permission` 21 | Vue.directive('permission', { 22 | // 当被绑定的元素插入到 DOM 中时…… 23 | inserted: function (el, binding, vnode) { 24 | const permission = binding.value; // 获取权限值 25 | const allPermissions = store.getters['user/permissions'] || ''; // 当前用户拥有的权限 26 | if (!allPermissions.includes(permission)) { 27 | el.parentElement.removeChild(el); //不拥有该权限移除dom元素 28 | } 29 | }, 30 | }); 31 | 32 | new Vue({ 33 | router, 34 | store, 35 | render: h => h(App), 36 | }).$mount('#app'); 37 | -------------------------------------------------------------------------------- /src/mixins/index.js: -------------------------------------------------------------------------------- 1 | import dayjs from 'dayjs'; 2 | import { doDelete as doDeleteTask, doEdit as doEditTask } from '@/api/taskManagement'; 3 | import multiDownload from 'multi-download'; 4 | import store from '@/store'; 5 | import axios from 'axios'; 6 | 7 | export default { 8 | methods: { 9 | dateFormat(date, template) { 10 | return dayjs(date).format(template); 11 | }, 12 | recoverTask(task) { 13 | return new Promise((resolve, reject) => { 14 | try { 15 | this.$confirm('恢复后可在任务列表中查看', '确定恢复内容?', { 16 | confirmButtonText: '确定', 17 | cancelButtonText: '取消', 18 | type: 'warning', 19 | }).then(async () => { 20 | await doEditTask({ 21 | ...task, 22 | is_recycle: 0, 23 | }); 24 | }); 25 | } catch (e) { 26 | reject(e); 27 | } 28 | }); 29 | }, 30 | deleteTask(task) { 31 | return new Promise((resolve, reject) => { 32 | try { 33 | this.$confirm('彻底删除任务后,该任务将会被永久被删除。', '确定彻底删除任务?', { 34 | confirmButtonText: '确定', 35 | cancelButtonText: '取消', 36 | type: 'warning', 37 | }).then(async () => { 38 | await doDeleteTask({ ids: [task.id] }); 39 | resolve(); 40 | }); 41 | } catch (e) { 42 | reject(e); 43 | } 44 | }); 45 | }, 46 | 47 | // 下载文件 48 | multiDownload(item) { 49 | multiDownload([item.path], { 50 | rename: () => `${item.title}${item.extension}`, 51 | }); 52 | }, 53 | 54 | /** 55 | * 复制文本 56 | * @param text 57 | */ 58 | doCopy(text) { 59 | const input = document.createElement('input'); 60 | const div = document.createElement('div'); 61 | input.setAttribute('readonly', 'readonly'); 62 | input.setAttribute('value', text); 63 | input.setAttribute('style', 'position: absolute;left: 100000px;'); 64 | div.setAttribute('style', 'position: absolute;width: 0px;height: 0px;overflow: hidden;'); 65 | div.appendChild(input); 66 | document.body.appendChild(div); 67 | input.select(); 68 | document.execCommand('copy'); 69 | document.body.removeChild(div); 70 | }, 71 | 72 | /** 73 | * 获取picsum随机图片路径 74 | * @param string 75 | * @return string 76 | */ 77 | async getRandomPicsumPicturePath(path = 'https://picsum.photos/100') { 78 | const { 79 | request: { responseURL }, 80 | } = await axios({ 81 | url: path, 82 | method: 'get', 83 | }); 84 | return responseURL; 85 | }, 86 | 87 | /** 88 | * 从localstorage中获取picsum随机图片路径 89 | * @param string 90 | * @return string 91 | */ 92 | async getRandomImgPath(path = 'https://picsum.photos/290/160') { 93 | let data = localStorage.getItem(path); 94 | // 异步重新设置新的写入localStorage 95 | this.getRandomPicsumPicturePath(path).then(data => { 96 | localStorage.setItem(path, data); 97 | }); 98 | // 存在则返回 99 | if (data) { 100 | return data; 101 | } 102 | // 不存在,则同步获取 103 | return await this.getRandomPicsumPicturePath(path); 104 | }, 105 | }, 106 | }; 107 | -------------------------------------------------------------------------------- /src/plugins/echarts.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import ECharts from 'vue-echarts'; 3 | import { use } from 'echarts/core'; 4 | // 手动引入 ECharts 各模块来减小打包体积 5 | 6 | import { CanvasRenderer } from 'echarts/renderers'; 7 | import { PieChart } from 'echarts/charts'; 8 | import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components'; 9 | 10 | use([CanvasRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent]); 11 | 12 | // 全局注册组件(也可以使用局部注册) 13 | Vue.component('v-chart', ECharts); 14 | -------------------------------------------------------------------------------- /src/plugins/element.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import ElementUI from 'element-ui'; 3 | import 'element-ui/lib/theme-chalk/display.css'; 4 | 5 | import '@/styles/element-variables.scss'; 6 | 7 | Vue.use(ElementUI, { 8 | size: 'small', 9 | }); 10 | -------------------------------------------------------------------------------- /src/plugins/index.js: -------------------------------------------------------------------------------- 1 | /* 公共引入,勿随意修改,修改时需经过确认 */ 2 | import Vue from 'vue'; 3 | import './element'; 4 | import './echarts'; 5 | import '@/styles/vab.scss'; 6 | import '@/styles/custom.scss'; 7 | import '@/config/permission'; 8 | import '@/utils/errorLog'; 9 | 10 | import Vab from '@/utils/vab'; 11 | import VabQueryForm from '@/components/VabQueryForm/export'; 12 | import VueCropper from 'vue-cropper'; 13 | 14 | Vue.use(Vab); 15 | Vue.use(VabQueryForm); 16 | Vue.use(VueCropper); 17 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 导入所有 vuex 模块,自动加入namespaced:true,用于解决vuex命名冲突,请勿修改。 3 | */ 4 | 5 | import Vue from 'vue'; 6 | import Vuex from 'vuex'; 7 | 8 | Vue.use(Vuex); 9 | const files = require.context('./modules', false, /\.js$/); 10 | const modules = {}; 11 | 12 | files.keys().forEach(key => { 13 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default; 14 | }); 15 | Object.keys(modules).forEach(key => { 16 | modules[key]['namespaced'] = true; 17 | }); 18 | const store = new Vuex.Store({ 19 | modules, 20 | }); 21 | export default store; 22 | -------------------------------------------------------------------------------- /src/store/modules/errorLog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 异常捕获的状态拦截,请勿修改 3 | */ 4 | 5 | const state = { errorLogs: [] }; 6 | const getters = { 7 | errorLogs: state => state.errorLogs, 8 | }; 9 | const mutations = { 10 | addErrorLog(state, errorLog) { 11 | state.errorLogs.push(errorLog); 12 | }, 13 | clearErrorLog: state => { 14 | state.errorLogs.splice(0); 15 | }, 16 | }; 17 | const actions = { 18 | addErrorLog({ commit }, errorLog) { 19 | commit('addErrorLog', errorLog); 20 | }, 21 | clearErrorLog({ commit }) { 22 | commit('clearErrorLog'); 23 | }, 24 | }; 25 | export default { state, getters, mutations, actions }; 26 | -------------------------------------------------------------------------------- /src/store/modules/project.js: -------------------------------------------------------------------------------- 1 | import { getList as getProjectList } from '@/api/projectManagement'; 2 | import { getList as getTaskTypeList } from '@/api/taskTypeManagement'; 3 | import { getList as getTaskStateList } from '@/api/taskStateManagement'; 4 | import { getList as getTaskPriorityList } from '@/api/taskPriorityManagement'; 5 | import { getList as getTaskTagsList } from '@/api/taskTagManagement'; 6 | import { getList as getProjectMembers } from '@/api/user'; 7 | 8 | const state = { 9 | projectList: [], 10 | taskTypes: [], 11 | taskStates: [], 12 | taskPrioritys: [], 13 | taskTags: [], 14 | projectMembers: [], // 项目成员 15 | currentProjectId: null, // 当前项目ID 16 | indexTab: 0, // 项目导航栏的index 17 | }; 18 | 19 | const getters = { 20 | // 当前项目 21 | currentProject: state => state.projectList.find(item => item.id === state.currentProjectId) || {}, 22 | // 当前登陆这是否为当前项目的成员 23 | isCurrentProjectMember: (state, getters, rootState) => 24 | getters.currentProject.member?.find(item => item.id === rootState.user.userInfo.id) ? true : false, 25 | }; 26 | 27 | const mutations = { 28 | setProjectList(state, projectList) { 29 | state.projectList = projectList; 30 | }, 31 | setTaskTypes(state, taskTypes) { 32 | state.taskTypes = taskTypes; 33 | }, 34 | setTaskStates(state, taskStates) { 35 | state.taskStates = taskStates; 36 | }, 37 | setTaskPrioritys(state, taskPrioritys) { 38 | state.taskPrioritys = taskPrioritys; 39 | }, 40 | setTaskTags(state, taskTags) { 41 | state.taskTags = taskTags; 42 | }, 43 | setCurrentProjectId(state, currentProjectId) { 44 | state.currentProjectId = currentProjectId; 45 | }, 46 | setProjectMembers(state, projectMembers) { 47 | state.projectMembers = projectMembers; 48 | }, 49 | setIndexTab(state, indexTab) { 50 | state.indexTab = indexTab; 51 | }, 52 | }; 53 | const actions = { 54 | async setProjectList({ commit }) { 55 | const { 56 | data: { rows }, 57 | } = await getProjectList({ 58 | limit: 1000, 59 | // is_recycle: 0, 60 | }); 61 | commit('setProjectList', rows); 62 | }, 63 | async setTaskTypes({ commit }) { 64 | const { 65 | data: { rows }, 66 | } = await getTaskTypeList({ 67 | prop_order: 'sort', 68 | order: 'desc', 69 | }); 70 | commit('setTaskTypes', rows); 71 | }, 72 | async setTaskStates({ commit }) { 73 | const { 74 | data: { rows }, 75 | } = await getTaskStateList({ 76 | prop_order: 'sort', 77 | order: 'desc', 78 | }); 79 | commit('setTaskStates', rows); 80 | }, 81 | async setTaskPrioritys({ commit }) { 82 | const { 83 | data: { rows }, 84 | } = await getTaskPriorityList({ 85 | prop_order: 'sort', 86 | order: 'desc', 87 | }); 88 | commit('setTaskPrioritys', rows); 89 | }, 90 | async setTaskTags({ commit, state }) { 91 | const { 92 | data: { rows }, 93 | } = await getTaskTagsList({ project_id: state.currentProjectId }); 94 | commit('setTaskTags', rows); 95 | }, 96 | async setProjectMembers({ commit, state }) { 97 | const { 98 | data: { rows }, 99 | } = await getProjectMembers({ project_id: state.currentProjectId }); 100 | commit('setProjectMembers', rows); 101 | }, 102 | }; 103 | 104 | export default { state, getters, mutations, actions }; 105 | -------------------------------------------------------------------------------- /src/store/modules/routes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 路由拦截状态管理,目前两种模式:all模式与intelligence模式,其中partialRoutes是菜单暂未使用 3 | */ 4 | import { asyncRoutes, constantRoutes } from '@/router'; 5 | import { getRouterList } from '@/api/router'; 6 | import { filterAllRoutes, listToTree } from '@/utils/handleRoutes'; 7 | 8 | const state = { 9 | routes: [], 10 | partialRoutes: [], 11 | accessRoutesTree: [], 12 | navIndex: -1, 13 | noNav: false, 14 | }; 15 | const getters = { 16 | routes: state => state.routes, 17 | partialRoutes: state => state.partialRoutes, 18 | accessRoutesTree: state => state.accessRoutesTree, 19 | accessRoutesTreeNoHidden: state => state.accessRoutesTree?.filter(item => !item.hidden) || [], 20 | navIndex: state => state.navIndex, 21 | noNav: state => state.noNav, 22 | currentNav: state => { 23 | const accessRoutesTreeNoHidden = state.accessRoutesTree?.filter(item => !item.hidden) || []; 24 | return accessRoutesTreeNoHidden.find((item, index) => index === state.navIndex) || []; 25 | }, 26 | }; 27 | const mutations = { 28 | setAllRoutes(state, routes) { 29 | state.routes = constantRoutes.concat(routes); 30 | }, 31 | setPartialRoutes(state, routes) { 32 | state.partialRoutes = constantRoutes.concat(routes); 33 | }, 34 | setAccessRoutesTree(state, accessRoutesTree) { 35 | state.accessRoutesTree = accessRoutesTree; 36 | }, 37 | setNavIndex(state, navIndex) { 38 | state.navIndex = navIndex; 39 | }, 40 | setNoNav(state, noNav) { 41 | state.noNav = noNav; 42 | }, 43 | }; 44 | const actions = { 45 | async setAllRoutes({ commit }) { 46 | let { data } = await getRouterList(); 47 | data.push({ path: '*', redirect: '/404', hidden: true }); 48 | let accessRoutes_tree = []; 49 | listToTree(data, accessRoutes_tree, 0); 50 | commit('setAccessRoutesTree', accessRoutes_tree); 51 | let accessRoutes = filterAllRoutes(accessRoutes_tree); 52 | accessRoutes.push({ 53 | path: '*', 54 | redirect: '/404', 55 | hidden: true, 56 | }); 57 | commit('setAllRoutes', accessRoutes); 58 | return accessRoutes; 59 | }, 60 | setPartialRoutes({ commit }, accessRoutes) { 61 | commit('setPartialRoutes', accessRoutes); 62 | return accessRoutes; 63 | }, 64 | }; 65 | export default { state, getters, mutations, actions }; 66 | -------------------------------------------------------------------------------- /src/store/modules/settings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 所有全局配置的状态管理,如无必要请勿修改 3 | */ 4 | 5 | import defaultSettings from '@/config/settings'; 6 | 7 | const { tagsBar, logo, layout, header, themeBar, skeleton } = defaultSettings; 8 | const theme = JSON.parse(localStorage.getItem('BYUI-VUE-THEME')) || ''; 9 | const state = { 10 | tagsBar: theme.tagsBar || tagsBar, 11 | logo, 12 | collapse: false, 13 | layout: theme.layout || layout, 14 | header: theme.header || header, 15 | skeleton, 16 | device: 'desktop', 17 | themeBar, 18 | }; 19 | const getters = { 20 | collapse: state => state.collapse, 21 | device: state => state.device, 22 | header: state => state.header, 23 | layout: state => state.layout, 24 | logo: state => state.logo, 25 | tagsBar: state => state.tagsBar, 26 | themeBar: state => state.themeBar, 27 | skeleton: state => state.skeleton, 28 | }; 29 | const mutations = { 30 | changeLayout: (state, layout) => { 31 | if (layout) state.layout = layout; 32 | }, 33 | changeHeader: (state, header) => { 34 | if (header) state.header = header; 35 | }, 36 | changeTagsBar: (state, tagsBar) => { 37 | if (tagsBar) state.tagsBar = tagsBar; 38 | }, 39 | changeCollapse: state => { 40 | state.collapse = !state.collapse; 41 | }, 42 | foldSideBar: state => { 43 | state.collapse = true; 44 | }, 45 | openSideBar: state => { 46 | state.collapse = false; 47 | }, 48 | toggleDevice: (state, device) => { 49 | state.device = device; 50 | }, 51 | }; 52 | const actions = { 53 | changeLayout({ commit }, layout) { 54 | commit('changeLayout', layout); 55 | }, 56 | changeHeader({ commit }, header) { 57 | commit('changeHeader', header); 58 | }, 59 | changeTagsBar({ commit }, tagsBar) { 60 | commit('changeTagsBar', tagsBar); 61 | }, 62 | changeCollapse({ commit }) { 63 | commit('changeCollapse'); 64 | }, 65 | foldSideBar({ commit }) { 66 | commit('foldSideBar'); 67 | }, 68 | openSideBar({ commit }) { 69 | commit('openSideBar'); 70 | }, 71 | toggleDevice({ commit }, device) { 72 | commit('toggleDevice', device); 73 | }, 74 | }; 75 | export default { state, getters, mutations, actions }; 76 | -------------------------------------------------------------------------------- /src/store/modules/table.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 代码生成机状态管理 3 | */ 4 | 5 | const state = { srcCode: '' }; 6 | const getters = { 7 | srcTableCode: state => state.srcCode, 8 | }; 9 | 10 | const mutations = { 11 | setTableCode(state, srcCode) { 12 | state.srcCode = srcCode; 13 | }, 14 | }; 15 | const actions = { 16 | setTableCode({ commit }, srcCode) { 17 | commit('setTableCode', srcCode); 18 | }, 19 | }; 20 | export default { state, getters, mutations, actions }; 21 | -------------------------------------------------------------------------------- /src/store/modules/tagsBar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description tagsBar多标签页逻辑,前期借鉴了很多开源项目发现都有个共同的特点很繁琐并不符合框架设计的初衷,后来在github用户cyea的启发下完成了重构,请勿修改 3 | */ 4 | 5 | const state = { 6 | visitedRoutes: [], 7 | }; 8 | const getters = { 9 | visitedRoutes: state => state.visitedRoutes, 10 | }; 11 | const mutations = { 12 | addVisitedRoute(state, route) { 13 | if (state.visitedRoutes.some(item => item.path === route.path)) return; 14 | state.visitedRoutes.push(Object.assign({}, route)); 15 | }, 16 | delVisitedRoute(state, route) { 17 | state.visitedRoutes.forEach((item, index) => { 18 | if (item.path === route.path) { 19 | state.visitedRoutes.splice(index, 1); 20 | } 21 | }); 22 | }, 23 | delOthersVisitedRoute(state, route) { 24 | state.visitedRoutes = state.visitedRoutes.filter(item => { 25 | return item.meta.affix || item.path === route.path; 26 | }); 27 | }, 28 | delLeftVisitedRoute(state, route) { 29 | let index = state.visitedRoutes.length; 30 | state.visitedRoutes = state.visitedRoutes.filter(item => { 31 | if (item.name === route.name) { 32 | index = state.visitedRoutes.indexOf(item); 33 | } 34 | return item.meta.affix || index <= state.visitedRoutes.indexOf(item); 35 | }); 36 | }, 37 | delRightVisitedRoute(state, route) { 38 | let index = state.visitedRoutes.length; 39 | state.visitedRoutes = state.visitedRoutes.filter(item => { 40 | if (item.name === route.name) { 41 | index = state.visitedRoutes.indexOf(item); 42 | } 43 | return item.meta.affix || index >= state.visitedRoutes.indexOf(item); 44 | }); 45 | }, 46 | delAllVisitedRoutes(state) { 47 | state.visitedRoutes = state.visitedRoutes.filter(item => item.meta.affix); 48 | }, 49 | updateVisitedRoute(state, route) { 50 | state.visitedRoutes.forEach(item => { 51 | if (item.path === route.path) { 52 | item = Object.assign(item, route); 53 | } 54 | }); 55 | }, 56 | }; 57 | const actions = { 58 | addVisitedRoute({ commit }, route) { 59 | commit('addVisitedRoute', route); 60 | }, 61 | async delRoute({ dispatch, state }, route) { 62 | await dispatch('delVisitedRoute', route); 63 | return { 64 | visitedRoutes: [...state.visitedRoutes], 65 | }; 66 | }, 67 | delVisitedRoute({ commit, state }, route) { 68 | commit('delVisitedRoute', route); 69 | return [...state.visitedRoutes]; 70 | }, 71 | async delOthersRoutes({ dispatch, state }, route) { 72 | await dispatch('delOthersVisitedRoute', route); 73 | return { 74 | visitedRoutes: [...state.visitedRoutes], 75 | }; 76 | }, 77 | async delLeftRoutes({ dispatch, state }, route) { 78 | await dispatch('delLeftVisitedRoute', route); 79 | return { 80 | visitedRoutes: [...state.visitedRoutes], 81 | }; 82 | }, 83 | async delRightRoutes({ dispatch, state }, route) { 84 | await dispatch('delRightVisitedRoute', route); 85 | return { 86 | visitedRoutes: [...state.visitedRoutes], 87 | }; 88 | }, 89 | delOthersVisitedRoute({ commit, state }, route) { 90 | commit('delOthersVisitedRoute', route); 91 | return [...state.visitedRoutes]; 92 | }, 93 | delLeftVisitedRoute({ commit, state }, route) { 94 | commit('delLeftVisitedRoute', route); 95 | return [...state.visitedRoutes]; 96 | }, 97 | delRightVisitedRoute({ commit, state }, route) { 98 | commit('delRightVisitedRoute', route); 99 | return [...state.visitedRoutes]; 100 | }, 101 | async delAllRoutes({ dispatch, state }, route) { 102 | await dispatch('delAllVisitedRoutes', route); 103 | return { 104 | visitedRoutes: [...state.visitedRoutes], 105 | }; 106 | }, 107 | delAllVisitedRoutes({ commit, state }) { 108 | commit('delAllVisitedRoutes'); 109 | return [...state.visitedRoutes]; 110 | }, 111 | updateVisitedRoute({ commit }, route) { 112 | commit('updateVisitedRoute', route); 113 | }, 114 | }; 115 | export default { state, getters, mutations, actions }; 116 | -------------------------------------------------------------------------------- /src/styles/custom.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Imfdj/vue-beehive/be858f359bef902a4e44c24a99a5bfe221ef6c7f/src/styles/custom.scss -------------------------------------------------------------------------------- /src/styles/spinner/dots.css: -------------------------------------------------------------------------------- 1 | .dots-loader:not(:required) { 2 | position: relative; 3 | display: inline-block; 4 | width: 7px; 5 | height: 7px; 6 | margin-bottom: 30px; 7 | overflow: hidden; 8 | text-indent: -9999px; 9 | background: transparent; 10 | border-radius: 100%; 11 | box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 12 | transform-origin: 50% 50%; 13 | animation: dots-loader 5s infinite ease-in-out; 14 | } 15 | 16 | @keyframes dots-loader { 17 | 0% { 18 | box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 19 | } 20 | 21 | 8.33% { 22 | box-shadow: #f86 14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 23 | } 24 | 25 | 16.67% { 26 | box-shadow: #f86 14px 14px 0 7px, #fc6 14px 14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 27 | } 28 | 29 | 25% { 30 | box-shadow: #f86 -14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px 14px 0 7px, #4ae -14px 14px 0 7px; 31 | } 32 | 33 | 33.33% { 34 | box-shadow: #f86 -14px -14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae -14px -14px 0 7px; 35 | } 36 | 37 | 41.67% { 38 | box-shadow: #f86 14px -14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; 39 | } 40 | 41 | 50% { 42 | box-shadow: #f86 14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; 43 | } 44 | 45 | 58.33% { 46 | box-shadow: #f86 -14px 14px 0 7px, #fc6 -14px 14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; 47 | } 48 | 49 | 66.67% { 50 | box-shadow: #f86 -14px -14px 0 7px, #fc6 -14px -14px 0 7px, #6d7 -14px -14px 0 7px, #4ae 14px -14px 0 7px; 51 | } 52 | 53 | 75% { 54 | box-shadow: #f86 14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px -14px 0 7px, #4ae 14px -14px 0 7px; 55 | } 56 | 57 | 83.33% { 58 | box-shadow: #f86 14px 14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae 14px 14px 0 7px; 59 | } 60 | 61 | 91.67% { 62 | box-shadow: #f86 -14px 14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 63 | } 64 | 65 | 100% { 66 | box-shadow: #f86 -14px -14px 0 7px, #fc6 14px -14px 0 7px, #6d7 14px 14px 0 7px, #4ae -14px 14px 0 7px; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/styles/spinner/gauge.css: -------------------------------------------------------------------------------- 1 | .gauge-loader:not(:required) { 2 | position: relative; 3 | display: inline-block; 4 | width: 64px; 5 | height: 32px; 6 | margin-bottom: 10px; 7 | overflow: hidden; 8 | text-indent: -9999px; 9 | background: #6ca; 10 | border-top-left-radius: 32px; 11 | border-top-right-radius: 32px; 12 | } 13 | 14 | .gauge-loader:not(:required)::before { 15 | position: absolute; 16 | top: 5px; 17 | left: 30px; 18 | width: 4px; 19 | height: 27px; 20 | content: ''; 21 | background: white; 22 | border-radius: 2px; 23 | transform-origin: 50% 100%; 24 | animation: gauge-loader 4000ms infinite ease; 25 | } 26 | 27 | .gauge-loader:not(:required)::after { 28 | position: absolute; 29 | top: 26px; 30 | left: 26px; 31 | width: 13px; 32 | height: 13px; 33 | content: ''; 34 | background: white; 35 | -moz-border-radius: 8px; 36 | -webkit-border-radius: 8px; 37 | border-radius: 8px; 38 | } 39 | 40 | @keyframes gauge-loader { 41 | 0% { 42 | transform: rotate(-50deg); 43 | } 44 | 45 | 10% { 46 | transform: rotate(20deg); 47 | } 48 | 49 | 20% { 50 | transform: rotate(60deg); 51 | } 52 | 53 | 24% { 54 | transform: rotate(60deg); 55 | } 56 | 57 | 40% { 58 | transform: rotate(-20deg); 59 | } 60 | 61 | 54% { 62 | transform: rotate(70deg); 63 | } 64 | 65 | 56% { 66 | transform: rotate(78deg); 67 | } 68 | 69 | 58% { 70 | transform: rotate(73deg); 71 | } 72 | 73 | 60% { 74 | transform: rotate(75deg); 75 | } 76 | 77 | 62% { 78 | transform: rotate(70deg); 79 | } 80 | 81 | 70% { 82 | transform: rotate(-20deg); 83 | } 84 | 85 | 80% { 86 | transform: rotate(20deg); 87 | } 88 | 89 | 83% { 90 | transform: rotate(25deg); 91 | } 92 | 93 | 86% { 94 | transform: rotate(20deg); 95 | } 96 | 97 | 89% { 98 | transform: rotate(25deg); 99 | } 100 | 101 | 100% { 102 | transform: rotate(-50deg); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/styles/spinner/inner-circles.css: -------------------------------------------------------------------------------- 1 | .inner-circles-loader:not(:required) { 2 | position: relative; 3 | display: inline-block; 4 | width: 50px; 5 | height: 50px; 6 | margin-bottom: 10px; 7 | overflow: hidden; 8 | text-indent: -9999px; 9 | background: rgba(25, 165, 152, 0.5); 10 | border-radius: 50%; 11 | transform: translate3d(0, 0, 0); 12 | } 13 | 14 | .inner-circles-loader:not(:required)::before, 15 | .inner-circles-loader:not(:required)::after { 16 | position: absolute; 17 | top: 0; 18 | display: inline-block; 19 | width: 50px; 20 | height: 50px; 21 | content: ''; 22 | border-radius: 50%; 23 | } 24 | 25 | .inner-circles-loader:not(:required)::before { 26 | left: 0; 27 | background: #c7efcf; 28 | transform-origin: 0 50%; 29 | animation: inner-circles-loader 3s infinite; 30 | } 31 | 32 | .inner-circles-loader:not(:required)::after { 33 | right: 0; 34 | background: #eef5db; 35 | transform-origin: 100% 50%; 36 | animation: inner-circles-loader 3s 0.2s reverse infinite; 37 | } 38 | 39 | @keyframes inner-circles-loader { 40 | 0% { 41 | transform: rotate(0deg); 42 | } 43 | 44 | 50% { 45 | transform: rotate(360deg); 46 | } 47 | 48 | 100% { 49 | transform: rotate(0deg); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/styles/transition.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * @description vue过渡动画 3 | */ 4 | 5 | @charset "utf-8"; 6 | 7 | .fade-transform-leave-active, 8 | .fade-transform-enter-active { 9 | transition: $base-transition; 10 | } 11 | 12 | .fade-transform-enter { 13 | opacity: 0; 14 | transform: translateX(-30px); 15 | } 16 | 17 | .fade-transform-leave-to { 18 | opacity: 0; 19 | transform: translateX(30px); 20 | } 21 | -------------------------------------------------------------------------------- /src/styles/variables.scss: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 全局主题变量配置,VIP文档内提供多种好看的配色方案(ant-design风格、layui风格、iview风格),请查看VIP文档主题配置篇 3 | */ 4 | /* stylelint-disable */ 5 | @charset "utf-8"; 6 | //框架默认主题色 7 | $base-color-default: #1890ff; 8 | //默认层级 9 | $base-z-index: 999; 10 | //横向布局纵向布局时菜单背景色 11 | $base-menu-background: #001529; 12 | //菜单文字颜色 13 | $base-menu-color: hsla(0, 0%, 100%, 0.95); 14 | //菜单选中文字颜色 15 | $base-menu-color-active: hsla(0, 0%, 100%, 0.95); 16 | //菜单选中背景色 17 | $base-menu-background-active: $base-color-default; 18 | //标题颜色 19 | $base-title-color: #fff; 20 | //字体大小配置 21 | $base-font-size-small: 12px; 22 | $base-font-size-default: 14px; 23 | $base-font-size-big: 16px; 24 | $base-font-size-bigger: 18px; 25 | $base-font-size-max: 22px; 26 | $base-font-color: #606266; 27 | $base-color-blue: $base-color-default; 28 | $base-color-green: #13ce66; 29 | $base-color-white: #fff; 30 | $base-color-black: #000; 31 | $base-color-yellow: #ffba00; 32 | $base-color-orange: #ff6700; 33 | $base-color-red: #ff4d4f; 34 | $base-color-gray: rgba(0, 0, 0, 0.65); 35 | $base-main-width: 1279px; 36 | $base-border-radius: 2px; 37 | $base-border-color: #dcdfe6; 38 | //输入框高度 39 | $base-input-height: 32px; 40 | //默认paddiing 41 | $base-padding: 20px; 42 | //默认阴影 43 | $base-box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); 44 | //横向布局时top-bar、logo、一级菜单的高度 45 | $base-top-bar-height: 65px; 46 | //纵向布局时logo的高度 47 | $base-logo-height: 75px; 48 | //顶部nav-bar的高度 49 | $base-nav-bar-height: 60px; 50 | //顶部多标签页tags-bar的高度 51 | $base-tags-bar-height: 55px; 52 | //顶部多标签页tags-bar中每一个item的高度 53 | $base-tag-item-height: 34px; 54 | //菜单li标签的高度 55 | $base-menu-item-height: 50px; 56 | //app-main的高度 57 | $base-app-main-height: calc( 58 | 100vh - #{$base-nav-bar-height} - #{$base-tags-bar-height} - #{$base-padding} - #{$base-padding} - 55px - 30px 59 | ); 60 | //纵向布局时左侧导航未折叠时的宽度 61 | $base-left-menu-width: 256px; 62 | //纵向布局时左侧导航未折叠时右侧内容的宽度 63 | $base-right-content-width: calc(100% - #{$base-left-menu-width}); 64 | //纵向布局时左侧导航已折叠时的宽度 65 | $base-left-menu-width-min: 65px; 66 | //纵向布局时左侧导航已折叠时右侧内容的宽度 67 | $base-right-content-width-min: calc(100% - #{$base-left-menu-width-min}); 68 | //默认动画 69 | $base-transition: all 0.2s; 70 | //默认动画时长 71 | $base-transition-time: 0.2s; 72 | // 登录、注册、找回密码页面input背景色 73 | $color-lucency-input-bgc: rgba(246, 244, 252, 0.57); 74 | // 登录、注册、找回密码页面按钮背景色 75 | $color-lucency-btn-bgc: rgba(255, 199, 80, 0.52); 76 | 77 | $colorLight: rgba(0, 0, 0, 0.45); 78 | $colorLight2: rgba(0, 0, 0, 0.65); 79 | $colorLight3: rgba(0, 0, 0, 0.75); 80 | $color333: #333; 81 | $colorE5: #e5e5e5; 82 | $colorF5: #f5f5f5; 83 | $colorF7: #f7f7f7; 84 | $colorE8: #e8e8e8; 85 | $colorBlue: #1b9aee; 86 | $colorDanger: #f56c6c; 87 | 88 | .wrap-content-main { 89 | padding: 20px; 90 | background-color: #fff; 91 | border-radius: 2px; 92 | } 93 | .color-light { 94 | color: $colorLight; 95 | } 96 | 97 | .ellipsis { 98 | overflow: hidden; 99 | text-overflow: ellipsis; 100 | white-space: nowrap; 101 | } 102 | 103 | .disabled-custom { 104 | pointer-events: none; 105 | cursor: default; 106 | opacity: 0.6; 107 | } 108 | 109 | .wrap-el-table-100width { 110 | width: 100%; 111 | } 112 | 113 | :export { 114 | //菜单文字颜色变量导出 115 | menu-color: $base-menu-color; 116 | //菜单选中文字颜色变量导出 117 | menu-color-active: $base-menu-color-active; 118 | //菜单背景色变量导出 119 | menu-background: $base-menu-background; 120 | //菜单选中背景色变量导出 121 | menu-background-active: $base-menu-background-active; 122 | //多标签页选中背景色变量导出 123 | tag-background-active: $base-color-blue; 124 | //默认按钮背景色变量导出 125 | button-background: $base-color-blue; 126 | //分页选中背景色变量导出 127 | pagination-background-active: $base-color-blue; 128 | } 129 | -------------------------------------------------------------------------------- /src/utils/accessToken.js: -------------------------------------------------------------------------------- 1 | import { storage, tokenTableName } from '@/config/settings'; 2 | import cookie from 'js-cookie'; 3 | 4 | /** 5 | * @description 获取accessToken 6 | * @returns {string|ActiveX.IXMLDOMNode|Promise|any|IDBRequest|MediaKeyStatus|FormDataEntryValue|Function|Promise} 7 | */ 8 | export function getAccessToken() { 9 | return getField('jwt'); 10 | } 11 | 12 | /** 13 | * @description 获取AccessCsrf 14 | * @returns {string|ActiveX.IXMLDOMNode|Promise|any|IDBRequest|MediaKeyStatus|FormDataEntryValue|Function|Promise} 15 | */ 16 | export function getAccessCsrf() { 17 | return getField('csrf'); 18 | } 19 | 20 | /** 21 | * @description 获取RefreshToken 22 | * @returns {string|ActiveX.IXMLDOMNode|Promise|any|IDBRequest|MediaKeyStatus|FormDataEntryValue|Function|Promise} 23 | */ 24 | export function getRefreshToken() { 25 | return getField('refreshToken'); 26 | } 27 | 28 | function getField(field) { 29 | if (storage) { 30 | if ('localStorage' === storage) { 31 | return getLocalJwt(); 32 | } else if ('sessionStorage' === storage) { 33 | try { 34 | return ( 35 | (sessionStorage.getItem(tokenTableName) && JSON.parse(sessionStorage.getItem(tokenTableName))[field]) || '' 36 | ); 37 | } catch (e) { 38 | sessionStorage.removeItem(tokenTableName); 39 | throw e; 40 | } 41 | } else if ('cookie' === storage) { 42 | return cookie.get(tokenTableName); 43 | } else { 44 | return getLocalJwt(); 45 | } 46 | } else { 47 | return getLocalJwt(); 48 | } 49 | 50 | function getLocalJwt() { 51 | try { 52 | return (localStorage.getItem(tokenTableName) && JSON.parse(localStorage.getItem(tokenTableName))[field]) || ''; 53 | } catch (e) { 54 | localStorage.removeItem(tokenTableName); 55 | throw e; 56 | } 57 | } 58 | } 59 | 60 | /** 61 | * @description 存储accessToken 62 | * @param accessToken 63 | * @returns {void|*} 64 | */ 65 | export function setAccessToken(accessToken) { 66 | if (storage) { 67 | if ('localStorage' === storage) { 68 | return localStorage.setItem(tokenTableName, accessToken); 69 | } else if ('sessionStorage' === storage) { 70 | return sessionStorage.setItem(tokenTableName, accessToken); 71 | } else if ('cookie' === storage) { 72 | return cookie.set(tokenTableName, accessToken); 73 | } else { 74 | return localStorage.setItem(tokenTableName, accessToken); 75 | } 76 | } else { 77 | return localStorage.setItem(tokenTableName, accessToken); 78 | } 79 | } 80 | 81 | /** 82 | * @description 移除accessToken 83 | * @returns {void|Promise} 84 | */ 85 | export function removeAccessToken() { 86 | if (storage) { 87 | if ('localStorage' === storage) { 88 | return localStorage.removeItem(tokenTableName); 89 | } else if ('sessionStorage' === storage) { 90 | return sessionStorage.clear(); 91 | } else if ('cookie' === storage) { 92 | return cookie.remove(tokenTableName); 93 | } else { 94 | return localStorage.removeItem(tokenTableName); 95 | } 96 | } else { 97 | return localStorage.removeItem(tokenTableName); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/utils/encrypt.js: -------------------------------------------------------------------------------- 1 | import NodeRSA from 'node-rsa'; 2 | import JSEncrypt from 'jsencrypt'; 3 | import { getPublicKey } from '@/api/publicKey'; 4 | 5 | const privateKey = 6 | 'MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMFPa+v52FkSUXvcUnrGI/XzW3EpZRI0s9BCWJ3oNQmEYA5luWW5p8h0uadTIoTyYweFPdH4hveyxlwmS7oefvbIdiP+o+QIYW/R4Wjsb4Yl8MhR4PJqUE3RCy6IT9fM8ckG4kN9ECs6Ja8fQFc6/mSl5dJczzJO3k1rWMBhKJD/AgMBAAECgYEAucMakH9dWeryhrYoRHcXo4giPVJsH9ypVt4KzmOQY/7jV7KFQK3x//27UoHfUCak51sxFw9ek7UmTPM4HjikA9LkYeE7S381b4QRvFuf3L6IbMP3ywJnJ8pPr2l5SqQ00W+oKv+w/VmEsyUHr+k4Z+4ik+FheTkVWp566WbqFsECQQDjYaMcaKw3j2Zecl8T6eUe7fdaRMIzp/gcpPMfT/9rDzIQk+7ORvm1NI9AUmFv/FAlfpuAMrdL2n7p9uznWb7RAkEA2aP934kbXg5bdV0R313MrL+7WTK/qdcYxATUbMsMuWWQBoS5irrt80WCZbG48hpocJavLNjbtrjmUX3CuJBmzwJAOJg8uP10n/+ZQzjEYXh+BszEHDuw+pp8LuT/fnOy5zrJA0dO0RjpXijO3vuiNPVgHXT9z1LQPJkNrb5ACPVVgQJBALPeb4uV0bNrJDUb5RB4ghZnIxv18CcaqNIft7vuGCcFBAIPIRTBprR+RuVq+xHDt3sNXdsvom4h49+Hky1b0ksCQBBwUtVaqH6ztCtwUF1j2c/Zcrt5P/uN7IHAd44K0gIJc1+Csr3qPG+G2yoqRM8KVqLI8Z2ZYn9c+AvEE+L9OQY='; 7 | 8 | /** 9 | * @description RSA加密 10 | * @param data 11 | * @returns {Promise<{param: PromiseLike}|*>} 12 | */ 13 | export async function encryptedData(data) { 14 | let publicKey = ''; 15 | const res = await getPublicKey(); 16 | publicKey = res.data.rsa_public_key; 17 | if (publicKey.mockServer) { 18 | publicKey = ''; 19 | } 20 | if (publicKey == '') { 21 | return data; 22 | } 23 | const key = new NodeRSA(publicKey); 24 | data = key.encrypt(data, 'base64'); 25 | return data; 26 | } 27 | 28 | /** 29 | * @description RSA解密 30 | * @param data 31 | * @returns {PromiseLike} 32 | */ 33 | export function decryptedData(data) { 34 | const decrypt = new JSEncrypt(); 35 | decrypt.setPrivateKey(`-----BEGIN RSA PRIVATE KEY-----${privateKey}-----END RSA PRIVATE KEY-----`); 36 | data = decrypt.decrypt(JSON.stringify(data)); 37 | return data; 38 | } 39 | -------------------------------------------------------------------------------- /src/utils/errorLog.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import store from '@/store'; 3 | import { isArray, isString } from '@/utils/validate'; 4 | import { errorLog } from '@/config/settings'; 5 | 6 | const needErrorLog = errorLog; 7 | const checkNeed = () => { 8 | const env = process.env.NODE_ENV; 9 | if (isString(needErrorLog)) { 10 | return env === needErrorLog; 11 | } 12 | if (isArray(needErrorLog)) { 13 | return needErrorLog.includes(env); 14 | } 15 | return false; 16 | }; 17 | if (checkNeed()) { 18 | Vue.config.errorHandler = (err, vm, info) => { 19 | console.error('vue-beehive错误拦截:', err, vm, info); 20 | const url = window.location.href; 21 | Vue.nextTick(() => { 22 | store.dispatch('errorLog/addErrorLog', { err, vm, info, url }); 23 | }); 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /src/utils/handleRoutes.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description all模式渲染后端返回路由 3 | * @param constantRoutes 4 | * @returns {*} 5 | */ 6 | export function filterAllRoutes(constantRoutes) { 7 | return constantRoutes.filter(route => { 8 | if (route.component) { 9 | if (route.component === 'Layout') { 10 | route.component = resolve => require(['@/layouts'], resolve); 11 | } else if (route.component === 'EmptyLayout') { 12 | route.component = resolve => require(['@/layouts/EmptyLayout'], resolve); 13 | } else { 14 | let path = 'views/' + route.component; 15 | if (new RegExp('^/views/.*$').test(route.component) || new RegExp('^views/.*$').test(route.component)) { 16 | path = route.component; 17 | } else if (new RegExp('^/.*$').test(route.component)) { 18 | path = 'views' + route.component; 19 | } else if (new RegExp('^@views/.*$').test(route.component)) { 20 | path = route.component.str.slice(2); 21 | } else { 22 | path = 'views/' + route.component; 23 | } 24 | route.component = resolve => require([`@/${path}`], resolve); 25 | } 26 | } 27 | if (route.children && route.children.length) { 28 | route.children = filterAllRoutes(route.children); 29 | } 30 | if (route.children && route.children.length === 0) { 31 | delete route.children; 32 | } 33 | // hide 34 | route.hidden = route.hidden === 1 ? true : false; 35 | return true; 36 | }); 37 | } 38 | 39 | /** 40 | * 数组转树形结构 41 | * @param list 源数组 42 | * @param tree 树 43 | * @param parentId 父ID 44 | */ 45 | export function listToTree(list, tree, parentId) { 46 | list.forEach(item => { 47 | // 判断是否为父级菜单 48 | if (item.parent_id === parentId) { 49 | const child = { 50 | ...item, 51 | key: item.key || item.name, 52 | children: [], 53 | meta: { 54 | title: item.title, 55 | icon: item.icon, 56 | }, 57 | }; 58 | // 迭代 list, 找到当前菜单相符合的所有子菜单 59 | listToTree(list, child.children, item.id); 60 | // 删掉不存在 children 值的属性 61 | if (child.children.length <= 0) { 62 | delete child.children; 63 | } 64 | // 加入到树中 65 | tree.push(child); 66 | } 67 | }); 68 | } 69 | -------------------------------------------------------------------------------- /src/utils/pageTitle.js: -------------------------------------------------------------------------------- 1 | import { title } from '@/config/settings'; 2 | 3 | /** 4 | * @description 设置标题 5 | * @param pageTitle 6 | * @returns {string} 7 | */ 8 | export default function getPageTitle(pageTitle) { 9 | if (pageTitle) { 10 | return `${pageTitle}-${title}`; 11 | } 12 | return `${title}`; 13 | } 14 | -------------------------------------------------------------------------------- /src/utils/validate-rule-el-form.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @Author Imfdj 3 | * @Description: 4 | * @Date Created in 2021/8/13 12:05 5 | * @Modified By: 6 | */ 7 | import { isEmail, isExternal } from './validate'; 8 | 9 | export function validatePhone(rule, value, callback) { 10 | if (value) { 11 | if (/^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/.test(value)) { 12 | callback(); 13 | } else { 14 | callback(new Error('手机号格式有误')); 15 | } 16 | } else { 17 | callback(); 18 | } 19 | } 20 | 21 | export function validateEmail(rule, value, callback) { 22 | if (value) { 23 | if (isEmail(value)) { 24 | callback(); 25 | } else { 26 | callback(new Error('邮箱格式有误')); 27 | } 28 | } else { 29 | callback(); 30 | } 31 | } 32 | 33 | export function validateUrl(rule, value, callback) { 34 | if (value) { 35 | if (isExternal(value)) { 36 | callback(); 37 | } else { 38 | callback(new Error('格式有误')); 39 | } 40 | } else { 41 | callback(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/utils/validate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @description 判读是否为外链 3 | * @param path 4 | * @returns {boolean} 5 | */ 6 | export function isExternal(path) { 7 | return /^(https?:|mailto:|tel:)/.test(path); 8 | } 9 | 10 | /** 11 | * @description 校验密码是否小于6位 12 | * @param str 13 | * @returns {boolean} 14 | */ 15 | export function isPassword(str) { 16 | return str.length >= 6; 17 | } 18 | 19 | /** 20 | * @description 判断是否为数字 21 | * @param value 22 | * @returns {boolean} 23 | */ 24 | export function isNumber(value) { 25 | const reg = /^[0-9]*$/; 26 | return reg.test(value); 27 | } 28 | 29 | /** 30 | * @description 判断是否是字符串 31 | * @param str 32 | * @returns {boolean} 33 | */ 34 | export function isString(str) { 35 | return typeof str === 'string' || str instanceof String; 36 | } 37 | 38 | /** 39 | * @description 判断是否是数组 40 | * @param arg 41 | * @returns {arg is any[]|boolean} 42 | */ 43 | export function isArray(arg) { 44 | if (typeof Array.isArray === 'undefined') { 45 | return Object.prototype.toString.call(arg) === '[object Array]'; 46 | } 47 | return Array.isArray(arg); 48 | } 49 | 50 | /** 51 | * @description 判断是否是邮箱 52 | * @param str 53 | * @returns {boolean} 54 | */ 55 | export function isEmail(str) { 56 | const reg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/; 57 | return reg.test(str); 58 | } 59 | 60 | /** 61 | * @description 判断是否为数字且最多两位小数 62 | * @param str 63 | * @returns {boolean} 64 | */ 65 | export function isNum(str) { 66 | const reg = /^\d+(\.\d{1,2})?$/; 67 | return reg.test(str); 68 | } 69 | -------------------------------------------------------------------------------- /src/views/departmentManagement/components/DepartmentManagementEdit.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 66 | -------------------------------------------------------------------------------- /src/views/departmentManagement/components/DepartmentOperation.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 114 | 115 | 119 | -------------------------------------------------------------------------------- /src/views/index/components/UserInfo/index.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 63 | 64 | 108 | -------------------------------------------------------------------------------- /src/views/index/index.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 42 | 48 | -------------------------------------------------------------------------------- /src/views/personalCenter/components/Cropper.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 79 | 80 | 135 | -------------------------------------------------------------------------------- /src/views/personalCenter/index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 42 | 43 | 49 | -------------------------------------------------------------------------------- /src/views/personnelManagement/roleManagement/components/RoleManagementEdit.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 71 | -------------------------------------------------------------------------------- /src/views/personnelManagement/userManagement/components/UserManagementEdit.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 93 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/Events/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/Overview/components/TaskStatisticsEcharts/index.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 119 | 120 | 134 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/Overview/index.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 42 | 43 | 52 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/Version/index.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 11 | 21 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/CreateTask.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 96 | 97 | 130 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/CreateTaskList.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 62 | 63 | 74 | 100 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/EditorTaskListDialog.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 69 | 70 | 75 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/ProjectSetting/index.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 91 | 92 | 114 | 118 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/RichText.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 91 | 92 | 101 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/TaskFilter.vue: -------------------------------------------------------------------------------- 1 | 47 | 48 | 88 | 89 | 93 | -------------------------------------------------------------------------------- /src/views/projectManagement/project/components/task/components/TaskLog/components/LogComment.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 44 | 45 | 69 | -------------------------------------------------------------------------------- /src/views/projectManagement/projectTemplateTask/components/ProjectTemplateTaskEdit.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 86 | 87 | 94 | -------------------------------------------------------------------------------- /src/views/projectManagement/projectTemplateTask/index.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 103 | 104 | 139 | -------------------------------------------------------------------------------- /tests/e2e/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: ['cypress'], 3 | env: { 4 | mocha: true, 5 | 'cypress/globals': true, 6 | }, 7 | rules: { 8 | strict: 'off', 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /tests/e2e/plugins/index.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable arrow-body-style */ 2 | // https://docs.cypress.io/guides/guides/plugins-guide.html 3 | 4 | // if you need a custom webpack configuration you can uncomment the following import 5 | // and then use the `file:preprocessor` event 6 | // as explained in the cypress docs 7 | // https://docs.cypress.io/api/plugins/preprocessors-api.html#Examples 8 | 9 | // /* eslint-disable import/no-extraneous-dependencies, global-require */ 10 | // const webpack = require('@cypress/webpack-preprocessor') 11 | 12 | module.exports = (on, config) => { 13 | // on('file:preprocessor', webpack({ 14 | // webpackOptions: require('@vue/cli-service/webpack.config'), 15 | // watchOptions: {} 16 | // })) 17 | 18 | return Object.assign({}, config, { 19 | fixturesFolder: 'tests/e2e/fixtures', 20 | integrationFolder: 'tests/e2e/specs', 21 | screenshotsFolder: 'tests/e2e/screenshots', 22 | videosFolder: 'tests/e2e/videos', 23 | supportFile: 'tests/e2e/support/index.js', 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /tests/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // https://docs.cypress.io/api/introduction/api.html 2 | 3 | describe('My First Test', () => { 4 | it('Visits the app root url', () => { 5 | cy.visit('/'); 6 | cy.contains('h1', 'Welcome to Your Vue.js App'); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /tests/e2e/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /tests/e2e/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /tests/unit/example.spec.js: -------------------------------------------------------------------------------- 1 | import { shallowMount } from '@vue/test-utils'; 2 | import HelloWorld from '@/components/HelloWorld.vue'; 3 | 4 | describe('HelloWorld.vue', () => { 5 | it('renders props.msg when passed', () => { 6 | const msg = 'new message'; 7 | const wrapper = shallowMount(HelloWorld, { 8 | propsData: { msg }, 9 | }); 10 | expect(wrapper.text()).toMatch(msg); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /upload-qiniu.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const qiniu = require('qiniu'); 5 | 6 | const argv1 = process.argv.splice(2); 7 | const accessKey = (argv1.filter(e => e.includes('--accessKey='))[0] || '').split('--accessKey=')[1]; 8 | const secretKey = (argv1.filter(e => e.includes('--secretKey='))[0] || '').split('--secretKey=')[1]; 9 | const bucket = (argv1.filter(e => e.includes('--bucket='))[0] || '').split('--bucket=')[1]; 10 | if (!(accessKey && secretKey && bucket)) throw new Error('参数缺省'); 11 | 12 | const mac = new qiniu.auth.digest.Mac(accessKey, secretKey); 13 | 14 | const prefix = fs.readFileSync(path.resolve(__dirname, './src/config/prefix'), 'utf-8'); 15 | console.log(`prefix: ${prefix}`); 16 | 17 | //自定义凭证有效期(示例2小时,expires单位为秒,为上传凭证的有效时间) 18 | const options = { 19 | scope: bucket, 20 | expires: 7200, 21 | }; 22 | const putPolicy = new qiniu.rs.PutPolicy(options); 23 | const uploadToken = putPolicy.uploadToken(mac); 24 | 25 | const config = new qiniu.conf.Config(); 26 | // 空间对应的机房 27 | config.zone = qiniu.zone.Zone_z2; 28 | // 是否使用https域名 29 | //config.useHttpsDomain = true; 30 | // 上传是否使用cdn加速 31 | config.useCdnDomain = true; 32 | 33 | const formUploader = new qiniu.form_up.FormUploader(config); 34 | const putExtra = new qiniu.form_up.PutExtra(); 35 | 36 | const _filesAll = []; 37 | 38 | /** 39 | * 遍历目录返回结构 40 | * @param targetPath 41 | * @returns {{path: *, dirsData: [], files: []}} 42 | */ 43 | function readDir(targetPath) { 44 | const filesAll = fs.readdirSync(targetPath); 45 | const dirs = []; 46 | const files = []; 47 | let dirsData = []; 48 | filesAll.filter(file => { 49 | const status = fs.statSync(path.join(targetPath, file)); 50 | status.isDirectory() ? dirs.push(file) : files.push(file); 51 | }); 52 | dirsData = dirs.map(dir => readDir(path.join(targetPath, dir))); 53 | const key = targetPath.replace(/.*dist/, prefix).replace(/\\/g, '/'); 54 | files.forEach(e => { 55 | _filesAll.push({ 56 | path: path.join(targetPath, e), 57 | key: `${key}/${e}`, 58 | }); 59 | }); 60 | return { 61 | path: targetPath, 62 | key, 63 | files, 64 | dirsData, 65 | }; 66 | } 67 | 68 | // 文件上传 69 | const putFile = function (key, localFile) { 70 | return new Promise((resolve, reject) => { 71 | let again = true; 72 | const push = function () { 73 | formUploader.putFile(uploadToken, key, localFile, putExtra, function (respErr, respBody, respInfo) { 74 | if (respErr) { 75 | // 失败1秒后重试一次 76 | if (again) { 77 | again = false; 78 | setTimeout(() => { 79 | push(); 80 | }, 1000); 81 | } else { 82 | reject(respErr); 83 | throw respErr; 84 | } 85 | } 86 | if (respInfo.statusCode === 200) { 87 | console.log(`${localFile} 上传成功`); 88 | console.log(respBody); 89 | resolve(respBody); 90 | } else { 91 | console.log(respInfo.statusCode); 92 | console.log(respBody); 93 | reject(respInfo.statusCode, respBody); 94 | } 95 | }); 96 | }; 97 | push(); 98 | }); 99 | }; 100 | 101 | (async function () { 102 | try { 103 | await readDir(path.resolve(__dirname, './dist')); 104 | console.log('upload-qiniu-cdn-start!!!'); 105 | const putFilePromiseAll = []; 106 | for (let i = 0; i < _filesAll.length; i++) { 107 | putFilePromiseAll.push(putFile(_filesAll[i].key, _filesAll[i].path)); 108 | } 109 | Promise.all(putFilePromiseAll) 110 | .then(() => { 111 | console.log('upload-qiniu-cdn-done!!!'); 112 | }) 113 | .catch(err => { 114 | throw err; 115 | }); 116 | } catch (e) { 117 | throw e; 118 | } 119 | })(); 120 | --------------------------------------------------------------------------------