From 009f9edb9391da3a3f2084f592ea118893b62f76 Mon Sep 17 00:00:00 2001 From: 13693261870 <252740454@qq.com> Date: 星期三, 02 七月 2025 14:59:06 +0800 Subject: [PATCH] 初始化,批量提交代码 --- src/assets/icons/svg/component.svg | 1 src/assets/icons/svg/clipboard.svg | 1 src/assets/styles/index.scss | 182 src/assets/icons/svg/download.svg | 1 src/assets/icons/svg/eye.svg | 1 src/views/components/icons/index.vue | 87 src/layout/index.vue | 111 src/assets/images/light.svg | 39 src/views/system/user/authRole.vue | 117 src/utils/generator/drawingDefault.js | 29 public/robots.txt | 2 src/api/system/notice.js | 44 src/views/monitor/operlog/index.vue | 323 src/views/tool/build/IconsDialog.vue | 123 src/api/manage/device.js | 55 src/assets/icons/svg/cascader.svg | 1 src/views/tool/build/DraggableItem.vue | 100 src/views/tool/build/CodeTypeDialog.vue | 106 src/api/manage/Untitled-1.json | 37 src/api/monitor/jobLog.js | 26 src/views/dashboard/BarChart.vue | 102 src/assets/icons/svg/tool.svg | 1 src/api/login.js | 59 src/assets/icons/svg/radio.svg | 1 src/views/monitor/cache/index.vue | 144 src/assets/401_images/401.gif | 0 src/views/system/peizhi/tencentEmailForm.vue | 67 src/views/error/404.vue | 233 src/directive/dialog/dragHeight.js | 34 src/settings.js | 44 src/utils/generator/config.js | 438 src/utils/generator/html.js | 359 src/components/SizeSelect/index.vue | 56 src/assets/icons/svg/user.svg | 1 src/components/Breadcrumb/index.vue | 74 .env.development | 19 src/assets/icons/svg/form.svg | 1 src/store/modules/tagsView.js | 228 src/utils/dict/DictData.js | 13 src/api/tool/gen.js | 76 src/assets/styles/element-variables.scss | 31 src/assets/icons/svg/time.svg | 1 src/components/TopNav/index.vue | 194 src/directive/permission/hasPermi.js | 28 src/assets/icons/svg/chart.svg | 1 src/assets/icons/svg/switch.svg | 1 src/assets/icons/svg/upload.svg | 1 src/assets/styles/mixin.scss | 66 src/views/system/role/index.vue | 605 + src/views/manage/assure/index.vue | 540 src/assets/icons/svg/log.svg | 1 src/utils/ruoyi.js | 233 src/assets/icons/svg/theme.svg | 1 src/assets/icons/svg/date-range.svg | 1 src/views/monitor/server/index.vue | 207 public/config.js | 1 src/assets/icons/svg/guide.svg | 1 src/views/error/401.vue | 88 src/views/system/dict/data.vue | 446 src/views/tool/gen/editTable.vue | 234 src/views/tool/gen/importTable.vue | 120 src/api/manage/stock.js | 53 src/assets/icons/svg/job.svg | 1 src/assets/icons/svg/checkbox.svg | 1 src/directive/dialog/drag.js | 64 public/index.html | 209 src/views/system/dept/index.vue | 377 src/api/system/gkInformation/gkInfo.js | 28 src/api/manage/dsTask.js | 71 src/layout/mixin/ResizeHandler.js | 45 src/assets/icons/svg/qq.svg | 1 src/utils/generator/render.js | 126 babel.config.js | 13 src/views/manage/shipDevice/index.vue | 325 src/views/system/user/profile/userInfo.vue | 75 src/components/iFrame/index.vue | 36 src/views/manage/ships/index.vue | 432 src/components/ThemePicker/index.vue | 173 src/plugins/download.js | 73 src/components/RuoYi/Doc/index.vue | 21 src/assets/icons/svg/language.svg | 1 src/plugins/auth.js | 60 src/assets/icons/svg/github.svg | 1 src/assets/icons/svg/dict.svg | 1 src/views/dashboard/PieChart.vue | 79 src/api/manage/equType.js | 62 src/assets/styles/btn.scss | 99 src/views/dashboard/mixins/resize.js | 56 src/assets/icons/svg/row.svg | 1 src/assets/icons/svg/link.svg | 1 src/utils/generator/icon.json | 1 src/assets/icons/svg/wechat.svg | 1 src/assets/icons/svg/druid.svg | 1 src/views/register.vue | 209 .eslintrc.js | 199 src/layout/components/Sidebar/Logo.vue | 93 src/api/manage/clean.js | 28 src/assets/icons/svg/input.svg | 1 src/assets/icons/svg/validCode.svg | 1 src/views/manage/assess/index.vue | 323 src/assets/icons/svg/icon.svg | 1 src/assets/icons/svg/number.svg | 1 src/views/manage/equipment/index.vue | 452 src/views/tool/gen/basicInfoForm.vue | 60 src/assets/icons/svg/exit-fullscreen.svg | 1 src/assets/icons/svg/rate.svg | 1 src/router/index.js | 184 src/components/Pagination/index.vue | 114 src/layout/components/Sidebar/FixiOSBug.js | 25 src/assets/icons/svg/money.svg | 1 src/assets/icons/svg/phone.svg | 1 src/assets/icons/svg/size.svg | 1 src/assets/icons/svg/system.svg | 2 src/components/FileUpload/index.vue | 215 src/views/system/dict/index.vue | 347 src/assets/404_images/404.png | 0 src/api/monitor/online.js | 18 src/components/Crontab/year.vue | 131 src/assets/images/dark.svg | 39 .gitignore | 29 src/api/monitor/job.js | 71 src/utils/generator/css.js | 18 src/views/monitor/druid/index.vue | 15 src/api/manage/ships.js | 52 src/views/manage/data/metaData.vue | 493 src/components/RuoYi/Git/index.vue | 21 src/views/system/peizhi/index.vue | 65 src/api/manage/berth.js | 52 src/plugins/tab.js | 71 src/views/system/role/selectUser.vue | 138 src/utils/errorCode.js | 6 src/components/HeaderSearch/index.vue | 198 src/assets/icons/svg/education.svg | 1 src/assets/icons/svg/international.svg | 1 src/api/manage/shipType.js | 55 src/components/RightPanel/index.vue | 106 src/views/monitor/job/index.vue | 602 + src/assets/icons/svg/pdf.svg | 1 src/assets/404_images/404_cloud.png | 0 src/components/SvgIcon/index.vue | 61 src/components/RightToolbar/index.vue | 104 src/views/monitor/online/index.vue | 132 src/components/Crontab/day.vue | 161 src/api/monitor/server.js | 9 src/components/IconSelect/index.vue | 104 src/views/system/user/index.vue | 670 + src/views/tool/swagger/index.vue | 15 src/views/login.vue | 221 src/views/tool/gen/genInfoForm.vue | 299 src/assets/icons/svg/search.svg | 1 src/layout/components/IframeToggle/index.vue | 24 package.json | 92 src/App.vue | 28 src/assets/images/login-background.jpg | 0 src/components/IconSelect/requireIcons.js | 11 src/components/Crontab/index.vue | 430 vue.config.js | 137 src/assets/icons/svg/shopping.svg | 1 src/assets/icons/svg/message.svg | 1 src/utils/dict/Dict.js | 82 src/assets/icons/svg/drag.svg | 1 src/api/manage/wharf.js | 52 src/assets/icons/svg/textarea.svg | 1 src/assets/icons/svgo.yml | 22 src/assets/icons/svg/button.svg | 1 src/assets/icons/svg/peoples.svg | 1 src/store/modules/settings.js | 42 src/views/monitor/logininfor/index.vue | 246 src/assets/icons/svg/tab.svg | 1 src/assets/styles/ruoyi.scss | 277 src/assets/icons/svg/list.svg | 1 src/assets/icons/svg/online.svg | 1 src/views/monitor/job/log.vue | 347 src/api/manage/supplement.js | 45 src/assets/icons/svg/eye-open.svg | 1 src/components/ImageUpload/index.vue | 226 src/views/dashboard/PanelGroup.vue | 181 src/api/system/menu.js | 60 src/assets/icons/svg/404.svg | 1 src/store/modules/user.js | 101 src/store/index.js | 25 src/api/system/dict/data.js | 52 src/assets/icons/svg/tree-table.svg | 1 src/assets/icons/svg/documentation.svg | 1 src/layout/components/Sidebar/Link.vue | 43 src/components/Hamburger/index.vue | 44 src/views/tool/gen/index.vue | 337 src/components/ParentView/index.vue | 3 src/plugins/index.js | 20 src/views/manage/data/chartView.vue | 578 + src/views/manage/equType/index.vue | 349 src/utils/index.js | 390 public/berthPOI.json | 62 src/api/monitor/cache.js | 57 src/assets/icons/svg/password.svg | 1 src/components/ImagePreview/index.vue | 90 src/directive/module/clipboard.js | 54 src/assets/icons/svg/question.svg | 1 src/assets/icons/svg/zip.svg | 1 src/assets/images/login-background1.jpg | 0 src/assets/icons/svg/people.svg | 1 src/components/Crontab/hour.vue | 114 src/views/monitor/cache/list.vue | 241 src/components/Crontab/result.vue | 559 src/assets/icons/svg/edit.svg | 1 src/components/Editor/index.vue | 274 src/views/redirect.vue | 12 src/api/monitor/logininfor.js | 34 src/directive/dialog/dragWidth.js | 30 src/assets/icons/svg/skill.svg | 1 src/components/Crontab/month.vue | 114 src/views/system/menu/index.vue | 524 src/api/peizhi/index.js | 18 src/directive/index.js | 23 src/assets/icons/svg/server.svg | 1 src/layout/components/Sidebar/index.vue | 57 src/store/modules/app.js | 66 src/views/manage/stock/index.vue | 423 src/assets/icons/svg/excel.svg | 1 src/api/manage/equRes.js | 85 src/api/system/user.js | 135 src/assets/icons/svg/table.svg | 1 src/assets/styles/variables.scss | 54 src/assets/styles/sidebar.scss | 227 src/assets/images/profile.jpg | 0 src/views/manage/berth/index.vue | 322 src/assets/styles/element-ui.scss | 92 src/utils/dict/DictConverter.js | 17 src/layout/components/TagsView/index.vue | 332 src/assets/icons/svg/redis-list.svg | 2 src/utils/request.js | 181 build/index.js | 35 public/保障需求模板.xls | 0 src/assets/icons/svg/star.svg | 1 src/assets/icons/svg/code.svg | 1 src/views/system/user/profile/resetPwd.vue | 68 src/layout/components/AppMain.vue | 75 .eslintignore | 10 src/assets/icons/svg/post.svg | 1 src/components/Crontab/second.vue | 117 src/views/manage/wharf/index.vue | 309 src/views/index.vue | 897 + src/assets/icons/svg/fullscreen.svg | 1 src/assets/icons/index.js | 9 src/assets/icons/svg/build.svg | 1 src/api/system/config.js | 60 src/assets/icons/svg/dashboard.svg | 1 src/views/manage/shipType/index.vue | 362 src/views/system/user/profile/userAvatar.vue | 182 src/components/Screenfull/index.vue | 57 src/views/index_v1.vue | 98 src/assets/icons/svg/date.svg | 1 src/utils/auth.js | 15 src/api/system/dept.js | 52 src/views/dashboard/RaddarChart.vue | 116 src/views/manage/supplement/index.vue | 268 src/layout/components/InnerLink/index.vue | 47 src/views/system/role/authUser.vue | 199 src/api/system/dict/type.js | 60 src/store/getters.js | 19 public/favicon.ico | 0 .editorconfig | 22 src/assets/icons/svg/nested.svg | 1 src/components/PanThumb/index.vue | 142 src/views/tool/build/index.vue | 768 + src/permission.js | 56 src/views/system/peizhi/aliyunEmailForm.vue | 67 src/assets/icons/svg/monitor.svg | 2 src/utils/scroll-to.js | 58 src/utils/dict/index.js | 33 src/views/system/post/index.vue | 309 src/assets/images/pay.png | 0 src/assets/icons/svg/example.svg | 1 src/views/system/user/profile/index.vue | 91 src/assets/styles/transition.scss | 49 src/utils/generator/js.js | 235 src/assets/icons/svg/time-range.svg | 1 src/layout/components/Sidebar/Item.vue | 33 README.md | 30 src/views/manage/data/resultData.vue | 397 src/plugins/modal.js | 83 src/assets/icons/svg/logininfor.svg | 1 src/views/system/peizhi/localEmailForm.vue | 92 src/api/manage/assess.js | 46 src/main.js | 89 src/components/DictData/index.js | 49 src/layout/components/TagsView/ScrollPane.vue | 94 .env.production | 12 src/layout/components/index.js | 5 src/views/system/notice/index.vue | 337 src/layout/components/Settings/index.vue | 260 src/assets/icons/svg/lock.svg | 1 src/views/system/gkInformation/index.vue | 642 + src/views/system/config/index.vue | 343 src/api/system/role.js | 119 src/views/tool/build/RightPanel.vue | 946 + src/layout/components/Navbar.vue | 192 src/utils/jsencrypt.js | 30 src/components/Crontab/min.vue | 116 .env.staging | 10 src/assets/icons/svg/bug.svg | 1 src/views/tool/build/TreeNodeDialog.vue | 149 src/api/manage/equipment.js | 91 src/api/monitor/operlog.js | 26 src/assets/icons/svg/email.svg | 1 src/layout/components/Sidebar/SidebarItem.vue | 100 public/html/ie.html | 46 src/assets/icons/svg/redis.svg | 1 src/utils/dict/DictOptions.js | 51 src/assets/icons/svg/color.svg | 1 src/components/DictTag/index.vue | 92 src/assets/icons/svg/swagger.svg | 1 src/store/modules/permission.js | 133 src/assets/icons/svg/slider.svg | 1 src/assets/logo/logo.png | 0 src/api/menu.js | 9 src/views/components/icons/svg-icons.js | 10 src/utils/dict/DictMeta.js | 38 src/utils/validate.js | 83 src/utils/permission.js | 51 src/plugins/cache.js | 77 src/store/modules/dict.js | 50 src/views/dashboard/LineChart.vue | 135 src/api/system/post.js | 44 src/assets/icons/svg/tree.svg | 1 src/components/Crontab/week.vue | 202 src/directive/permission/hasRole.js | 28 src/views/components/icons/element-icons.js | 3 src/views/manage/daily/index.vue | 392 src/assets/icons/svg/select.svg | 1 330 files changed, 33,943 insertions(+), 9 deletions(-) diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..7034f9b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,22 @@ +# 鍛婅瘔EditorConfig鎻掍欢锛岃繖鏄牴鏂囦欢锛屼笉鐢ㄧ户缁線涓婃煡鎵� +root = true + +# 鍖归厤鍏ㄩ儴鏂囦欢 +[*] +# 璁剧疆瀛楃闆� +charset = utf-8 +# 缂╄繘椋庢牸锛屽彲閫塻pace銆乼ab +indent_style = space +# 缂╄繘鐨勭┖鏍兼暟 +indent_size = 2 +# 缁撳熬鎹㈣绗︼紝鍙�塴f銆乧r銆乧rlf +end_of_line = lf +# 鍦ㄦ枃浠剁粨灏炬彃鍏ユ柊琛� +insert_final_newline = true +# 鍒犻櫎涓�琛屼腑鐨勫墠鍚庣┖鏍� +trim_trailing_whitespace = true + +# 鍖归厤md缁撳熬鐨勬枃浠� +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..bca7570 --- /dev/null +++ b/.env.development @@ -0,0 +1,19 @@ +# 椤甸潰鏍囬 +VUE_APP_TITLE = 鏁板瓧鍖栫鐞嗙郴缁� + +# 寮�鍙戠幆澧冮厤缃� +ENV = 'development' + +port = '8080' + +# 鑻ヤ緷绠$悊绯荤粺/寮�鍙戠幆澧� +# VUE_APP_BASE_API = '/dev-api' + +# 璺敱鎳掑姞杞� +VUE_CLI_BABEL_TRANSPILE_MODULES = true + +VUE_URL = http://192.168.0.4:8095/ +VUE_APP_BASE_API = http://192.168.0.4:8095/ + +# VUE_URL = http://10.1.10.100:8095/ +# VUE_APP_BASE_API = http://10.1.10.100:8095/ \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..38a3b5b --- /dev/null +++ b/.env.production @@ -0,0 +1,12 @@ +# 椤甸潰鏍囬 +VUE_APP_TITLE = 鏁板瓧鍖栫鐞嗙郴缁� + +# 鐢熶骇鐜閰嶇疆 +ENV = 'production' + +# 鑻ヤ緷绠$悊绯荤粺/鐢熶骇鐜 +# VUE_APP_BASE_API = '/rYdist/prod-api' +# 鎺ュ彛鍦板潃 鍕挎敼 +#VUE_APP_BASE_API = http://192.168.0.4:8095/ +VUE_URL = http://10.1.10.10:8095/ +VUE_APP_BASE_API = http://10.1.10.10:8095/ diff --git a/.env.staging b/.env.staging new file mode 100644 index 0000000..39c92f7 --- /dev/null +++ b/.env.staging @@ -0,0 +1,10 @@ +# 椤甸潰鏍囬 +VUE_APP_TITLE = 鏁板瓧鍖栫鐞嗙郴缁� + +NODE_ENV = production + +# 娴嬭瘯鐜閰嶇疆 +ENV = 'staging' + +# 鑻ヤ緷绠$悊绯荤粺/娴嬭瘯鐜 +VUE_APP_BASE_API = '/stage-api' diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..89be6f6 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,10 @@ +# 蹇界暐build鐩綍涓嬬被鍨嬩负js鐨勬枃浠剁殑璇硶妫�鏌� +build/*.js +# 蹇界暐src/assets鐩綍涓嬫枃浠剁殑璇硶妫�鏌� +src/assets +# 蹇界暐public鐩綍涓嬫枃浠剁殑璇硶妫�鏌� +public +# 蹇界暐褰撳墠鐩綍涓嬩负js鐨勬枃浠剁殑璇硶妫�鏌� +*.js +# 蹇界暐褰撳墠鐩綍涓嬩负vue鐨勬枃浠剁殑璇硶妫�鏌� +*.vue \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..82bbdee --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,199 @@ +// ESlint 妫�鏌ラ厤缃� +module.exports = { + root: true, + parserOptions: { + parser: 'babel-eslint', + sourceType: 'module' + }, + env: { + browser: true, + node: true, + es6: true, + }, + extends: ['plugin:vue/recommended', 'eslint:recommended'], + + // add your custom rules here + //it is base on https://github.com/vuejs/eslint-config-vue + rules: { + "vue/max-attributes-per-line": [2, { + "singleline": 10, + "multiline": { + "max": 1, + "allowFirstLine": false + } + }], + "vue/singleline-html-element-content-newline": "off", + "vue/multiline-html-element-content-newline":"off", + "vue/name-property-casing": ["error", "PascalCase"], + "vue/no-v-html": "off", + 'accessor-pairs': 2, + 'arrow-spacing': [2, { + 'before': true, + 'after': true + }], + 'block-spacing': [2, 'always'], + 'brace-style': [2, '1tbs', { + 'allowSingleLine': true + }], + 'camelcase': [0, { + 'properties': 'always' + }], + 'comma-dangle': [2, 'never'], + 'comma-spacing': [2, { + 'before': false, + 'after': true + }], + 'comma-style': [2, 'last'], + 'constructor-super': 2, + 'curly': [2, 'multi-line'], + 'dot-location': [2, 'property'], + 'eol-last': 2, + 'eqeqeq': ["error", "always", {"null": "ignore"}], + 'generator-star-spacing': [2, { + 'before': true, + 'after': true + }], + 'handle-callback-err': [2, '^(err|error)$'], + 'indent': [2, 2, { + 'SwitchCase': 1 + }], + 'jsx-quotes': [2, 'prefer-single'], + 'key-spacing': [2, { + 'beforeColon': false, + 'afterColon': true + }], + 'keyword-spacing': [2, { + 'before': true, + 'after': true + }], + 'new-cap': [2, { + 'newIsCap': true, + 'capIsNew': false + }], + 'new-parens': 2, + 'no-array-constructor': 2, + 'no-caller': 2, + 'no-console': 'off', + 'no-class-assign': 2, + 'no-cond-assign': 2, + 'no-const-assign': 2, + 'no-control-regex': 0, + 'no-delete-var': 2, + 'no-dupe-args': 2, + 'no-dupe-class-members': 2, + 'no-dupe-keys': 2, + 'no-duplicate-case': 2, + 'no-empty-character-class': 2, + 'no-empty-pattern': 2, + 'no-eval': 2, + 'no-ex-assign': 2, + 'no-extend-native': 2, + 'no-extra-bind': 2, + 'no-extra-boolean-cast': 2, + 'no-extra-parens': [2, 'functions'], + 'no-fallthrough': 2, + 'no-floating-decimal': 2, + 'no-func-assign': 2, + 'no-implied-eval': 2, + 'no-inner-declarations': [2, 'functions'], + 'no-invalid-regexp': 2, + 'no-irregular-whitespace': 2, + 'no-iterator': 2, + 'no-label-var': 2, + 'no-labels': [2, { + 'allowLoop': false, + 'allowSwitch': false + }], + 'no-lone-blocks': 2, + 'no-mixed-spaces-and-tabs': 2, + 'no-multi-spaces': 2, + 'no-multi-str': 2, + 'no-multiple-empty-lines': [2, { + 'max': 1 + }], + 'no-native-reassign': 2, + 'no-negated-in-lhs': 2, + 'no-new-object': 2, + 'no-new-require': 2, + 'no-new-symbol': 2, + 'no-new-wrappers': 2, + 'no-obj-calls': 2, + 'no-octal': 2, + 'no-octal-escape': 2, + 'no-path-concat': 2, + 'no-proto': 2, + 'no-redeclare': 2, + 'no-regex-spaces': 2, + 'no-return-assign': [2, 'except-parens'], + 'no-self-assign': 2, + 'no-self-compare': 2, + 'no-sequences': 2, + 'no-shadow-restricted-names': 2, + 'no-spaced-func': 2, + 'no-sparse-arrays': 2, + 'no-this-before-super': 2, + 'no-throw-literal': 2, + 'no-trailing-spaces': 2, + 'no-undef': 2, + 'no-undef-init': 2, + 'no-unexpected-multiline': 2, + 'no-unmodified-loop-condition': 2, + 'no-unneeded-ternary': [2, { + 'defaultAssignment': false + }], + 'no-unreachable': 2, + 'no-unsafe-finally': 2, + 'no-unused-vars': [2, { + 'vars': 'all', + 'args': 'none' + }], + 'no-useless-call': 2, + 'no-useless-computed-key': 2, + 'no-useless-constructor': 2, + 'no-useless-escape': 0, + 'no-whitespace-before-property': 2, + 'no-with': 2, + 'one-var': [2, { + 'initialized': 'never' + }], + 'operator-linebreak': [2, 'after', { + 'overrides': { + '?': 'before', + ':': 'before' + } + }], + 'padded-blocks': [2, 'never'], + 'quotes': [2, 'single', { + 'avoidEscape': true, + 'allowTemplateLiterals': true + }], + 'semi': [2, 'never'], + 'semi-spacing': [2, { + 'before': false, + 'after': true + }], + 'space-before-blocks': [2, 'always'], + 'space-before-function-paren': [2, 'never'], + 'space-in-parens': [2, 'never'], + 'space-infix-ops': 2, + 'space-unary-ops': [2, { + 'words': true, + 'nonwords': false + }], + 'spaced-comment': [2, 'always', { + 'markers': ['global', 'globals', 'eslint', 'eslint-disable', '*package', '!', ','] + }], + 'template-curly-spacing': [2, 'never'], + 'use-isnan': 2, + 'valid-typeof': 2, + 'wrap-iife': [2, 'any'], + 'yield-star-spacing': [2, 'both'], + 'yoda': [2, 'never'], + 'prefer-const': 2, + 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, + 'object-curly-spacing': [2, 'always', { + objectsInObjects: false + }], + 'array-bracket-spacing': [2, 'never'] + } +} diff --git a/.gitignore b/.gitignore index 32858aa..78a752d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,23 @@ -*.class +.DS_Store +node_modules/ +dist/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* +**/*.log -# Mobile Tools for Java (J2ME) -.mtj.tmp/ +tests/**/coverage/ +tests/e2e/reports +selenium-debug.log -# Package Files # -*.jar -*.war -*.ear +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.local -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* +package-lock.json +yarn.lock diff --git a/README.md b/README.md new file mode 100644 index 0000000..00c0ab8 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +## 寮�鍙� + +```bash +# 鍏嬮殕椤圭洰 +git clone https://gitee.com/y_project/RuoYi-Vue + +# 杩涘叆椤圭洰鐩綍 +cd ruoyi-ui + +# 瀹夎渚濊禆 +npm install + +# 寤鸿涓嶈鐩存帴浣跨敤 cnpm 瀹夎渚濊禆锛屼細鏈夊悇绉嶈寮傜殑 bug銆傚彲浠ラ�氳繃濡備笅鎿嶄綔瑙e喅 npm 涓嬭浇閫熷害鎱㈢殑闂 +npm install --registry=https://registry.npmmirror.com + +# 鍚姩鏈嶅姟 +npm run dev +``` + +娴忚鍣ㄨ闂� http://localhost:80 + +## 鍙戝竷 + +```bash +# 鏋勫缓娴嬭瘯鐜 +npm run build:stage + +# 鏋勫缓鐢熶骇鐜 +npm run build:prod +``` \ No newline at end of file diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..c8267b2 --- /dev/null +++ b/babel.config.js @@ -0,0 +1,13 @@ +module.exports = { + presets: [ + // https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app + '@vue/cli-plugin-babel/preset' + ], + 'env': { + 'development': { + // babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require(). + // This plugin can significantly increase the speed of hot updates, when you have a large number of pages. + 'plugins': ['dynamic-import-node'] + } + } +} \ No newline at end of file diff --git a/build/index.js b/build/index.js new file mode 100644 index 0000000..0c57de2 --- /dev/null +++ b/build/index.js @@ -0,0 +1,35 @@ +const { run } = require('runjs') +const chalk = require('chalk') +const config = require('../vue.config.js') +const rawArgv = process.argv.slice(2) +const args = rawArgv.join(' ') + +if (process.env.npm_config_preview || rawArgv.includes('--preview')) { + const report = rawArgv.includes('--report') + + run(`vue-cli-service build ${args}`) + + const port = 9526 + const publicPath = config.publicPath + + var connect = require('connect') + var serveStatic = require('serve-static') + const app = connect() + + app.use( + publicPath, + serveStatic('./dist', { + index: ['index.html', '/'] + }) + ) + + app.listen(port, function () { + console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) + if (report) { + console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) + } + + }) +} else { + run(`vue-cli-service build ${args}`) +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..063d6f0 --- /dev/null +++ b/package.json @@ -0,0 +1,92 @@ +{ + "name": "ruoyi", + "version": "3.8.6", + "description": "绠$悊绯荤粺", + "author": "鑻ヤ緷", + "license": "MIT", + "scripts": { + "dev": "vue-cli-service serve", + "build:prod": "vue-cli-service build", + "build:stage": "vue-cli-service build --mode staging", + "preview": "node build/index.js --preview", + "lint": "eslint --ext .js,.vue src" + }, + "husky": { + "hooks": { + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "src/**/*.{js,vue}": [ + "eslint --fix", + "git add" + ] + }, + "keywords": [ + "vue", + "admin", + "dashboard", + "element-ui", + "boilerplate", + "admin-template", + "management-system" + ], + "repository": { + "type": "git", + "url": "https://gitee.com/y_project/RuoYi-Vue.git" + }, + "dependencies": { + "@riophae/vue-treeselect": "0.4.0", + "axios": "0.24.0", + "clipboard": "2.0.8", + "core-js": "3.25.3", + "dayjs": "^1.11.13", + "echarts": "5.4.0", + "element-ui": "2.15.13", + "file-saver": "2.0.5", + "fuse.js": "6.4.3", + "highlight.js": "9.18.5", + "js-beautify": "1.13.0", + "js-cookie": "3.0.1", + "jsencrypt": "3.0.0-rc.1", + "nprogress": "0.2.0", + "quill": "1.3.7", + "screenfull": "5.0.2", + "sortablejs": "1.10.2", + "vue": "2.6.12", + "vue-count-to": "1.0.13", + "vue-cropper": "0.5.5", + "vue-meta": "2.4.0", + "vue-router": "3.4.9", + "vuedraggable": "2.24.3", + "vuex": "3.6.0" + }, + "devDependencies": { + "@jiaminghi/data-view": "^2.10.0", + "@vue/cli-plugin-babel": "4.4.6", + "@vue/cli-plugin-eslint": "4.4.6", + "@vue/cli-service": "4.4.6", + "babel-eslint": "10.1.0", + "babel-plugin-dynamic-import-node": "2.3.3", + "chalk": "4.1.0", + "compression-webpack-plugin": "5.0.2", + "connect": "3.6.6", + "eslint": "7.15.0", + "eslint-plugin-vue": "7.2.0", + "lint-staged": "10.5.3", + "runjs": "4.4.2", + "sass": "1.32.13", + "sass-loader": "10.1.1", + "script-ext-html-webpack-plugin": "2.1.5", + "svg-sprite-loader": "5.1.1", + "vue-template-compiler": "2.6.12" + }, + "engines": { + "node": ">=8.9", + "npm": ">= 3.0.0" + }, + "browserslist": [ + "> 1%", + "last 2 versions" + ] +} diff --git a/public/berthPOI.json b/public/berthPOI.json new file mode 100644 index 0000000..d994222 --- /dev/null +++ b/public/berthPOI.json @@ -0,0 +1,62 @@ +[ + { + "berthId": 1, + "berthName": "娉婁綅1", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.7099912516832, + "lat": 26.00577037794584, + "alt": 30, + "heading": 102 + }, + { + "berthId": 2, + "berthName": "娉婁綅2", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.6884952238629, + "lat": 26.61603325224163, + "alt": 30, + "heading": 102 + }, + { + "berthId": 3, + "berthName": "娉婁綅4", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.6869946875741, + "lat": 26.61632763076653, + "alt": 30, + "heading": 102 + }, + { + "berthId": 6, + "berthName": "娉婁綅6", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.6857056258854, + "lat": 26.61655026398386, + "alt": 30, + "heading": 102 + }, + { + "berthId": 10, + "berthName": "娉婁綅3", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.6842493488982, + "lat": 26.61683090999896, + "alt": 30, + "heading": 102 + }, + { + "berthId": 12, + "berthName": "娉婁綅5", + "harborId": 1, + "harborName": "瀹佸痉1鍙风爜澶�", + "lon": 119.6828187287134, + "lat": 26.61707948397497, + "alt": 30, + "heading": 102 + } +] \ No newline at end of file diff --git a/public/config.js b/public/config.js new file mode 100644 index 0000000..723d6d2 --- /dev/null +++ b/public/config.js @@ -0,0 +1 @@ +const VUE_BASE_URL = 'http://127.0.0.1:8095' \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..e263760 --- /dev/null +++ b/public/favicon.ico Binary files differ diff --git a/public/html/ie.html b/public/html/ie.html new file mode 100644 index 0000000..052ffcd --- /dev/null +++ b/public/html/ie.html @@ -0,0 +1,46 @@ + +<!DOCTYPE html> +<html lang="zh-CN"> +<head> + <meta charset="UTF-8" /> + <title>璇峰崌绾ф偍鐨勬祻瑙堝櫒</title> + <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" > + <meta name="renderer" content="webkit"> + <base target="_blank" /> + <style type="text/css"> + html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} + a{text-decoration:none;color:#0072c6;}a:hover{text-decoration:none;color:#004d8c;} + body{width:960px;margin:0 auto;padding:10px;font-size:14px;line-height:24px;color:#454545;font-family:'Microsoft YaHei UI','Microsoft YaHei',DengXian,SimSun,'Segoe UI',Tahoma,Helvetica,sans-serif;overflow-y:scroll} + h1{font-size:40px;line-height:80px;font-weight:100;margin-bottom:10px;} + h2{font-size:20px;line-height:25px;font-weight:100;margin:10px 0;} + em{color:red} + p{margin-bottom:10px;} + hr{margin:20px 0;border:0;border-top:1px solid #dadada} + span{display:block;font-size:12px;line-height:12px;} + .clean{clear:both;} + .browser{padding:10px 10px;} + .browser li{width:auto;padding:0 80px;margin-top:30px;height:34px;line-height:22px;float:left;list-style:none;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACIAAADMCAYAAAAWCXEwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKTWlDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVN3WJP3Fj7f92UPVkLY8LGXbIEAIiOsCMgQWaIQkgBhhBASQMWFiApWFBURnEhVxILVCkidiOKgKLhnQYqIWotVXDjuH9yntX167+3t+9f7vOec5/zOec8PgBESJpHmomoAOVKFPDrYH49PSMTJvYACFUjgBCAQ5svCZwXFAADwA3l4fnSwP/wBr28AAgBw1S4kEsfh/4O6UCZXACCRAOAiEucLAZBSAMguVMgUAMgYALBTs2QKAJQAAGx5fEIiAKoNAOz0ST4FANipk9wXANiiHKkIAI0BAJkoRyQCQLsAYFWBUiwCwMIAoKxAIi4EwK4BgFm2MkcCgL0FAHaOWJAPQGAAgJlCLMwAIDgCAEMeE80DIEwDoDDSv+CpX3CFuEgBAMDLlc2XS9IzFLiV0Bp38vDg4iHiwmyxQmEXKRBmCeQinJebIxNI5wNMzgwAABr50cH+OD+Q5+bk4eZm52zv9MWi/mvwbyI+IfHf/ryMAgQAEE7P79pf5eXWA3DHAbB1v2upWwDaVgBo3/ldM9sJoFoK0Hr5i3k4/EAenqFQyDwdHAoLC+0lYqG9MOOLPv8z4W/gi372/EAe/tt68ABxmkCZrcCjg/1xYW52rlKO58sEQjFu9+cj/seFf/2OKdHiNLFcLBWK8ViJuFAiTcd5uVKRRCHJleIS6X8y8R+W/QmTdw0ArIZPwE62B7XLbMB+7gECiw5Y0nYAQH7zLYwaC5EAEGc0Mnn3AACTv/mPQCsBAM2XpOMAALzoGFyolBdMxggAAESggSqwQQcMwRSswA6cwR28wBcCYQZEQAwkwDwQQgbkgBwKoRiWQRlUwDrYBLWwAxqgEZrhELTBMTgN5+ASXIHrcBcGYBiewhi8hgkEQcgIE2EhOogRYo7YIs4IF5mOBCJhSDSSgKQg6YgUUSLFyHKkAqlCapFdSCPyLXIUOY1cQPqQ28ggMor8irxHMZSBslED1AJ1QLmoHxqKxqBz0XQ0D12AlqJr0Rq0Hj2AtqKn0UvodXQAfYqOY4DRMQ5mjNlhXIyHRWCJWBomxxZj5Vg1Vo81Yx1YN3YVG8CeYe8IJAKLgBPsCF6EEMJsgpCQR1hMWEOoJewjtBK6CFcJg4Qxwicik6hPtCV6EvnEeGI6sZBYRqwm7iEeIZ4lXicOE1+TSCQOyZLkTgohJZAySQtJa0jbSC2kU6Q+0hBpnEwm65Btyd7kCLKArCCXkbeQD5BPkvvJw+S3FDrFiOJMCaIkUqSUEko1ZT/lBKWfMkKZoKpRzame1AiqiDqfWkltoHZQL1OHqRM0dZolzZsWQ8ukLaPV0JppZ2n3aC/pdLoJ3YMeRZfQl9Jr6Afp5+mD9HcMDYYNg8dIYigZaxl7GacYtxkvmUymBdOXmchUMNcyG5lnmA+Yb1VYKvYqfBWRyhKVOpVWlX6V56pUVXNVP9V5qgtUq1UPq15WfaZGVbNQ46kJ1Bar1akdVbupNq7OUndSj1DPUV+jvl/9gvpjDbKGhUaghkijVGO3xhmNIRbGMmXxWELWclYD6yxrmE1iW7L57Ex2Bfsbdi97TFNDc6pmrGaRZp3mcc0BDsax4PA52ZxKziHODc57LQMtPy2x1mqtZq1+rTfaetq+2mLtcu0W7eva73VwnUCdLJ31Om0693UJuja6UbqFutt1z+o+02PreekJ9cr1Dund0Uf1bfSj9Rfq79bv0R83MDQINpAZbDE4Y/DMkGPoa5hpuNHwhOGoEctoupHEaKPRSaMnuCbuh2fjNXgXPmasbxxirDTeZdxrPGFiaTLbpMSkxeS+Kc2Ua5pmutG003TMzMgs3KzYrMnsjjnVnGueYb7ZvNv8jYWlRZzFSos2i8eW2pZ8ywWWTZb3rJhWPlZ5VvVW16xJ1lzrLOtt1ldsUBtXmwybOpvLtqitm63Edptt3xTiFI8p0in1U27aMez87ArsmuwG7Tn2YfYl9m32zx3MHBId1jt0O3xydHXMdmxwvOuk4TTDqcSpw+lXZxtnoXOd8zUXpkuQyxKXdpcXU22niqdun3rLleUa7rrStdP1o5u7m9yt2W3U3cw9xX2r+00umxvJXcM970H08PdY4nHM452nm6fC85DnL152Xlle+70eT7OcJp7WMG3I28Rb4L3Le2A6Pj1l+s7pAz7GPgKfep+Hvqa+It89viN+1n6Zfgf8nvs7+sv9j/i/4XnyFvFOBWABwQHlAb2BGoGzA2sDHwSZBKUHNQWNBbsGLww+FUIMCQ1ZH3KTb8AX8hv5YzPcZyya0RXKCJ0VWhv6MMwmTB7WEY6GzwjfEH5vpvlM6cy2CIjgR2yIuB9pGZkX+X0UKSoyqi7qUbRTdHF09yzWrORZ+2e9jvGPqYy5O9tqtnJ2Z6xqbFJsY+ybuIC4qriBeIf4RfGXEnQTJAntieTE2MQ9ieNzAudsmjOc5JpUlnRjruXcorkX5unOy553PFk1WZB8OIWYEpeyP+WDIEJQLxhP5aduTR0T8oSbhU9FvqKNolGxt7hKPJLmnVaV9jjdO31D+miGT0Z1xjMJT1IreZEZkrkj801WRNberM/ZcdktOZSclJyjUg1plrQr1zC3KLdPZisrkw3keeZtyhuTh8r35CP5c/PbFWyFTNGjtFKuUA4WTC+oK3hbGFt4uEi9SFrUM99m/ur5IwuCFny9kLBQuLCz2Lh4WfHgIr9FuxYji1MXdy4xXVK6ZHhp8NJ9y2jLspb9UOJYUlXyannc8o5Sg9KlpUMrglc0lamUycturvRauWMVYZVkVe9ql9VbVn8qF5VfrHCsqK74sEa45uJXTl/VfPV5bdra3kq3yu3rSOuk626s91m/r0q9akHV0IbwDa0b8Y3lG19tSt50oXpq9Y7NtM3KzQM1YTXtW8y2rNvyoTaj9nqdf13LVv2tq7e+2Sba1r/dd3vzDoMdFTve75TsvLUreFdrvUV99W7S7oLdjxpiG7q/5n7duEd3T8Wej3ulewf2Re/ranRvbNyvv7+yCW1SNo0eSDpw5ZuAb9qb7Zp3tXBaKg7CQeXBJ9+mfHvjUOihzsPcw83fmX+39QjrSHkr0jq/dawto22gPaG97+iMo50dXh1Hvrf/fu8x42N1xzWPV56gnSg98fnkgpPjp2Snnp1OPz3Umdx590z8mWtdUV29Z0PPnj8XdO5Mt1/3yfPe549d8Lxw9CL3Ytslt0utPa49R35w/eFIr1tv62X3y+1XPK509E3rO9Hv03/6asDVc9f41y5dn3m978bsG7duJt0cuCW69fh29u0XdwruTNxdeo94r/y+2v3qB/oP6n+0/rFlwG3g+GDAYM/DWQ/vDgmHnv6U/9OH4dJHzEfVI0YjjY+dHx8bDRq98mTOk+GnsqcTz8p+Vv9563Or59/94vtLz1j82PAL+YvPv655qfNy76uprzrHI8cfvM55PfGm/K3O233vuO+638e9H5ko/ED+UPPR+mPHp9BP9z7nfP78L/eE8/sl0p8zAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAC7ESURBVHja5Lx5dFRV1rBfgHwYRQQVtB26ZWhtabtfeUGxGxFbUGZF8RMHGkVbRkekVYiKisicVhE0gEwBokgDAhEMMSSQkAECwcxkrlRSqVTqJqnxzs/vj5t7qUyAvr9e37fWV2vtleSm6p6n9t5nn733OVU2RaUaEP5PiqJSbeMXPBTA5/Xhzk9Vnd9vo3HFx21E2LYJX9IRgh6npvyCe9uaqS4K4C3IpXHFx9S99CTuJ8Z0KLVjRlA7ZgTuJ8ZgXxmJL+kIlwAkXBQk6HFq9pWRVA8fSvXwodYgdS892a6EA1UNvouqwXdR99KTeAtyfz2IL+kI1cOHYh9wqwVwKWJqpXbMCOv19gG3Imzb1JF2OgZxfr/NukH4jcNVfyEAE8IU+4BbKet1PfaVke3BtA/i/H6b8aIBt7a4mWmaC0nr55vmqRp8F5V33Mm5LhHtwbQF8SUdsSDCb1I1+K42g1xIWgOYYh9wK+e6RCBs29QxSIWus37aJM51iWjx4so77mwD1d5AHQ1eecedlN9yuyVlva6nrNf14Q7cEmRn4W7u3T2E9ME3UX7L7W1uZg5Weced1s3sA2613ql5LXzQjuRclwjcT4wxTXQeRHC7GLdnHPeensiCVwa3e0PznZk3EbZtwluQa0kofz8NcVNxr++Ce30XnNuv61Bcu7viXt8Fvyu7JYipjfGHxzD+8Bh2j+7fAiZcC+Y0zPDIbCyD6DyV6DyVeDcIQR2C39J4oieNJ3oSOnkVcnZ35Ozu6MVdDHF0N6S4C43OqJYg/0ydzb27hzDx0FjuPT2R+asfa6OVsl7X40s6QoWus/CQk6fWZPHChhxe3lbMCxtyrN9TyxSQSwidvMoC0XK6tRGybPjSRmOuNUKVo4Zxe8YxIu4+Jh4ay/jDY7j39MQWWjnXJYLGFR9Toes8tSaLiavTrIHDxfxfapkCwW8hy9YuhCmhk1fR1FRnaCS1NM4yy8RDYy2tjIkZRXq/HtYsCnqc2sJDTkYsTrU00J6YkEJQR7M/eEGY0MmrcOenqjZA2JmyzTJLuJiOe65LBHUvPUmGR2bE4lQmrk7jqTVZHcrE1WkMWpRIdJ4KnpUXBCHLRl3e16EWIOEaMU00/vAY9na/gsYVH/NdgYe+8w9bMBeSQYsSWXjICcFvL2ga+dhlFwcJ10rjio/ZklprgbSWiavTWvzdd/5hXt5W/OtATC201sq9u4eQ+PVijmSW0nf+YQYtSmTQosR2gUYsTmXQokT6zj9saeRCpmkJ0hxD2gOZeGgsI+Lu45+ps7FXlFmDmDDtSd/5h+k7/zCpZQpa9cwOQciyIR+77LyzFhXlMyZmFOP2jLP8orVWRsTdR2ppHFtSa+k6ZZM1WHvSdcomwyxySceayO4OWTY88TdirygzUkWf18eL2//RQiutYcwYE/Q4tagDOUQ8uo6uUzbRZ3qMJV2nbCLi0XU8tSbrolNXzu6OfOyylgEN4NOkaO5acw/j9ozr0ET37h5imehIZimPL91rAfSZHsOQBfuISS7E7vaTETeX0MmrOoQInbwK+dhlNKWsahni0zPSuGvNPW1M1BrI1NrOwt0WkCn2ijJSS+MYt2ccuQk3oxd36RCi8URPY+HLT1VbgGiSzPsx71laCddMe2Yygf6ZOtuScXvG0XfJn/n8YL+LQnjibyQ34WZ8Xl/bfKSoKL+FVi4EYwKZcu/uIQzaPoExMaPQcrq1ADFX33AI1+6u1OV9HVI6ShU/TYqm75I/dwjTHtDEQ2MZt2ccg7ZPaGGScIDWEBlxc42UoSMQ00StYdoDCgcbtH0Cbx+8p40ZTIBwiFM7RmB3+y+exZvT2YRpDdR6ZoVrw1xRWwN44m/Euf06A6Ki7NLrmnDNmH7TEdSg7RP4/GA/yLK1GdwEKNzSk1M7RlDlqPl1JefOlG2MXTGmXaAxMaMsB/XE34h4tH+7ANlrB7T2iV8OAlDlqOH9mPcsIBPKlF3R16Ad7GwlxoVberYAKCrKv1ghfmkg5sPldLIzZVsLqLErxpC9doAlp3aMICNurlGyVpRdSAu/HqS1Q58rd1JUlI87P1UtKsrHXlGG3e1HCOoov+x2wiX3RxT+o49L1IgutXxVUCfDIxNfLraQDI+M3e3/NdCXbhohqBNfLrIsVzZqmoT6dmXG0SBLTrmJLxd/CVRLECXcDGFaSC1TmHE0yKg4B0P2uxiy38WoOAePHaptAfHYoVqG7HcxcGc5o+IcfFfgsbQUPoYoSa213BbE78oGucTSwpJTbobFFjNgbQHdvi6g8/Z6Om+vZ8h+VxsQE7T/97UMWFvA+Og0UvIryfDIZBQ4CeXvt8a5IAhAY/RImlJWUaHrPHaolhuXFXHN+8e58qNcbomq5P6t3xG973WePLzPgnnsUG0LiP7f1zJwZzk3LisyctfSOFxOJ4lfLzYToQubxu/KpmpWBFWzInguOokrP8ql7/zDRMxLpFfUabasHwlZNnITbmbgznI6b6+3Bu7/fa2lrW5fF9Ar6jQD1hYwLLaYx5fupdi+EiGok748koa4qa010xKkKWUV2UM7kd6vB7tH9yfpnUFkLzQiZOGWnmgHO9N4oie9ok5bA4YPbkqvqNNc8/5xIuYl8tSaLOLLRXambENXF+PxNJD0ziAanVHhYaEliH1lJD/1iqD0qSsIzu2M/N550TZ3QjvYmS3rR1qDtwdhgpgwnabGMj46zRjQsxJdXYw7P1X1pY0GuaRjkMKxPah5qxuV8y6nct7l1LzVDfdyo6miHexM+ou9mblwKfdv/Y77t37HNe8fbwMQDhIxL5FOU2PZklqLJjUYdU7wWxBuN+ricBAF0KQG6pcNovZpw0fCQao/MEBcu7tSOLYHjnu7EZzbmeDczqyfNokrP8ptMXi4XDnzAJ0n72TIgn1oUoMB4VlpgIjj24I0payi9KkrqHj+Ssth2wM5c38f8p68D2nbHKRtc3h86d42A/eZHsOVMw9Y0nXKJmxDvyS1NA70z8Gz0qh5hNvbzpr6ZYMofzyiBUwLkOVdjfR/eVcao0dSl/d1aHx0GhHzEi0TXDnzAJ2mxtJpaixdp2yypM/0GLrcs5D3Y94ztNDsK7qjuxmzDBBz2rYGqZoVQc1b3dr4yfppk+g8eWeLd91aAxGPrqPbyKV0G7mUiEfXMWdz+nmQ0Jsgn1AbT/SkMXrkeZC6vK9DpU9d0S5I5bzLqf6gq6UV7WBn5q9+zDJBuEQ8us4SE6LLPQvpcs9CjmSW4ndlo1XPNBxWLiE34WbSX+wNapEBEsrfT/njERSO7WGBmDA1b3Wj9KkrSO/Xg1WjBjJl/CT+8sQ8a0BT/eGDhwN0uWchXe94ia07YkE+oSLc3gxyQt2yfiSrRg0E+YRqgRSO7UHh2B4UT7ragqmcdznFk67mp14ROO7txpTxk7AN/bLFgN1GLsU29EvrejiACdG59xQjKgu3GzVP9UwIvcmCVwYb102NmBHVBDFNVDUrgjP39yF98E0E5xox5Dcj5lsDhwOYQObg4dK59xR2RV8D4njEo/0NIEd3dkVfgy9t9HkfMTWSO6pXG63kjupF8aSrqXj+SoJzO1M573KmjJ/Eb0bM5y9PzGPBK4Mp3GKUEFvWj+Q3I+a3AOjcewp/eWKesUQ0T1mz2att7oSU9+F5EE2SqXvpSbKHdrIGNmHCoapmRVgh33LezZ3QNncyloGDnVnwyuA2IFvWj0Q+dplREzu6Wy0r9/KubVvg9pWRpPfrwZn7+1haMSHCxdSM/J4RWWufjiC9Xw/m9PgtN9w0uo1JbrhpNI0njAXTrAIbT/TEvb4LjdEj2641vqQjpPfrQfrgm1qYKHxKlz51BbmjerFj4G2WtAYwtWDKglcGG2ZoXrldu43AWDUrAmnbnLaRVZMayHvyPn7qZThoa38pfeoKap+OIDi3M6tGDeSGm0a3GTT82g03jeaGm0bj3H4d8rHLrN0I93LDpDsG3kb68si2a425hfZTrwjSB9/UBiZcM+YM6ghoyvhJpL/Ym+yFhknc67tYQVF+z3gjc3r8Fuf32zpOFTMeHXpRGDNfMYF2j+7PqlEDWTVqIOkv9rZ8SNvcCff6LlTOu9yK1Okv9mZOj9+S8ehQNKmBDhs17vxU9adeES1gwoHKH49oFyhcwhfKynmXWzOu4vkryR7aieyhnQjl7+84QzNNJGzbxN7uV1gw7WmntYZaLw2mmNdrn44ge2gnztzfx9od7zBnDa9t0pdHtgsTDhRustaaCndwEyLj0aG481PVS9r3FSUJj6eBrConMZHvnodpntrh2gkHCgcLl/TBN7G3+xXGLMlIo0LXjU7ixeoaUZIQ3C7OlTtJya8kJvJddgy8DctvWgGFaylcHPd2Y2/3K5jT47esGjWQrTtiyapy4nI6jUrvUmpfUytFRfmkZ6SxdUcs66dNYsfA2ywNtQBrJeb/dgy8jZjId/kx4YgF4fP6Ln1L3uyhhWvnSGYpOw6lEBP5LuunTWLDAw+x4YGHrAi74YGHWD9tEuunTSIm8l227ohtAyBK0i8/pNDagTVJxuf1YXf7OVfuJKvKMF16RhrpGWkcySwlJb+SrCqn1awRgjqaJP9nO0b/Zxo1v+ahS0ZqKJ9QCX5rJMyhN42aRj6h/udB5BKjiAp+i64uNrJ2M0Vs3rUiy4aU92G42X49iCYZDZjUMoX4ctFIcILfGgVU6E0LwEyCxKP98aWNxpc2GvFof+RjlyHlfdjxWnOxh93tJya5kIWHnDx2qJbnopP4NCmaYvtKC0LL6WYkQps70RA3laaUVbjzU1V7RRn2ijK8BbkWUJsM7VIAog7k8MyuPKtD1AJA/9zQQpYN9/oubFk/kpkLl7J4a0KbtrdZa/vSRrfMWS8GcSSzlGd25TH5VIjptTpR9T5SS+OMsrHZD3RHd7SDnTm1YwSzY2KsTtL46DSei07iSGZpm/tKeR8a5gnf0+vI8zfE5zAstpjptTrvifBJeeZ5LTQDkGXDtbsr0fte59mjDmaWaUyv1ZlZpvH3XJlRcQ6Grj5OTHJhy/t7VhrpwMVAog7kMCrOwcs+nZWaccak2L7S0oLpC6d2jGDJiUyWN8E6FVZqsLwJ5ruwYO5O9jFoUSIb4nPOT+/gtxf3kZjkQobFFreAaHRGGZoQbm+hhWd25fHsUQevHilgbo7bAmoNM2S/i6Grj3Mks9Tolcgn1Hb39MzHuXInw9edZrJd4z3xPISuLrYgCrf0ZOuOWKLzVFLLFDIKmlfr5EJmHMxhfoWvDczkUyELxl5RduFUUZNkIvdm8+BpkZd9eocQPyYc6XDnocpRQ+TebObmuFmptdTK5FMhBqwt4K1vMi4cWTMKnIyKczDZrvFJeWaHEBdrbVc5aphxMIflTR1rJaPA2TFI1IEc7k72tZwdYRCLtyZc6h4MMcmF7WrlwRSRAWsLiNyb3T6Iz+vjmV15jIpztIHwxN/I7JgY4svFS47CHk9DG62Y5hm4s5zx0Wntb0CnlikMiy3m06ToFpFSO9iZnSnbeGZXHkcyS8kocF6SHMksZc7m9AuaJyW/si3IltRaZsfEGNM09KZVs2bEzWV5EyzLlXn1SEG7MuNgTruy5JS73dlzd7IvPMi1BIlJLmRnyjbLJFawar7ZHi5NdrSS9jRyd7KPXlGnzQDXyjSlcYY2mk1SuKUnS05kslI7f9M9/HKgdaoh74nn/cR02NV7M9t2A9A/t/qf2uZOvB/zHvNdxk3Mm0bV+36VzK8wxHTWVutPmEbkE6q1hjQ3/yefCvGeeB7k1SPGlLsUeeubDOtnezJnczpvfZPBuXJnGEjzAqSri9FyulG4pSf3b/3OCvErNQNmxsEczpU70ST5kuWXJc9yiZXemQ3du5N9TK/VedmnW1qZm+M+v3r+gpTS42nA42nA5XRa4vE0hFd8zSDBb63cInvtAAYtSuTuZB+T7ZoFYy7tz+zK6+igQZtHRoGTyL3ZLab4M7vyGB+dxpAF+1i8NaEliLmWyNndsa+MZPi60/T/vpaJhTKT7ZqllZWaoZW3vsnA42m4IMS5cifPRScxN8fNeyK87NOZXqszsdDITa55/3i4dgVb0OPUTG2IR/vjzk9Vt6Qau5R3J/uYWCi3MJEJM2dzOkcyS80Q3WKrPia50IIIX2cmnwrxYIpIr6jTPBed1Mo0apFgpv0NcVMR3C5ESWLO5nS6fV3Ag6fFdmHmV/iYcTCHyL3ZRB3IsSRybzbP7MpjfoWvXYj+39cyZME+c7aEgTQ36smy0RA31dostrv9DF193IIJ9xcTxgSam+O2xAQwg9fMMo2JhTIPnjYgBi1KbC+RPq8REyR8iT9X7rRgWptpvssYLBwqHGB6rc7fc2ULYsh+F4MWJbLjUErH09c8ytcaxNTMCxtyGLC2oIUDT6/VO5TJdkMLJsTAneUMWpTYNotvE0eaj3rKxy6zun2t69mdKdt4fOley4lN35ls11pIOIC51D8XnWQu9xcGUQCteibyscuM5n31TKNqD5fm1H9DfA7PRScxdPVxhsUWMyy22Dq4MGS/i2GxxQxfd9oC2HEopb1WVcdtCU2Sqcv7OmTWpGbRLOV9SCh/P0GPUwvPvDIKnMQkFxK5N5s5m9N5LjqJ56KTeOubDFbvzSQlv7LN1P5FxzZ8Xp918v8SWk5WsWStLbr0a5oLHRdY/+GjPP8vtq7+0yCiJOHz+hDcLlxOJ2bzxeV0Irhdlk/9x0B8Xh9VjhoEt6s5rZTaFU1qQHC7qHLU/PpZ05EGqhw1uJxO0CVESSIlv5KoAznM2ZxufTJgzuZ0og7kkJJfaR1mcjmdVDlqflkc6ahSs1eUWdMzJrmQQYsSrYMJNy4raiHmYQWzD2IC2SvKLpa/dAzi8/qsc6cZBU6GLNjHlTMPcEtUJVMSdd45qRGdp7KxDOvDPu+c1JhxNMgtUZVcOfMAQxbss0K7vaLsQqbq+GCtCbEhPodOU2O58qNcZhwNsrMK4t0Xlp1VMONokCs/yqXT1FgrE7sATPvbJK0hblxWxDsnNWugvc7zcqFry3JlbomqbANzSdskpk9kFDjpOmWTpQnzne6sMgbbWWWYY8kpN0tOuYnOU1v8z9TcOyc1blxWRNcpmwwz6dLFjxr7vD5rY+eO13YSMS+Rh/co1iAby4wBluXKLDnl5rsCD1lVxk7FdwUelpxysyxXbvHcjWUwYb9CxLxE7nhtp7X10spELUHMMiHqQA6dJ+9k8KYaJh1u6ZRLTrnZklrb+hS3lURtSa1lySm39fyNZTAlUWfwpho6T95p1rqtS5LzICapJsmWNkbEBpiSqLMs1/gY3DsntfAuT4tDlkrYtci92bxzUmNjmaG9KYk6I2IDbbTStsBqjhma1EBKfiVdp2xiwNoCHt6jMOmwxjsnNev46KWUkaIksfCQk2W5Mu+c1Jh0WGPCfoUBawvoOmWT1d4Miy3nQczIuXpvJp2mxjJ4Uw0T9hsg09KM6fhcdBIxyYWXJM9FJzHjaJBpaTDpsAEzeFMNnabGGhVec+RtA1LlqAFd4vGley0Q8wZTEnWmpWGdWX3sUC3PHnW0K+b/n0qoZ1oaTEszfCQc5PGle0GXwv0k7PxI87S9EMjMMo35rvMdILPDbErrzlA4iOmw4SBh0/iXgUxLg8mnQvw9V2Zmmdau/D1XtpoxpiYe3qPw8B6FW6IqreOCvwpkWhqMinMwaFEi46PTfrFMXG38HLr6OHe8ttPykXZNYzrr4q0JdJoay4C1BS2cdfCmGuZsTrd6Hv/T5ozZJ7no9L1xWZE1fU0bD193unXx3GESFZNcyIb4nDazaUN8Dh6PkTy1O307CmgT9itM2K9YWnkuOumi26wTV6dZR43NXOXKj3LpPHknEY+us0DaDWiWnwCr92bSdcomBm+q4eE9ShsThTXh2jRn5mxOZ/CmmjYzZkRsgE5TY40Q33bhu/iiF66VcJjh604TuTfbUnnk3myGrzttQZgzZtJhzQrvfabHWGNccNELnz2tfSUcJjxADVhbwIC1BdYsMyOp+fyH9yhWGnAks/TS0gDTV4qK8q2NxU5TY7klqrIFTDhQ6+gZ/hwzdoSbpKgo/9LPj5hnR8yUwEwVw810MRkRG7BSRXPpLyrKv/RUsT2YI5mlLZLnEbEBK1q2lhGxASt5vuO1nZY5ioryL5TJX7icENwuioryjV1rr4+oAzkMWbDvouXEkAX7iDqQg8/rQ5MaLgZxaQWWJslWSWkWWBkFzl9UYP2PvgjFPNrj8/osM/2YcIQfE46QnpFmfL7K7SLocWpBj1Mz6+D0jLQWzzPb3b/6aI8SVnCbvXTTVOZxno6kqCjfKlPNUH4pIP9XPGz/N319UFnrf2iKLGi6LmggqCBoIOi6JuiqIqCrgqIrgqyrgoYu6JpiiK4LKgigCpquCCEdQdVVAU0VdP2iMGW29tplmtbcQNQ1QEXXNDQdQGsWHZBbvdQsKkTQfaiaBJrc/PyLPpQ2zqqbL9U10GV0TUbTZUCyQAoaJPaVinx5RmbVKZnVWRpf56r8WKlQFww2Q4bf8VdMXwsEtfkdGb97xSAb8yRG7df4zYYQ3deEsK2WsK1UsK1U6LIqxJWfKQzcEODVw0GS7KbG1F8Pout6C7WuL5Dpv1PBtlLEFgWXfyHTY61Ery91rvkiwLWfB7h6jcxV/5LoskLF9gl0+tjLI7FesuuxzKnrHeqneQdL143Bjacj6wqg4ZFUph8JYvusCdsXIldvhGvXi/T+SuS6dQrXrZO4fp3Ib76UuH5NiD6fi1z/mcgNnwa5epWMbbHG1StEvsoSjbeoq2i60h6MYNN1XTAhNF1vdlBoVFSG7/Nh+1Ti2o1Brl8v03uDyDVfN3DDVz5u+FKh15cKvdbp9FoHvT5X6PW5wjVr4LrPda6NkugTJdL1EwXbIpkVx5sdGaXZ8S9gGgNIJ6ipPHgghO3TED23h+ixTafXZpmb1ofos0ml+9dw1VcaV3wapMvKIF1WSVz+qULPzxV6faZw9Wc613yq0Xt1iN9Ehei+WMG2QObz03JHDtxsGk07P2XRmZ/hx7ZG5rqtMjdubqTHFonrNov8doPMZRvA9pmPqz8X+MNWhb/tkrg/VuGWaJXLPmmk85Imen6m0+sz6BMlcsNqP9etVujysU63jwIcrwy1N6UFm6Zrgma4KKBxrE7lyq999PnaT58dcMNWjV5bFa7d6sP2lcj/+szP6/FNHK2SqQtpSKqIKItUN2psyJH52yYXtkV+uq9UuP5fMj1XqVy9WuWGFSE6LQgxbHMQv6kVXW92B12wKZouSEjGNNMVJvwgYdugcGOsym+2q/TZqnD9dh3bVz5u3h4guVJtnpJa808zkJlBMMS7SQG6vB/gimUKvVdK9Fmu0nu5zLXLZGzvaWzLDhggmoysqwYIKoKqG+rKqVO5douP62JUfvutxg2xCn1iZTpv0rgpRuF0XQAIgRJElSUURUWWZWRZRpFlgrIKeIEg7yaC7X2FXkslei+XDVkmY1sQ4pFNDaA3hwcdNF0XbGjNZwNQWXZaxrZV5XexMjftFLnpW4ne34rYNvjZUywBQUJqEEkMoEk6oqIgySqipCCKEt6Qis8fRNEaAB+TtijYInV6Lwtx7VKRPstkIj5S6PGBRGFtwFCgApquCDYFTQANXZeZkiARsVPnlu9kfhcr0/cbiYivA4w94DM0oet4VQVJUQiJGiFRIiTKBEMSAX+QhoBIvU/C1SQCfpIKGrl8kZerFitcu0Tkuk9ErlsiYXtDYuMpYyobE0gVbIouC6DiDsgMiwtx406Z/rs0+u6WGPCNSI8tIZbnSoCCEvITkBRkWSMUkAgEJbz+EE2+IA3eAPUNjTR6fNTWSni9PuoFN/d8KtBpkcg1n3jp82GQ3h/6sc33seAHb/P6pYOmCTY0VQCNEkHhrgMhfrdL5k/fafT/XqT/boU+sRI/2r0AhESFYFDCF1TwBSWa/CE8TQHcjQFcDX6cdQGq63w43PWU1AoEmup4emMjtvl+enzop/d7Aa57N4Btvo/Z37jCHBzBpuqaAHDOHWDo/iD99in8+XuZO/er/H6fxsB/h0irDgGqoYGAhOAL0eALUd/oo87TRK2nCUddI3anQKXTTUl1DUVVNXga6nh2mwvb6066L3Bz3btOekU2YXtd5MVNDmuVVtEFm6brAmiUu4OMPODnjv0idx+UGHpQ4q6DEnf928+h0iCg0egN0OgXqW8MUCd4cXm81LgbqHIJlDs9lFd5KK90U1hWQ3GlgLOqlrs/rsQ2q45rFjq57q0yukc6sL3iYc62akBDR0fRNcGmq5oAQYSAyuQEibsPhnjgkMYD8T4ePOTnv/ZrfJrtBTWE4A3ibvRTJ3hx1jdRXddApbOeMoebEruL3Ao3p8vqOVVSR1JuDZkFtbywvgDb0zl0eqmanm+Wct2bFdhmlvP2Po/hH6qIrmiCTdNUAVVElTVeyfTz10My435UGHNE5JGfJIYf1ZiV4kFo8uILBKirD+LwBHC43Dhq6ymurqfAUU9ORS05RSU0NHmQVRW/JCMqOho6354U6DEri04z8+nxWim2fxSx8ZgLEAlJCqoiCzZZUwVZVECDjUVNDD8s8sRRlSmJOs8mwbPHZJ466iO2yI8aDNJU56a8tpGqaicOZx2FVfWcLa8lq7CMBn8IHfAGZQKSik/SQAoBOjEZtdiezqTTS/l0fzmPrFIBNB9CUCcoSYJN0TTBKymgS5TXBXn8pwCTj8lMT1WZmarx+nGR2Rk680+GOFleh9/bgMtZR3V1HYWVLvJKajiTV0pVjRsV8IVEgrLaLApeERSCAAx5/xS2+48zZvlZAmKIQFMTHq+PppAi2DRdFQIyyKIfRImoMz6ePO7lpUyJl08r/PN0iMjTEh9kS6zNEUgp92GvaaDAXstZh4DLG0JoChAMyviDMn5Jxi/K+EISIVnFr0h4JWPZ33a8mNteSCI6vhpZbMDhaqChyYfHHxRsmhYURBECoRDoMvkukVfTFN7IlHk7W+aDXIlVOSHW5ob4qhi2F4v8WNLIiSov5wLgkVVERSUYMqa2LyTjF1UCkkpQ1vGLImJAxCsai2SdKFJQ6aG0ooqK+gBuVxOCTxBsuq4IkqQSFCVCkgyqzg8lXt5J9/H+WViVJ7G+KMSOEoVdJSp77DJxdRrH3Rq5goLDJyMERRqCIt6QbPiHqBAQFSRJJSCrhGSZJklDUs/nIefsNRRXe3DWefE0NjUf21BURFEiGDRWVH9I5Nu8Rt7Pk/lXocbWIpFvKzT2VSr8YJdIcEqk1Svke2TsPhV3SMYTEmkISngDCr6QTFBSCUkqQUnFL2kEJUNLflFF1aGuyUepow6HuxG34DdyVkVRkCQFUVLxBWR0ScEfFPmuuIG1hTIxpSr/rpA46FBIqJHJdGmcqVPJa1Co9MrUBiTcQQlPQKYhoNAUUvCJCn5JJSApBCTZEr8oEVJU/IpKiaOOmnov9Q1+QyOqqiErGqKiIYk6/mAATQ4QalRItPvZU+EnvkrmxxqJRJdIVp1KTr1GQaNChVei2idTE9BwBRTqAzKeoEyjKNMkKvglhaCkNAMZogAeX4DS6npcDQE8jYHmM0aajqLqyLJOSNbwSTJev0woEKCxyU9OdZCEkgAJ1UGSBYWsBo3cRihq0qj0KVT5ZBwBjdqQRn1IRhBVGiWVRlklqOiIikZQ1hAV4ytjJE2n0ummqt6LU/AjNAYEm64jaBqoqo6iaEiKhiirBESVhkAQr9eH0ChSUu3nVGkdGY4mUmt8ZLoC5DWoFDUplHpVKnw6VT6ZWn+IuqCEJ6TQEFINzUgSflXFJ8nUe304XALVdQ3UNwaob/TT5A0ZILoO4TCyrBKSZHxBGcEfxNPgpdETwO32U+ZoIKesnrPlHrLtbn6urCfPXk+B3U2R3cO5qgbOVTVQUilwrkKgtEqguLKe4sp6yhwNlNg9VLkEhKYgjd4QTX6RYFA+X2Dpuo6maaiqiqqqKIqGKKn4QwrekERjIIC70YenMUBjk0S9EKK23our3ovb48Xj8SI0BfD4ROq9IdyNQeoa/Lg8AZxuPzV1PuobRASfguAN0egP4Q1KBEMykqwKNkAxMnpDNM1oSxhQGrKiI6oqTapIkyTiDYUIiDLBkEwoICOGjHghKxqKqqCoEooqEVJFgkqIkBIiKIsEpBB+MYA/FMAXkgiICiHRmK2KoilWo6bZRIKu61bjRdd1QdEQVBVBkzRBlVRBFhVBVTRBUXRBknVB1hAUECQQNF0XUHVB13RB0XRBVDRBUjRBUTVBUlRBlBRBlGQhJGuCJOuCouiCpuqCqqpl/7Eemqor5HnS2Ja/hPezpvCP1PuYlfo3vvo5EnfA0baH9qs+CKZpBIIh7DUuyuw1lNprqHDU4mnwoqoamq5xyn2YVTkv8cKJO3n+TH+eTB7Ao/H9eSr+TnbmrfyfgdiddZzKKaK0yklhuYN6oWVfvabay+6Tu3gzaSJPpPZm9E9XMmnvH1n60wKSanZypuEg35WuZlrCMLb9vPSXgzicdWTkFLX7vya5Dq/spk62s8v1AW+cu53ns29kSd6z/Fi9mZ/L8tpqVFfZeHYxBe7MSwdJy85v8Xd1oJwDFRtZlTeTD88+wcKsMSzMGsv8rL8wNbMnc7LuJN6xg6AcsF6TW1xBkzfQct9P8pDrSkfT1QuDKKrKz8UV1t+V3kKi89/m1YyhvHlyMPOz/ouFZ4fwYe59fJAzjLfO3s66wuep8p7jbF0iUTkzOe76/rzZ6jxUVteGtch06gL2C4PIikJFtcv6e3/ZeuamDOHNU//NivwxfFY8jnXlE/iyYiKflz/Eh4WD2Gv/CL/YQIJjI2+dvJvXTt7FtJS+LPt5OvVBY383KEoUlFaGzSz5wqb5ubC0WSsyG3PfZUbKnXzw8wOsKX6EdWUT+NI+nq8cY1nrGMnikjuJd0Xhld1sr3iTt37+IyuLHmZN0WMszxnPzLSBvJnxMMWNPxv7vUITLrdw8VlzMswnNud+xD+O3cGy3LF8ce5R1pZN4IuKsXzlGM0X1SP4uPJ2jgpraJAcfFb+CJHnbuOz8pF8UT6OL0om8nnRJFblPcrLaXfxxolROHzGd2idq7xIHBEavTQFQwAcLNvMP5Lu5JOcsawpmsRnJROIKnuYtVWjWVP9Vz6q7McRz0pUTSa2Zh6LSgeytOJPfGa/j3UVY1lTMoFPz01kdcEjLM95hNmp/8UHmU+j6MYnlrJyz3UMknHW0IbDW8rLyfexIGs4nxU8zqqi8Xx07gGiKkfyheN+ltnvJEFYGdYOFWlUqjniWcGK8iFElQ1jTek4Pi2awOqCR1iZ9wgfnx3Hs4l9+aHc+BqH2voGRFFqC+JpaEKSjOR2Y84iZqX8majcx1ieN57Xc+/hvXPD+aziAZaX30VGY0yH0/1s00E+KR7KquL7+ezceFbnT2BFzkSW5Uzg7VP38UbKQ3hCdc1aKWoLktHsG06/nbnJ9/H+6VGsyJnIC9l38kreMNaUPsKSkkHsdy26aABMcK3lw4L/5l9FY1mdP56lOeP55Ox4Psh+mOeT7+BAyUZj17O8qiWIKMkUlNoBOFQaw4zkQSw+M5bZp+7in7mPsKnkFVade4DPSsfTJNVeFCSk+lhbPIVl+Q+wMnccS8+OY/GZsXxwZjTTj9/OkqwXACi3O/H5A+dBKhy1lFQac33t2bf5R/KdvJnxFxadnkSyYzuf5j3BssIR/Kt4DBvLp/NF2dOsqXiSNRVPsKbyCeNnxZN8XjaFz4ufJrr4Bf5V8Agr8h5iWc5YPs4ey4enR/P+6YeYnfZn3kh9CAUfqgz2Gtd5kLOFpZTYjUMHH516jmlJA3jjxHCO2XexteBtFpwZyqqC0awo+huLCv7Eu4W38V7x73mvtD/vl/Xl/bJ+vFfye94tuo2F+X/g3dw/szT/b6zIHcMnZ0fz0ZmHWXT6ISKzRvJq5mBeSh5MSeNZyzyyrBggWTlFlNsNssiMKYz9oQe7i/9FmmM/r6bezZKfx7Is5yGW5f+NFYUjWHXuflaXDmN12V+JKhtGVNkwVpX9lZXFw1lRNILl+Q/ySc6DfHRmFIuyRhF5ciRvZ/6NNzPvZ3baIJ5N+AM/1xsfXcg9V47XH2wLMidpFE/9eAcVQg7Lsp7j9fShfHTmIT4+M4rIrKG8ljGAeSf78eaZfszP7sc/z/bln9n9mH+mH29m9eO1jP7MPfF7ZibfxvSE3zP1UD+eiruVxw/cxIT9fRj+764Mje3M6bqjAOQVl+MPhgyQvHPllFQapnkhfgRf5y7haNV3PJvwe945+QDvnnyAf2bcQ0zR22S7fySzbj+Z7n2cdO/jZP1eTtbvI9O9j8y6fWS49pHm3Edq9T6OV+0luXIPRyt2k1C+i/jybzhYupUfSrfjV40wX1zhQNN0A8RR66bEbjjr5p+Xc9IRz9snJvJ88h94O/N+3s64j1dS7mJLXuT/v0e/vT6qa93nnVXXdXLOlRtJi6qSWLmL8Yd682rGvcxLG8qbJ4byRuoQXj56L+UNuRcdoDHk5kDJNvaXbuZA2Rb2l21hX9nX7C3byNaCKJKr4pqnbw3+QLBlQDttxn4dPsh4hseP3sjcjP/m5dRBvJYymNdTBjMtvh8rT865KMja0wsZvqsr4/f3ZNyBnjx88CpGxV3BiAM2bt5iY8PPKwz/KKlsG1lDooTgCRJAYPKR/jyb2pcZaQOZdfyPzDn+J145/l/MSfojU364lW05yzuE2F30FU/80JcZSQN5+fifmH38Tmam3MGM1Dt4LOE6pv90DyHFCGLZ+SXtL3pn88rJCR5hbPy1TEq6jqnJv2XGsduZdfwPzD52By8n/5FZSX9g8sGbeDflGU7VHMUTqKMhVM/Z2hMsSZ/JY3G38I/E25l77I/MOv4HZhy/nRkptzE1+Rbu+beNhMrvjLEKSi+cj0T+8AaPZfTi2eQ/8Gj89fz96C3MSB7AjOTfMzPpNmYn3c7MowN4/IdrmXKoPy8l3MtLP/2Fpw7fxiMHr+HFxH7MTrqNmUm/56XkAbyY3I/pyb/jr/tsRJ542hqnOGydaRdkxv6J/DXBxvflX/Fd0Rru2W3jmYTrmZnUnxlJ/ZhxtB+zjg5g1tH+vJBwM1Pjr+fZ+Ot5PuFmZiX2Y9ZR43kvJfXlpeR+PJ90M3/da2Nm4gME5MZ2c5F2QV5OeYA/7rZxrOYgANE/f8S933ViTFxXZiX1ZfbRvsxK7MusxFuZnXgrs8JkZuKtzEi8lZlHf8espL48Gd+Lu3fbeDVpLA1BY+kvc7T7ZTktQUQlyLQjg/nzv20cyo+zrsdX7OKR/bcybLeNp368hpd+uok5ib9lbuKtzfI75ib+jtmJv2PGT7fwfMJveOj7zty/O4JPs+YjKsYUdTc04Wloav/YRusLz/04lAeTIsgsPENewfnc0is1EH32Qx47MICH913F+O//F+O/t/H4wW7877gIHtnfhXHfd2Hs91cyZl9v3k19lgLPaev15TV1NDR6Oz4/0vrC26ceYVhcL45X/GB4d2Eljf7Q+cJI9pHqiGPVqVeZd+wRZicOZ0bCvbyS9DAfpD3PnnNfUuO3ny9NVI2T+eVI8oVPGrUB2ZsfzX1HehJTtMK6FgyJZOYW0+gXf1EIz8wro9LhvKTn2lrugkMoFOS5n/7C0APXYK8tb3GepMrh5HB8Cmknz5JbXEpBSQVlFbVU2N0UlVWRW1RK1s95/JCQzMkzPyPLMpqm4ff7CQQChEIhJElCURQ0TcPsVOm6fn6tCT+oUOkq4bGE27n/qzv4KeMIwVCQQCBAbV0ttXW1VFRWkJ19lrS0DJKSj5F4NInk5OOcPHmK/Px8amtrcbvd1NTU4HQ6cbvdNDU1WTCyLKOqaguYDmvfgNzE4bIYdpWv4UT5EezuMkQl9B877PT/DQC7cLwx8LR3hQAAAABJRU5ErkJggg==) no-repeat;padding-left:40px} + .browser .browser-firefox{background-position:0 -34px} + .browser .browser-ie{background-position:0 -68px;margin-left:0px} + .browser .browser-360{background-position:0 -170px;margin-left: -27px} + </style> +</head> +<body style="margin-top:50px"> +<h1>璇峰崌绾ф偍鐨勬祻瑙堝櫒锛屼互渚挎垜浠洿濂界殑涓烘偍鎻愪緵鏈嶅姟锛�</h1> +<p>鎮ㄦ鍦ㄤ娇鐢� Internet Explorer 鐨勬棭鏈熺増鏈紙IE11浠ヤ笅鐗堟湰鎴栦娇鐢ㄨ鍐呮牳鐨勬祻瑙堝櫒锛夈�傝繖鎰忓懗鐫�鍦ㄥ崌绾ф祻瑙堝櫒鍓嶏紝鎮ㄥ皢鏃犳硶璁块棶姝ょ綉绔欍��</p> +<hr> +<h2>璇锋敞鎰忥細寰蒋鍏徃瀵筗indows XP 鍙� Internet Explorer 鏃╂湡鐗堟湰鐨勬敮鎸佸凡缁忕粨鏉�</h2> +<p>鑷� 2016 骞� 1 鏈� 12 鏃ヨ捣锛孧icrosoft 涓嶅啀涓� IE 11 浠ヤ笅鐗堟湰鎻愪緵鐩稿簲鏀寔鍜屾洿鏂般�傛病鏈夊叧閿殑娴忚鍣ㄥ畨鍏ㄦ洿鏂帮紝鎮ㄧ殑鐢佃剳鍙兘鏄撳彈鏈夊鐥呮瘨銆侀棿璋嶈蒋浠跺拰鍏朵粬鎭舵剰杞欢鐨勬敾鍑伙紝瀹冧滑鍙互绐冨彇鎴栨崯瀹虫偍鐨勪笟鍔℃暟鎹拰淇℃伅銆傝鍙傞槄 <a href="https://www.microsoft.com/zh-cn/WindowsForBusiness/End-of-IE-support">寰蒋瀵� Internet Explorer 鏃╂湡鐗堟湰鐨勬敮鎸佸皢浜� 2016 骞� 1 鏈� 12 鏃ョ粨鏉熺殑璇存槑</a> 銆�</p> +<hr> +<h2>鎮ㄥ彲浠ラ�夋嫨鏇村厛杩涚殑娴忚鍣�</h2> +<p>鎺ㄨ崘浣跨敤浠ヤ笅娴忚鍣ㄧ殑鏈�鏂扮増鏈�傚鏋滄偍鐨勭數鑴戝凡鏈変互涓嬫祻瑙堝櫒鐨勬渶鏂扮増鏈垯鐩存帴浣跨敤璇ユ祻瑙堝櫒璁块棶鍗冲彲銆�</p> +<ul class="browser"> + <li class="browser-chrome"><a href="https://www.google.cn/chrome/browser/desktop/index.html?hl=zh-CN&standalone=1"> 璋锋瓕娴忚鍣�<span>Google Chrome</span></a></li> + <li class="browser-firefox"><a href="https://www.mozilla.org/zh-CN/firefox/new/"> 鐏嫄娴忚鍣�<span>Mozilla Firefox</span></a></li> + <li class="browser-ie"><a href="https://windows.microsoft.com/zh-cn/internet-explorer/download-ie"> IE 11 娴忚鍣�<span>Internet Explorer</span></a></li> + <li class="browser-360"><a href="http://se.360.cn/"> 360瀹夊叏娴忚鍣�<span>360 Chrome</span></a></li> + <div class="clean"></div> +</ul> +<hr> +</body> +</html> \ No newline at end of file diff --git a/public/index.html b/public/index.html new file mode 100644 index 0000000..28533a4 --- /dev/null +++ b/public/index.html @@ -0,0 +1,209 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> + <meta name="renderer" content="webkit"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> + <link rel="icon" href="<%= BASE_URL %>favicon.ico"> + <title><%= webpackConfig.name %></title> + <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> + <style> + html, + body, + #app { + height: 100%; + margin: 0px; + padding: 0px; + } + .chromeframe { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; + } + + #loader-wrapper { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + } + + #loader { + display: block; + position: relative; + left: 50%; + top: 50%; + width: 150px; + height: 150px; + margin: -75px 0 0 -75px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #FFF; + -webkit-animation: spin 2s linear infinite; + -ms-animation: spin 2s linear infinite; + -moz-animation: spin 2s linear infinite; + -o-animation: spin 2s linear infinite; + animation: spin 2s linear infinite; + z-index: 1001; + } + + #loader:before { + content: ""; + position: absolute; + top: 5px; + left: 5px; + right: 5px; + bottom: 5px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #FFF; + -webkit-animation: spin 3s linear infinite; + -moz-animation: spin 3s linear infinite; + -o-animation: spin 3s linear infinite; + -ms-animation: spin 3s linear infinite; + animation: spin 3s linear infinite; + } + + #loader:after { + content: ""; + position: absolute; + top: 15px; + left: 15px; + right: 15px; + bottom: 15px; + border-radius: 50%; + border: 3px solid transparent; + border-top-color: #FFF; + -moz-animation: spin 1.5s linear infinite; + -o-animation: spin 1.5s linear infinite; + -ms-animation: spin 1.5s linear infinite; + -webkit-animation: spin 1.5s linear infinite; + animation: spin 1.5s linear infinite; + } + + + @-webkit-keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + @keyframes spin { + 0% { + -webkit-transform: rotate(0deg); + -ms-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + -ms-transform: rotate(360deg); + transform: rotate(360deg); + } + } + + + #loader-wrapper .loader-section { + position: fixed; + top: 0; + width: 51%; + height: 100%; + background: #7171C6; + z-index: 1000; + -webkit-transform: translateX(0); + -ms-transform: translateX(0); + transform: translateX(0); + } + + #loader-wrapper .loader-section.section-left { + left: 0; + } + + #loader-wrapper .loader-section.section-right { + right: 0; + } + + + .loaded #loader-wrapper .loader-section.section-left { + -webkit-transform: translateX(-100%); + -ms-transform: translateX(-100%); + transform: translateX(-100%); + -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); + transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); + } + + .loaded #loader-wrapper .loader-section.section-right { + -webkit-transform: translateX(100%); + -ms-transform: translateX(100%); + transform: translateX(100%); + -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); + transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000); + } + + .loaded #loader { + opacity: 0; + -webkit-transition: all 0.3s ease-out; + transition: all 0.3s ease-out; + } + + .loaded #loader-wrapper { + visibility: hidden; + -webkit-transform: translateY(-100%); + -ms-transform: translateY(-100%); + transform: translateY(-100%); + -webkit-transition: all 0.3s 1s ease-out; + transition: all 0.3s 1s ease-out; + } + + .no-js #loader-wrapper { + display: none; + } + + .no-js h1 { + color: #222222; + } + + #loader-wrapper .load_title { + font-family: 'Open Sans'; + color: #FFF; + font-size: 19px; + width: 100%; + text-align: center; + z-index: 9999999999999; + position: absolute; + top: 60%; + opacity: 1; + line-height: 30px; + } + + #loader-wrapper .load_title span { + font-weight: normal; + font-style: italic; + font-size: 13px; + color: #FFF; + opacity: 0.5; + } + </style> + </head> + <body> + <div id="app"> + <div id="loader-wrapper"> + <div id="loader"></div> + <div class="loader-section section-left"></div> + <div class="loader-section section-right"></div> + <div class="load_title">姝e湪鍔犺浇绯荤粺璧勬簮锛岃鑰愬績绛夊緟</div> + </div> + </div> + </body> + <script src="./config.js"></script> +</html> diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..77470cb --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: / \ No newline at end of file diff --git "a/public/\344\277\235\351\232\234\351\234\200\346\261\202\346\250\241\346\235\277.xls" "b/public/\344\277\235\351\232\234\351\234\200\346\261\202\346\250\241\346\235\277.xls" new file mode 100644 index 0000000..af694c0 --- /dev/null +++ "b/public/\344\277\235\351\232\234\351\234\200\346\261\202\346\250\241\346\235\277.xls" Binary files differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..29de49f --- /dev/null +++ b/src/App.vue @@ -0,0 +1,28 @@ +<template> + <div id="app"> + <router-view /> + <theme-picker /> + </div> +</template> + +<script> +import ThemePicker from "@/components/ThemePicker"; + +export default { + name: "App", + components: { ThemePicker }, + metaInfo() { + return { + title: this.$store.state.settings.dynamicTitle && this.$store.state.settings.title, + titleTemplate: title => { + return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE + } + } + } +}; +</script> +<style scoped> +#app .theme-picker { + display: none; +} +</style> diff --git a/src/api/login.js b/src/api/login.js new file mode 100644 index 0000000..649f59c --- /dev/null +++ b/src/api/login.js @@ -0,0 +1,59 @@ +import request from '@/utils/request' + +// 鐧诲綍鏂规硶 +export function login(username, password, code, uuid) { + const data = { + username, + password, + code, + uuid + } + return request({ + url: '/login', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 娉ㄥ唽鏂规硶 +export function register(data) { + return request({ + url: '/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 鑾峰彇鐢ㄦ埛璇︾粏淇℃伅 +export function getInfo() { + return request({ + url: '/getInfo', + method: 'get' + }) +} + +// 閫�鍑烘柟娉� +export function logout() { + return request({ + url: '/logout', + method: 'post' + }) +} + +// 鑾峰彇楠岃瘉鐮� +export function getCodeImg() { + return request({ + url: '/captchaImage', + headers: { + isToken: false + }, + method: 'get', + timeout: 20000 + }) +} \ No newline at end of file diff --git a/src/api/manage/Untitled-1.json b/src/api/manage/Untitled-1.json new file mode 100644 index 0000000..63a5501 --- /dev/null +++ b/src/api/manage/Untitled-1.json @@ -0,0 +1,37 @@ +{ + "pie": { + "metaData": 1111, + "resultData": 12 + }, + "line": { + "date": [ + "2025-04-11", + "2025-04-12" + ], + "insert": [ + 10, + 10 + ], + "update": [ + 10, + 10 + ], + "read": [ + 10, + 10 + ], + "delete": [ + 10, + 10 + ] + }, + "swipe": [ + { + "username": "admin", + "ip": "192.168.0.4", + "operType": "鍒犻櫎", + "number": "9", + "operTime": "2025-04-12 12:00:30" + } + ] +} \ No newline at end of file diff --git a/src/api/manage/assess.js b/src/api/manage/assess.js new file mode 100644 index 0000000..7c3c653 --- /dev/null +++ b/src/api/manage/assess.js @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +// 鏌ヨ鏁堣兘璇勪及鎸囨爣淇℃伅鍒楄〃锛堝垎椤碉級 +export function getAssessList(data) { + return request({ + url: '/dp/dpEffectAssessList/list', + method: 'POST', + data + // params: data + }) +} + +// 鏌ヨ鏁堣兘璇勪及鎸囨爣 +export function getAssessItem(pkid) { + return request({ + url: '/dp/dpEffectAssessList/' + pkid, + method: 'get' + }) +} + + +// 鏂板鏁堣兘璇勪及鎸囨爣 +export function addAssessItem(data) { + return request({ + url: '/dp/dpEffectAssessList', + method: 'post', + data + }) +} + +// 淇敼鏁堣兘璇勪及鎸囨爣 +export function updateAssessItem(data) { + return request({ + url: '/dp/dpEffectAssessList', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鏁堣兘璇勪及鎸囨爣 +export function delAssessItem(pkid) { + return request({ + url: '/dp/dpEffectAssessList/' + pkid, + method: 'delete' + }) +} diff --git a/src/api/manage/berth.js b/src/api/manage/berth.js new file mode 100644 index 0000000..53304e8 --- /dev/null +++ b/src/api/manage/berth.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 鏌ヨ鐮佸ご-娉婁綅鍒嗛〉鍒楄〃 +export function listBerth(query) { + return request({ + url: '/dp/dpBerth/pageList', + method: 'get', + params: query + }) +} + +// 鏌ヨ鐮佸ご-娉婁綅鍒楄〃 +export function beList(whId) { + return request({ + url: '/dp/dpBerth/list?whId='+whId, + method: 'get' + }) +} + +// 鏌ヨ鐮佸ご-娉婁綅璇︾粏 +export function getBerth(beId) { + return request({ + url: '/dp/dpBerth/' + beId, + method: 'get' + }) +} + +// 鏂板鐮佸ご-娉婁綅 +export function addBerth(data) { + return request({ + url: '/dp/dpBerth', + method: 'post', + data: data + }) +} + +// 淇敼鐮佸ご-娉婁綅 +export function updateBerth(data) { + return request({ + url: '/dp/dpBerth', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鐮佸ご-娉婁綅 +export function delBerth(beId) { + return request({ + url: '/dp/dpBerth/' + beId, + method: 'delete' + }) +} diff --git a/src/api/manage/clean.js b/src/api/manage/clean.js new file mode 100644 index 0000000..25eded3 --- /dev/null +++ b/src/api/manage/clean.js @@ -0,0 +1,28 @@ +import request from '@/utils/request' + + +export function getCount(params) { + return request({ + url: '/dp/receiveInfoFinal/queryCount', + method: 'get', + params + }) +} + +export function getLineData(params) { + return request({ + url: '/dp/receiveInfoFinal/selectDailyData', + method: 'get', + params + }) +} + +export function getOperList(data) { + return request({ + url: '/dp/receiveInfoFinal/selectData', + method: 'post', + data + }) +} + + diff --git a/src/api/manage/device.js b/src/api/manage/device.js new file mode 100644 index 0000000..17f3325 --- /dev/null +++ b/src/api/manage/device.js @@ -0,0 +1,55 @@ +import request from '@/utils/request' + +// 鏌ヨ鑸拌墖璁惧鍒楄〃 +export function listDevice(query) { + return request({ + url: '/dp/dpShipDevice/getDpShipDevicesPage', + method: 'get', + params: query + }) +} + +// 鏌ヨ鑸拌墖璁惧璇︾粏 +export function getDevice(ID) { + return request({ + url: '/dp/dpShipDevice/getDpShipDeviceByID?id=' + ID, + method: 'get' + }) +} + +// selectDpShipDeviceByShipId + +// 鏌ヨ鑸拌墖璁惧璇︾粏 +export function getDeviceList(deviceShipId) { + return request({ + url: '/dp/dpShipDevice/selectDpShipDeviceByShipId?deviceShipId=' + deviceShipId, + method: 'get' + }) +} + + +// 鏂板鑸拌墖璁惧 +export function addDevice(data) { + return request({ + url: '/dp/dpShipDevice/insertDpShipDevice', + method: 'post', + data: data + }) +} + +// 淇敼鑸拌墖璁惧 +export function updateDevice(data) { + return request({ + url: '/dp/dpShipDevice/updateDpShipDevice', + method: 'post', + data: data + }) +} + +// 鍒犻櫎鑸拌墖璁惧 +export function delDevice(ID) { + return request({ + url: '/dp/dpShipDevice/deleteDpShipDevice?id=' + ID, + method: 'get' + }) +} diff --git a/src/api/manage/dsTask.js b/src/api/manage/dsTask.js new file mode 100644 index 0000000..d57e379 --- /dev/null +++ b/src/api/manage/dsTask.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' + +// 鏌ヨ琛ョ粰闇�姹備换鍔′俊鎭垪琛� +export function dsTaskList(query) { + return request({ + url: '/dp/dsTaskList/pageList', + method: 'get', + params: query + }) +} + +// 鏌ヨ琛ョ粰闇�姹備换鍔′俊鎭缁� +export function getDsTask(pkid) { + return request({ + url: '/dp/dsTaskList/' + pkid, + method: 'get' + }) +} + + +// 缇ょ粍鏂板淇濋殰闇�姹備俊鎭� +export function addDsTask(data) { + return request({ + url: '/dp/dsTaskList', + method: 'post', + data: data + }) +} + + +// 淇敼淇濋殰闇�姹備俊鎭� +export function updateDsTask(data) { + return request({ + url: '/dp/dsTaskList', + method: 'put', + data: data + }) +} + +// 鍒犻櫎淇濋殰闇�姹� +export function delDsTask(pkid) { + return request({ + url: '/dp/dsTaskList/' + pkid, + method: 'delete' + }) +} +// 鏃ュ父鏌ヨ +export function getDailyTask(query) { + return request({ + url: '/dp/dsTaskList/pageListDaily', + method: 'get', + params: query + }) +} + +// 鏃ュ父鏂板 +export function addDailyTask(query, data) { + return request({ + url: '/dp/dsTaskList/dailyAdd', + method: 'post', + params: query, + data: data, + }) +} +// 鏃ュ父鍒犻櫎 +export function delDailyTask(pkid) { + return request({ + url: '/dp/dsTaskList/deleteDaily/' + pkid, + method: 'delete' + }) +} diff --git a/src/api/manage/equRes.js b/src/api/manage/equRes.js new file mode 100644 index 0000000..52c96fb --- /dev/null +++ b/src/api/manage/equRes.js @@ -0,0 +1,85 @@ +import request from '@/utils/request' + +// 鏌ヨ娉婁綅--璁惧鍒嗛〉鍒楄〃 +export function listEquipment(query) { + return request({ + url: '/dp/dpEquipment/pageList', + method: 'get', + params: query + }) +} +// 鏌ヨ娉婁綅--璁惧鍒楄〃 +export function equList(beId) { + return request({ + url: '/dp/dpEquipment/list?beId=' + beId, + method: 'get' + }) +} + +// 璁惧鍒楄〃--鏍戠粨鏋� +export function equTree() { + return request({ + url: '/dp/dpEquipment/getListByWhId', + method: 'get' + }) +} + +// 璁惧--鏁版嵁鍒嗛〉鑾峰彇鍒楄〃 +export function dataPageList(data) { + return request({ + url: '/dp/receiveInfoFinal/getPageListByIdRuoyi', + method: 'post', + data: data + }) +} + +// 璁惧--鏁版嵁鍒楄〃 +export function dataList(data) { + return request({ + url: '/dp/dpEquipment/getDataById', + method: 'post', + data: data + }) +} + +// 鏌ヨ娉婁綅--璁惧璇︾粏 +export function getEquipment(id) { + return request({ + url: '/dp/dpEquipment/' + id, + method: 'get' + }) +} +// 鏌ヨ鑺傜偣鎵�灞炵被鍨� +export function getEquTypeByid(id) { + return request({ + url: '/dp/receiveInfoFinal/getUrl?equId=' + id, + method: 'get' + }) +} + +// // 鏂板 +// export function addEquipment(data) { +// return request({ +// url: '/dp/dpEquipment', +// method: 'post', +// data: data +// }) +// } + +// 淇敼 +export function updateResData(url, data) { + return request({ + url: `/dp/${url}/updateDate`, + method: 'post', + data: data + }) +} + +// 鍒犻櫎 +export function delResData(url, data) { + return request({ + url: `/dp/${url}/deleteBatch`, + method: 'post', + data: data + }) +} diff --git a/src/api/manage/equType.js b/src/api/manage/equType.js new file mode 100644 index 0000000..f562103 --- /dev/null +++ b/src/api/manage/equType.js @@ -0,0 +1,62 @@ +import request from '@/utils/request' + + +//鑾峰彇鎵�鏈夌殑璁惧绫诲瀷鍒楄〃 +export function getAllEquype(){ + return request({ + url: '/dp/dpEquipmentType/list', + method: 'get' + }) +} + + +// 鏌ヨ璁惧绫诲瀷鍒嗛〉鍒楄〃 +export function listEquipment(query) { + return request({ + url: '/dp/dpEquipmentType/pageList', + method: 'get', + params: query + }) +} +// 鏌ヨ璁惧绫诲瀷鍒楄〃 +export function equList(beId) { + return request({ + url: '/dp/dpEquipment/list?beId='+beId, + method: 'get' + }) +} + + +// 鏌ヨ璁惧绫诲瀷 +export function getEquipment(id) { + return request({ + url: '/dp/dpEquipmentType/' + id, + method: 'get' + }) +} + +// 鏂板璁惧绫诲瀷 +export function addEquipment(data) { + return request({ + url: '/dp/dpEquipmentType', + method: 'post', + data: data + }) +} + +// 淇敼璁惧绫诲瀷 +export function updateEquipment(data) { + return request({ + url: '/dp/dpEquipmentType', + method: 'put', + data: data + }) +} + +// 鍒犻櫎璁惧绫诲瀷 +export function delEquipment(ID) { + return request({ + url: '/dp/dpEquipmentType/' + ID, + method: 'delete' + }) +} diff --git a/src/api/manage/equipment.js b/src/api/manage/equipment.js new file mode 100644 index 0000000..748949e --- /dev/null +++ b/src/api/manage/equipment.js @@ -0,0 +1,91 @@ +import request from '@/utils/request' + +// 鏌ヨ娉婁綅--璁惧鍒嗛〉鍒楄〃 +export function listEquipment(query) { + return request({ + url: '/dp/dpEquipment/pageList', + method: 'get', + params: query + }) +} +// 鏌ヨ娉婁綅--璁惧鍒楄〃 +export function equList(beId) { + return request({ + url: '/dp/dpEquipment/list?beId=' + beId, + method: 'get' + }) +} + +// 璁惧鍒楄〃--鏍戠粨鏋� +export function equTree() { + return request({ + url: '/dp/dpEquipment/getListByWhId', + method: 'get' + }) +} + +// 璁惧--鏁版嵁鍒嗛〉鑾峰彇鍒楄〃 +export function dataPageList(data) { + return request({ + url: '/dp/dpEquipment/getPageListByIdRuoyi', + method: 'post', + data: data + }) +} + +// 璁惧--鏁版嵁鍒楄〃 +export function dataList(data) { + return request({ + url: '/dp/dpEquipment/getDataById', + method: 'post', + data: data + }) +} + +// 鏌ヨ娉婁綅--璁惧璇︾粏 +export function getEquipment(id) { + return request({ + url: '/dp/dpEquipment/' + id, + method: 'get' + }) +} +// 鏌ヨ鑺傜偣鎵�灞炵被鍨� +export function getEquTypeByid(id) { + return request({ + url: '/dp/receiveInfoFinal/getUrl?equId=' + id, + method: 'get' + }) +} +// 鏁版嵁娓呮礂-鏂板鏁版嵁 +export function addEquRes(url, data) { + return request({ + url: `/dp/${url}/saveBatch`, + method: 'post', + data: data + }) +} +// 鏂板娉婁綅--璁惧 +export function addEquipment(data) { + return request({ + url: '/dp/dpEquipment', + method: 'post', + data: data + }) +} + +// 淇敼娉婁綅--璁惧 +export function updateEquipment(data) { + return request({ + url: '/dp/dpEquipment', + method: 'put', + data: data + }) +} + +// 鍒犻櫎娉婁綅--璁惧 +export function delEquipment(ID) { + return request({ + url: '/dp/dpEquipment/' + ID, + method: 'delete' + }) +} diff --git a/src/api/manage/shipType.js b/src/api/manage/shipType.js new file mode 100644 index 0000000..4c9d15c --- /dev/null +++ b/src/api/manage/shipType.js @@ -0,0 +1,55 @@ +import request from '@/utils/request' + +// 鏌ヨ鑸拌墖绫诲瀷鍒嗛〉鍒楄〃 +export function listSipType(query) { + return request({ + url: '/dp/dpShipType/pageList', + method: 'get', + params: query + }) +} + +// 鏌ヨ鎵�鏈夎埌鑹囩被鍨嬪垪琛� +export function listAlldpShipTypeList(query) { + return request({ + url: '/dp/dpShipType/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ璁惧绫诲瀷璇︾粏 +export function getdpShipType(ID) { + return request({ + url: '/dp/dpShipType/' + ID, + method: 'get' + }) +} + + + +// 鏂板鑸拌墖绫诲瀷 +export function adddpShipType(data) { + return request({ + url: '/dp/dpShipType', + method: 'post', + data: data + }) +} + +// 淇敼鑸拌墖绫诲瀷 +export function updatedpShipType(data) { + return request({ + url: '/dp/dpShipType', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鑸拌墖绫诲瀷 +export function deldpShipType(ID) { + return request({ + url: '/dp/dpShipType/' + ID, + method: 'delete' + }) +} diff --git a/src/api/manage/ships.js b/src/api/manage/ships.js new file mode 100644 index 0000000..38b9940 --- /dev/null +++ b/src/api/manage/ships.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 鏌ヨ鑸拌埞鍒嗛〉鍒楄〃 +export function listShips(query) { + return request({ + url: '/dp/dpShips/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ鑸拌埞鍒楄〃 +export function shipList() { + return request({ + url: '/dp/dpShips/getDpShips', + method: 'get' + }) +} + +// 鏌ヨ鑸拌埞璇︾粏 +export function getShips(ID) { + return request({ + url: '/dp/dpShips/' + ID, + method: 'get' + }) +} + +// 鏂板鑸拌埞 +export function addShips(data) { + return request({ + url: '/dp/dpShips/insertDpShip', + method: 'post', + data: data + }) +} + +// 淇敼鑸拌埞 +export function updateShips(data) { + return request({ + url: '/dp/dpShips/updateDpShip', + method: 'post', + data: data + }) +} + +// 鍒犻櫎鑸拌埞 +export function delShips(id) { + return request({ + url: '/dp/dpShips/deleteDpShip?id=' + id, + method: 'get' + }) +} diff --git a/src/api/manage/stock.js b/src/api/manage/stock.js new file mode 100644 index 0000000..ec4db62 --- /dev/null +++ b/src/api/manage/stock.js @@ -0,0 +1,53 @@ +import request from '@/utils/request' + +// 鏌ヨ娓彛淇℃伅鍒楄〃 +export function listHarbor(query) { + return request({ + url: '/dp/harbor/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ娓彛淇℃伅璇︾粏 +export function getHarbor(pkId) { + return request({ + url: '/dp/harbor/' + pkId, + method: 'get' + }) +} + + +// 鏌ヨ娓彛淇℃伅璇︾粏 +export function listAll() { + return request({ + url: '/dp/harbor/listAll', + method: 'get' + }) +} + +// 鏂板娓彛淇℃伅 +export function addHarbor(data) { + return request({ + url: '/dp/harbor', + method: 'post', + data: data + }) +} + +// 淇敼娓彛淇℃伅 +export function updateHarbor(data) { + return request({ + url: '/dp/harbor', + method: 'put', + data: data + }) +} + +// 鍒犻櫎娓彛淇℃伅 +export function delHarbor(pkId) { + return request({ + url: '/dp/harbor/' + pkId, + method: 'delete' + }) +} diff --git a/src/api/manage/supplement.js b/src/api/manage/supplement.js new file mode 100644 index 0000000..64f3ee6 --- /dev/null +++ b/src/api/manage/supplement.js @@ -0,0 +1,45 @@ +import request from '@/utils/request' + +export function listsupplement(query) { + return request({ + url: '/dp/dpUnitSupplyTime/pageList', + method: 'get', + params: query + }) +} + + + +// 鏌ヨ璇︾粏 +export function getsupplement(ID) { + return request({ + url: '/dp/dpUnitSupplyTime/' + ID, + method: 'get' + }) +} + +// 鏂板 +export function addsupplement(data) { + return request({ + url: '/dp/dpUnitSupplyTime', + method: 'post', + data: data + }) +} + +// 淇敼 +export function updatesupplement(data) { + return request({ + url: '/dp/dpUnitSupplyTime', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鑸拌埞 +export function delsupplement(id) { + return request({ + url: '/dp/dpUnitSupplyTime/' + id, + method: 'delete' + }) +} diff --git a/src/api/manage/wharf.js b/src/api/manage/wharf.js new file mode 100644 index 0000000..2f0e934 --- /dev/null +++ b/src/api/manage/wharf.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 鏌ヨ鐮佸ご鍒嗛〉鍒楄〃 +export function listWharf(query) { + return request({ + url: '/dp/dpWharf/pageList', + method: 'get', + params: query + }) +} + +// 鏌ヨ鐮佸ご鍒楄〃 +export function list() { + return request({ + url: '/dp/dpWharf/list', + method: 'get' + }) +} + +// 鏌ヨ鐮佸ご璇︾粏 +export function getWharf(whId) { + return request({ + url: '/dp/dpWharf/' + whId, + method: 'get' + }) +} + +// 鏂板鐮佸ご +export function addWharf(data) { + return request({ + url: '/dp/dpWharf', + method: 'post', + data: data + }) +} + +// 淇敼鐮佸ご +export function updateWharf(data) { + return request({ + url: '/dp/dpWharf', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鐮佸ご +export function delWharf(whId) { + return request({ + url: '/dp/dpWharf/' + whId, + method: 'delete' + }) +} diff --git a/src/api/menu.js b/src/api/menu.js new file mode 100644 index 0000000..faef101 --- /dev/null +++ b/src/api/menu.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 鑾峰彇璺敱 +export const getRouters = () => { + return request({ + url: '/getRouters', + method: 'get' + }) +} \ No newline at end of file diff --git a/src/api/monitor/cache.js b/src/api/monitor/cache.js new file mode 100644 index 0000000..72c5f6a --- /dev/null +++ b/src/api/monitor/cache.js @@ -0,0 +1,57 @@ +import request from '@/utils/request' + +// 鏌ヨ缂撳瓨璇︾粏 +export function getCache() { + return request({ + url: '/monitor/cache', + method: 'get' + }) +} + +// 鏌ヨ缂撳瓨鍚嶇О鍒楄〃 +export function listCacheName() { + return request({ + url: '/monitor/cache/getNames', + method: 'get' + }) +} + +// 鏌ヨ缂撳瓨閿悕鍒楄〃 +export function listCacheKey(cacheName) { + return request({ + url: '/monitor/cache/getKeys/' + cacheName, + method: 'get' + }) +} + +// 鏌ヨ缂撳瓨鍐呭 +export function getCacheValue(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey, + method: 'get' + }) +} + +// 娓呯悊鎸囧畾鍚嶇О缂撳瓨 +export function clearCacheName(cacheName) { + return request({ + url: '/monitor/cache/clearCacheName/' + cacheName, + method: 'delete' + }) +} + +// 娓呯悊鎸囧畾閿悕缂撳瓨 +export function clearCacheKey(cacheKey) { + return request({ + url: '/monitor/cache/clearCacheKey/' + cacheKey, + method: 'delete' + }) +} + +// 娓呯悊鍏ㄩ儴缂撳瓨 +export function clearCacheAll() { + return request({ + url: '/monitor/cache/clearCacheAll', + method: 'delete' + }) +} diff --git a/src/api/monitor/job.js b/src/api/monitor/job.js new file mode 100644 index 0000000..3815569 --- /dev/null +++ b/src/api/monitor/job.js @@ -0,0 +1,71 @@ +import request from '@/utils/request' + +// 鏌ヨ瀹氭椂浠诲姟璋冨害鍒楄〃 +export function listJob(query) { + return request({ + url: '/monitor/job/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ瀹氭椂浠诲姟璋冨害璇︾粏 +export function getJob(jobId) { + return request({ + url: '/monitor/job/' + jobId, + method: 'get' + }) +} + +// 鏂板瀹氭椂浠诲姟璋冨害 +export function addJob(data) { + return request({ + url: '/monitor/job', + method: 'post', + data: data + }) +} + +// 淇敼瀹氭椂浠诲姟璋冨害 +export function updateJob(data) { + return request({ + url: '/monitor/job', + method: 'put', + data: data + }) +} + +// 鍒犻櫎瀹氭椂浠诲姟璋冨害 +export function delJob(jobId) { + return request({ + url: '/monitor/job/' + jobId, + method: 'delete' + }) +} + +// 浠诲姟鐘舵�佷慨鏀� +export function changeJobStatus(jobId, status) { + const data = { + jobId, + status + } + return request({ + url: '/monitor/job/changeStatus', + method: 'put', + data: data + }) +} + + +// 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆� +export function runJob(jobId, jobGroup) { + const data = { + jobId, + jobGroup + } + return request({ + url: '/monitor/job/run', + method: 'put', + data: data + }) +} \ No newline at end of file diff --git a/src/api/monitor/jobLog.js b/src/api/monitor/jobLog.js new file mode 100644 index 0000000..6e0be61 --- /dev/null +++ b/src/api/monitor/jobLog.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 鏌ヨ璋冨害鏃ュ織鍒楄〃 +export function listJobLog(query) { + return request({ + url: '/monitor/jobLog/list', + method: 'get', + params: query + }) +} + +// 鍒犻櫎璋冨害鏃ュ織 +export function delJobLog(jobLogId) { + return request({ + url: '/monitor/jobLog/' + jobLogId, + method: 'delete' + }) +} + +// 娓呯┖璋冨害鏃ュ織 +export function cleanJobLog() { + return request({ + url: '/monitor/jobLog/clean', + method: 'delete' + }) +} diff --git a/src/api/monitor/logininfor.js b/src/api/monitor/logininfor.js new file mode 100644 index 0000000..4d112b7 --- /dev/null +++ b/src/api/monitor/logininfor.js @@ -0,0 +1,34 @@ +import request from '@/utils/request' + +// 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 +export function list(query) { + return request({ + url: '/monitor/logininfor/list', + method: 'get', + params: query + }) +} + +// 鍒犻櫎鐧诲綍鏃ュ織 +export function delLogininfor(infoId) { + return request({ + url: '/monitor/logininfor/' + infoId, + method: 'delete' + }) +} + +// 瑙i攣鐢ㄦ埛鐧诲綍鐘舵�� +export function unlockLogininfor(userName) { + return request({ + url: '/monitor/logininfor/unlock/' + userName, + method: 'get' + }) +} + +// 娓呯┖鐧诲綍鏃ュ織 +export function cleanLogininfor() { + return request({ + url: '/monitor/logininfor/clean', + method: 'delete' + }) +} diff --git a/src/api/monitor/online.js b/src/api/monitor/online.js new file mode 100644 index 0000000..bd22137 --- /dev/null +++ b/src/api/monitor/online.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 鏌ヨ鍦ㄧ嚎鐢ㄦ埛鍒楄〃 +export function list(query) { + return request({ + url: '/monitor/online/list', + method: 'get', + params: query + }) +} + +// 寮洪��鐢ㄦ埛 +export function forceLogout(tokenId) { + return request({ + url: '/monitor/online/' + tokenId, + method: 'delete' + }) +} diff --git a/src/api/monitor/operlog.js b/src/api/monitor/operlog.js new file mode 100644 index 0000000..a04bca8 --- /dev/null +++ b/src/api/monitor/operlog.js @@ -0,0 +1,26 @@ +import request from '@/utils/request' + +// 鏌ヨ鎿嶄綔鏃ュ織鍒楄〃 +export function list(query) { + return request({ + url: '/monitor/operlog/list', + method: 'get', + params: query + }) +} + +// 鍒犻櫎鎿嶄綔鏃ュ織 +export function delOperlog(operId) { + return request({ + url: '/monitor/operlog/' + operId, + method: 'delete' + }) +} + +// 娓呯┖鎿嶄綔鏃ュ織 +export function cleanOperlog() { + return request({ + url: '/monitor/operlog/clean', + method: 'delete' + }) +} diff --git a/src/api/monitor/server.js b/src/api/monitor/server.js new file mode 100644 index 0000000..e1f9ca2 --- /dev/null +++ b/src/api/monitor/server.js @@ -0,0 +1,9 @@ +import request from '@/utils/request' + +// 鑾峰彇鏈嶅姟淇℃伅 +export function getServer() { + return request({ + url: '/monitor/server', + method: 'get' + }) +} \ No newline at end of file diff --git a/src/api/peizhi/index.js b/src/api/peizhi/index.js new file mode 100644 index 0000000..ea0b78f --- /dev/null +++ b/src/api/peizhi/index.js @@ -0,0 +1,18 @@ +import request from '@/utils/request' + +// 缂栬緫 +export function edit(query) { + return request({ + url: '/dev/config/edit', + method: 'post', + data: query + }) +} + +export function configList(query) { + return request({ + url: '/dev/config/list', + method: 'get', + params: query + }) + } \ No newline at end of file diff --git a/src/api/system/config.js b/src/api/system/config.js new file mode 100644 index 0000000..a404d82 --- /dev/null +++ b/src/api/system/config.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 鏌ヨ鍙傛暟鍒楄〃 +export function listConfig(query) { + return request({ + url: '/system/config/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ鍙傛暟璇︾粏 +export function getConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'get' + }) +} + +// 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊� +export function getConfigKey(configKey) { + return request({ + url: '/system/config/configKey/' + configKey, + method: 'get' + }) +} + +// 鏂板鍙傛暟閰嶇疆 +export function addConfig(data) { + return request({ + url: '/system/config', + method: 'post', + data: data + }) +} + +// 淇敼鍙傛暟閰嶇疆 +export function updateConfig(data) { + return request({ + url: '/system/config', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鍙傛暟閰嶇疆 +export function delConfig(configId) { + return request({ + url: '/system/config/' + configId, + method: 'delete' + }) +} + +// 鍒锋柊鍙傛暟缂撳瓨 +export function refreshCache() { + return request({ + url: '/system/config/refreshCache', + method: 'delete' + }) +} diff --git a/src/api/system/dept.js b/src/api/system/dept.js new file mode 100644 index 0000000..fc943cd --- /dev/null +++ b/src/api/system/dept.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 鏌ヨ閮ㄩ棬鍒楄〃 +export function listDept(query) { + return request({ + url: '/system/dept/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級 +export function listDeptExcludeChild(deptId) { + return request({ + url: '/system/dept/list/exclude/' + deptId, + method: 'get' + }) +} + +// 鏌ヨ閮ㄩ棬璇︾粏 +export function getDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'get' + }) +} + +// 鏂板閮ㄩ棬 +export function addDept(data) { + return request({ + url: '/system/dept', + method: 'post', + data: data + }) +} + +// 淇敼閮ㄩ棬 +export function updateDept(data) { + return request({ + url: '/system/dept', + method: 'put', + data: data + }) +} + +// 鍒犻櫎閮ㄩ棬 +export function delDept(deptId) { + return request({ + url: '/system/dept/' + deptId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/src/api/system/dict/data.js b/src/api/system/dict/data.js new file mode 100644 index 0000000..6c9eb79 --- /dev/null +++ b/src/api/system/dict/data.js @@ -0,0 +1,52 @@ +import request from '@/utils/request' + +// 鏌ヨ瀛楀吀鏁版嵁鍒楄〃 +export function listData(query) { + return request({ + url: '/system/dict/data/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ瀛楀吀鏁版嵁璇︾粏 +export function getData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'get' + }) +} + +// 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅 +export function getDicts(dictType) { + return request({ + url: '/system/dict/data/type/' + dictType, + method: 'get' + }) +} + +// 鏂板瀛楀吀鏁版嵁 +export function addData(data) { + return request({ + url: '/system/dict/data', + method: 'post', + data: data + }) +} + +// 淇敼瀛楀吀鏁版嵁 +export function updateData(data) { + return request({ + url: '/system/dict/data', + method: 'put', + data: data + }) +} + +// 鍒犻櫎瀛楀吀鏁版嵁 +export function delData(dictCode) { + return request({ + url: '/system/dict/data/' + dictCode, + method: 'delete' + }) +} diff --git a/src/api/system/dict/type.js b/src/api/system/dict/type.js new file mode 100644 index 0000000..a7a6e01 --- /dev/null +++ b/src/api/system/dict/type.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 +export function listType(query) { + return request({ + url: '/system/dict/type/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ瀛楀吀绫诲瀷璇︾粏 +export function getType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'get' + }) +} + +// 鏂板瀛楀吀绫诲瀷 +export function addType(data) { + return request({ + url: '/system/dict/type', + method: 'post', + data: data + }) +} + +// 淇敼瀛楀吀绫诲瀷 +export function updateType(data) { + return request({ + url: '/system/dict/type', + method: 'put', + data: data + }) +} + +// 鍒犻櫎瀛楀吀绫诲瀷 +export function delType(dictId) { + return request({ + url: '/system/dict/type/' + dictId, + method: 'delete' + }) +} + +// 鍒锋柊瀛楀吀缂撳瓨 +export function refreshCache() { + return request({ + url: '/system/dict/type/refreshCache', + method: 'delete' + }) +} + +// 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛� +export function optionselect() { + return request({ + url: '/system/dict/type/optionselect', + method: 'get' + }) +} \ No newline at end of file diff --git a/src/api/system/gkInformation/gkInfo.js b/src/api/system/gkInformation/gkInfo.js new file mode 100644 index 0000000..8bad490 --- /dev/null +++ b/src/api/system/gkInformation/gkInfo.js @@ -0,0 +1,28 @@ +import request from '@/utils/request' + +// 鏌ヨ鏂囦欢鍒楄〃 +export function listFile(query) { + return request({ + url: '/dp/sysFile/listAll', + method: 'get', + params: query + }) +} + +//鏌ヨ鏂囦欢鎼滅储鍒楄〃 +export function SearchlistFile(data) { + return request({ + url: '/dp/sysFile/getPageList', + method: 'post', + data: data + }) +} + +// 鍒犻櫎 +export function deleteBatch(fileId) { + return request({ + url: '/dp/sysFile/deleteBatch', + method: 'post', + data: fileId + }) +} diff --git a/src/api/system/menu.js b/src/api/system/menu.js new file mode 100644 index 0000000..f6415c6 --- /dev/null +++ b/src/api/system/menu.js @@ -0,0 +1,60 @@ +import request from '@/utils/request' + +// 鏌ヨ鑿滃崟鍒楄〃 +export function listMenu(query) { + return request({ + url: '/system/menu/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ鑿滃崟璇︾粏 +export function getMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'get' + }) +} + +// 鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋� +export function treeselect() { + return request({ + url: '/system/menu/treeselect', + method: 'get' + }) +} + +// 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋� +export function roleMenuTreeselect(roleId) { + return request({ + url: '/system/menu/roleMenuTreeselect/' + roleId, + method: 'get' + }) +} + +// 鏂板鑿滃崟 +export function addMenu(data) { + return request({ + url: '/system/menu', + method: 'post', + data: data + }) +} + +// 淇敼鑿滃崟 +export function updateMenu(data) { + return request({ + url: '/system/menu', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鑿滃崟 +export function delMenu(menuId) { + return request({ + url: '/system/menu/' + menuId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/src/api/system/notice.js b/src/api/system/notice.js new file mode 100644 index 0000000..c274ea5 --- /dev/null +++ b/src/api/system/notice.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 鏌ヨ鍏憡鍒楄〃 +export function listNotice(query) { + return request({ + url: '/system/notice/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ鍏憡璇︾粏 +export function getNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'get' + }) +} + +// 鏂板鍏憡 +export function addNotice(data) { + return request({ + url: '/system/notice', + method: 'post', + data: data + }) +} + +// 淇敼鍏憡 +export function updateNotice(data) { + return request({ + url: '/system/notice', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鍏憡 +export function delNotice(noticeId) { + return request({ + url: '/system/notice/' + noticeId, + method: 'delete' + }) +} \ No newline at end of file diff --git a/src/api/system/post.js b/src/api/system/post.js new file mode 100644 index 0000000..1a8e9ca --- /dev/null +++ b/src/api/system/post.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 鏌ヨ宀椾綅鍒楄〃 +export function listPost(query) { + return request({ + url: '/system/post/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ宀椾綅璇︾粏 +export function getPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'get' + }) +} + +// 鏂板宀椾綅 +export function addPost(data) { + return request({ + url: '/system/post', + method: 'post', + data: data + }) +} + +// 淇敼宀椾綅 +export function updatePost(data) { + return request({ + url: '/system/post', + method: 'put', + data: data + }) +} + +// 鍒犻櫎宀椾綅 +export function delPost(postId) { + return request({ + url: '/system/post/' + postId, + method: 'delete' + }) +} diff --git a/src/api/system/role.js b/src/api/system/role.js new file mode 100644 index 0000000..f13e6f4 --- /dev/null +++ b/src/api/system/role.js @@ -0,0 +1,119 @@ +import request from '@/utils/request' + +// 鏌ヨ瑙掕壊鍒楄〃 +export function listRole(query) { + return request({ + url: '/system/role/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ瑙掕壊璇︾粏 +export function getRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'get' + }) +} + +// 鏂板瑙掕壊 +export function addRole(data) { + return request({ + url: '/system/role', + method: 'post', + data: data + }) +} + +// 淇敼瑙掕壊 +export function updateRole(data) { + return request({ + url: '/system/role', + method: 'put', + data: data + }) +} + +// 瑙掕壊鏁版嵁鏉冮檺 +export function dataScope(data) { + return request({ + url: '/system/role/dataScope', + method: 'put', + data: data + }) +} + +// 瑙掕壊鐘舵�佷慨鏀� +export function changeRoleStatus(roleId, status) { + const data = { + roleId, + status + } + return request({ + url: '/system/role/changeStatus', + method: 'put', + data: data + }) +} + +// 鍒犻櫎瑙掕壊 +export function delRole(roleId) { + return request({ + url: '/system/role/' + roleId, + method: 'delete' + }) +} + +// 鏌ヨ瑙掕壊宸叉巿鏉冪敤鎴峰垪琛� +export function allocatedUserList(query) { + return request({ + url: '/system/role/authUser/allocatedList', + method: 'get', + params: query + }) +} + +// 鏌ヨ瑙掕壊鏈巿鏉冪敤鎴峰垪琛� +export function unallocatedUserList(query) { + return request({ + url: '/system/role/authUser/unallocatedList', + method: 'get', + params: query + }) +} + +// 鍙栨秷鐢ㄦ埛鎺堟潈瑙掕壊 +export function authUserCancel(data) { + return request({ + url: '/system/role/authUser/cancel', + method: 'put', + data: data + }) +} + +// 鎵归噺鍙栨秷鐢ㄦ埛鎺堟潈瑙掕壊 +export function authUserCancelAll(data) { + return request({ + url: '/system/role/authUser/cancelAll', + method: 'put', + params: data + }) +} + +// 鎺堟潈鐢ㄦ埛閫夋嫨 +export function authUserSelectAll(data) { + return request({ + url: '/system/role/authUser/selectAll', + method: 'put', + params: data + }) +} + +// 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戠粨鏋� +export function deptTreeSelect(roleId) { + return request({ + url: '/system/role/deptTree/' + roleId, + method: 'get' + }) +} diff --git a/src/api/system/user.js b/src/api/system/user.js new file mode 100644 index 0000000..f2f76ef --- /dev/null +++ b/src/api/system/user.js @@ -0,0 +1,135 @@ +import request from '@/utils/request' +import { parseStrEmpty } from "@/utils/ruoyi"; + +// 鏌ヨ鐢ㄦ埛鍒楄〃 +export function listUser(query) { + return request({ + url: '/system/user/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ鐢ㄦ埛璇︾粏 +export function getUser(userId) { + return request({ + url: '/system/user/' + parseStrEmpty(userId), + method: 'get' + }) +} + +// 鏂板鐢ㄦ埛 +export function addUser(data) { + return request({ + url: '/system/user', + method: 'post', + data: data + }) +} + +// 淇敼鐢ㄦ埛 +export function updateUser(data) { + return request({ + url: '/system/user', + method: 'put', + data: data + }) +} + +// 鍒犻櫎鐢ㄦ埛 +export function delUser(userId) { + return request({ + url: '/system/user/' + userId, + method: 'delete' + }) +} + +// 鐢ㄦ埛瀵嗙爜閲嶇疆 +export function resetUserPwd(userId, password) { + const data = { + userId, + password + } + return request({ + url: '/system/user/resetPwd', + method: 'put', + data: data + }) +} + +// 鐢ㄦ埛鐘舵�佷慨鏀� +export function changeUserStatus(userId, status) { + const data = { + userId, + status + } + return request({ + url: '/system/user/changeStatus', + method: 'put', + data: data + }) +} + +// 鏌ヨ鐢ㄦ埛涓汉淇℃伅 +export function getUserProfile() { + return request({ + url: '/system/user/profile', + method: 'get' + }) +} + +// 淇敼鐢ㄦ埛涓汉淇℃伅 +export function updateUserProfile(data) { + return request({ + url: '/system/user/profile', + method: 'put', + data: data + }) +} + +// 鐢ㄦ埛瀵嗙爜閲嶇疆 +export function updateUserPwd(oldPassword, newPassword) { + const data = { + oldPassword, + newPassword + } + return request({ + url: '/system/user/profile/updatePwd', + method: 'put', + params: data + }) +} + +// 鐢ㄦ埛澶村儚涓婁紶 +export function uploadAvatar(data) { + return request({ + url: '/system/user/profile/avatar', + method: 'post', + data: data + }) +} + +// 鏌ヨ鎺堟潈瑙掕壊 +export function getAuthRole(userId) { + return request({ + url: '/system/user/authRole/' + userId, + method: 'get' + }) +} + +// 淇濆瓨鎺堟潈瑙掕壊 +export function updateAuthRole(data) { + return request({ + url: '/system/user/authRole', + method: 'put', + params: data + }) +} + +// 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� +export function deptTreeSelect() { + return request({ + url: '/system/user/deptTree', + method: 'get' + }) +} diff --git a/src/api/tool/gen.js b/src/api/tool/gen.js new file mode 100644 index 0000000..4506927 --- /dev/null +++ b/src/api/tool/gen.js @@ -0,0 +1,76 @@ +import request from '@/utils/request' + +// 鏌ヨ鐢熸垚琛ㄦ暟鎹� +export function listTable(query) { + return request({ + url: '/tool/gen/list', + method: 'get', + params: query + }) +} +// 鏌ヨdb鏁版嵁搴撳垪琛� +export function listDbTable(query) { + return request({ + url: '/tool/gen/db/list', + method: 'get', + params: query + }) +} + +// 鏌ヨ琛ㄨ缁嗕俊鎭� +export function getGenTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'get' + }) +} + +// 淇敼浠g爜鐢熸垚淇℃伅 +export function updateGenTable(data) { + return request({ + url: '/tool/gen', + method: 'put', + data: data + }) +} + +// 瀵煎叆琛� +export function importTable(data) { + return request({ + url: '/tool/gen/importTable', + method: 'post', + params: data + }) +} + +// 棰勮鐢熸垚浠g爜 +export function previewTable(tableId) { + return request({ + url: '/tool/gen/preview/' + tableId, + method: 'get' + }) +} + +// 鍒犻櫎琛ㄦ暟鎹� +export function delTable(tableId) { + return request({ + url: '/tool/gen/' + tableId, + method: 'delete' + }) +} + +// 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛� +export function genCode(tableName) { + return request({ + url: '/tool/gen/genCode/' + tableName, + method: 'get' + }) +} + +// 鍚屾鏁版嵁搴� +export function synchDb(tableName) { + return request({ + url: '/tool/gen/synchDb/' + tableName, + method: 'get' + }) +} diff --git a/src/assets/401_images/401.gif b/src/assets/401_images/401.gif new file mode 100644 index 0000000..cd6e0d9 --- /dev/null +++ b/src/assets/401_images/401.gif Binary files differ diff --git a/src/assets/404_images/404.png b/src/assets/404_images/404.png new file mode 100644 index 0000000..3d8e230 --- /dev/null +++ b/src/assets/404_images/404.png Binary files differ diff --git a/src/assets/404_images/404_cloud.png b/src/assets/404_images/404_cloud.png new file mode 100644 index 0000000..c6281d0 --- /dev/null +++ b/src/assets/404_images/404_cloud.png Binary files differ diff --git a/src/assets/icons/index.js b/src/assets/icons/index.js new file mode 100644 index 0000000..2c6b309 --- /dev/null +++ b/src/assets/icons/index.js @@ -0,0 +1,9 @@ +import Vue from 'vue' +import SvgIcon from '@/components/SvgIcon'// svg component + +// register globally +Vue.component('svg-icon', SvgIcon) + +const req = require.context('./svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys().map(requireContext) +requireAll(req) diff --git a/src/assets/icons/svg/404.svg b/src/assets/icons/svg/404.svg new file mode 100644 index 0000000..6df5019 --- /dev/null +++ b/src/assets/icons/svg/404.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/bug.svg b/src/assets/icons/svg/bug.svg new file mode 100644 index 0000000..05a150d --- /dev/null +++ b/src/assets/icons/svg/bug.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/build.svg b/src/assets/icons/svg/build.svg new file mode 100644 index 0000000..97c4688 --- /dev/null +++ b/src/assets/icons/svg/build.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899741379" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2054" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M960 591.424V368.96c0-0.288 0.16-0.512 0.16-0.768S960 367.68 960 367.424V192a32 32 0 0 0-32-32H96a32 32 0 0 0-32 32v175.424c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768v222.464c0 0.288-0.16 0.512-0.16 0.768s0.16 0.48 0.16 0.768V864a32 32 0 0 0 32 32h832a32 32 0 0 0 32-32v-271.04c0-0.288 0.16-0.512 0.16-0.768S960 591.68 960 591.424z m-560-31.232v-160H608v160h-208z m208 64V832h-208v-207.808H608z m-480-224h208v160H128v-160z m544 0h224v160h-224v-160zM896 224v112.192H128V224h768zM128 624.192h208V832H128v-207.808zM672 832v-207.808h224V832h-224z" p-id="2055"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/button.svg b/src/assets/icons/svg/button.svg new file mode 100644 index 0000000..904fddc --- /dev/null +++ b/src/assets/icons/svg/button.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1588670460195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1314" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M230.4 307.712c13.824 0 25.088-11.264 25.088-25.088 0-100.352 81.92-182.272 182.272-182.272s182.272 81.408 182.272 182.272c0 13.824 11.264 25.088 25.088 25.088s25.088-11.264 24.576-25.088c0-127.488-103.936-231.936-231.936-231.936S205.824 154.624 205.824 282.624c-0.512 14.336 10.752 25.088 24.576 25.088z m564.736 234.496c-11.264 0-21.504 2.048-31.232 6.144 0-44.544-40.448-81.92-88.064-81.92-14.848 0-28.16 3.584-39.936 10.24-13.824-28.16-44.544-48.128-78.848-48.128-12.288 0-24.576 2.56-35.328 7.68V284.16c0-45.568-37.888-81.92-84.48-81.92s-84.48 36.864-84.48 81.92v348.672l-69.12-112.64c-18.432-28.16-58.368-36.864-91.136-19.968-26.624 14.336-46.592 47.104-30.208 88.064 3.072 8.192 76.8 205.312 171.52 311.296 0 0 28.16 24.576 43.008 58.88 4.096 9.728 13.312 15.36 22.528 15.36 3.072 0 6.656-0.512 9.728-2.048 12.288-5.12 18.432-19.968 12.8-32.256-19.456-44.544-53.76-74.752-53.76-74.752C281.6 768 209.408 573.44 208.384 570.88c-5.12-12.8-2.56-20.992 7.168-26.112 9.216-4.608 21.504-4.608 26.112 2.56l113.152 184.32c4.096 8.704 12.8 14.336 22.528 14.336 13.824 0 25.088-10.752 25.088-25.088V284.16c0-17.92 15.36-32.256 34.816-32.256s34.816 14.336 34.816 32.256v284.16c0 13.824 10.24 25.088 24.576 25.088 13.824 0 25.088-11.264 25.088-25.088v-57.344c0-17.92 15.36-32.768 34.816-32.768 19.968 0 37.376 15.36 37.376 32.768v95.232c0 7.168 3.072 13.312 7.68 17.92 4.608 4.608 10.752 7.168 17.92 7.168 13.824 0 24.576-11.264 24.576-25.088V547.84c0-18.432 13.824-32.256 32.256-32.256 20.48 0 38.912 15.36 38.912 32.256v95.232c0 13.824 11.264 25.088 25.088 25.088s24.576-11.264 25.088-25.088v-18.944c0-18.944 12.8-32.256 30.72-32.256 18.432 0 22.528 18.944 22.528 31.744 0 1.024-11.776 99.84-50.688 173.056-30.72 58.368-45.056 112.128-51.2 146.944-2.56 13.312 6.656 26.112 19.968 28.672 1.536 0 3.072 0.512 4.608 0.512 11.776 0 22.016-8.192 24.064-20.48 5.632-31.232 18.432-79.36 46.08-132.608 43.52-81.92 55.808-186.88 56.32-193.536-0.512-50.688-29.696-83.968-72.704-83.968z"></path></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/cascader.svg b/src/assets/icons/svg/cascader.svg new file mode 100644 index 0000000..e256024 --- /dev/null +++ b/src/assets/icons/svg/cascader.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576153230908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="971" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M772.87036133 734.06115723c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714843H475.90991211c-56.60705567 0-102.66723633-46.06018067-102.66723633-102.66723633V600.82446289h305.859375c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012S827.9942627 467.50537109 772.87036133 467.50537109c-43.34106445 0-80.00793458 27.93273926-93.76831055 66.57714844H373.24267578V401.01062011h321.92687989c55.12390137 0 99.94812012-44.82421875 99.94812011-99.94812011V190.07312011C795.11767578 134.94921875 750.29345703 90.125 695.16955567 90.125H251.12963867C196.0057373 90.125 151.18151855 134.94921875 151.18151855 190.07312011V301.0625c0 55.12390137 44.82421875 99.94812012 99.94812012 99.94812012h55.53588867v296.96044921c0 93.35632325 75.97045898 169.32678223 169.32678224 169.32678223h203.19213866c13.76037598 38.64440918 50.42724609 66.57714844 93.76831055 66.57714844 55.12390137 0 99.94812012-44.82421875 99.94812012-99.94812012s-44.90661622-99.86572266-100.03051758-99.86572265z m0-199.89624024c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857423s-14.91394043 33.28857422-33.28857422 33.28857421-33.28857422-14.91394043-33.28857422-33.28857421 14.91394043-33.28857422 33.28857422-33.28857422zM217.75866699 301.0625V190.07312011c0-18.37463379 14.91394043-33.28857422 33.28857423-33.28857421h444.03991698c18.37463379 0 33.28857422 14.91394043 33.28857422 33.28857422V301.0625c0 18.37463379-14.91394043 33.28857422-33.28857422 33.28857422H251.12963867c-18.37463379 0-33.37097168-14.91394043-33.37097168-33.28857422z m555.11169434 566.23535156c-18.37463379 0-33.28857422-14.91394043-33.28857422-33.28857422 0-18.37463379 14.91394043-33.28857422 33.28857422-33.28857422s33.28857422 14.91394043 33.28857422 33.28857422c0.08239747 18.29223633-14.91394043 33.28857422-33.28857422 33.28857422z" p-id="972"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/chart.svg b/src/assets/icons/svg/chart.svg new file mode 100644 index 0000000..27728fb --- /dev/null +++ b/src/assets/icons/svg/chart.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/checkbox.svg b/src/assets/icons/svg/checkbox.svg new file mode 100644 index 0000000..013fd3a --- /dev/null +++ b/src/assets/icons/svg/checkbox.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575982282951" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="902" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M828.40625 90.125H195.59375C137.375 90.125 90.125 137.375 90.125 195.59375v632.8125c0 58.21875 47.25 105.46875 105.46875 105.46875h632.8125c58.21875 0 105.46875-47.25 105.46875-105.46875V195.59375c0-58.21875-47.25-105.46875-105.46875-105.46875z m52.734375 738.28125c0 29.16-23.57015625 52.734375-52.734375 52.734375H195.59375c-29.109375 0-52.734375-23.574375-52.734375-52.734375V195.59375c0-29.109375 23.625-52.734375 52.734375-52.734375h632.8125c29.16 0 52.734375 23.625 52.734375 52.734375v632.8125z" p-id="903"></path><path d="M421.52890625 709.55984375a36.28125 36.28125 0 0 1-27.55265625-12.66890625L205.17453125 476.613125a36.28546875 36.28546875 0 0 1 55.10109375-47.22890625l164.986875 192.4846875 342.16171875-298.48078125a36.2896875 36.2896875 0 0 1 47.70984375 54.68765625L445.3859375 700.6203125a36.3234375 36.3234375 0 0 1-23.85703125 8.93953125z" p-id="904"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/clipboard.svg b/src/assets/icons/svg/clipboard.svg new file mode 100644 index 0000000..90923ff --- /dev/null +++ b/src/assets/icons/svg/clipboard.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/code.svg b/src/assets/icons/svg/code.svg new file mode 100644 index 0000000..5f9c5ab --- /dev/null +++ b/src/assets/icons/svg/code.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1546567861908" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2422" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M318.577778 819.2L17.066667 512l301.511111-307.2 45.511111 45.511111L96.711111 512l267.377778 261.688889zM705.422222 819.2l-45.511111-45.511111L927.288889 512l-267.377778-261.688889 45.511111-45.511111L1006.933333 512zM540.785778 221.866667l55.751111 11.150222L483.157333 802.133333l-55.751111-11.093333z" p-id="2423"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/color.svg b/src/assets/icons/svg/color.svg new file mode 100644 index 0000000..44a81aa --- /dev/null +++ b/src/assets/icons/svg/color.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577252187056" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2508" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M747.59340925 691.12859384c11.51396329 0.25305413 22.43746719-0.21087818 40.74171707-1.51832482 29.35428085-2.10878421 35.84933734-2.36183835 46.47761114-0.8856895 24.71495444 3.37405491 41.12129828 21.76265671 32.47528161 47.95376084-85.57447632 258.19957947-442.00123984 249.76444099-628.67084683 50.73735554-153.47733892-159.33976008-153.09775772-414.41833795 0.92786545-573.42069196 159.71934128-162.67163983 424.03439521-166.59397897 565.78689185 0.63263534 80.38686649 94.81095318 108.34934958 169.16669549 89.11723508 230.57450162-15.01454608 47.99593598-50.61082928 77.68762207-119.77896259 114.63352789-4.89237973 2.65706845-29.35428085 15.52065436-35.84933652 19.02123633-46.94154346 25.30541465-63.51659033 41.20565021-62.20914449 58.45550757 2.95229856 39.13904114 24.16667102 52.7196135 70.98168823 53.81618115z m44.41100207 50.10472101c-19.82257471 1.43397372-32.05352527 1.940082-45.63409763 1.6448519-70.34905207-1.60267593-115.98314969-30.91478165-121.38163769-101.64341492-3.45840683-46.05585397 24.7571304-73.13264758 89.24376132-107.96976837 6.7902866-3.66928501 31.37871396-16.57504688 36.06021551-19.06341229 57.69634516-30.83042972 85.15271997-53.73183005 94.76877722-84.47790866 12.77923398-40.78389304-9.10994898-98.94417051-79.24812286-181.6507002-121.17075953-142.97559219-350.14258521-139.60153647-489.2380134 2.06660824-134.49827774 138.84237405-134.79350784 362.12048163-0.42175717 501.637667 158.53842169 168.99799328 451.9968783 181.18676788 534.57688175-11.80919339-4.68150156 0.2952301-10.71262573 0.67481131-18.72600705 1.26527069z" p-id="2509"></path><path d="M346.03865637 637.18588562a78.82636652 78.82636652 0 0 0 78.32025825-79.29029883c0-43.69401562-35.005823-79.29029883-78.32025825-79.29029882a78.82636652 78.82636652 0 0 0-78.36243338 79.29029882c0 43.69401562 35.005823 79.29029883 78.36243338 79.29029883z m0-51.7495729a27.07679361 27.07679361 0 0 1-26.5706845-27.54072593c0-15.30977536 11.97789643-27.54072593 26.5706845-27.54072592 14.55061295 0 26.57068533 12.23095057 26.57068533 27.54072592a27.07679361 27.07679361 0 0 1-26.57068533 27.54072593zM475.7289063 807.11174353a78.82636652 78.82636652 0 0 0 78.3624334-79.29029882c0-43.69401562-34.96364785-79.29029883-78.32025825-79.29029883a78.82636652 78.82636652 0 0 0-78.32025742 79.29029883c0 43.69401562 34.96364785 79.29029883 78.32025742 79.29029882z m0-51.74957208a27.07679361 27.07679361 0 0 1-26.57068532-27.54072674c0-15.30977536 12.06224753-27.54072593 26.57068532-27.54072593 14.59278892 0 26.57068533 12.23095057 26.57068453 27.54072593a27.07679361 27.07679361 0 0 1-26.57068453 27.54072674zM601.24376214 377.21492718a78.82636652 78.82636652 0 0 0 78.32025742-79.29029883c0-43.69401562-34.96364785-79.29029883-78.32025742-79.29029882a78.82636652 78.82636652 0 0 0-78.32025823 79.29029883c0 43.69401562 34.96364785 79.29029883 78.32025824 79.29029883z m1e-8-51.74957208a27.07679361 27.07679361 0 0 1-26.57068534-27.54072675c0-15.30977536 11.97789643-27.54072593 26.57068534-27.54072591 14.55061295 0 26.57068533 12.23095057 26.57068451 27.54072592a27.07679361 27.07679361 0 0 1-26.57068451 27.54072674zM378.80916809 433.85687983a78.82636652 78.82636652 0 0 0 78.32025824-79.29029883c0-43.69401562-34.96364785-79.29029883-78.32025824-79.29029802a78.82636652 78.82636652 0 0 0-78.32025742 79.29029802c0 43.69401562 34.96364785 79.29029883 78.32025742 79.29029883z m0-51.74957209a27.07679361 27.07679361 0 0 1-26.57068451-27.54072674c0-15.30977536 11.97789643-27.54072593 26.57068451-27.54072593 14.55061295 0 26.57068533 12.23095057 26.57068533 27.54072593a27.07679361 27.07679361 0 0 1-26.57068533 27.54072674z" p-id="2510"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/component.svg b/src/assets/icons/svg/component.svg new file mode 100644 index 0000000..29c3458 --- /dev/null +++ b/src/assets/icons/svg/component.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575804206892" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3145" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M826.56 470.016c-32.896 0-64.384 12.288-89.984 35.52l0-104.96c0-62.208-50.496-112.832-112.64-113.088L623.936 287.04 519.552 287.104C541.824 262.72 554.56 230.72 554.56 197.12c0-73.536-59.904-133.44-133.504-133.44-73.472 0-133.376 59.904-133.376 133.44 0 32.896 12.224 64.256 35.52 89.984L175.232 287.104l0 0.576C113.728 288.704 64 338.88 64 400.576l0.32 0 0.32 116.48C60.864 544.896 70.592 577.728 100.8 588.48c12.736 4.608 37.632 7.488 60.864-25.28 12.992-18.368 34.24-29.248 56.64-29.248 38.336 0 69.504 31.104 69.504 69.312 0 38.4-31.168 69.504-69.504 69.504-22.656 0-44.032-11.264-57.344-30.4C138.688 610.112 112.576 615.36 102.464 619.136c-29.824 10.752-39.104 43.776-38.144 67.392l0 160.384L64 846.912C64 909.248 114.752 960 177.216 960l446.272 0c62.4 0 113.152-50.752 113.152-113.152l0-145.024c24.384 22.272 56.384 35.008 89.984 35.008 73.536 0 133.44-59.904 133.44-133.504C960 529.92 900.096 470.016 826.56 470.016zM826.56 672.896c-22.72 0-44.032-11.264-57.344-30.4-22.272-32.384-48.448-27.136-58.56-23.36-29.824 10.752-39.04 43.776-38.08 67.392l0 160.384c0 27.136-22.016 49.152-49.152 49.152L177.216 896.064C150.08 896 128 873.984 128 846.848l0.32 0 0-145.024c24.384 22.272 56.384 35.008 89.984 35.008 73.6 0 133.504-59.904 133.504-133.504 0-73.472-59.904-133.376-133.504-133.376-32.896 0-64.32 12.288-89.984 35.52l0-104.96L128 400.512c0-27.072 22.08-49.152 49.216-49.152L177.216 351.04 334.656 350.72c3.776 0.512 7.616 0.832 11.52 0.832 24.896 0 50.752-10.816 60.032-37.056 4.544-12.736 7.424-37.568-25.344-60.736C362.624 240.768 351.68 219.52 351.68 197.12c0-38.272 31.104-69.44 69.376-69.44 38.336 0 69.504 31.168 69.504 69.44 0 22.72-11.264 44.032-30.528 57.472C427.968 276.736 433.088 302.784 436.8 313.024c10.752 29.888 43.072 39.232 67.392 38.08l119.232 0 0 0.384c27.136 0 49.152 22.08 49.152 49.152l0.256 116.48c-3.776 27.84 6.016 60.736 36.224 71.488 12.736 4.608 37.632 7.488 60.8-25.28 13.056-18.368 34.24-29.248 56.704-29.248C864.832 534.016 896 565.12 896 603.392 896 641.728 864.832 672.896 826.56 672.896z" p-id="3146"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/dashboard.svg b/src/assets/icons/svg/dashboard.svg new file mode 100644 index 0000000..5317d37 --- /dev/null +++ b/src/assets/icons/svg/dashboard.svg @@ -0,0 +1 @@ +<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/date-range.svg b/src/assets/icons/svg/date-range.svg new file mode 100644 index 0000000..fda571e --- /dev/null +++ b/src/assets/icons/svg/date-range.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579774833889" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1376" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M887.466667 192.853333h-100.693334V119.466667c0-10.24-6.826667-17.066667-17.066666-17.066667s-17.066667 6.826667-17.066667 17.066667v73.386666H303.786667V119.466667c0-10.24-6.826667-17.066667-17.066667-17.066667s-17.066667 6.826667-17.066667 17.066667v73.386666H168.96c-46.08 0-85.333333 37.546667-85.333333 85.333334V836.266667c0 46.08 37.546667 85.333333 85.333333 85.333333H887.466667c46.08 0 85.333333-37.546667 85.333333-85.333333V278.186667c0-47.786667-37.546667-85.333333-85.333333-85.333334z m-718.506667 34.133334h100.693333v66.56c0 10.24 6.826667 17.066667 17.066667 17.066666s17.066667-6.826667 17.066667-17.066666v-66.56h450.56v66.56c0 10.24 6.826667 17.066667 17.066666 17.066666s17.066667-6.826667 17.066667-17.066666v-66.56H887.466667c27.306667 0 51.2 22.186667 51.2 51.2v88.746666H117.76v-88.746666c0-29.013333 22.186667-51.2 51.2-51.2zM887.466667 887.466667H168.96c-27.306667 0-51.2-22.186667-51.2-51.2V401.066667H938.666667V836.266667c0 27.306667-22.186667 51.2-51.2 51.2z" p-id="1377"></path><path d="M858.453333 493.226667H327.68c-10.24 0-17.066667 6.826667-17.066667 17.066666v114.346667h-116.053333c-10.24 0-17.066667 6.826667-17.066667 17.066667v133.12c0 10.24 6.826667 17.066667 17.066667 17.066666H460.8c10.24 0 17.066667-6.826667 17.066667-17.066666v-114.346667h380.586666c10.24 0 17.066667-6.826667 17.066667-17.066667v-133.12c0-10.24-6.826667-17.066667-17.066667-17.066666z m-413.013333 34.133333v97.28h-98.986667v-97.28h98.986667z m-230.4 131.413333h98.986667v98.986667h-98.986667v-98.986667z m131.413333 97.28v-97.28h98.986667v97.28h-98.986667z m133.12-228.693333h97.28v98.986667h-97.28v-98.986667z m131.413334 0h98.986666v98.986667h-98.986666v-98.986667z m230.4 97.28h-98.986667v-98.986667h98.986667v98.986667z" p-id="1378"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/date.svg b/src/assets/icons/svg/date.svg new file mode 100644 index 0000000..52dc73e --- /dev/null +++ b/src/assets/icons/svg/date.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577186573535" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1068" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M479.85714249 608.42857168h64.28571502c19.28571417 0 32.14285751-12.85714249 32.14285664-32.14285751s-12.85714249-32.14285751-32.14285664-32.14285664h-64.28571504c-19.28571417 0-32.14285751 12.85714249-32.14285664 32.14285662s12.85714249 32.14285751 32.14285664 32.14285753z m-2e-8 122.14285665h64.28571504c19.28571417 0 32.14285751-12.85714249 32.14285664-32.14285665s-12.85714249-32.14285751-32.14285664-32.14285751h-64.28571504c-19.28571417 0-32.14285751 12.85714249-32.14285664 32.14285751s12.85714249 32.14285751 32.14285664 32.14285664z m353.57142921-559.28571416h-128.57142921v-32.14285664c0-19.28571417-12.85714249-32.14285751-32.14285664-32.14285753s-32.14285751 12.85714249-32.14285751 32.14285753v32.14285664h-257.14285665v-32.14285664c0-19.28571417-12.85714249-32.14285751-32.14285752-32.14285753s-32.14285751 12.85714249-32.14285664 32.14285753v32.14285664h-128.57142919c-70.71428585 0-128.57142832 57.85714249-128.57142832 122.14285751v501.42857081c0 70.71428585 57.85714249 128.57142832 128.57142832 122.14285751h642.85714335c70.71428585 0 128.57142832-57.85714249 128.57142833-122.14285751v-501.42857081c0-70.71428585-57.85714249-122.14285753-128.57142833-122.14285751z m64.28571415 623.57142832c0 32.14285751-32.14285751 64.28571415-64.28571416 64.28571504h-642.85714335c-32.14285751 0-64.28571415-25.71428583-64.28571417-64.28571504v-372.85714249h771.42857168v372.85714249z m0-437.14285664h-771.42857168v-64.28571417c0-32.14285751 32.14285751-64.28571415 64.28571417-64.28571415h128.57142919v32.14285664c0 19.28571417 12.85714249 32.14285751 32.14285664 32.14285751s32.14285751-12.85714249 32.14285753-32.14285751v-32.14285664h257.14285665v32.14285664c0 19.28571417 12.85714249 32.14285751 32.1428575 32.14285751s32.14285751-12.85714249 32.14285664-32.14285751v-32.14285664h128.57142921c32.14285751 0 64.28571415 25.71428583 64.28571415 64.28571415v64.28571417z m-610.71428583 372.85714247h64.28571415c19.28571417 0 32.14285751-12.85714249 32.14285753-32.14285664s-12.85714249-32.14285751-32.14285753-32.14285751h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285751 32.14285751s12.85714249 32.14285751 32.14285751 32.14285665z m385.71428583-122.14285664h64.28571417c19.28571417 0 32.14285751-12.85714249 32.14285751-32.14285751s-12.85714249-32.14285751-32.14285751-32.14285664h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285753 32.14285664s12.85714249 32.14285751 32.14285753 32.14285751z m-385.71428583 0h64.28571415c19.28571417 0 32.14285751-12.85714249 32.14285753-32.14285751s-12.85714249-32.14285751-32.14285753-32.14285664h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285751 32.14285664s12.85714249 32.14285751 32.14285751 32.14285751z m385.71428583 122.14285665h64.28571417c19.28571417 0 32.14285751-12.85714249 32.14285751-32.14285665s-12.85714249-32.14285751-32.14285751-32.14285751h-64.28571415c-19.28571417 0-32.14285751 12.85714249-32.14285753 32.14285751s12.85714249 32.14285751 32.14285753 32.14285665z" p-id="1069"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/dict.svg b/src/assets/icons/svg/dict.svg new file mode 100644 index 0000000..4849377 --- /dev/null +++ b/src/assets/icons/svg/dict.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035680909" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3601" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1002.0848 744.672l-33.568 10.368c0.96 7.264 2.144 14.304 2.144 21.76 0 7.328-1.184 14.432-2.368 21.568l33.792 10.56c7.936 2.24 14.496 7.616 18.336 14.752 3.84 7.328 4.672 15.808 1.952 23.552-5.376 16-23.168 24.672-39.936 19.68l-34.176-10.624c-7.136 12.8-15.776 24.672-26.208 35.2l20.8 27.488a28.96 28.96 0 0 1 5.824 22.816 29.696 29.696 0 0 1-12.704 19.616 32.544 32.544 0 0 1-44.416-6.752l-20.8-27.552c-13.696 6.56-28.192 11.2-43.008 13.888v33.632c0 16.736-14.112 30.432-31.648 30.432-17.6 0-31.872-13.696-31.872-30.432v-33.632a167.616 167.616 0 0 1-42.88-13.888l-20.928 27.552c-10.72 13.76-30.08 16.64-44.288 6.752a29.632 29.632 0 0 1-12.704-19.616 29.28 29.28 0 0 1 5.696-22.816l20.896-27.808a166.72 166.72 0 0 1-27.008-34.688l-33.376 10.432c-16.8 5.184-34.56-3.552-39.936-19.616a29.824 29.824 0 0 1 20.224-38.24l33.472-10.432c-0.8-7.264-2.016-14.304-2.016-21.824 0-7.36 1.184-14.496 2.304-21.632l-33.792-10.368c-16.672-5.376-25.632-22.496-20.224-38.432 5.376-16 23.136-24.672 39.936-19.68l34.016 10.752c7.328-12.672 15.84-24.8 26.336-35.328l-20.8-27.552a29.44 29.44 0 0 1 6.944-42.432 32.704 32.704 0 0 1 44.384 6.752l20.832 27.616c13.696-6.432 28.224-11.2 43.104-13.952v-33.568c0-16.736 14.048-30.432 31.648-30.432 17.536 0 31.808 13.568 31.808 30.432v33.504c15.072 2.688 29.344 7.808 42.848 14.016l20.992-27.616a32.48 32.48 0 0 1 44.224-6.752 29.568 29.568 0 0 1 7.136 42.432l-21.024 27.808c10.432 10.432 19.872 21.888 27.04 34.752l33.376-10.432c16.768-5.12 34.56 3.68 39.936 19.68 5.536 15.936-3.712 33.056-20.32 38.304z m-206.016-74.432c-61.344 0-111.136 47.808-111.136 106.56 0 58.88 49.792 106.496 111.136 106.496 61.312 0 111.104-47.616 111.104-106.496 0-58.752-49.792-106.56-111.104-106.56z" p-id="3602"></path><path d="M802.7888 57.152h-76.448c0-22.08-21.024-38.24-42.848-38.24H39.3968a39.68 39.68 0 0 0-39.36 40.032v795.616s41.888 120.192 110.752 120.192H673.2848a227.488 227.488 0 0 1-107.04-97.44H117.6368s-40.608-13.696-40.608-41.248l470.304-0.256 1.664 3.36a227.68 227.68 0 0 1-12.64-73.632c0-60.576 24-118.624 66.88-161.44a228.352 228.352 0 0 1 123.552-63.392l-3.2 0.288 2.144-424.672h38.208l0.576 421.024c27.04 0 52.672 4.8 76.64 13.344V101.536c0.032 0-6.304-44.384-38.368-44.384zM149.7648 514.336H72.3888v-77.408H149.7648v77.408z m0-144.32H72.3888v-77.44H149.7648v77.44z m0-137.248H72.3888v-77.44H149.7648v77.44z m501.856 281.568H206.0848v-77.408h445.536v77.408z m0-144.32H206.0848v-77.44h445.536v77.44z m0-137.248H206.0848v-77.44h445.536v77.44z" p-id="3603"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/documentation.svg b/src/assets/icons/svg/documentation.svg new file mode 100644 index 0000000..7043122 --- /dev/null +++ b/src/assets/icons/svg/documentation.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/download.svg b/src/assets/icons/svg/download.svg new file mode 100644 index 0000000..c896951 --- /dev/null +++ b/src/assets/icons/svg/download.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569915748289" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3062" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M768.35456 416a256 256 0 1 0-512 0 192 192 0 1 0 0 384v64a256 256 0 0 1-58.88-505.216 320.128 320.128 0 0 1 629.76 0A256.128 256.128 0 0 1 768.35456 864v-64a192 192 0 0 0 0-384z m-512 384h64v64H256.35456v-64z m448 0h64v64h-64v-64z" fill="#333333" p-id="3063"></path><path d="M539.04256 845.248V512.192a32.448 32.448 0 0 0-32-32.192c-17.664 0-32 14.912-32 32.192v333.056l-36.096-36.096a32.192 32.192 0 0 0-45.056 0.192 31.616 31.616 0 0 0-0.192 45.056l90.88 90.944a31.36 31.36 0 0 0 22.528 9.088 30.08 30.08 0 0 0 22.4-9.088l90.88-90.88a32.192 32.192 0 0 0-0.192-45.12 31.616 31.616 0 0 0-45.056-0.192l-36.096 36.096z" fill="#333333" p-id="3064"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/drag.svg b/src/assets/icons/svg/drag.svg new file mode 100644 index 0000000..4185d3c --- /dev/null +++ b/src/assets/icons/svg/drag.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/druid.svg b/src/assets/icons/svg/druid.svg new file mode 100644 index 0000000..a2b4b4e --- /dev/null +++ b/src/assets/icons/svg/druid.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036347051" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5853" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M832 128H192a64.19 64.19 0 0 0-64 64v640a64.19 64.19 0 0 0 64 64h640a64.19 64.19 0 0 0 64-64V192a64.19 64.19 0 0 0-64-64z m0 703.89l-0.11 0.11H192.11l-0.11-0.11V768h640zM832 544H720L605.6 696.54 442.18 435.07 333.25 544H192v-64h114.75l147.07-147.07L610.4 583.46 688 480h144z m0-288H192v-63.89l0.11-0.11h639.78l0.11 0.11z" p-id="5854"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/edit.svg b/src/assets/icons/svg/edit.svg new file mode 100644 index 0000000..d26101f --- /dev/null +++ b/src/assets/icons/svg/edit.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/education.svg b/src/assets/icons/svg/education.svg new file mode 100644 index 0000000..7bfb01d --- /dev/null +++ b/src/assets/icons/svg/education.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/email.svg b/src/assets/icons/svg/email.svg new file mode 100644 index 0000000..74d25e2 --- /dev/null +++ b/src/assets/icons/svg/email.svg @@ -0,0 +1 @@ +<svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/example.svg b/src/assets/icons/svg/example.svg new file mode 100644 index 0000000..46f42b5 --- /dev/null +++ b/src/assets/icons/svg/example.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/excel.svg b/src/assets/icons/svg/excel.svg new file mode 100644 index 0000000..74d97b8 --- /dev/null +++ b/src/assets/icons/svg/excel.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.208 16.576v8.384h38.72v5.376h-38.72v8.704h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.512h38.72v5.376h-38.72v11.136H128v-94.72H78.208zM0 114.368L72.128 128V0L0 13.632v100.736z"/><path d="M28.672 82.56h-11.2l14.784-23.488-14.08-22.592h11.52l8.192 14.976 8.448-14.976h11.136l-14.08 22.208L58.368 82.56H46.656l-8.768-15.68z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/exit-fullscreen.svg b/src/assets/icons/svg/exit-fullscreen.svg new file mode 100644 index 0000000..485c128 --- /dev/null +++ b/src/assets/icons/svg/exit-fullscreen.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/eye-open.svg b/src/assets/icons/svg/eye-open.svg new file mode 100644 index 0000000..88dcc98 --- /dev/null +++ b/src/assets/icons/svg/eye-open.svg @@ -0,0 +1 @@ +<svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/eye.svg b/src/assets/icons/svg/eye.svg new file mode 100644 index 0000000..16ed2d8 --- /dev/null +++ b/src/assets/icons/svg/eye.svg @@ -0,0 +1 @@ +<svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/form.svg b/src/assets/icons/svg/form.svg new file mode 100644 index 0000000..dcbaa18 --- /dev/null +++ b/src/assets/icons/svg/form.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/fullscreen.svg b/src/assets/icons/svg/fullscreen.svg new file mode 100644 index 0000000..0e86b6f --- /dev/null +++ b/src/assets/icons/svg/fullscreen.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/github.svg b/src/assets/icons/svg/github.svg new file mode 100644 index 0000000..db0a0d4 --- /dev/null +++ b/src/assets/icons/svg/github.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1581238998885" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4187" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.542857 14.057143C228.914286 13.942857 0 242.742857 0 525.142857 0 748.457143 143.2 938.285714 342.628571 1008c26.857143 6.742857 22.742857-12.342857 22.742858-25.371429v-88.571428c-155.085714 18.171429-161.371429-84.457143-171.771429-101.6C172.571429 756.571429 122.857143 747.428571 137.714286 730.285714c35.314286-18.171429 71.314286 4.571429 113.028571 66.171429 30.171429 44.685714 89.028571 37.142857 118.857143 29.714286 6.514286-26.857143 20.457143-50.857143 39.657143-69.485715-160.685714-28.8-227.657143-126.857143-227.657143-243.428571 0-56.571429 18.628571-108.571429 55.2-150.514286-23.314286-69.142857 2.171429-128.342857 5.6-137.142857 66.4-5.942857 135.428571 47.542857 140.8 51.771429 37.714286-10.171429 80.8-15.542857 129.028571-15.542858 48.457143 0 91.657143 5.6 129.714286 15.885715 12.914286-9.828571 76.914286-55.771429 138.628572-50.171429 3.314286 8.8 28.228571 66.628571 6.285714 134.857143 37.028571 42.057143 55.885714 94.514286 55.885714 151.2 0 116.8-67.428571 214.971429-228.571428 243.314286a145.714286 145.714286 0 0 1 43.542857 104v128.571428c0.914286 10.285714 0 20.457143 17.142857 20.457143 202.4-68.228571 348.114286-259.428571 348.114286-484.685714 0-282.514286-229.028571-511.2-511.428572-511.2z" p-id="4188"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/guide.svg b/src/assets/icons/svg/guide.svg new file mode 100644 index 0000000..b271001 --- /dev/null +++ b/src/assets/icons/svg/guide.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.482 70.131l36.204 16.18 69.932-65.485-61.38 70.594 46.435 18.735c1.119.425 2.397-.17 2.797-1.363v-.085L127.998.047 1.322 65.874c-1.12.597-1.519 1.959-1.04 3.151.32.511.72.937 1.2 1.107zm44.676 57.821L64.22 107.26l-18.062-7.834v28.527z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/icon.svg b/src/assets/icons/svg/icon.svg new file mode 100644 index 0000000..82be8ee --- /dev/null +++ b/src/assets/icons/svg/icon.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 0 1 4.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 0 1 2.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/input.svg b/src/assets/icons/svg/input.svg new file mode 100644 index 0000000..ab91381 --- /dev/null +++ b/src/assets/icons/svg/input.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802859706" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3102" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 224H128c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V288c0-35.2-28.8-64-64-64z m0 480c0 19.2-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V320c0-19.2 12.8-32 32-32h704c19.2 0 32 12.8 32 32v384z" p-id="3103"></path><path d="M224 352c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V384c0-16-12.8-32-32-32z" p-id="3104"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/international.svg b/src/assets/icons/svg/international.svg new file mode 100644 index 0000000..e9b56ee --- /dev/null +++ b/src/assets/icons/svg/international.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M83.287 103.01c-1.57-3.84-6.778-10.414-15.447-19.548-2.327-2.444-2.182-4.306-1.338-9.862v-.64c.553-3.81 1.513-6.05 14.313-8.087 6.516-1.018 8.203 1.57 10.589 5.178l.785 1.193a12.625 12.625 0 0 0 6.43 5.207c1.134.524 2.53 1.164 4.421 2.24 4.596 2.53 4.596 5.41 4.596 11.753v.727a26.91 26.91 0 0 1-5.178 17.454 59.055 59.055 0 0 1-19.025 11.026c3.49-6.546.814-14.313 0-16.553l-.146-.087zM64 5.12a58.502 58.502 0 0 1 25.484 5.818 54.313 54.313 0 0 0-12.859 10.327c-.93 1.28-1.716 2.473-2.472 3.579-2.444 3.694-3.637 5.352-5.818 5.614a25.105 25.105 0 0 1-4.219 0c-4.276-.29-10.094-.64-11.956 4.422-1.193 3.23-1.396 11.956 2.444 16.495.66 1.077.778 2.4.32 3.578a7.01 7.01 0 0 1-2.066 3.229 18.938 18.938 0 0 1-2.909-2.91 18.91 18.91 0 0 0-8.32-6.603c-1.25-.349-2.647-.64-3.985-.93-3.782-.786-8.03-1.688-9.019-3.812a14.895 14.895 0 0 1-.727-5.818 21.935 21.935 0 0 0-1.396-9.25 8.873 8.873 0 0 0-5.557-4.946A58.705 58.705 0 0 1 64 5.12zM0 64c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/job.svg b/src/assets/icons/svg/job.svg new file mode 100644 index 0000000..2a93a25 --- /dev/null +++ b/src/assets/icons/svg/job.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036191400" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5472" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M934.912 1016.832H192c-14.336 0-25.6-11.264-25.6-25.6v-189.44c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v163.84h691.712V64H217.6v148.48c0 14.336-11.264 25.6-25.6 25.6s-25.6-11.264-25.6-25.6v-174.08c0-14.336 11.264-25.6 25.6-25.6h742.912c14.336 0 25.6 11.264 25.6 25.6v952.832c0 14.336-11.264 25.6-25.6 25.6z" p-id="5473"></path><path d="M232.96 371.2h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 540.16h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM232.96 698.88h-117.76c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h117.76c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM574.464 762.88c-134.144 0-243.2-109.056-243.2-243.2S440.32 276.48 574.464 276.48s243.2 109.056 243.2 243.2-109.056 243.2-243.2 243.2z m0-435.2c-105.984 0-192 86.016-192 192S468.48 711.68 574.464 711.68s192-86.016 192-192S680.448 327.68 574.464 327.68z" p-id="5474"></path><path d="M663.04 545.28h-87.04c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h87.04c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6z" p-id="5475"></path><path d="M576 545.28c-14.336 0-25.6-11.264-25.6-25.6v-87.04c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v87.04c0 14.336-11.264 25.6-25.6 25.6z" p-id="5476"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/language.svg b/src/assets/icons/svg/language.svg new file mode 100644 index 0000000..0082b57 --- /dev/null +++ b/src/assets/icons/svg/language.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.742 36.8c2.398 7.2 5.595 12.8 11.19 18.4 4.795-4.8 7.992-11.2 10.39-18.4h-21.58zm-52.748 40h20.78l-10.39-28-10.39 28z"/><path d="M111.916 0H16.009C7.218 0 .025 7.2.025 16v96c0 8.8 7.193 16 15.984 16h95.907c8.791 0 15.984-7.2 15.984-16V16c0-8.8-6.394-16-15.984-16zM72.754 103.2c-1.598 1.6-3.197 1.6-4.795 1.6-.8 0-2.398 0-3.197-.8-.8-.8-1.599 0-1.599-.8s-.799-1.6-1.598-3.2c-.8-1.6-.8-2.4-1.599-4l-3.196-8.8H28.797L25.6 96c-1.598 3.2-2.398 5.6-3.197 7.2-.8 1.6-2.398 1.6-4.795 1.6-1.599 0-3.197-.8-4.796-1.6-1.598-1.6-2.397-2.4-2.397-4 0-.8 0-1.6.799-3.2.8-1.6.8-2.4 1.598-4l17.583-44.8c.8-1.6.8-3.2 1.599-4.8.799-1.6 1.598-3.2 2.397-4 .8-.8 1.599-2.4 3.197-3.2 1.599-.8 3.197-.8 4.796-.8 1.598 0 3.196 0 4.795.8 1.598.8 2.398 1.6 3.197 3.2.799.8 1.598 2.4 2.397 4 .8 1.6 1.599 3.2 2.398 5.6l17.583 44c1.598 3.2 2.398 5.6 2.398 7.2-.8.8-1.599 2.4-2.398 4zM116.711 72c-8.791-3.2-15.185-7.2-20.78-12-5.594 5.6-12.787 9.6-21.579 12l-2.397-4c8.791-2.4 15.984-5.6 21.579-11.2C87.939 51.2 83.144 44 81.545 36h-7.992v-3.2h21.58c-1.6-2.4-3.198-5.6-4.796-8l2.397-.8c1.599 2.4 3.997 5.6 5.595 8.8h19.98v4h-7.992c-2.397 8-6.393 15.2-11.189 20 5.595 4.8 11.988 8.8 20.78 11.2l-3.197 4z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/link.svg b/src/assets/icons/svg/link.svg new file mode 100644 index 0000000..48197ba --- /dev/null +++ b/src/assets/icons/svg/link.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/list.svg b/src/assets/icons/svg/list.svg new file mode 100644 index 0000000..20259ed --- /dev/null +++ b/src/assets/icons/svg/list.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/lock.svg b/src/assets/icons/svg/lock.svg new file mode 100644 index 0000000..74fee54 --- /dev/null +++ b/src/assets/icons/svg/lock.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M119.88 49.674h-7.987V39.52C111.893 17.738 90.45.08 63.996.08 37.543.08 16.1 17.738 16.1 39.52v10.154H8.113c-4.408 0-7.987 2.94-7.987 6.577v65.13c0 3.637 3.57 6.577 7.987 6.577H119.88c4.407 0 7.987-2.94 7.987-6.577v-65.13c-.008-3.636-3.58-6.577-7.987-6.577zm-23.953 0H32.065V39.52c0-14.524 14.301-26.295 31.931-26.295 17.63 0 31.932 11.777 31.932 26.295v10.153z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/log.svg b/src/assets/icons/svg/log.svg new file mode 100644 index 0000000..d879d33 --- /dev/null +++ b/src/assets/icons/svg/log.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035943711" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4805" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M208.736 566.336H64.384v59.328h144.352v-59.328z m0-336.096H165.44V74.592c0-7.968 4.896-14.848 10.464-14.848h502.016V0.448H175.936c-38.72 1.248-69.248 34.368-68.192 74.144v155.648H64.384V289.6h144.352V230.24z m0 168.096H64.384v59.328h144.352v-59.328z m714.656 76.576h-57.76v474.496c0 7.936-4.896 14.848-10.464 14.848H175.936c-5.568 0-10.464-6.912-10.464-14.848v-155.68h43.296v-59.296H64.384v59.296h43.328v155.68c-1.024 39.776 29.472 72.896 68.192 74.144h679.232c38.72-1.184 69.248-34.368 68.256-74.144V474.912z m14.944-290.336l-83.072-85.312a71.264 71.264 0 0 0-52.544-21.728 71.52 71.52 0 0 0-51.616 23.872L386.528 507.264a30.496 30.496 0 0 0-6.176 10.72L308.16 740.512a30.016 30.016 0 0 0 6.976 30.24c7.712 7.968 19.2 10.752 29.568 7.2l216.544-74.112a28.736 28.736 0 0 0 12.128-7.936L940.448 287.456a75.552 75.552 0 0 0-2.112-102.88z m-557.12 518.272l39.104-120.64 78.336 80.416-117.44 40.224z m170.048-70.016l-103.552-106.016 200.16-222.4 103.52 106.304-200.128 222.112zM897.952 247.072l-0.256 0.224-107.136 119.168-103.52-106.528 106.432-118.624a14.144 14.144 0 0 1 10.304-4.736 13.44 13.44 0 0 1 10.464 4.288l83.264 85.696c5.472 5.6 5.664 14.72 0.448 20.512z" p-id="4806"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/logininfor.svg b/src/assets/icons/svg/logininfor.svg new file mode 100644 index 0000000..267f844 --- /dev/null +++ b/src/assets/icons/svg/logininfor.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036016814" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5261" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 128h-85.333333a42.666667 42.666667 0 0 0 0 85.333333h42.666666v640H170.666667V213.333333h42.666666a42.666667 42.666667 0 0 0 0-85.333333H128a42.666667 42.666667 0 0 0-42.666667 42.666667v725.333333a42.666667 42.666667 0 0 0 42.666667 42.666667h768a42.666667 42.666667 0 0 0 42.666667-42.666667V170.666667a42.666667 42.666667 0 0 0-42.666667-42.666667z" p-id="5262"></path><path d="M341.333333 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666666 42.666667zM512 298.666667a42.666667 42.666667 0 0 0 42.666667-42.666667V128a42.666667 42.666667 0 0 0-85.333334 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM682.666667 298.666667a42.666667 42.666667 0 0 0 42.666666-42.666667V128a42.666667 42.666667 0 0 0-85.333333 0v128a42.666667 42.666667 0 0 0 42.666667 42.666667zM341.333333 768a42.666667 42.666667 0 0 0 42.666667-42.666667 128 128 0 0 1 256 0 42.666667 42.666667 0 0 0 85.333333 0 213.333333 213.333333 0 0 0-107.52-184.32A128 128 0 0 0 640 469.333333a128 128 0 0 0-256 0 128 128 0 0 0 22.186667 71.68A213.333333 213.333333 0 0 0 298.666667 725.333333a42.666667 42.666667 0 0 0 42.666666 42.666667z m128-298.666667a42.666667 42.666667 0 1 1 42.666667 42.666667 42.666667 42.666667 0 0 1-42.666667-42.666667z" p-id="5263"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/message.svg b/src/assets/icons/svg/message.svg new file mode 100644 index 0000000..14ca817 --- /dev/null +++ b/src/assets/icons/svg/message.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/money.svg b/src/assets/icons/svg/money.svg new file mode 100644 index 0000000..c1580de --- /dev/null +++ b/src/assets/icons/svg/money.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/monitor.svg b/src/assets/icons/svg/monitor.svg new file mode 100644 index 0000000..bc308cb --- /dev/null +++ b/src/assets/icons/svg/monitor.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827393750" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4695" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; } +</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"></path><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"></path><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/nested.svg b/src/assets/icons/svg/nested.svg new file mode 100644 index 0000000..06713a8 --- /dev/null +++ b/src/assets/icons/svg/nested.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/number.svg b/src/assets/icons/svg/number.svg new file mode 100644 index 0000000..ad5ce9a --- /dev/null +++ b/src/assets/icons/svg/number.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802851180" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2867" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M279.272727 791.272727h512a46.545455 46.545455 0 0 1 0 93.090909H279.272727a46.545455 46.545455 0 0 1 0-93.090909z m33.838546-617.984V651.636364H193.722182V395.170909c0-37.003636-0.884364-59.298909-2.653091-66.746182a24.948364 24.948364 0 0 0-14.615273-16.989091c-8.005818-3.863273-25.786182-5.771636-53.341091-5.771636h-11.822545v-55.854545c57.716364-12.381091 101.562182-37.888 131.490909-76.520728h70.283636z m303.709091 396.8V651.636364H354.164364v-68.235637c77.777455-127.255273 124.043636-206.010182 138.705454-236.218182 14.661818-30.254545 22.016-53.853091 22.016-70.74909 0-13.032727-2.234182-22.714182-6.656-29.137455-4.421818-6.376727-11.170909-9.588364-20.247273-9.588364a22.248727 22.248727 0 0 0-20.200727 10.612364c-4.468364 7.121455-6.656 21.178182-6.656 42.263273v45.521454H354.164364v-17.454545c0-26.763636 1.396364-47.941818 4.142545-63.348364 2.746182-15.499636 9.541818-30.72 20.386909-45.661091 10.798545-14.987636 24.901818-26.298182 42.216727-33.978182 17.361455-7.68 38.167273-11.543273 62.37091-11.543272 47.476364 0 83.316364 11.776 107.706181 35.328 24.296727 23.552 36.445091 53.341091 36.445091 89.367272 0 27.368727-6.842182 56.32-20.48 86.853819-13.730909 30.533818-54.039273 95.325091-121.018182 194.420363h130.885819z m270.615272-189.393454c18.152727 6.097455 31.650909 16.104727 40.494546 29.975272 8.843636 13.917091 13.312 46.452364 13.312 97.652364 0 38.027636-4.328727 67.490909-13.032727 88.529455-8.657455 20.945455-23.598545 36.910545-44.869819 47.848727-21.271273 10.938182-48.593455 16.384-81.873454 16.384-37.794909 0-67.490909-6.330182-89.088-19.083636-21.550545-12.660364-35.746909-28.253091-42.542546-46.638546-6.795636-18.432-10.193455-50.362182-10.193454-95.883636v-37.841455h119.389091v77.730909c0 20.666182 1.210182 33.838545 3.723636 39.424 2.420364 5.585455 7.912727 8.424727 16.337455 8.424728 9.309091 0 15.36-3.537455 18.338909-10.612364 2.932364-7.121455 4.421818-25.6 4.421818-55.575273v-33.047273c0-18.338909-2.048-31.744-6.190546-40.215272a30.72 30.72 0 0 0-18.338909-16.709818c-8.052364-2.653091-23.738182-4.189091-46.964363-4.561455V357.050182c28.392727 0 45.893818-1.070545 52.596363-3.258182a22.946909 22.946909 0 0 0 14.475637-14.149818c2.932364-7.307636 4.421818-18.711273 4.421818-34.257455v-26.624c0-16.756364-1.722182-27.741091-5.12-33.047272-3.490909-5.352727-8.843636-8.005818-16.151273-8.005819-8.285091 0-13.963636 2.792727-16.989091 8.378182-3.025455 5.632-4.561455 17.640727-4.561454 35.933091v39.284364h-119.389091v-40.773818c0-45.661091 10.472727-76.567273 31.325091-92.625455 20.898909-16.058182 54.085818-24.064 99.607272-24.064 56.878545 0 95.511273 11.170909 115.805091 33.373091 20.293818 22.248727 30.394182 53.201455 30.394182 92.765091 0 26.810182-3.630545 46.173091-10.891636 58.088727-7.307636 11.915636-20.107636 22.807273-38.446546 32.628364z" p-id="2868"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/online.svg b/src/assets/icons/svg/online.svg new file mode 100644 index 0000000..330a202 --- /dev/null +++ b/src/assets/icons/svg/online.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1568899557259" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="535" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M356.246145 681.56286c-68.156286-41.949414-107.246583-103.84102-107.246583-169.805384 0-65.966411 39.090297-127.860063 107.246583-169.809477 12.046361-7.414877 15.800871-23.190165 8.385994-35.236526-7.413853-12.046361-23.191188-15.801894-35.236526-8.387018-39.640836 24.399713-72.539106 56.044434-95.137801 91.515297-23.86657 37.461193-36.481889 79.620385-36.481889 121.917724 0 42.297338 12.615319 84.454484 36.481889 121.914654 22.598694 35.469839 55.496965 67.11456 95.137801 91.51325 4.185322 2.576685 8.821923 3.804652 13.400195 3.804652 8.598842 0 16.998139-4.329609 21.836331-12.190647C372.047016 704.752002 368.291482 688.976714 356.246145 681.56286zM263.943926 754.580874c-92.603071-61.111846-145.713686-149.623739-145.713686-242.840794 0-93.195565 53.094242-181.682899 145.667637-242.774279 11.805884-7.79043 15.061021-23.677259 7.269567-35.483142-7.79043-11.805884-23.677259-15.062044-35.483142-7.269567C128.487861 296.954249 67.006602 401.024489 67.006602 511.74008c0 110.73708 61.496609 214.830857 168.721703 285.593504 4.343935 2.867304 9.240455 4.238534 14.08274 4.238534 8.317433 0 16.476253-4.046153 21.400403-11.507078C279.003923 778.258133 275.748786 762.372328 263.943926 754.580874zM788.660552 226.213092c-11.80486-7.791453-27.692712-4.536316-35.483142 7.269567-7.79043 11.805884-4.536316 27.692712 7.269567 35.483142 92.575442 61.092403 145.670707 149.579737 145.670707 242.774279 0 93.216032-53.111638 181.727924-145.715733 242.840794-11.805884 7.79043-15.059997 23.678282-7.269567 35.484166 4.925173 7.461949 13.081946 11.507078 21.400403 11.507078 4.841262 0 9.739828-1.37123 14.083763-4.238534 107.22714-70.761624 168.724773-174.857447 168.724773-285.593504C957.341323 401.025513 895.860063 296.955272 788.660552 226.213092zM790.090111 633.67213c23.865547-37.459147 36.480866-79.617315 36.480866-121.914654 0-42.298362-12.615319-84.45653-36.480866-121.917724-22.598694-35.470863-55.496965-67.115584-95.139847-91.515297-12.047384-7.413853-27.821649-3.659343-35.236526 8.387018-7.414877 12.045337-3.659343 27.821649 8.385994 35.236526 68.156286 41.949414 107.247606 103.842043 107.247606 169.809477 0 65.964364-39.090297 127.85597-107.247606 169.804361-12.045337 7.414877-15.800871 23.190165-8.385994 35.237549 4.838192 7.861038 13.236466 12.190647 21.835308 12.190647 4.579295 0 9.215896-1.227967 13.400195-3.804652C734.591099 700.786691 767.490394 669.142993 790.090111 633.67213zM567.129086 518.274914c24.12342-17.150612 39.887452-45.305859 39.887452-77.07133 0-52.128241-42.452881-94.538143-94.634334-94.538143-52.18043 0-94.633311 42.408879-94.633311 94.538143 0 31.695886 15.696494 59.797921 39.730886 76.958766-49.875944 21.128203-84.917018 70.234621-84.917018 127.301338 0 2.366907 0.061398 4.762467 0.182149 7.119141l1.249457 24.296359 276.373515 0 1.238201-24.308639c0.119727-2.358721 0.181125-4.750187 0.181125-7.106862C651.786185 588.497255 616.865861 539.465538 567.129086 518.274914zM512.381182 397.889079c23.937179 0 43.411719 19.430538 43.411719 43.314505 0 23.882943-19.47454 43.313481-43.411719 43.313481-23.936155 0-43.409672-19.430538-43.409672-43.313481C468.971509 417.320641 488.445026 397.889079 512.381182 397.889079zM426.08884 625.656573c9.119705-38.542828 44.254923-67.337641 86.085634-67.337641s76.966952 28.794813 86.085634 67.337641L426.08884 625.656573z" p-id="536"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/password.svg b/src/assets/icons/svg/password.svg new file mode 100644 index 0000000..6c64def --- /dev/null +++ b/src/assets/icons/svg/password.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802846045" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2750" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M868.593046 403.832442c-30.081109-28.844955-70.037123-44.753273-112.624057-44.753273L265.949606 359.079168c-42.554188 0-82.510202 15.908318-112.469538 44.690852-30.236652 28.782533-46.857191 67.222007-46.857191 108.198258l0 294.079782c0 40.977273 16.619516 79.414701 46.702672 108.136859 29.959336 28.844955 70.069869 44.814672 112.624057 44.814672l490.019383 0c42.585911 0 82.696444-15.969717 112.624057-44.814672 30.082132-28.844955 46.579875-67.222007 46.579875-108.136859L915.172921 511.968278C915.171897 471.053426 898.675178 432.677397 868.593046 403.832442zM841.821309 806.049083c0 22.098297-8.882298 42.772152-25.099654 58.306964-16.154935 15.661701-37.81935 24.203238-60.752666 24.203238L265.949606 888.559285c-22.934339 0-44.567032-8.54256-60.877509-24.264637-16.186657-15.474436-25.067932-36.148291-25.067932-58.246589L180.004165 511.968278c0-22.035876 8.881274-42.772152 25.192775-58.307987 16.186657-15.536858 37.81935-24.139793 60.753689-24.139793l490.019383 0c22.933315 0 44.597731 8.602935 60.752666 24.139793 16.21838 15.535835 25.099654 36.272112 25.099654 58.307987L841.822332 806.049083zM510.974136 135.440715c114.914216 0 208.318536 89.75214 208.318536 200.055338l73.350588 0c0-149.113109-126.366036-270.496667-281.669124-270.496667-155.333788 0-281.699824 121.383558-281.699824 270.496667l73.350588 0C302.623877 225.193879 396.059919 135.440715 510.974136 135.440715zM474.299865 747.244792l73.350588 0L547.650453 629.576859l-73.350588 0L474.299865 747.244792z" p-id="2751"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/pdf.svg b/src/assets/icons/svg/pdf.svg new file mode 100644 index 0000000..957aa0c --- /dev/null +++ b/src/assets/icons/svg/pdf.svg @@ -0,0 +1 @@ +<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M869.073 277.307H657.111V65.344l211.962 211.963zm-238.232 26.27V65.344l-476.498-.054v416.957h714.73v-178.67H630.841zm-335.836 360.57c-5.07-3.064-10.944-5.133-17.61-6.201-6.67-1.064-13.603-1.6-20.81-1.6h-48.821v85.641h48.822c7.206 0 14.14-.532 20.81-1.6 6.665-1.065 12.54-3.133 17.609-6.202 5.064-3.063 9.134-7.406 12.208-13.007 3.065-5.602 4.6-12.937 4.6-22.011 0-9.07-1.535-16.408-4.6-22.01-3.074-5.603-7.144-9.94-12.208-13.01zM35.82 541.805v416.904h952.358V541.805H35.821zm331.421 191.179c-3.6 11.071-9.343 20.879-17.209 29.413-7.874 8.542-18.078 15.408-30.617 20.61-12.544 5.206-27.747 7.807-45.621 7.807h-66.036v102.45h-62.831V607.517h128.867c17.874 0 33.077 2.6 45.62 7.802 12.541 5.207 22.745 12.076 30.618 20.615 7.866 8.538 13.604 18.277 17.21 29.212 3.6 10.943 5.401 22.278 5.401 34.018 0 11.477-1.8 22.752-5.402 33.819zM644.9 806.417c-5.343 17.61-13.408 32.818-24.212 45.627-10.807 12.803-24.283 22.879-40.423 30.213-16.146 7.343-35.155 11.007-57.03 11.007h-123.26V607.518h123.26c18.41 0 35.552 2.941 51.428 8.808 15.873 5.869 29.618 14.671 41.22 26.412 11.608 11.744 20.674 26.411 27.217 44.02 6.535 17.61 9.803 38.288 9.803 62.035 0 20.81-2.67 40.02-8.003 57.624zm245.362-146.07h-138.07v66.03h119.66v48.829h-119.66v118.058h-62.83V607.518h200.9v52.829h-.001zm-318.2 25.611c-6.402-8.266-14.877-14.604-25.412-19.01-10.544-4.402-23.551-6.602-39.019-6.602h-44.825v180.088h56.029c9.07 0 17.872-1.463 26.415-4.401 8.535-2.932 16.14-7.802 22.812-14.609 6.665-6.8 12.007-15.667 16.007-26.61 4.003-10.94 6.003-24.275 6.003-40.021 0-14.408-1.4-27.416-4.202-39.019-2.8-11.607-7.406-21.542-13.808-29.816zm0 0"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/people.svg b/src/assets/icons/svg/people.svg new file mode 100644 index 0000000..2bd54ae --- /dev/null +++ b/src/assets/icons/svg/people.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M104.185 95.254c8.161 7.574 13.145 17.441 13.145 28.28 0 1.508-.098 2.998-.285 4.466h-10.784c.238-1.465.403-2.948.403-4.465 0-8.983-4.36-17.115-11.419-23.216C86 104.66 75.355 107.162 64 107.162c-11.344 0-21.98-2.495-31.22-6.83-7.064 6.099-11.444 14.218-11.444 23.203 0 1.517.165 3 .403 4.465H10.955a35.444 35.444 0 0 1-.285-4.465c0-10.838 4.974-20.713 13.127-28.291C9.294 85.42.003 70.417.003 53.58.003 23.99 28.656.001 64 .001s63.997 23.988 63.997 53.58c0 16.842-9.299 31.85-23.812 41.673zM64 36.867c-29.454 0-53.33-10.077-53.33 15.342 0 25.418 23.876 46.023 53.33 46.023 29.454 0 53.33-20.605 53.33-46.023 0-25.419-23.876-15.342-53.33-15.342zm24.888 25.644c-3.927 0-7.111-2.665-7.111-5.953 0-3.288 3.184-5.954 7.11-5.954 3.928 0 7.111 2.666 7.111 5.954s-3.183 5.953-7.11 5.953zm-3.556 16.372c0 4.11-9.55 7.442-21.332 7.442-11.781 0-21.332-3.332-21.332-7.442 0-1.06.656-2.064 1.8-2.976 3.295 2.626 10.79 4.465 19.532 4.465 8.743 0 16.237-1.84 19.531-4.465 1.145.912 1.801 1.916 1.801 2.976zm-46.22-16.372c-3.927 0-7.11-2.665-7.11-5.953 0-3.288 3.183-5.954 7.11-5.954 3.927 0 7.111 2.666 7.111 5.954s-3.184 5.953-7.11 5.953z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/peoples.svg b/src/assets/icons/svg/peoples.svg new file mode 100644 index 0000000..aab852e --- /dev/null +++ b/src/assets/icons/svg/peoples.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/phone.svg b/src/assets/icons/svg/phone.svg new file mode 100644 index 0000000..ab8e8c4 --- /dev/null +++ b/src/assets/icons/svg/phone.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1567417214476" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2266" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M761.503029 2.90619 242.121921 2.90619c-32.405037 0-58.932204 26.060539-58.932204 58.527998l0 902.302287c0 32.156374 26.217105 58.216913 58.932204 58.216913l519.381108 0c32.344662 0 58.591443-26.060539 58.591443-58.216913L820.094472 61.123103C820.094472 28.966729 793.847691 2.90619 761.503029 2.90619M452.878996 61.123103l98.147344 0c6.780427 0 12.31549 5.536087 12.31549 12.253068 0 6.748704-5.535063 12.253068-12.31549 12.253068l-98.147344 0c-6.779404 0-12.345166-5.504364-12.345166-12.253068C440.532807 66.659189 446.099592 61.123103 452.878996 61.123103M501.641583 980.593398c-29.636994 0-53.987588-23.946388-53.987588-53.677527 0-29.356608 24.039509-53.614082 53.987588-53.614082 29.91738 0 53.987588 23.883967 53.987588 53.614082C555.629171 956.647009 531.559986 980.593398 501.641583 980.593398M766.35657 803.142893c0 16.23373-13.186324 29.107945-29.233811 29.107945l-470.618521 0c-16.35755 0-29.325909-13.186324-29.325909-29.107945L237.178329 163.500794c0-16.232706 13.279445-29.138644 29.325909-29.138644l470.246037 0c16.420995 0 29.357632 13.1853 29.357632 29.138644l0 639.642099L766.35657 803.142893zM766.35657 803.142893" p-id="2267"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/post.svg b/src/assets/icons/svg/post.svg new file mode 100644 index 0000000..2922c61 --- /dev/null +++ b/src/assets/icons/svg/post.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566035724641" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3998" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M136.4 434.3h77.7c21.5 0 38.9-17.4 38.9-38.9s-17.4-38.9-38.9-38.9h-77.7c-21.5 0-38.9 17.4-38.9 38.9s17.4 38.9 38.9 38.9zM252.9 628.6c0-21.5-17.4-38.9-38.9-38.9h-77.7c-21.5 0-38.9 17.4-38.9 38.9s17.4 38.9 38.9 38.9H214c21.5-0.1 38.9-17.5 38.9-38.9z" p-id="3999"></path><path d="M874.7 97.5H227c-28.6 0-51.8 23.2-51.8 51.8v194.3h38.9c28.6 0 51.8 23.2 51.8 51.8 0 28.6-23.2 51.8-51.8 51.8h-38.9v129.5h38.9c28.6 0 51.8 23.2 51.8 51.8 0 28.6-23.2 51.8-51.8 51.8h-38.9v194.3c0 28.6 23.2 51.8 51.8 51.8h647.7c28.6 0 51.8-23.2 51.8-51.8V149.3c0-28.6-23.2-51.8-51.8-51.8z m-311.3 723c-15.6 0-146.7-71.6-146.7-91 0-19.4 102-368.6 102-368.6l-83.6-104s-12.3-23.1 24.6-23.1h208.9c36.9 0 18.4 23.1 18.4 23.1l-79 104s102 351.3 102 368.6c0.1 17.3-131 91-146.6 91z m169.2-253.6l-27.9 40.2-74.5-240 103.4 171.7c4.6 7.9 4.2 20.6-1 28.1z" p-id="4000"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/qq.svg b/src/assets/icons/svg/qq.svg new file mode 100644 index 0000000..ee13d4e --- /dev/null +++ b/src/assets/icons/svg/qq.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M18.448 57.545l-.244-.744-.198-.968-.132-.53v-2.181l.236-.859.24-.908.317-.953.428-1.06.561-1.103.794-1.104v-.773l.077-.724.123-.984.34-1.106.313-1.194.25-.548.289-.511.371-.569.405-.423v-2.73l.234-1.407.236-1.633.42-1.955.577-2.035.43-1.118.426-1.217.468-1.135.559-1.216.57-1.332.655-1.247.737-1.331.929-1.33.43-.762.457-.624.995-1.406 1.025-1.403 1.163-1.444 1.246-1.405 1.352-1.384 1.41-1.423 1.708-1.536 1.083-.934 1.322-1.008 1.34-.89 1.448-.855 1.392-.76 1.57-.63 1.667-.775 1.657-.532 1.653-.552 1.787-.548 1.785-.417 1.876-.347L59.128.68l1.879-.245 1.876-.252 2.002-.106h5.912l1.97.243 1.981.231 2.019.207 1.874.441 1.979.413 1.857.475 2.035.53 1.862.646 1.782.738 1.904.78 1.736.853 1.689.95 1.655 1.044 1.425.971.662.548.693.401 1.323 1.1 1.115 1.064 1.112 1.1 1.083 1.214.894 1.178 1.064 1.217.74 1.306.752 1.162.798 1.352.661 1.175 1.113 2.489.546 1.286.428 1.192.428 1.294.384 1.217.267 1.047.347 1.231.607 2.198.388 1.924.253 1.861.217 1.497.342 2.28.077.362.274.41.737 1.18.473.8.42.832.534.892.472 1.07.307 1.093.334 1.2.252 1.232.115.605.106.746v.648l-.106.643v.8l-.192.774-.35 1.5-.403.76-.299.852v.213l.142.264.4.623 1.746 2.53 1.377 1.9.66 1.267.889 1.389.774 1.52.893 1.627.894 1.828 1.006 2.069.567 1.268.518 1.239.447 1.307.44 1.175.336 1.235.342 1.16.432 2.261.343 2.31.235 2.05v2.891l-.158 1.025-.226 1.768-.308 1.59-.48 1.44-.18.588-.336.707-.28.493-.375.607-.33.383-.42.494-.375.4-.401.34-.48.207-.432.207-.355.114h-.543l-.346-.114-.66-.32-.302-.212-.317-.223-.347-.304-.35-.342-.579-.63-.684-.89-.539-.917-.538-.734-.526-.855-.741-1.517-.833-1.579-.098-.055h-.138l-.338.247-.196.415-.326.516-.567 1.533-.856 2.182-1.096 2.626-.824 1.308-.864 1.366-1.027 1.536-1.09 1.503-.557.68-.676.743-1.555 1.497.136.135.21.214.777.446 3.235 1.524 1.41.779 1.347.756 1.332.953 1.187.982.574.443.432.511.445.593.367.643.198.533.242.64.105.554.115.647-.115.433v.44l-.105.454-.242.415-.092.325-.22.394-.587.784-.543.627-.42.47-.35.348-.893.638-1.01.556-1.077.532-1.155.511-1.287.495-.693.207-.608.167-1.496.342-1.545.325-1.552.323-1.689.27-1.74.072-1.785.21h-5.539l-1.998-.114-1.86-.168-2.005-.27-1.99-.209-2.095-.286-2.03-.495-1.981-.374-1.968-.552-2.019-.707-1.98-.585-1.044-.342-.927-.323-.586-.223-.582-.12h-1.647l-1.904-.131-.962-.096-1.24-.135-.795.705-1.085.665-1.471.701-1.628.875-.99.475-1.033.376-2.281.914-1.24.305-1.3.343-1.803.344-1.13.086-1.193.1-1.246.135-1.45.053h-5.926l-3.346-.053-3.25-.321-1.644-.23-1.589-.23-1.546-.227-1.547-.305-1.442-.456-1.434-.325-1.294-.51-1.223-.474-1.142-.533-.99-.583-.984-.71-.336-.343-.44-.415-.334-.362-.3-.417-.278-.415-.215-.42-.311-.89-.109-.46-.138-.51v-.473l.138-.533v-.53l.109-.53v-1.069l.052-.564.259-.647.215-.646.39-.779.286-.3.236-.348.615-.738.49-.38.464-.266.428-.338.676-.21.543-.324.676-.341.77-.227.775-.231.897-.192.85-.11 1.008-.13 1.093-.081.284-.092h.063l.137-.115v-.13l-.2-.266-.58-.27-1.45-1.231-.975-.761-1.127-.967-1.136-1.082-1.181-1.382-1.36-1.558-.508-.843-.672-.87-.58-1.007-.522-1.1-.704-1.047-.459-1.194-.547-1.192-.546-1.33-.397-1.273-.378-1.575-.112-.057h-.115l-.059-.113h-.14l-.23.113-.114.057-.158.264-.057.321-.119.286-.206.477-.664 1.157-.345.701-.546.612-.58.736-.641.816-.677.724-.795.701-.734.658-.814.524-.89.546-.855.325-1.008.247-.99.095h-.233l-.228-.095-.18-.384-.29-.188-.38-.912-.237-.493-.255-.707-.21-.734-.113-.724-.313-1.648-.12-.972v-3.185l.12-2.379.196-1.214.23-1.252.21-1.347.374-1.254.42-1.443.431-1.407.578-1.448.545-1.38.754-1.4.699-1.52.855-1.425 1.006-1.538 1.023-1.382 1.069-1.538.891-1.071 1.142-1.227 1.202-1.237.56-.59.678-.662.985-.836 1.012-.853 1.647-1.446 1.242-.889z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/question.svg b/src/assets/icons/svg/question.svg new file mode 100644 index 0000000..cf75bd4 --- /dev/null +++ b/src/assets/icons/svg/question.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1581238842264" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1409" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M512 0C229.233778 0 0 229.233778 0 512s229.233778 512 512 512 512-229.233778 512-512A512 512 0 0 0 512 0z m0 938.666667C276.366222 938.666667 85.333333 747.633778 85.333333 512 85.333333 276.366222 276.366222 85.333333 512 85.333333c235.633778 0 426.666667 191.032889 426.666667 426.666667a426.666667 426.666667 0 0 1-426.666667 426.666667z m0-717.653334a170.666667 170.666667 0 0 0-170.666667 170.666667 42.666667 42.666667 0 0 0 85.333334 0 85.333333 85.333333 0 1 1 85.333333 85.333333 42.666667 42.666667 0 0 0-42.666667 42.666667v111.36a42.666667 42.666667 0 0 0 85.333334 0v-74.24A170.666667 170.666667 0 0 0 512 221.013333z m-42.666667 542.293334a42.666667 42.666667 0 1 0 85.333334 0 42.666667 42.666667 0 0 0-85.333334 0z" p-id="1410"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/radio.svg b/src/assets/icons/svg/radio.svg new file mode 100644 index 0000000..0cde345 --- /dev/null +++ b/src/assets/icons/svg/radio.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575966775973" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="879" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M507.39346659 71.84873358c241.53533667 0 437.39770766 195.85422109 437.39770767 437.37442191 0 241.53766571-195.86237099 437.38955776-437.39770767 437.38955776-241.50040803 0-437.34997219-195.85189205-437.34997219-437.38955776C70.0434944 267.70295467 265.89189347 71.84873358 507.39346659 71.84873358L507.39346659 71.84873358zM507.39346659 282.81899805c-125.00686734 0-226.37039389 101.38914133-226.37039388 226.41813048 0 125.01268821 101.36352768 226.39717262 226.37039388 226.39717262 125.04295993 0 226.42395136-101.38448441 226.42395136-226.39717262C733.81625401 384.20813938 632.43642653 282.81899805 507.39346659 282.81899805L507.39346659 282.81899805zM507.39346659 120.78172615c-214.46664192 0-388.42047261 173.95150279-388.4204726 388.44026539 0 214.51204949 173.95499463 388.46122325 388.4204726 388.46122325 214.52369237 0 388.46005817-173.94800981 388.46005818-388.46122325C895.85236082 294.73322894 721.91715897 120.78172615 507.39346659 120.78172615z" p-id="880"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/rate.svg b/src/assets/icons/svg/rate.svg new file mode 100644 index 0000000..aa3b14d --- /dev/null +++ b/src/assets/icons/svg/rate.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577246781606" class="icon" viewBox="0 0 1069 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1098" xmlns:xlink="http://www.w3.org/1999/xlink" width="84.5595703125" height="81"><defs><style type="text/css"></style></defs><path d="M633.72929961 378.02038203l9.49872568 18.68789795 20.78025469 2.79745225 206.61592412 27.33248408a11.46496817 11.46496817 0 0 1 6.6095543 19.47324902l-147.2675168 147.35350284-14.89299345 14.89299345 3.8006376 20.68280244 37.84585956 204.89044571a11.46496817 11.46496817 0 0 1-16.4808914 12.2961788L554.68980898 751.84713388l-18.68789794-9.49299345-18.48726123 9.99171915-183.23885392 99.34968163a11.46496817 11.46496817 0 0 1-16.78471347-11.8662416l32.5433127-205.79617881 3.29617793-20.78598692-15.19108243-14.49172002-151.03375839-143.48407587a11.46496817 11.46496817 0 0 1 6.09936328-19.63949062l205.79617881-32.63503185 20.78598691-3.2961788L428.87898125 380.72038203 518.59235674 192.64331182a11.46496817 11.46496817 0 0 1 20.56815264-0.26369385l94.56879023 185.63503183zM496.64840732 85.52038203l-121.75796162 254.98089229L95.76433145 384.76178369A34.3949045 34.3949045 0 0 0 77.46050938 443.66879023l204.87324901 194.66369385-44.16879023 279.1146498a34.3949045 34.3949045 0 0 0 50.36560489 35.61592325l248.4-134.67898038 251.84522285 128.27579591a34.3949045 34.3949045 0 0 0 49.43694287-36.89426777l-51.30573223-277.85350284 199.73120977-199.90891758a34.3949045 34.3949045 0 0 0-19.82866201-58.40827998l-280.11783428-37.03184736L558.32993633 84.71210205a34.3949045 34.3949045 0 0 0-61.68152901 0.80254775z" p-id="1099"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/redis-list.svg b/src/assets/icons/svg/redis-list.svg new file mode 100644 index 0000000..98a15b2 --- /dev/null +++ b/src/assets/icons/svg/redis-list.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1656035183065" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3395" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: feedback-iconfont; src: url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff2?t=1630033759944") format("woff2"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.woff?t=1630033759944") format("woff"), url("//at.alicdn.com/t/font_1031158_u69w8yhxdu.ttf?t=1630033759944") format("truetype"); } +</style></defs><path d="M958.88 730.06H65.12c-18.28 0-33.12-14.82-33.12-33.12V68.91c0-18.29 14.83-33.12 33.12-33.12h893.77c18.28 0 33.12 14.82 33.12 33.12v628.03c-0.01 18.3-14.84 33.12-33.13 33.12zM98.23 663.83h827.53v-561.8H98.23v561.8z" p-id="3396"></path><path d="M512 954.55c-18.28 0-33.12-14.82-33.12-33.12V733.92c0-18.29 14.83-33.12 33.12-33.12s33.12 14.82 33.12 33.12v187.51c0 18.3-14.84 33.12-33.12 33.12z" p-id="3397"></path><path d="M762.01 988.21H261.99c-18.28 0-33.12-14.82-33.12-33.12 0-18.29 14.83-33.12 33.12-33.12h500.03c18.28 0 33.12 14.82 33.12 33.12-0.01 18.29-14.84 33.12-33.13 33.12zM514.74 578.55c-21.63 0-43.31-3.87-64.21-11.65-45.95-17.13-82.49-51.13-102.86-95.74-5.07-11.08-0.19-24.19 10.89-29.26 11.08-5.09 24.19-0.18 29.26 10.91 15.5 33.88 43.25 59.7 78.14 72.71 34.93 12.99 72.79 11.64 106.66-3.85 33.22-15.17 58.8-42.26 72.03-76.3 4.42-11.37 17.21-17.01 28.57-12.58 11.36 4.42 16.99 17.22 12.57 28.58-17.42 44.82-51.1 80.5-94.82 100.47-24.34 11.12-50.25 16.71-76.23 16.71z" p-id="3398"></path><path d="M325.27 528.78c-1.66 0-3.34-0.18-5.02-0.57-11.88-2.77-19.28-14.63-16.49-26.51l18.84-81c1.34-5.82 5-10.84 10.13-13.92 5.09-3.09 11.3-3.96 17.03-2.41l80.51 21.43c11.79 3.14 18.8 15.23 15.67 27.02-3.15 11.79-15.42 18.75-27.02 15.65l-58.49-15.57-13.69 58.81c-2.37 10.2-11.45 17.07-21.47 17.07zM360.8 351.01c-2.65 0-5.37-0.49-8-1.51-11.36-4.41-16.99-17.21-12.59-28.57 17.4-44.79 51.06-80.47 94.8-100.48 92.15-42.06 201.25-1.39 243.31 90.68 5.07 11.08 0.19 24.19-10.89 29.26-11.13 5.07-24.19 0.17-29.26-10.91-31.97-69.91-114.9-100.82-184.79-68.86-33.22 15.19-58.8 42.28-71.99 76.29-3.41 8.74-11.75 14.1-20.59 14.1z" p-id="3399"></path><path d="M684.68 376.74c-1.47 0-2.95-0.15-4.42-0.44l-81.61-16.68c-11.94-2.45-19.64-14.11-17.21-26.06 2.44-11.96 14.1-19.64 26.04-17.22l59.29 12.12 10.23-59.5c2.05-12 13.52-20.19 25.48-18.01 12.03 2.06 20.09 13.48 18.02 25.5l-14.08 81.96a22.089 22.089 0 0 1-9.29 14.49c-3.7 2.51-8.03 3.84-12.45 3.84z" p-id="3400"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/redis.svg b/src/assets/icons/svg/redis.svg new file mode 100644 index 0000000..2f1d62d --- /dev/null +++ b/src/assets/icons/svg/redis.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605865043777" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="856" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M1023.786667 611.84c-0.426667 9.770667-13.354667 20.693333-39.893334 34.56-54.613333 28.458667-337.749333 144.896-397.994666 176.298667-60.288 31.402667-93.738667 31.104-141.354667 8.32-47.616-22.741333-348.842667-144.469333-403.114667-170.368-27.093333-12.970667-40.917333-23.893333-41.386666-34.218667v103.509333c0 10.325333 14.250667 21.290667 41.386666 34.261334 54.272 25.941333 355.541333 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.362667 60.245333-31.402667 343.338667-147.797333 397.994666-176.298667 27.776-14.464 40.106667-25.728 40.106667-35.925333v-102.058667l-0.213333-0.085333z m0-168.746667c-0.512 9.770667-13.397333 20.650667-39.893334 34.517334-54.613333 28.458667-337.749333 144.896-397.994666 176.298666-60.288 31.402667-93.738667 31.104-141.354667 8.362667-47.616-22.741333-348.842667-144.469333-403.114667-170.410667-27.093333-12.928-40.917333-23.893333-41.386666-34.176v103.509334c0 10.325333 14.250667 21.248 41.386666 34.218666 54.272 25.941333 355.498667 147.626667 403.114667 170.368 47.616 22.784 81.066667 23.082667 141.354667-8.32 60.245333-31.402667 343.338667-147.84 397.994666-176.298666 27.776-14.506667 40.106667-25.770667 40.106667-35.968v-102.058667l-0.256-0.042667z m0-175.018666c0.469333-10.410667-13.141333-19.541333-40.533334-29.610667-53.248-19.498667-334.634667-131.498667-388.522666-151.253333-53.888-19.712-75.818667-18.901333-139.093334 3.84C392.234667 113.706667 92.629333 231.253333 39.338667 252.074667c-26.666667 10.496-39.68 20.181333-39.253334 30.506666V386.133333c0 10.325333 14.250667 21.248 41.386667 34.218667 54.272 25.941333 355.498667 147.669333 403.114667 170.410667 47.616 22.741333 81.066667 23.04 141.354666-8.362667 60.245333-31.402667 343.338667-147.84 397.994667-176.298667 27.776-14.506667 40.106667-25.770667 40.106667-35.968V268.074667h-0.341334zM366.677333 366.08l237.269334-36.437333-71.68 105.088-165.546667-68.650667z m524.8-94.634667l-140.330666 55.466667-15.232 5.973333-140.245334-55.466666 155.392-61.44 140.373334 55.466666z m-411.989333-101.674666l-22.954667-42.325334 71.594667 27.989334 67.498667-22.101334-18.261334 43.733334 68.778667 25.770666-88.704 9.216-19.882667 47.786667-32.085333-53.290667-102.4-9.216 76.416-27.562666z m-176.768 59.733333c70.058667 0 126.805333 21.973333 126.805333 49.109333s-56.746667 49.152-126.805333 49.152-126.848-22.058667-126.848-49.152c0-27.136 56.789333-49.152 126.848-49.152z" p-id="857"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/row.svg b/src/assets/icons/svg/row.svg new file mode 100644 index 0000000..0780992 --- /dev/null +++ b/src/assets/icons/svg/row.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579339929870" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1182" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M152 854.856875h325.7146875V237.715625H134.856875v600q0 6.99375 5.0746875 12.0684375T152 854.856875z m737.143125-17.1421875v-600H546.284375v617.1421875H872q6.99375 0 12.0684375-5.07375t5.0746875-12.0684375z m68.5715625-651.429375V837.715625q0 35.3821875-25.16625 60.5484375T872 923.4284375H152q-35.383125 0-60.5484375-25.1653125T66.284375 837.7146875V186.284375q0-35.3821875 25.16625-60.5484375T152 100.5715625h720q35.383125 0 60.5484375 25.1653125t25.16625 60.5484375z" p-id="1183"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/search.svg b/src/assets/icons/svg/search.svg new file mode 100644 index 0000000..84233dd --- /dev/null +++ b/src/assets/icons/svg/search.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M124.884 109.812L94.256 79.166c-.357-.357-.757-.629-1.129-.914a50.366 50.366 0 0 0 8.186-27.59C101.327 22.689 78.656 0 50.67 0 22.685 0 0 22.688 0 50.663c0 27.989 22.685 50.663 50.656 50.663 10.186 0 19.643-3.03 27.6-8.201.286.385.557.771.9 1.114l30.628 30.632a10.633 10.633 0 0 0 7.543 3.129c2.728 0 5.457-1.043 7.543-3.115 4.171-4.157 4.171-10.915.014-15.073M50.671 85.338C31.557 85.338 16 69.78 16 50.663c0-19.102 15.557-34.661 34.67-34.661 19.115 0 34.657 15.559 34.657 34.675 0 19.102-15.557 34.661-34.656 34.661"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/select.svg b/src/assets/icons/svg/select.svg new file mode 100644 index 0000000..d628382 --- /dev/null +++ b/src/assets/icons/svg/select.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575803481213" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="804" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M62 511.97954521C62 263.86590869 263.90681826 62 511.97954521 62s449.97954521 201.825 449.97954521 449.97954521c0 248.19545479-201.90681826 449.97954521-449.97954521 449.97954521C263.90681826 962 62 760.175 62 511.97954521M901.98636348 511.97954521c0-215.24318174-175.00909131-390.41590869-390.00681827-390.41590869-215.03863652 0-389.96590869 175.17272695-389.96590868 390.41590869 0 215.28409131 175.00909131 390.45681826 389.96590868 390.45681826C727.01818174 902.47727305 901.98636348 727.30454521 901.98636348 511.97954521M264.17272695 430.28409131c0-5.76818174 2.12727305-11.51590869 6.64772696-15.87272696 8.71363652-8.75454521 22.88863652-8.75454521 31.725 0l209.4340913 208.22727305L721.45454521 414.53409131c8.75454521-8.71363652 22.97045479-8.71363652 31.90909132 0 8.71363652 8.75454521 8.71363652 22.88863652 0 31.60227304L511.97954521 685.74090869 270.71818174 446.01363653C266.27954521 441.77954521 264.17272695 436.05227305 264.17272695 430.28409131" p-id="805"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/server.svg b/src/assets/icons/svg/server.svg new file mode 100644 index 0000000..eb287e3 --- /dev/null +++ b/src/assets/icons/svg/server.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1547360688278" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6717" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M890 120H134a70 70 0 0 0-70 70v500a70 70 0 0 0 70 70h756a70 70 0 0 0 70-70V190a70 70 0 0 0-70-70z m-10 520a40 40 0 0 1-40 40H712V448a40 40 0 0 0-80 0v232h-80V368a40 40 0 0 0-80 0v312h-80V512a40 40 0 0 0-80 0v168H184a40 40 0 0 1-40-40V240a40 40 0 0 1 40-40h656a40 40 0 0 1 40 40zM696 824H328a40 40 0 0 0 0 80h368a40 40 0 0 0 0-80z" p-id="6718"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/shopping.svg b/src/assets/icons/svg/shopping.svg new file mode 100644 index 0000000..87513e7 --- /dev/null +++ b/src/assets/icons/svg/shopping.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 0 1 3.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 0 1-3.889 2.843 10.582 10.582 0 0 1-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 0 1-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 0 1-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 0 1 3.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 0 1 3.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 0 1-3.89 2.843 11 11 0 0 1-4.732 1.066 10.58 10.58 0 0 1-4.667-1.066 12.478 12.478 0 0 1-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 0 1-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 0 1 3.824-2.772 11.212 11.212 0 0 1 4.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 0 1 .778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 0 1-2.788 8.743 1236.373 1236.373 0 0 0-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 0 1-1.88-4.478 44.128 44.128 0 0 1-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 0 1-2.14-2.558 10.416 10.416 0 0 1-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 0 1 1.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/size.svg b/src/assets/icons/svg/size.svg new file mode 100644 index 0000000..ddb25b8 --- /dev/null +++ b/src/assets/icons/svg/size.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/skill.svg b/src/assets/icons/svg/skill.svg new file mode 100644 index 0000000..a3b7312 --- /dev/null +++ b/src/assets/icons/svg/skill.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M31.652 93.206h33.401c1.44 2.418 3.077 4.663 4.93 6.692h-38.33v-6.692zm0-10.586h28.914a44.8 44.8 0 0 1-1.264-6.688h-27.65v6.688zm0-17.27H59.39c.288-2.286.714-4.532 1.34-6.687H31.65v6.687h.003zm53.913 44.84v5.85c0 2.798-2.095 5.075-4.667 5.075h-70.07c-2.576 0-4.663-2.277-4.663-5.075V31.26l23.22-20.96v22.25H17.16v6.688h18.39V6.688h45.348c2.576 0 4.667 2.277 4.667 5.066v20.009c1.987-.675 4.053-1.128 6.17-1.445v-18.56C91.738 5.28 86.874 0 80.902 0H31.15L0 28.118v87.917c0 6.48 4.859 11.759 10.832 11.759h70.07c5.974 0 10.837-5.27 10.837-11.759v-4.41c-2.117-.312-4.183-.765-6.17-1.435h-.004zM23.279 58.667h-7.96v6.688h7.96v-6.688zm-7.956 41.23h7.96v-6.691h-7.96v6.692zm7.956-23.96h-7.96v6.687h7.96v-6.688zm89.718-15.042l-4.896-4.07-12.447 17.613-11.19-9.305-3.762 5.311 16.091 13.38 16.204-22.929zM128 70.978c0-18.632-13.97-33.782-31.147-33.782-17.168 0-31.135 15.155-31.135 33.782 0 18.628 13.97 33.783 31.135 33.783 17.172 0 31.143-15.15 31.143-33.783H128zm-6.17 0c0 14.933-11.203 27.1-24.981 27.1-13.77 0-24.987-12.158-24.987-27.1 0-14.941 11.195-27.099 24.987-27.099 13.778 0 24.982 12.158 24.982 27.1z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/slider.svg b/src/assets/icons/svg/slider.svg new file mode 100644 index 0000000..fbe4f39 --- /dev/null +++ b/src/assets/icons/svg/slider.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577185310368" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1238" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M951.453125 476.84375H523.671875a131.8359375 131.8359375 0 0 0-254.1796875 0H72.546875v70.3125h196.9453125a131.8359375 131.8359375 0 0 0 254.1796875 0H951.453125z" p-id="1239"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/star.svg b/src/assets/icons/svg/star.svg new file mode 100644 index 0000000..6cf86e6 --- /dev/null +++ b/src/assets/icons/svg/star.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M70.66 4.328l14.01 29.693c1.088 2.29 3.177 3.882 5.603 4.25l31.347 4.76c6.087.926 8.528 8.756 4.117 13.247L103.05 79.395c-1.75 1.78-2.544 4.352-2.132 6.867l5.352 32.641c1.043 6.337-5.33 11.182-10.778 8.19l-28.039-15.409a7.13 7.13 0 0 0-6.91 0l-28.039 15.41c-5.448 2.99-11.821-1.854-10.777-8.19l5.352-32.642c.415-2.515-.387-5.088-2.136-6.867L2.264 56.278C-2.146 51.787.286 43.957 6.38 43.031l31.343-4.76c2.419-.368 4.51-1.96 5.595-4.25L57.334 4.328c2.728-5.77 10.605-5.77 13.325 0z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/swagger.svg b/src/assets/icons/svg/swagger.svg new file mode 100644 index 0000000..05d4e7b --- /dev/null +++ b/src/assets/icons/svg/swagger.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1566036776944" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6463" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M64 223.995345h168.001164v47.997673c0 26.428509 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.569164 41.984-47.997673v-47.997673h504.003491a32.004655 32.004655 0 0 0 0-64.009309H455.996509V111.988364c0-26.428509-18.878836-47.997673-41.984-47.997673H273.985164c-23.095855 0-41.984 21.569164-41.984 47.997673v47.997672H64a32.004655 32.004655 0 0 0 0 64.009309zM288.004655 128h111.997672V256H288.004655V128zM960 479.995345H791.998836v-47.997672c0-26.372655-18.878836-47.997673-41.984-47.997673H609.978182c-23.095855 0-41.984 21.634327-41.984 47.997673v47.997672H64a32.004655 32.004655 0 0 0 0 64.00931h504.003491v47.997672c0 26.363345 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.634327 41.984-47.997673v-47.997672h168.001164a32.004655 32.004655 0 1 0-0.009309-64.00931zM735.995345 576H623.997673v-128h111.997672v128zM960 800.293236v-0.288581H455.996509v-47.997673c0-26.363345-18.878836-47.997673-41.984-47.997673H274.050327c-23.105164 0-41.984 21.634327-41.984 47.997673v47.997673H64v0.288581a32.004655 32.004655 0 0 0 0 64.009309c0.986764 0 1.917673-0.195491 2.885818-0.288581h165.115346v47.997672c0 26.363345 18.878836 47.997673 41.984 47.997673h140.036654c23.095855 0 41.984-21.634327 41.984-47.997673v-47.997672h501.108364c0.968145 0.093091 1.899055 0.288582 2.895127 0.288581a32.004655 32.004655 0 1 0-0.009309-64.009309zM400.002327 896H288.004655V768h111.997672v128z" fill="" p-id="6464"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/switch.svg b/src/assets/icons/svg/switch.svg new file mode 100644 index 0000000..0ba61e3 --- /dev/null +++ b/src/assets/icons/svg/switch.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1576042673958" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1110" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M692 792H332c-150 0-270-120-270-270s120-270 270-270h360c150 0 270 120 270 270 0 147-120 270-270 270zM332 312c-117 0-210 93-210 210s93 210 210 210h360c117 0 210-93 210-210s-93-210-210-210H332z" p-id="1111"></path><path d="M341 522m-150 0a150 150 0 1 0 300 0 150 150 0 1 0-300 0Z" p-id="1112"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/system.svg b/src/assets/icons/svg/system.svg new file mode 100644 index 0000000..5992593 --- /dev/null +++ b/src/assets/icons/svg/system.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543827724451" class="icon" style="" viewBox="0 0 1084 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10233" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.71875" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; } +</style></defs><path d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/tab.svg b/src/assets/icons/svg/tab.svg new file mode 100644 index 0000000..b4b48e4 --- /dev/null +++ b/src/assets/icons/svg/tab.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.921.052H49.08c-1.865 0-3.198 1.599-3.198 3.464v6.661c0 1.865 1.6 3.464 3.198 3.464h29.84c1.865 0 3.198-1.599 3.198-3.464V3.516C82.385 1.65 80.786.052 78.92.052zm45.563 0H94.642c-1.865 0-3.464 1.599-3.464 3.464v6.661c0 1.865 1.599 3.464 3.464 3.464h29.842c1.865-.266 3.464-1.599 3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464zm0 22.382H40.02c-1.866 0-3.464-1.599-3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464H3.516C1.65.052.052 1.651.052 3.516V124.75c0 1.598 1.599 3.197 3.464 3.197h120.968c1.865 0 3.464-1.599 3.464-3.464V25.898c0-1.865-1.599-3.464-3.464-3.464z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/table.svg b/src/assets/icons/svg/table.svg new file mode 100644 index 0000000..0e3dc9d --- /dev/null +++ b/src/assets/icons/svg/table.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/textarea.svg b/src/assets/icons/svg/textarea.svg new file mode 100644 index 0000000..2709f29 --- /dev/null +++ b/src/assets/icons/svg/textarea.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1575802855098" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2984" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M896 160H128c-35.2 0-64 28.8-64 64v576c0 35.2 28.8 64 64 64h768c35.2 0 64-28.8 64-64V224c0-35.2-28.8-64-64-64z m0 608c0 16-12.8 32-32 32H160c-19.2 0-32-12.8-32-32V256c0-16 12.8-32 32-32h704c19.2 0 32 12.8 32 32v512z" p-id="2985"></path><path d="M224 288c-19.2 0-32 12.8-32 32v256c0 16 12.8 32 32 32s32-12.8 32-32V320c0-16-12.8-32-32-32z m608 480c19.2 0 32-12.8 32-32V608L704 768h128z" p-id="2986"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/theme.svg b/src/assets/icons/svg/theme.svg new file mode 100644 index 0000000..5982a2f --- /dev/null +++ b/src/assets/icons/svg/theme.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M125.5 36.984L95.336 2.83C93.735 1.018 91.565 0 89.3 0c-2.263 0-4.433 1.018-6.033 2.83l-3.786 4.286c-1.6 1.812-3.77 2.83-6.032 2.831H54.553c-2.263 0-4.434-1.018-6.033-2.83L44.734 2.83C43.134 1.018 40.964 0 38.701 0c-2.263 0-4.434 1.018-6.034 2.83L2.5 36.984C.9 38.796 0 41.254 0 43.815c0 2.562.899 5.02 2.5 6.831L14.565 64.31c2.178 2.468 5.367 3.403 8.33 2.444 1.35-.435 2.709.592 2.709 2.18v49.407c0 5.313 3.84 9.66 8.532 9.66h59.726c4.693 0 8.532-4.347 8.532-9.66V68.934c0-1.59 1.36-2.616 2.71-2.181 2.962.96 6.15.024 8.329-2.444L125.5 50.646c1.6-1.811 2.499-4.269 2.499-6.83 0-2.563-.899-5.02-2.5-6.832z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/time-range.svg b/src/assets/icons/svg/time-range.svg new file mode 100644 index 0000000..13c1202 --- /dev/null +++ b/src/assets/icons/svg/time-range.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1579774825624" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1248" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M498.595712 482.290351 345.420077 482.290351l0 57.307194 210.477712 0L555.897789 274.196942l-57.301054 0L498.596735 482.290351zM498.595712 482.290351" p-id="1249"></path><path d="M577.685002 644.98478l379.879913 0 0 57.302077L577.685002 702.286858 577.685002 644.98478 577.685002 644.98478zM577.685002 644.98478" p-id="1250"></path><path d="M577.685002 773.764795l379.879913 0 0 57.307194L577.685002 831.071989 577.685002 773.764795 577.685002 773.764795zM577.685002 773.764795" p-id="1251"></path><path d="M577.685002 902.549927l379.879913 0 0 57.307194L577.685002 959.857121 577.685002 902.549927 577.685002 902.549927zM577.685002 902.549927" p-id="1252"></path><path d="M102.523001 382.290823c4.450359 2.615571 9.470699 3.954055 14.530948 3.954055 2.969635 0 5.952572-0.461511 8.836249-1.394766l190.809767-61.886489c15.052834-4.882194 23.297612-21.040199 18.415418-36.08894-4.882194-15.052834-21.040199-23.297612-36.093033-18.415418L175.676092 308.458257c15.994276-26.115797 35.170011-50.537 57.370639-72.743768 73.767074-73.767074 171.845857-114.388237 276.16783-114.388237 104.32095 0 202.39564 40.622186 276.16169 114.388237s114.393353 171.845857 114.393353 276.16783c0 26.427906-2.615571 52.449559-7.709589 77.780481l58.302871 0c4.464685-25.499767 6.708795-51.470255 6.708795-77.780481 0-60.449767-11.845793-119.102608-35.204803-174.336584-22.559808-53.334719-54.850236-101.226472-95.968725-142.349055-41.122583-41.122583-89.017406-73.408917-142.348032-95.968725C628.317169 75.866898 569.659211 64.021106 509.215584 64.021106c-60.448744 0-119.106702 11.845793-174.336584 35.207873-53.334719 22.559808-101.230566 54.846142-142.349055 95.968725-23.980157 23.980157-44.934398 50.278103-62.727647 78.601172l-20.738323-105.655342c-3.043313-15.527648-18.105357-25.642007-33.631982-22.599717-15.527648 3.048429-25.64303 18.105357-22.599717 33.637098l36.102243 183.932126C90.51348 371.153158 95.460142 378.13313 102.523001 382.290823L102.523001 382.290823zM102.523001 382.290823" p-id="1253"></path><path d="M126.020158 587.9416 67.768453 587.9416c5.759167 33.679054 15.368012 66.544579 28.789697 98.278327 22.559808 53.333696 54.850236 101.225449 95.971795 142.348032 41.122583 41.122583 89.014336 73.408917 142.349055 95.968725 54.112432 22.88829 111.517863 34.71157 170.668031 35.18229L505.547031 902.395408c-102.94972-0.941442-199.594851-41.445948-272.499277-114.349351C177.545672 732.543975 140.810003 663.275355 126.020158 587.9416L126.020158 587.9416zM126.020158 587.9416" p-id="1254"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/time.svg b/src/assets/icons/svg/time.svg new file mode 100644 index 0000000..b376e32 --- /dev/null +++ b/src/assets/icons/svg/time.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577099827399" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1008" xmlns:xlink="http://www.w3.org/1999/xlink" width="81" height="81"><defs><style type="text/css"></style></defs><path d="M520 559h204c17.673 0 32 14.327 32 32 0 17.673-14.327 32-32 32H488c-17.673 0-32-14.327-32-32 0-0.167 0.001-0.334 0.004-0.5a32.65 32.65 0 0 1-0.004-0.5V277c0-17.673 14.327-32 32-32 17.673 0 32 14.327 32 32v282z m-8 401C264.576 960 64 759.424 64 512S264.576 64 512 64s448 200.576 448 448-200.576 448-448 448z m0-64c212.077 0 384-171.923 384-384S724.077 128 512 128 128 299.923 128 512s171.923 384 384 384z" p-id="1009"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/tool.svg b/src/assets/icons/svg/tool.svg new file mode 100644 index 0000000..48e0e35 --- /dev/null +++ b/src/assets/icons/svg/tool.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1553828490559" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1684" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M898.831744 900.517641 103.816972 900.517641c-36.002982 0-65.363683-29.286-65.363683-65.313541l0-554.949184c0-36.041868 29.361725-65.326844 65.363683-65.326844l795.015795 0c36.002982 0 65.198931 29.284977 65.198931 65.326844l0 554.949184C964.030675 871.231641 934.834726 900.517641 898.831744 900.517641L898.831744 900.517641zM103.816972 255.593236c-13.576203 0-24.711821 11.085476-24.711821 24.662703l0 554.949184c0 13.576203 11.136641 24.662703 24.711821 24.662703l795.015795 0c13.577227 0 24.547069-11.086499 24.547069-24.662703l0-554.949184c0-13.577227-10.970866-24.662703-24.547069-24.662703L103.816972 255.593236 103.816972 255.593236zM664.346245 251.774257c-11.161201 0-20.332071-9.080819-20.332071-20.332071l0-101.278661c0-13.576203-11.047614-24.623817-24.699542-24.623817L383.181611 105.539708c-13.576203 0-24.712845 11.04659-24.712845 24.623817l0 101.278661c0 11.252275-9.041934 20.332071-20.332071 20.332071-11.20111 0-20.319791-9.080819-20.319791-20.332071l0-101.278661c0-35.989679 29.323862-65.275679 65.364707-65.275679l236.133022 0c36.06745 0 65.402569 29.284977 65.402569 65.275679l0 101.278661C684.717202 242.694461 675.636383 251.774257 664.346245 251.774257L664.346245 251.774257zM413.233044 521.725502 75.694471 521.725502c-11.163247 0-20.333094-9.117658-20.333094-20.35663 0-11.252275 9.169847-20.332071 20.333094-20.332071l337.538573 0c11.277858 0 20.319791 9.080819 20.319791 20.332071C433.552835 512.607844 424.510902 521.725502 413.233044 521.725502L413.233044 521.725502zM912.894018 521.725502 575.367725 521.725502c-11.213389 0-20.332071-9.117658-20.332071-20.35663 0-11.252275 9.118682-20.332071 20.332071-20.332071l337.526293 0c11.290137 0 20.332071 9.080819 20.332071 20.332071C933.226089 512.607844 924.184155 521.725502 912.894018 521.725502L912.894018 521.725502zM557.56322 634.217552 445.085496 634.217552c-11.213389 0-20.332071-9.079796-20.332071-20.331048l0-168.763658c0-11.251252 9.118682-20.332071 20.332071-20.332071l112.478747 0c11.290137 0 20.370956 9.080819 20.370956 20.332071l0 168.763658C577.934177 625.137757 568.853357 634.217552 557.56322 634.217552L557.56322 634.217552zM465.417567 593.514525l71.827909 0L537.245476 465.454918l-71.827909 0L465.417567 593.514525 465.417567 593.514525z" p-id="1685"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/tree-table.svg b/src/assets/icons/svg/tree-table.svg new file mode 100644 index 0000000..8aafdb8 --- /dev/null +++ b/src/assets/icons/svg/tree-table.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M44.8 0h79.543C126.78 0 128 1.422 128 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H44.8c-2.438 0-3.657-1.422-3.657-4.267V4.267C41.143 1.422 42.362 0 44.8 0zm22.857 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 80 64 78.578 64 75.733V52.267C64 49.422 65.219 48 67.657 48zm0 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 128 64 126.578 64 123.733v-23.466C64 97.422 65.219 96 67.657 96zM50.286 68.267c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V32h6.4c2.02 0 3.658-1.91 3.658-4.267V4.267C27.429 1.91 25.79 0 23.77 0H3.657C1.637 0 0 1.91 0 4.267v23.466C0 30.09 1.637 32 3.657 32h6.4v80c0 2.356 1.638 4.267 3.657 4.267h36.572c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V68.267h32.915z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/tree.svg b/src/assets/icons/svg/tree.svg new file mode 100644 index 0000000..dd4b7dd --- /dev/null +++ b/src/assets/icons/svg/tree.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/upload.svg b/src/assets/icons/svg/upload.svg new file mode 100644 index 0000000..bae49c0 --- /dev/null +++ b/src/assets/icons/svg/upload.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1577540289643" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7922" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M530.944 458.24l4.8 3.456 122.176 106.816a32 32 0 0 1-37.44 51.584l-4.672-3.392L546.56 556.16v280.704a32 32 0 0 1-26.24 31.488l-5.76 0.512a32 32 0 0 1-31.424-26.24l-0.512-5.76-0.064-280.704-69.12 60.48a32 32 0 0 1-40.96 0.896l-4.16-3.968a32 32 0 0 1-0.96-40.96l4.032-4.16 122.176-106.816a32 32 0 0 1 37.312-3.456zM497.92 128c128.128 0 239.168 82.304 275.52 199.04 123.968 11.264 221.312 113.088 221.312 237.44 0 128.128-103.68 232.96-234.88 238.272h-5.888l-35.52 0.192a32 32 0 0 1-0.192-64l35.264-0.128 4.672-0.064c96.384-3.84 172.544-80.896 172.544-174.272 0-96.128-80.512-174.464-179.584-174.464h-1.984a32 32 0 0 1-32-25.28C695.872 264.96 604.736 192 497.92 192 381.824 192 285.44 277.76 274.816 388.48a32 32 0 0 1-28.352 28.8c-83.968 9.152-147.84 78.208-147.84 159.552l0.192 7.936c3.84 85.76 77.056 154.112 166.592 154.112h45.632a32 32 0 0 1 0 64h-45.632C142.016 802.944 40.32 708.032 34.88 586.88l-0.192-9.28c0-106.88 76.352-197.184 179.968-219.904C239.488 226.112 357.76 128 497.856 128z" p-id="7923"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/user.svg b/src/assets/icons/svg/user.svg new file mode 100644 index 0000000..0ba0716 --- /dev/null +++ b/src/assets/icons/svg/user.svg @@ -0,0 +1 @@ +<svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/validCode.svg b/src/assets/icons/svg/validCode.svg new file mode 100644 index 0000000..cfb1021 --- /dev/null +++ b/src/assets/icons/svg/validCode.svg @@ -0,0 +1 @@ +<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1569580729849" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1939" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M513.3 958.5c-142.2 0-397.9-222.1-401.6-440.5V268c1.7-39.6 31.7-72.3 71.1-77.3 49-4.6 97.1-16.5 142.7-35.3 47.8-14 91.9-38.3 129.4-71.1 30.3-24.4 72.9-26.3 105.3-4.6 39.9 30.7 83.8 55.9 130.5 74.6 48.6 14.7 98.2 25.9 148.4 33.7 38.5 7.6 67.1 40.3 69.5 79.5 3.3 84.9 2.5 169.9-2.6 254.7-33.7 281.6-253.7 436.4-392.7 436.3z m-0.1-813.7c-7.2-0.2-14.3 2-20 6.4-39.7 35.2-86.8 61.1-137.7 75.7-46.8 19.2-96.2 31-146.6 35.2-11 3.2-18.8 13-19.5 24.4v230.1c3.5 180.3 223.3 361 323.9 361s287.3-120.2 317.6-360.5c7.3-142.7 0-228.6 0-229.6-1.3-13.3-11-24.3-24-27.3-49.6-7.7-98.6-19-146.5-33.7-46.3-19.5-89.7-45.3-129-76.7-5.8-3.8-12.7-5.5-19.5-4.9l1.3-0.1z" fill="#C6CCDA" p-id="1940"></path><path d="M750.1 428L490.7 673.2c-11.7 11.1-29.5 12.9-43.1 4.2l-6.8-5.8-141.2-149.4c-9.3-9.3-12.7-22.9-9-35.5 3.8-12.6 14.1-22.1 27-24.8 12.9-2.7 26.1 1.9 34.6 11.9L469 597.5l233.7-221c14.6-12.8 36.8-11.6 49.9 2.7 13.2 14.2 11.5 35.3-2.5 48.8" fill="#C6CCDA" p-id="1941"></path></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/wechat.svg b/src/assets/icons/svg/wechat.svg new file mode 100644 index 0000000..c586e55 --- /dev/null +++ b/src/assets/icons/svg/wechat.svg @@ -0,0 +1 @@ +<svg width="128" height="110" xmlns="http://www.w3.org/2000/svg"><path d="M86.635 33.334c1.467 0 2.917.113 4.358.283C87.078 14.392 67.58.111 45.321.111 20.44.111.055 17.987.055 40.687c0 13.104 6.781 23.863 18.115 32.209l-4.527 14.352 15.82-8.364c5.666 1.182 10.207 2.395 15.858 2.395 1.42 0 2.829-.073 4.227-.189-.886-3.19-1.398-6.53-1.398-9.996 0-20.845 16.98-37.76 38.485-37.76zm-24.34-12.936c3.407 0 5.665 2.363 5.665 5.954 0 3.576-2.258 5.97-5.666 5.97-3.392 0-6.795-2.395-6.795-5.97 0-3.591 3.403-5.954 6.795-5.954zM30.616 32.323c-3.393 0-6.818-2.395-6.818-5.971 0-3.591 3.425-5.954 6.818-5.954 3.392 0 5.65 2.363 5.65 5.954 0 3.576-2.258 5.97-5.65 5.97z"/><path d="M127.945 70.52c0-19.075-18.108-34.623-38.448-34.623-21.537 0-38.5 15.548-38.5 34.623 0 19.108 16.963 34.622 38.5 34.622 4.508 0 9.058-1.2 13.584-2.395l12.414 7.167-3.404-11.923c9.087-7.184 15.854-16.712 15.854-27.471zm-50.928-5.97c-2.254 0-4.53-2.362-4.53-4.773 0-2.378 2.276-4.771 4.53-4.771 3.422 0 5.665 2.393 5.665 4.771 0 2.41-2.243 4.773-5.665 4.773zm24.897 0c-2.24 0-4.498-2.362-4.498-4.773 0-2.378 2.258-4.771 4.498-4.771 3.392 0 5.665 2.393 5.665 4.771 0 2.41-2.273 4.773-5.665 4.773z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svg/zip.svg b/src/assets/icons/svg/zip.svg new file mode 100644 index 0000000..f806fc4 --- /dev/null +++ b/src/assets/icons/svg/zip.svg @@ -0,0 +1 @@ +<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.527 116.793c.178.008.348.024.527.024h40.233c4.711-.005 8.53-3.677 8.534-8.21V18.895c-.004-4.532-3.823-8.204-8.534-8.209H79.054c-.179 0-.353.016-.527.024V0L0 10.082v107.406l78.527 10.342v-11.037zm0-101.362c.174-.024.348-.052.527-.052h40.233c2.018 0 3.659 1.578 3.659 3.52v89.713c-.003 1.942-1.64 3.517-3.659 3.519H79.054c-.179 0-.353-.028-.527-.052V15.431zM30.262 75.757l-18.721-.46V72.37l11.3-16.673v-.148l-10.266.164v-4.51l17.504-.44v3.264L18.696 70.76v.144l11.566.176v4.678zm9.419.231l-5.823-.144V50.671l5.823-.144v25.461zm22.255-11.632c-2.168 1.922-5.353 2.76-9.02 2.736-.702.004-1.402-.04-2.097-.131v9.303l-5.997-.148V50.743c1.852-.352 4.473-.647 8.218-.743 3.838-.096 6.608.539 8.48 1.913 1.807 1.306 3.032 3.5 3.032 6.112s-.926 4.833-2.612 6.331h-.004zM53.36 54.45c-.856-.01-1.71.083-2.541.275v7.682c.523.116 1.167.152 2.06.152 3.301-.004 5.36-1.614 5.36-4.314 0-2.425-1.772-3.843-4.875-3.791l-.004-.004zm39.847-37.066h9.564v3.795h-9.564v-3.795zm-9.568 5.68h9.564v3.8h-9.564v-3.8zm9.568 6.216h9.564v3.799h-9.564V29.28zm0 12h9.564v3.794h-9.564V41.28zm-9.568-6.096h9.564v3.795h-9.564v-3.795zm9.472 47.064c2.512 0 4.921-.96 6.697-2.67 1.776-1.708 2.773-4.026 2.772-6.442l-1.748-15.263c0-5.033-2.492-9.112-7.725-9.112-5.232 0-7.72 4.079-7.72 9.112l-1.752 15.263c-.001 2.417.996 4.735 2.773 6.444 1.777 1.71 4.187 2.669 6.7 2.668h.003zm-3.135-16.75h6.27v12.743h-6.27V65.5z"/></svg> \ No newline at end of file diff --git a/src/assets/icons/svgo.yml b/src/assets/icons/svgo.yml new file mode 100644 index 0000000..d11906a --- /dev/null +++ b/src/assets/icons/svgo.yml @@ -0,0 +1,22 @@ +# replace default config + +# multipass: true +# full: true + +plugins: + + # - name + # + # or: + # - name: false + # - name: true + # + # or: + # - name: + # param1: 1 + # param2: 2 + +- removeAttrs: + attrs: + - 'fill' + - 'fill-rule' diff --git a/src/assets/images/dark.svg b/src/assets/images/dark.svg new file mode 100644 index 0000000..f646bd7 --- /dev/null +++ b/src/assets/images/dark.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix> + <feMerge> + <feMergeNode in="shadowMatrixOuter1"></feMergeNode> + <feMergeNode in="SourceGraphic"></feMergeNode> + </feMerge> + </filter> + <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect> + <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix> + </filter> + </defs> + <g id="閰嶇疆闈㈡澘" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)"> + <g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)"> + <g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)"> + <mask id="mask-3" fill="white"> + <use xlink:href="#path-2"></use> + </mask> + <g id="Rectangle-18"> + <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use> + <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use> + </g> + <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect> + <rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect> + </g> + </g> + </g> + </g> +</svg> \ No newline at end of file diff --git a/src/assets/images/light.svg b/src/assets/images/light.svg new file mode 100644 index 0000000..ab7cc08 --- /dev/null +++ b/src/assets/images/light.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix> + <feMerge> + <feMergeNode in="shadowMatrixOuter1"></feMergeNode> + <feMergeNode in="SourceGraphic"></feMergeNode> + </feMerge> + </filter> + <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect> + <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix> + </filter> + </defs> + <g id="閰嶇疆闈㈡澘" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)"> + <g id="Group-8" transform="translate(1167.000000, 0.000000)"> + <g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)"> + <mask id="mask-3" fill="white"> + <use xlink:href="#path-2"></use> + </mask> + <g id="Rectangle-18"> + <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use> + <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use> + </g> + <rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect> + <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect> + </g> + </g> + </g> + </g> +</svg> \ No newline at end of file diff --git a/src/assets/images/login-background.jpg b/src/assets/images/login-background.jpg new file mode 100644 index 0000000..c7e73a3 --- /dev/null +++ b/src/assets/images/login-background.jpg Binary files differ diff --git a/src/assets/images/login-background1.jpg b/src/assets/images/login-background1.jpg new file mode 100644 index 0000000..8a89eb8 --- /dev/null +++ b/src/assets/images/login-background1.jpg Binary files differ diff --git a/src/assets/images/pay.png b/src/assets/images/pay.png new file mode 100644 index 0000000..bb8b967 --- /dev/null +++ b/src/assets/images/pay.png Binary files differ diff --git a/src/assets/images/profile.jpg b/src/assets/images/profile.jpg new file mode 100644 index 0000000..b3a940b --- /dev/null +++ b/src/assets/images/profile.jpg Binary files differ diff --git a/src/assets/logo/logo.png b/src/assets/logo/logo.png new file mode 100644 index 0000000..e263760 --- /dev/null +++ b/src/assets/logo/logo.png Binary files differ diff --git a/src/assets/styles/btn.scss b/src/assets/styles/btn.scss new file mode 100644 index 0000000..e6ba1a8 --- /dev/null +++ b/src/assets/styles/btn.scss @@ -0,0 +1,99 @@ +@import './variables.scss'; + +@mixin colorBtn($color) { + background: $color; + + &:hover { + color: $color; + + &:before, + &:after { + background: $color; + } + } +} + +.blue-btn { + @include colorBtn($blue) +} + +.light-blue-btn { + @include colorBtn($light-blue) +} + +.red-btn { + @include colorBtn($red) +} + +.pink-btn { + @include colorBtn($pink) +} + +.green-btn { + @include colorBtn($green) +} + +.tiffany-btn { + @include colorBtn($tiffany) +} + +.yellow-btn { + @include colorBtn($yellow) +} + +.pan-btn { + font-size: 14px; + color: #fff; + padding: 14px 36px; + border-radius: 8px; + border: none; + outline: none; + transition: 600ms ease all; + position: relative; + display: inline-block; + + &:hover { + background: #fff; + + &:before, + &:after { + width: 100%; + transition: 600ms ease all; + } + } + + &:before, + &:after { + content: ''; + position: absolute; + top: 0; + right: 0; + height: 2px; + width: 0; + transition: 400ms ease all; + } + + &::after { + right: inherit; + top: inherit; + left: 0; + bottom: 0; + } +} + +.custom-button { + display: inline-block; + line-height: 1; + white-space: nowrap; + cursor: pointer; + background: #fff; + color: #fff; + -webkit-appearance: none; + text-align: center; + box-sizing: border-box; + outline: 0; + margin: 0; + padding: 10px 15px; + font-size: 14px; + border-radius: 4px; +} diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss new file mode 100644 index 0000000..363092a --- /dev/null +++ b/src/assets/styles/element-ui.scss @@ -0,0 +1,92 @@ +// cover some element-ui styles + +.el-breadcrumb__inner, +.el-breadcrumb__inner a { + font-weight: 400 !important; +} + +.el-upload { + input[type="file"] { + display: none !important; + } +} + +.el-upload__input { + display: none; +} + +.cell { + .el-tag { + margin-right: 0px; + } +} + +.small-padding { + .cell { + padding-left: 5px; + padding-right: 5px; + } +} + +.fixed-width { + .el-button--mini { + padding: 7px 10px; + width: 60px; + } +} + +.status-col { + .cell { + padding: 0 10px; + text-align: center; + + .el-tag { + margin-right: 0px; + } + } +} + +// to fixed https://github.com/ElemeFE/element/issues/2461 +.el-dialog { + transform: none; + left: 0; + position: relative; + margin: 0 auto; +} + +// refine element ui upload +.upload-container { + .el-upload { + width: 100%; + + .el-upload-dragger { + width: 100%; + height: 200px; + } + } +} + +// dropdown +.el-dropdown-menu { + a { + display: block + } +} + +// fix date-picker ui bug in filter-item +.el-range-editor.el-input__inner { + display: inline-flex !important; +} + +// to fix el-date-picker css style +.el-range-separator { + box-sizing: content-box; +} + +.el-menu--collapse + > div + > .el-submenu + > .el-submenu__title + .el-submenu__icon-arrow { + display: none; +} \ No newline at end of file diff --git a/src/assets/styles/element-variables.scss b/src/assets/styles/element-variables.scss new file mode 100644 index 0000000..1615ff2 --- /dev/null +++ b/src/assets/styles/element-variables.scss @@ -0,0 +1,31 @@ +/** +* I think element-ui's default theme color is too light for long-term use. +* So I modified the default color and you can modify it to your liking. +**/ + +/* theme color */ +$--color-primary: #1890ff; +$--color-success: #13ce66; +$--color-warning: #ffba00; +$--color-danger: #ff4949; +// $--color-info: #1E1E1E; + +$--button-font-weight: 400; + +// $--color-text-regular: #1f2d3d; + +$--border-color-light: #dfe4ed; +$--border-color-lighter: #e6ebf5; + +$--table-border: 1px solid #dfe6ec; + +/* icon font path, required */ +$--font-path: '~element-ui/lib/theme-chalk/fonts'; + +@import "~element-ui/packages/theme-chalk/src/index"; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + theme: $--color-primary; +} diff --git a/src/assets/styles/index.scss b/src/assets/styles/index.scss new file mode 100644 index 0000000..2f3b9ef --- /dev/null +++ b/src/assets/styles/index.scss @@ -0,0 +1,182 @@ +@import './variables.scss'; +@import './mixin.scss'; +@import './transition.scss'; +@import './element-ui.scss'; +@import './sidebar.scss'; +@import './btn.scss'; + +body { + height: 100%; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; +} + +label { + font-weight: 700; +} + +html { + height: 100%; + box-sizing: border-box; +} + +#app { + height: 100%; +} + +*, +*:before, +*:after { + box-sizing: inherit; +} + +.no-padding { + padding: 0px !important; +} + +.padding-content { + padding: 4px 0; +} + +a:focus, +a:active { + outline: none; +} + +a, +a:focus, +a:hover { + cursor: pointer; + color: inherit; + text-decoration: none; +} + +div:focus { + outline: none; +} + +.fr { + float: right; +} + +.fl { + float: left; +} + +.pr-5 { + padding-right: 5px; +} + +.pl-5 { + padding-left: 5px; +} + +.block { + display: block; +} + +.pointer { + cursor: pointer; +} + +.inlineBlock { + display: block; +} + +.clearfix { + &:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; + } +} + +aside { + background: #eef1f6; + padding: 8px 24px; + margin-bottom: 20px; + border-radius: 2px; + display: block; + line-height: 32px; + font-size: 16px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + color: #2c3e50; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + a { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } + } +} + +//main-container鍏ㄥ眬鏍峰紡 +.app-container { + padding: 20px; +} + +.components-container { + margin: 30px 50px; + position: relative; +} + +.pagination-container { + margin-top: 30px; +} + +.text-center { + text-align: center +} + +.sub-navbar { + height: 50px; + line-height: 50px; + position: relative; + width: 100%; + text-align: right; + padding-right: 20px; + transition: 600ms ease position; + background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%); + + .subtitle { + font-size: 20px; + color: #fff; + } + + &.draft { + background: #d0d0d0; + } + + &.deleted { + background: #d0d0d0; + } +} + +.link-type, +.link-type:focus { + color: #337ab7; + cursor: pointer; + + &:hover { + color: rgb(32, 160, 255); + } +} + +.filter-container { + padding-bottom: 10px; + + .filter-item { + display: inline-block; + vertical-align: middle; + margin-bottom: 10px; + } +} diff --git a/src/assets/styles/mixin.scss b/src/assets/styles/mixin.scss new file mode 100644 index 0000000..06fa061 --- /dev/null +++ b/src/assets/styles/mixin.scss @@ -0,0 +1,66 @@ +@mixin clearfix { + &:after { + content: ""; + display: table; + clear: both; + } +} + +@mixin scrollBar { + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } +} + +@mixin relative { + position: relative; + width: 100%; + height: 100%; +} + +@mixin pct($pct) { + width: #{$pct}; + position: relative; + margin: 0 auto; +} + +@mixin triangle($width, $height, $color, $direction) { + $width: $width/2; + $color-border-style: $height solid $color; + $transparent-border-style: $width solid transparent; + height: 0; + width: 0; + + @if $direction==up { + border-bottom: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==right { + border-left: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } + + @else if $direction==down { + border-top: $color-border-style; + border-left: $transparent-border-style; + border-right: $transparent-border-style; + } + + @else if $direction==left { + border-right: $color-border-style; + border-top: $transparent-border-style; + border-bottom: $transparent-border-style; + } +} diff --git a/src/assets/styles/ruoyi.scss b/src/assets/styles/ruoyi.scss new file mode 100644 index 0000000..db8c29b --- /dev/null +++ b/src/assets/styles/ruoyi.scss @@ -0,0 +1,277 @@ + /** + * 閫氱敤css鏍峰紡甯冨眬澶勭悊 + * Copyright (c) 2019 ruoyi + */ + + /** 鍩虹閫氱敤 **/ +.pt5 { + padding-top: 5px; +} +.pr5 { + padding-right: 5px; +} +.pb5 { + padding-bottom: 5px; +} +.mt5 { + margin-top: 5px; +} +.mr5 { + margin-right: 5px; +} +.mb5 { + margin-bottom: 5px; +} +.mb8 { + margin-bottom: 8px; +} +.ml5 { + margin-left: 5px; +} +.mt10 { + margin-top: 10px; +} +.mr10 { + margin-right: 10px; +} +.mb10 { + margin-bottom: 10px; +} +.ml10 { + margin-left: 10px; +} +.mt20 { + margin-top: 20px; +} +.mr20 { + margin-right: 20px; +} +.mb20 { + margin-bottom: 20px; +} +.ml20 { + margin-left: 20px; +} + +.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 { + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; +} + +.el-message-box__status + .el-message-box__message{ + word-break: break-word; +} + +.el-dialog:not(.is-fullscreen) { + margin-top: 6vh !important; +} + +.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body { + overflow: auto; + overflow-x: hidden; + max-height: 70vh; + padding: 10px 20px 0; +} + +.el-table { + .el-table__header-wrapper, .el-table__fixed-header-wrapper { + th { + word-break: break-word; + background-color: #f8f8f9; + color: #515a6e; + height: 40px; + font-size: 13px; + } + } + .el-table__body-wrapper { + .el-button [class*="el-icon-"] + span { + margin-left: 1px; + } + } +} + +/** 琛ㄥ崟甯冨眬 **/ +.form-header { + font-size:15px; + color:#6379bb; + border-bottom:1px solid #ddd; + margin:8px 10px 25px 10px; + padding-bottom:5px +} + +/** 琛ㄦ牸甯冨眬 **/ +.pagination-container { + position: relative; + height: 25px; + margin-bottom: 10px; + margin-top: 15px; + padding: 10px 20px !important; +} + +/* tree border */ +.tree-border { + margin-top: 5px; + border: 1px solid #e5e6e7; + background: #FFFFFF none; + border-radius:4px; +} + +.pagination-container .el-pagination { + right: 0; + position: absolute; +} + +@media ( max-width : 768px) { + .pagination-container .el-pagination > .el-pagination__jump { + display: none !important; + } + .pagination-container .el-pagination > .el-pagination__sizes { + display: none !important; + } +} + +.el-table .fixed-width .el-button--mini { + padding-left: 0; + padding-right: 0; + width: inherit; +} + +/** 琛ㄦ牸鏇村鎿嶄綔涓嬫媺鏍峰紡 */ +.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine { + cursor: pointer; + margin-left: 5px; +} + +.el-table .el-dropdown, .el-icon-arrow-down { + font-size: 12px; +} + +.el-tree-node__content > .el-checkbox { + margin-right: 8px; +} + +.list-group-striped > .list-group-item { + border-left: 0; + border-right: 0; + border-radius: 0; + padding-left: 0; + padding-right: 0; +} + +.list-group { + padding-left: 0px; + list-style: none; +} + +.list-group-item { + border-bottom: 1px solid #e7eaec; + border-top: 1px solid #e7eaec; + margin-bottom: -1px; + padding: 11px 0px; + font-size: 13px; +} + +.pull-right { + float: right !important; +} + +.el-card__header { + padding: 14px 15px 7px; + min-height: 40px; +} + +.el-card__body { + padding: 15px 20px 20px 20px; +} + +.card-box { + padding-right: 15px; + padding-left: 15px; + margin-bottom: 10px; +} + +/* button color */ +.el-button--cyan.is-active, +.el-button--cyan:active { + background: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +.el-button--cyan:focus, +.el-button--cyan:hover { + background: #48D1CC; + border-color: #48D1CC; + color: #FFFFFF; +} + +.el-button--cyan { + background-color: #20B2AA; + border-color: #20B2AA; + color: #FFFFFF; +} + +/* text color */ +.text-navy { + color: #1ab394; +} + +.text-primary { + color: inherit; +} + +.text-success { + color: #1c84c6; +} + +.text-info { + color: #23c6c8; +} + +.text-warning { + color: #f8ac59; +} + +.text-danger { + color: #ed5565; +} + +.text-muted { + color: #888888; +} + +/* image */ +.img-circle { + border-radius: 50%; +} + +.img-lg { + width: 120px; + height: 120px; +} + +.avatar-upload-preview { + position: relative; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 200px; + height: 200px; + border-radius: 50%; + box-shadow: 0 0 4px #ccc; + overflow: hidden; +} + +/* 鎷栨嫿鍒楁牱寮� */ +.sortable-ghost{ + opacity: .8; + color: #fff!important; + background: #42b983!important; +} + +.top-right-btn { + position: relative; + float: right; +} diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss new file mode 100644 index 0000000..abe5b63 --- /dev/null +++ b/src/assets/styles/sidebar.scss @@ -0,0 +1,227 @@ +#app { + + .main-container { + height: 100%; + transition: margin-left .28s; + margin-left: $base-sidebar-width; + position: relative; + } + + .sidebarHide { + margin-left: 0!important; + } + + .sidebar-container { + -webkit-transition: width .28s; + transition: width 0.28s; + width: $base-sidebar-width !important; + background-color: $base-menu-background; + height: 100%; + position: fixed; + font-size: 0px; + top: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: hidden; + -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); + box-shadow: 2px 0 6px rgba(0,21,41,.35); + + // reset element-ui css + .horizontal-collapse-transition { + transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; + } + + .scrollbar-wrapper { + overflow-x: hidden !important; + } + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + + .el-scrollbar { + height: 100%; + } + + &.has-logo { + .el-scrollbar { + height: calc(100% - 50px); + } + } + + .is-horizontal { + display: none; + } + + a { + display: inline-block; + width: 100%; + overflow: hidden; + } + + .svg-icon { + margin-right: 16px; + } + + .el-menu { + border: none; + height: 100%; + width: 100% !important; + } + + .el-menu-item, .el-submenu__title { + overflow: hidden !important; + text-overflow: ellipsis !important; + white-space: nowrap !important; + } + + // menu hover + .submenu-title-noDropdown, + .el-submenu__title { + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .is-active > .el-submenu__title { + color: $base-menu-color-active !important; + } + + & .nest-menu .el-submenu>.el-submenu__title, + & .el-submenu .el-menu-item { + min-width: $base-sidebar-width !important; + + &:hover { + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + & .theme-dark .nest-menu .el-submenu>.el-submenu__title, + & .theme-dark .el-submenu .el-menu-item { + background-color: $base-sub-menu-background !important; + + &:hover { + background-color: $base-sub-menu-hover !important; + } + } + } + + .hideSidebar { + .sidebar-container { + width: 54px !important; + } + + .main-container { + margin-left: 54px; + } + + .submenu-title-noDropdown { + padding: 0 !important; + position: relative; + + .el-tooltip { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + } + } + + .el-submenu { + overflow: hidden; + + &>.el-submenu__title { + padding: 0 !important; + + .svg-icon { + margin-left: 20px; + } + + } + } + + .el-menu--collapse { + .el-submenu { + &>.el-submenu__title { + &>span { + height: 0; + width: 0; + overflow: hidden; + visibility: hidden; + display: inline-block; + } + } + } + } + } + + .el-menu--collapse .el-menu .el-submenu { + min-width: $base-sidebar-width !important; + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar-container { + transition: transform .28s; + width: $base-sidebar-width !important; + } + + &.hideSidebar { + .sidebar-container { + pointer-events: none; + transition-duration: 0.3s; + transform: translate3d(-$base-sidebar-width, 0, 0); + } + } + } + + .withoutAnimation { + + .main-container, + .sidebar-container { + transition: none; + } + } +} + +// when menu collapsed +.el-menu--vertical { + &>.el-menu { + .svg-icon { + margin-right: 16px; + } + } + + .nest-menu .el-submenu>.el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: rgba(0, 0, 0, 0.06) !important; + } + } + + // the scroll bar appears when the subMenu is too long + >.el-menu--popup { + max-height: 100vh; + overflow-y: auto; + + &::-webkit-scrollbar-track-piece { + background: #d3dce6; + } + + &::-webkit-scrollbar { + width: 6px; + } + + &::-webkit-scrollbar-thumb { + background: #99a9bf; + border-radius: 20px; + } + } +} diff --git a/src/assets/styles/transition.scss b/src/assets/styles/transition.scss new file mode 100644 index 0000000..073f8c6 --- /dev/null +++ b/src/assets/styles/transition.scss @@ -0,0 +1,49 @@ +// global transition css + +/* fade */ +.fade-enter-active, +.fade-leave-active { + transition: opacity 0.28s; +} + +.fade-enter, +.fade-leave-active { + opacity: 0; +} + +/* fade-transform */ +.fade-transform--move, +.fade-transform-leave-active, +.fade-transform-enter-active { + transition: all .5s; +} + +.fade-transform-enter { + opacity: 0; + transform: translateX(-30px); +} + +.fade-transform-leave-to { + opacity: 0; + transform: translateX(30px); +} + +/* breadcrumb transition */ +.breadcrumb-enter-active, +.breadcrumb-leave-active { + transition: all .5s; +} + +.breadcrumb-enter, +.breadcrumb-leave-active { + opacity: 0; + transform: translateX(20px); +} + +.breadcrumb-move { + transition: all .5s; +} + +.breadcrumb-leave-active { + position: absolute; +} diff --git a/src/assets/styles/variables.scss b/src/assets/styles/variables.scss new file mode 100644 index 0000000..d6391a7 --- /dev/null +++ b/src/assets/styles/variables.scss @@ -0,0 +1,54 @@ +// base color +$blue:#324157; +$light-blue:#3A71A8; +$red:#C03639; +$pink: #E65D6E; +$green: #30B08F; +$tiffany: #4AB7BD; +$yellow:#FEC171; +$panGreen: #30B08F; + +// 榛樿鑿滃崟涓婚椋庢牸 +$base-menu-color:#bfcbd9; +$base-menu-color-active:#f4f4f5; +$base-menu-background:#0b3466; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#1f2d3d; +$base-sub-menu-hover:#001528; + +// 鑷畾涔夋殫鑹茶彍鍗曢鏍� +/** +$base-menu-color:hsla(0,0%,100%,.65); +$base-menu-color-active:#fff; +$base-menu-background:#001529; +$base-logo-title-color: #ffffff; + +$base-menu-light-color:rgba(0,0,0,.70); +$base-menu-light-background:#ffffff; +$base-logo-light-title-color: #001529; + +$base-sub-menu-background:#000c17; +$base-sub-menu-hover:#001528; +*/ + +$base-sidebar-width: 230px; + +// the :export directive is the magic sauce for webpack +// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass +:export { + menuColor: $base-menu-color; + menuLightColor: $base-menu-light-color; + menuColorActive: $base-menu-color-active; + menuBackground: $base-menu-background; + menuLightBackground: $base-menu-light-background; + subMenuBackground: $base-sub-menu-background; + subMenuHover: $base-sub-menu-hover; + sideBarWidth: $base-sidebar-width; + logoTitleColor: $base-logo-title-color; + logoLightTitleColor: $base-logo-light-title-color +} diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue new file mode 100644 index 0000000..1696f54 --- /dev/null +++ b/src/components/Breadcrumb/index.vue @@ -0,0 +1,74 @@ +<template> + <el-breadcrumb class="app-breadcrumb" separator="/"> + <transition-group name="breadcrumb"> + <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> + <span v-if="item.redirect === 'noRedirect' || index == levelList.length - 1" class="no-redirect">{{ item.meta.title }}</span> + <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> + </el-breadcrumb-item> + </transition-group> + </el-breadcrumb> +</template> + +<script> +export default { + data() { + return { + levelList: null + } + }, + watch: { + $route(route) { + // if you go to the redirect page, do not update the breadcrumbs + if (route.path.startsWith('/redirect/')) { + return + } + this.getBreadcrumb() + } + }, + created() { + this.getBreadcrumb() + }, + methods: { + getBreadcrumb() { + // only show routes with meta.title + let matched = this.$route.matched.filter(item => item.meta && item.meta.title) + const first = matched[0] + + if (!this.isDashboard(first)) { + matched = [{ path: '/index', meta: { title: '棣栭〉' }}].concat(matched) + } + + this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) + }, + isDashboard(route) { + const name = route && route.name + if (!name) { + return false + } + return name.trim() === 'Index' + }, + handleLink(item) { + const { redirect, path } = item + if (redirect) { + this.$router.push(redirect) + return + } + this.$router.push(path) + } + } +} +</script> + +<style lang="scss" scoped> +.app-breadcrumb.el-breadcrumb { + display: inline-block; + font-size: 14px; + line-height: 50px; + margin-left: 8px; + + .no-redirect { + color: #97a8be; + cursor: text; + } +} +</style> diff --git a/src/components/Crontab/day.vue b/src/components/Crontab/day.vue new file mode 100644 index 0000000..fe3eaf0 --- /dev/null +++ b/src/components/Crontab/day.vue @@ -0,0 +1,161 @@ +<template> + <el-form size="small"> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 鏃ワ紝鍏佽鐨勯�氶厤绗, - * ? / L W] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 涓嶆寚瀹� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min="1" :max="30" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="31" /> 鏃� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 浠� + <el-input-number v-model='average01' :min="1" :max="30" /> 鍙峰紑濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="31 - average01 || 1" /> 鏃ユ墽琛屼竴娆� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="5"> + 姣忔湀 + <el-input-number v-model='workday' :min="1" :max="31" /> 鍙锋渶杩戠殑閭d釜宸ヤ綔鏃� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="6"> + 鏈湀鏈�鍚庝竴澶� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="7"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="item in 31" :key="item" :value="item">{{item}}</el-option> + </el-select> + </el-radio> + </el-form-item> + </el-form> +</template> + +<script> +export default { + data() { + return { + radioValue: 1, + workday: 1, + cycle01: 1, + cycle02: 2, + average01: 1, + average02: 1, + checkboxList: [], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-day', + props: ['check', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + ('day rachange'); + if (this.radioValue !== 2 && this.cron.week !== '?') { + this.$emit('update', 'week', '?', 'day') + } + + switch (this.radioValue) { + case 1: + this.$emit('update', 'day', '*'); + break; + case 2: + this.$emit('update', 'day', '?'); + break; + case 3: + this.$emit('update', 'day', this.cycleTotal); + break; + case 4: + this.$emit('update', 'day', this.averageTotal); + break; + case 5: + this.$emit('update', 'day', this.workday + 'W'); + break; + case 6: + this.$emit('update', 'day', 'L'); + break; + case 7: + this.$emit('update', 'day', this.checkboxString); + break; + } + ('day rachange end'); + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '3') { + this.$emit('update', 'day', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '4') { + this.$emit('update', 'day', this.averageTotal); + } + }, + // 鏈�杩戝伐浣滄棩鍊煎彉鍖栨椂 + workdayChange() { + if (this.radioValue == '5') { + this.$emit('update', 'day', this.workdayCheck + 'W'); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '7') { + this.$emit('update', 'day', this.checkboxString); + } + } + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'workdayCheck': 'workdayChange', + 'checkboxString': 'checkboxChange', + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, 1, 30) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 31, 31) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, 1, 30) + const average02 = this.checkNum(this.average02, 1, 31 - average01 || 0) + return average01 + '/' + average02; + }, + // 璁$畻宸ヤ綔鏃ユ牸寮� + workdayCheck: function () { + const workday = this.checkNum(this.workday, 1, 31) + return workday; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> diff --git a/src/components/Crontab/hour.vue b/src/components/Crontab/hour.vue new file mode 100644 index 0000000..4b1f1fc --- /dev/null +++ b/src/components/Crontab/hour.vue @@ -0,0 +1,114 @@ +<template> + <el-form size="small"> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 灏忔椂锛屽厑璁哥殑閫氶厤绗, - * /] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min="0" :max="22" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="23" /> 灏忔椂 + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 浠� + <el-input-number v-model='average01' :min="0" :max="22" /> 灏忔椂寮�濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="23 - average01 || 0" /> 灏忔椂鎵ц涓�娆� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option> + </el-select> + </el-radio> + </el-form-item> + </el-form> +</template> + +<script> +export default { + data() { + return { + radioValue: 1, + cycle01: 0, + cycle02: 1, + average01: 0, + average02: 1, + checkboxList: [], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-hour', + props: ['check', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + switch (this.radioValue) { + case 1: + this.$emit('update', 'hour', '*') + break; + case 2: + this.$emit('update', 'hour', this.cycleTotal); + break; + case 3: + this.$emit('update', 'hour', this.averageTotal); + break; + case 4: + this.$emit('update', 'hour', this.checkboxString); + break; + } + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '2') { + this.$emit('update', 'hour', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '3') { + this.$emit('update', 'hour', this.averageTotal); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '4') { + this.$emit('update', 'hour', this.checkboxString); + } + } + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'checkboxString': 'checkboxChange' + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, 0, 22) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 23) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, 0, 22) + const average02 = this.checkNum(this.average02, 1, 23 - average01 || 0) + return average01 + '/' + average02; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> diff --git a/src/components/Crontab/index.vue b/src/components/Crontab/index.vue new file mode 100644 index 0000000..3963df2 --- /dev/null +++ b/src/components/Crontab/index.vue @@ -0,0 +1,430 @@ +<template> + <div> + <el-tabs type="border-card"> + <el-tab-pane label="绉�" v-if="shouldHide('second')"> + <CrontabSecond + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronsecond" + /> + </el-tab-pane> + + <el-tab-pane label="鍒嗛挓" v-if="shouldHide('min')"> + <CrontabMin + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronmin" + /> + </el-tab-pane> + + <el-tab-pane label="灏忔椂" v-if="shouldHide('hour')"> + <CrontabHour + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronhour" + /> + </el-tab-pane> + + <el-tab-pane label="鏃�" v-if="shouldHide('day')"> + <CrontabDay + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronday" + /> + </el-tab-pane> + + <el-tab-pane label="鏈�" v-if="shouldHide('month')"> + <CrontabMonth + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronmonth" + /> + </el-tab-pane> + + <el-tab-pane label="鍛�" v-if="shouldHide('week')"> + <CrontabWeek + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronweek" + /> + </el-tab-pane> + + <el-tab-pane label="骞�" v-if="shouldHide('year')"> + <CrontabYear + @update="updateCrontabValue" + :check="checkNumber" + :cron="crontabValueObj" + ref="cronyear" + /> + </el-tab-pane> + </el-tabs> + + <div class="popup-main"> + <div class="popup-result"> + <p class="title">鏃堕棿琛ㄨ揪寮�</p> + <table> + <thead> + <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th> + <th>Cron 琛ㄨ揪寮�</th> + </thead> + <tbody> + <td> + <span>{{crontabValueObj.second}}</span> + </td> + <td> + <span>{{crontabValueObj.min}}</span> + </td> + <td> + <span>{{crontabValueObj.hour}}</span> + </td> + <td> + <span>{{crontabValueObj.day}}</span> + </td> + <td> + <span>{{crontabValueObj.month}}</span> + </td> + <td> + <span>{{crontabValueObj.week}}</span> + </td> + <td> + <span>{{crontabValueObj.year}}</span> + </td> + <td> + <span>{{crontabValueString}}</span> + </td> + </tbody> + </table> + </div> + <CrontabResult :ex="crontabValueString"></CrontabResult> + + <div class="pop_btn"> + <el-button size="small" type="primary" @click="submitFill">纭畾</el-button> + <el-button size="small" type="warning" @click="clearCron">閲嶇疆</el-button> + <el-button size="small" @click="hidePopup">鍙栨秷</el-button> + </div> + </div> + </div> +</template> + +<script> +import CrontabSecond from "./second.vue"; +import CrontabMin from "./min.vue"; +import CrontabHour from "./hour.vue"; +import CrontabDay from "./day.vue"; +import CrontabMonth from "./month.vue"; +import CrontabWeek from "./week.vue"; +import CrontabYear from "./year.vue"; +import CrontabResult from "./result.vue"; + +export default { + data() { + return { + tabTitles: ["绉�", "鍒嗛挓", "灏忔椂", "鏃�", "鏈�", "鍛�", "骞�"], + tabActive: 0, + myindex: 0, + crontabValueObj: { + second: "*", + min: "*", + hour: "*", + day: "*", + month: "*", + week: "?", + year: "", + }, + }; + }, + name: "vcrontab", + props: ["expression", "hideComponent"], + methods: { + shouldHide(key) { + if (this.hideComponent && this.hideComponent.includes(key)) return false; + return true; + }, + resolveExp() { + // 鍙嶈В鏋� 琛ㄨ揪寮� + if (this.expression) { + let arr = this.expression.split(" "); + if (arr.length >= 6) { + //6 浣嶄互涓婃槸鍚堟硶琛ㄨ揪寮� + let obj = { + second: arr[0], + min: arr[1], + hour: arr[2], + day: arr[3], + month: arr[4], + week: arr[5], + year: arr[6] ? arr[6] : "", + }; + this.crontabValueObj = { + ...obj, + }; + for (let i in obj) { + if (obj[i]) this.changeRadio(i, obj[i]); + } + } + } else { + // 娌℃湁浼犲叆鐨勮〃杈惧紡 鍒欒繕鍘� + this.clearCron(); + } + }, + // tab鍒囨崲鍊� + tabCheck(index) { + this.tabActive = index; + }, + // 鐢卞瓙缁勪欢瑙﹀彂锛屾洿鏀硅〃杈惧紡缁勬垚鐨勫瓧娈靛�� + updateCrontabValue(name, value, from) { + "updateCrontabValue", name, value, from; + this.crontabValueObj[name] = value; + if (from && from !== name) { + console.log(`鏉ヨ嚜缁勪欢 ${from} 鏀瑰彉浜� ${name} ${value}`); + this.changeRadio(name, value); + } + }, + // 璧嬪�煎埌缁勪欢 + changeRadio(name, value) { + let arr = ["second", "min", "hour", "month"], + refName = "cron" + name, + insValue; + + if (!this.$refs[refName]) return; + + if (arr.includes(name)) { + if (value === "*") { + insValue = 1; + } else if (value.indexOf("-") > -1) { + let indexArr = value.split("-"); + isNaN(indexArr[0]) + ? (this.$refs[refName].cycle01 = 0) + : (this.$refs[refName].cycle01 = indexArr[0]); + this.$refs[refName].cycle02 = indexArr[1]; + insValue = 2; + } else if (value.indexOf("/") > -1) { + let indexArr = value.split("/"); + isNaN(indexArr[0]) + ? (this.$refs[refName].average01 = 0) + : (this.$refs[refName].average01 = indexArr[0]); + this.$refs[refName].average02 = indexArr[1]; + insValue = 3; + } else { + insValue = 4; + this.$refs[refName].checkboxList = value.split(","); + } + } else if (name == "day") { + if (value === "*") { + insValue = 1; + } else if (value == "?") { + insValue = 2; + } else if (value.indexOf("-") > -1) { + let indexArr = value.split("-"); + isNaN(indexArr[0]) + ? (this.$refs[refName].cycle01 = 0) + : (this.$refs[refName].cycle01 = indexArr[0]); + this.$refs[refName].cycle02 = indexArr[1]; + insValue = 3; + } else if (value.indexOf("/") > -1) { + let indexArr = value.split("/"); + isNaN(indexArr[0]) + ? (this.$refs[refName].average01 = 0) + : (this.$refs[refName].average01 = indexArr[0]); + this.$refs[refName].average02 = indexArr[1]; + insValue = 4; + } else if (value.indexOf("W") > -1) { + let indexArr = value.split("W"); + isNaN(indexArr[0]) + ? (this.$refs[refName].workday = 0) + : (this.$refs[refName].workday = indexArr[0]); + insValue = 5; + } else if (value === "L") { + insValue = 6; + } else { + this.$refs[refName].checkboxList = value.split(","); + insValue = 7; + } + } else if (name == "week") { + if (value === "*") { + insValue = 1; + } else if (value == "?") { + insValue = 2; + } else if (value.indexOf("-") > -1) { + let indexArr = value.split("-"); + isNaN(indexArr[0]) + ? (this.$refs[refName].cycle01 = 0) + : (this.$refs[refName].cycle01 = indexArr[0]); + this.$refs[refName].cycle02 = indexArr[1]; + insValue = 3; + } else if (value.indexOf("#") > -1) { + let indexArr = value.split("#"); + isNaN(indexArr[0]) + ? (this.$refs[refName].average01 = 1) + : (this.$refs[refName].average01 = indexArr[0]); + this.$refs[refName].average02 = indexArr[1]; + insValue = 4; + } else if (value.indexOf("L") > -1) { + let indexArr = value.split("L"); + isNaN(indexArr[0]) + ? (this.$refs[refName].weekday = 1) + : (this.$refs[refName].weekday = indexArr[0]); + insValue = 5; + } else { + this.$refs[refName].checkboxList = value.split(","); + insValue = 6; + } + } else if (name == "year") { + if (value == "") { + insValue = 1; + } else if (value == "*") { + insValue = 2; + } else if (value.indexOf("-") > -1) { + insValue = 3; + } else if (value.indexOf("/") > -1) { + insValue = 4; + } else { + this.$refs[refName].checkboxList = value.split(","); + insValue = 5; + } + } + this.$refs[refName].radioValue = insValue; + }, + // 琛ㄥ崟閫夐」鐨勫瓙缁勪欢鏍¢獙鏁板瓧鏍煎紡锛堥�氳繃-props浼犻�掞級 + checkNumber(value, minLimit, maxLimit) { + // 妫�鏌ュ繀椤讳负鏁存暟 + value = Math.floor(value); + if (value < minLimit) { + value = minLimit; + } else if (value > maxLimit) { + value = maxLimit; + } + return value; + }, + // 闅愯棌寮圭獥 + hidePopup() { + this.$emit("hide"); + }, + // 濉厖琛ㄨ揪寮� + submitFill() { + this.$emit("fill", this.crontabValueString); + this.hidePopup(); + }, + clearCron() { + // 杩樺師閫夋嫨椤� + ("鍑嗗杩樺師"); + this.crontabValueObj = { + second: "*", + min: "*", + hour: "*", + day: "*", + month: "*", + week: "?", + year: "", + }; + for (let j in this.crontabValueObj) { + this.changeRadio(j, this.crontabValueObj[j]); + } + }, + }, + computed: { + crontabValueString: function() { + let obj = this.crontabValueObj; + let str = + obj.second + + " " + + obj.min + + " " + + obj.hour + + " " + + obj.day + + " " + + obj.month + + " " + + obj.week + + (obj.year == "" ? "" : " " + obj.year); + return str; + }, + }, + components: { + CrontabSecond, + CrontabMin, + CrontabHour, + CrontabDay, + CrontabMonth, + CrontabWeek, + CrontabYear, + CrontabResult, + }, + watch: { + expression: "resolveExp", + hideComponent(value) { + // 闅愯棌閮ㄥ垎缁勪欢 + }, + }, + mounted: function() { + this.resolveExp(); + }, +}; +</script> +<style scoped> +.pop_btn { + text-align: center; + margin-top: 20px; +} +.popup-main { + position: relative; + margin: 10px auto; + background: #fff; + border-radius: 5px; + font-size: 12px; + overflow: hidden; +} +.popup-title { + overflow: hidden; + line-height: 34px; + padding-top: 6px; + background: #f2f2f2; +} +.popup-result { + box-sizing: border-box; + line-height: 24px; + margin: 25px auto; + padding: 15px 10px 10px; + border: 1px solid #ccc; + position: relative; +} +.popup-result .title { + position: absolute; + top: -28px; + left: 50%; + width: 140px; + font-size: 14px; + margin-left: -70px; + text-align: center; + line-height: 30px; + background: #fff; +} +.popup-result table { + text-align: center; + width: 100%; + margin: 0 auto; +} +.popup-result table span { + display: block; + width: 100%; + font-family: arial; + line-height: 30px; + height: 30px; + white-space: nowrap; + overflow: hidden; + border: 1px solid #e8e8e8; +} +.popup-result-scroll { + font-size: 12px; + line-height: 24px; + height: 10em; + overflow-y: auto; +} +</style> diff --git a/src/components/Crontab/min.vue b/src/components/Crontab/min.vue new file mode 100644 index 0000000..43cab90 --- /dev/null +++ b/src/components/Crontab/min.vue @@ -0,0 +1,116 @@ +<template> + <el-form size="small"> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 鍒嗛挓锛屽厑璁哥殑閫氶厤绗, - * /] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min="0" :max="58" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 鍒嗛挓 + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 浠� + <el-input-number v-model='average01' :min="0" :max="58" /> 鍒嗛挓寮�濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 鍒嗛挓鎵ц涓�娆� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option> + </el-select> + </el-radio> + </el-form-item> + </el-form> + +</template> + +<script> +export default { + data() { + return { + radioValue: 1, + cycle01: 1, + cycle02: 2, + average01: 0, + average02: 1, + checkboxList: [], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-min', + props: ['check', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + switch (this.radioValue) { + case 1: + this.$emit('update', 'min', '*', 'min'); + break; + case 2: + this.$emit('update', 'min', this.cycleTotal, 'min'); + break; + case 3: + this.$emit('update', 'min', this.averageTotal, 'min'); + break; + case 4: + this.$emit('update', 'min', this.checkboxString, 'min'); + break; + } + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '2') { + this.$emit('update', 'min', this.cycleTotal, 'min'); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '3') { + this.$emit('update', 'min', this.averageTotal, 'min'); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '4') { + this.$emit('update', 'min', this.checkboxString, 'min'); + } + }, + + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'checkboxString': 'checkboxChange', + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, 0, 58) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, 0, 58) + const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0) + return average01 + '/' + average02; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> \ No newline at end of file diff --git a/src/components/Crontab/month.vue b/src/components/Crontab/month.vue new file mode 100644 index 0000000..fd0ac38 --- /dev/null +++ b/src/components/Crontab/month.vue @@ -0,0 +1,114 @@ +<template> + <el-form size='small'> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 鏈堬紝鍏佽鐨勯�氶厤绗, - * /] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min="1" :max="11" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 2" :max="12" /> 鏈� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 浠� + <el-input-number v-model='average01' :min="1" :max="11" /> 鏈堝紑濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="12 - average01 || 0" /> 鏈堟湀鎵ц涓�娆� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="item in 12" :key="item" :value="item">{{item}}</el-option> + </el-select> + </el-radio> + </el-form-item> + </el-form> +</template> + +<script> +export default { + data() { + return { + radioValue: 1, + cycle01: 1, + cycle02: 2, + average01: 1, + average02: 1, + checkboxList: [], + checkNum: this.check + } + }, + name: 'crontab-month', + props: ['check', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + switch (this.radioValue) { + case 1: + this.$emit('update', 'month', '*'); + break; + case 2: + this.$emit('update', 'month', this.cycleTotal); + break; + case 3: + this.$emit('update', 'month', this.averageTotal); + break; + case 4: + this.$emit('update', 'month', this.checkboxString); + break; + } + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '2') { + this.$emit('update', 'month', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '3') { + this.$emit('update', 'month', this.averageTotal); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '4') { + this.$emit('update', 'month', this.checkboxString); + } + } + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'checkboxString': 'checkboxChange' + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, 1, 11) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 2, 12) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, 1, 11) + const average02 = this.checkNum(this.average02, 1, 12 - average01 || 0) + return average01 + '/' + average02; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> diff --git a/src/components/Crontab/result.vue b/src/components/Crontab/result.vue new file mode 100644 index 0000000..aea6e0e --- /dev/null +++ b/src/components/Crontab/result.vue @@ -0,0 +1,559 @@ +<template> + <div class="popup-result"> + <p class="title">鏈�杩�5娆¤繍琛屾椂闂�</p> + <ul class="popup-result-scroll"> + <template v-if='isShow'> + <li v-for='item in resultList' :key="item">{{item}}</li> + </template> + <li v-else>璁$畻缁撴灉涓�...</li> + </ul> + </div> +</template> + +<script> +export default { + data() { + return { + dayRule: '', + dayRuleSup: '', + dateArr: [], + resultList: [], + isShow: false + } + }, + name: 'crontab-result', + methods: { + // 琛ㄨ揪寮忓�煎彉鍖栨椂锛屽紑濮嬪幓璁$畻缁撴灉 + expressionChange() { + + // 璁$畻寮�濮�-闅愯棌缁撴灉 + this.isShow = false; + // 鑾峰彇瑙勫垯鏁扮粍[0绉掋��1鍒嗐��2鏃躲��3鏃ャ��4鏈堛��5鏄熸湡銆�6骞碷 + let ruleArr = this.$options.propsData.ex.split(' '); + // 鐢ㄤ簬璁板綍杩涘叆寰幆鐨勬鏁� + let nums = 0; + // 鐢ㄤ簬鏆傛椂瀛樼鍙锋椂闂磋鍒欑粨鏋滅殑鏁扮粍 + let resultArr = []; + // 鑾峰彇褰撳墠鏃堕棿绮剧‘鑷砙骞淬�佹湀銆佹棩銆佹椂銆佸垎銆佺] + let nTime = new Date(); + let nYear = nTime.getFullYear(); + let nMonth = nTime.getMonth() + 1; + let nDay = nTime.getDate(); + let nHour = nTime.getHours(); + let nMin = nTime.getMinutes(); + let nSecond = nTime.getSeconds(); + // 鏍规嵁瑙勫垯鑾峰彇鍒拌繎100骞村彲鑳藉勾鏁扮粍銆佹湀鏁扮粍绛夌瓑 + this.getSecondArr(ruleArr[0]); + this.getMinArr(ruleArr[1]); + this.getHourArr(ruleArr[2]); + this.getDayArr(ruleArr[3]); + this.getMonthArr(ruleArr[4]); + this.getWeekArr(ruleArr[5]); + this.getYearArr(ruleArr[6], nYear); + // 灏嗚幏鍙栧埌鐨勬暟缁勮祴鍊�-鏂逛究浣跨敤 + let sDate = this.dateArr[0]; + let mDate = this.dateArr[1]; + let hDate = this.dateArr[2]; + let DDate = this.dateArr[3]; + let MDate = this.dateArr[4]; + let YDate = this.dateArr[5]; + // 鑾峰彇褰撳墠鏃堕棿鍦ㄦ暟缁勪腑鐨勭储寮� + let sIdx = this.getIndex(sDate, nSecond); + let mIdx = this.getIndex(mDate, nMin); + let hIdx = this.getIndex(hDate, nHour); + let DIdx = this.getIndex(DDate, nDay); + let MIdx = this.getIndex(MDate, nMonth); + let YIdx = this.getIndex(YDate, nYear); + // 閲嶇疆鏈堟棩鏃跺垎绉掔殑鍑芥暟(鍚庨潰鐢ㄧ殑姣旇緝澶�) + const resetSecond = function () { + sIdx = 0; + nSecond = sDate[sIdx] + } + const resetMin = function () { + mIdx = 0; + nMin = mDate[mIdx] + resetSecond(); + } + const resetHour = function () { + hIdx = 0; + nHour = hDate[hIdx] + resetMin(); + } + const resetDay = function () { + DIdx = 0; + nDay = DDate[DIdx] + resetHour(); + } + const resetMonth = function () { + MIdx = 0; + nMonth = MDate[MIdx] + resetDay(); + } + // 濡傛灉褰撳墠骞翠唤涓嶄负鏁扮粍涓綋鍓嶅�� + if (nYear !== YDate[YIdx]) { + resetMonth(); + } + // 濡傛灉褰撳墠鏈堜唤涓嶄负鏁扮粍涓綋鍓嶅�� + if (nMonth !== MDate[MIdx]) { + resetDay(); + } + // 濡傛灉褰撳墠鈥滄棩鈥濅笉涓烘暟缁勪腑褰撳墠鍊� + if (nDay !== DDate[DIdx]) { + resetHour(); + } + // 濡傛灉褰撳墠鈥滄椂鈥濅笉涓烘暟缁勪腑褰撳墠鍊� + if (nHour !== hDate[hIdx]) { + resetMin(); + } + // 濡傛灉褰撳墠鈥滃垎鈥濅笉涓烘暟缁勪腑褰撳墠鍊� + if (nMin !== mDate[mIdx]) { + resetSecond(); + } + + // 寰幆骞翠唤鏁扮粍 + goYear: for (let Yi = YIdx; Yi < YDate.length; Yi++) { + let YY = YDate[Yi]; + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (nMonth > MDate[MDate.length - 1]) { + resetMonth(); + continue; + } + // 寰幆鏈堜唤鏁扮粍 + goMonth: for (let Mi = MIdx; Mi < MDate.length; Mi++) { + // 璧嬪�笺�佹柟渚垮悗闈㈣繍绠� + let MM = MDate[Mi]; + MM = MM < 10 ? '0' + MM : MM; + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (nDay > DDate[DDate.length - 1]) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue; + } + // 寰幆鏃ユ湡鏁扮粍 + goDay: for (let Di = DIdx; Di < DDate.length; Di++) { + // 璧嬪�笺�佹柟渚垮悗闈㈣繍绠� + let DD = DDate[Di]; + let thisDD = DD < 10 ? '0' + DD : DD; + + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (nHour > hDate[hDate.length - 1]) { + resetHour(); + if (Di == DDate.length - 1) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue goMonth; + } + continue; + } + + // 鍒ゆ柇鏃ユ湡鐨勫悎娉曟�э紝涓嶅悎娉曠殑璇濅篃鏄烦鍑哄綋鍓嶅惊鐜� + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true && this.dayRule !== 'workDay' && this.dayRule !== 'lastWeek' && this.dayRule !== 'lastDay') { + resetDay(); + continue goMonth; + } + // 濡傛灉鏃ユ湡瑙勫垯涓湁鍊兼椂 + if (this.dayRule == 'lastDay') { + // 濡傛灉涓嶆槸鍚堟硶鏃ユ湡鍒欓渶瑕佸皢鍓嶅皢鏃ユ湡璋冨埌鍚堟硶鏃ユ湡鍗虫湀鏈渶鍚庝竴澶� + + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + DD--; + + thisDD = DD < 10 ? '0' + DD : DD; + } + } + } else if (this.dayRule == 'workDay') { + // 鏍¢獙骞惰皟鏁村鏋滄槸2鏈�30鍙疯繖绉嶆棩鏈熶紶杩涙潵鏃堕渶璋冩暣鑷虫甯告湀搴� + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + DD--; + thisDD = DD < 10 ? '0' + DD : DD; + } + } + // 鑾峰彇杈惧埌鏉′欢鐨勬棩鏈熸槸鏄熸湡X + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week'); + // 褰撴槦鏈熸棩鏃� + if (thisWeek == 1) { + // 鍏堟壘涓嬩竴涓棩锛屽苟鍒ゆ柇鏄惁涓烘湀搴� + DD++; + thisDD = DD < 10 ? '0' + DD : DD; + // 鍒ゆ柇涓嬩竴鏃ュ凡缁忎笉鏄悎娉曟棩鏈� + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + DD -= 3; + } + } else if (thisWeek == 7) { + // 褰撴槦鏈�6鏃跺彧闇�鍒ゆ柇涓嶆槸1鍙峰氨鍙繘琛屾搷浣� + if (this.dayRuleSup !== 1) { + DD--; + } else { + DD += 2; + } + } + } else if (this.dayRule == 'weekDay') { + // 濡傛灉鎸囧畾浜嗘槸鏄熸湡鍑� + // 鑾峰彇褰撳墠鏃ユ湡鏄睘浜庢槦鏈熷嚑 + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week'); + // 鏍¢獙褰撳墠鏄熸湡鏄惁鍦ㄦ槦鏈熸睜锛坉ayRuleSup锛変腑 + if (this.dayRuleSup.indexOf(thisWeek) < 0) { + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (Di == DDate.length - 1) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue goMonth; + } + continue; + } + } else if (this.dayRule == 'assWeek') { + // 濡傛灉鎸囧畾浜嗘槸绗嚑鍛ㄧ殑鏄熸湡鍑� + // 鑾峰彇姣忔湀1鍙锋槸灞炰簬鏄熸湡鍑� + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + DD + ' 00:00:00'), 'week'); + if (this.dayRuleSup[1] >= thisWeek) { + DD = (this.dayRuleSup[0] - 1) * 7 + this.dayRuleSup[1] - thisWeek + 1; + } else { + DD = this.dayRuleSup[0] * 7 + this.dayRuleSup[1] - thisWeek + 1; + } + } else if (this.dayRule == 'lastWeek') { + // 濡傛灉鎸囧畾浜嗘瘡鏈堟渶鍚庝竴涓槦鏈熷嚑 + // 鏍¢獙骞惰皟鏁村鏋滄槸2鏈�30鍙疯繖绉嶆棩鏈熶紶杩涙潵鏃堕渶璋冩暣鑷虫甯告湀搴� + if (this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + while (DD > 0 && this.checkDate(YY + '-' + MM + '-' + thisDD + ' 00:00:00') !== true) { + DD--; + thisDD = DD < 10 ? '0' + DD : DD; + } + } + // 鑾峰彇鏈堟湯鏈�鍚庝竴澶╂槸鏄熸湡鍑� + let thisWeek = this.formatDate(new Date(YY + '-' + MM + '-' + thisDD + ' 00:00:00'), 'week'); + // 鎵惧埌瑕佹眰涓渶杩戠殑閭d釜鏄熸湡鍑� + if (this.dayRuleSup < thisWeek) { + DD -= thisWeek - this.dayRuleSup; + } else if (this.dayRuleSup > thisWeek) { + DD -= 7 - (this.dayRuleSup - thisWeek) + } + } + // 鍒ゆ柇鏃堕棿鍊兼槸鍚﹀皬浜�10缃崲鎴愨��05鈥濊繖绉嶆牸寮� + DD = DD < 10 ? '0' + DD : DD; + + // 寰幆鈥滄椂鈥濇暟缁� + goHour: for (let hi = hIdx; hi < hDate.length; hi++) { + let hh = hDate[hi] < 10 ? '0' + hDate[hi] : hDate[hi] + + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (nMin > mDate[mDate.length - 1]) { + resetMin(); + if (hi == hDate.length - 1) { + resetHour(); + if (Di == DDate.length - 1) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue goMonth; + } + continue goDay; + } + continue; + } + // 寰幆"鍒�"鏁扮粍 + goMin: for (let mi = mIdx; mi < mDate.length; mi++) { + let mm = mDate[mi] < 10 ? '0' + mDate[mi] : mDate[mi]; + + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (nSecond > sDate[sDate.length - 1]) { + resetSecond(); + if (mi == mDate.length - 1) { + resetMin(); + if (hi == hDate.length - 1) { + resetHour(); + if (Di == DDate.length - 1) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue goMonth; + } + continue goDay; + } + continue goHour; + } + continue; + } + // 寰幆"绉�"鏁扮粍 + goSecond: for (let si = sIdx; si <= sDate.length - 1; si++) { + let ss = sDate[si] < 10 ? '0' + sDate[si] : sDate[si]; + // 娣诲姞褰撳墠鏃堕棿锛堟椂闂村悎娉曟�у湪鏃ユ湡寰幆鏃跺凡缁忓垽鏂級 + if (MM !== '00' && DD !== '00') { + resultArr.push(YY + '-' + MM + '-' + DD + ' ' + hh + ':' + mm + ':' + ss) + nums++; + } + // 濡傛灉鏉℃暟婊′簡灏遍��鍑哄惊鐜� + if (nums == 5) break goYear; + // 濡傛灉鍒拌揪鏈�澶у�兼椂 + if (si == sDate.length - 1) { + resetSecond(); + if (mi == mDate.length - 1) { + resetMin(); + if (hi == hDate.length - 1) { + resetHour(); + if (Di == DDate.length - 1) { + resetDay(); + if (Mi == MDate.length - 1) { + resetMonth(); + continue goYear; + } + continue goMonth; + } + continue goDay; + } + continue goHour; + } + continue goMin; + } + } //goSecond + } //goMin + }//goHour + }//goDay + }//goMonth + } + // 鍒ゆ柇100骞村唴鐨勭粨鏋滄潯鏁� + if (resultArr.length == 0) { + this.resultList = ['娌℃湁杈惧埌鏉′欢鐨勭粨鏋滐紒']; + } else { + this.resultList = resultArr; + if (resultArr.length !== 5) { + this.resultList.push('鏈�杩�100骞村唴鍙湁涓婇潰' + resultArr.length + '鏉$粨鏋滐紒') + } + } + // 璁$畻瀹屾垚-鏄剧ず缁撴灉 + this.isShow = true; + + + }, + // 鐢ㄤ簬璁$畻鏌愪綅鏁板瓧鍦ㄦ暟缁勪腑鐨勭储寮� + getIndex(arr, value) { + if (value <= arr[0] || value > arr[arr.length - 1]) { + return 0; + } else { + for (let i = 0; i < arr.length - 1; i++) { + if (value > arr[i] && value <= arr[i + 1]) { + return i + 1; + } + } + } + }, + // 鑾峰彇"骞�"鏁扮粍 + getYearArr(rule, year) { + this.dateArr[5] = this.getOrderArr(year, year + 100); + if (rule !== undefined) { + if (rule.indexOf('-') >= 0) { + this.dateArr[5] = this.getCycleArr(rule, year + 100, false) + } else if (rule.indexOf('/') >= 0) { + this.dateArr[5] = this.getAverageArr(rule, year + 100) + } else if (rule !== '*') { + this.dateArr[5] = this.getAssignArr(rule) + } + } + }, + // 鑾峰彇"鏈�"鏁扮粍 + getMonthArr(rule) { + this.dateArr[4] = this.getOrderArr(1, 12); + if (rule.indexOf('-') >= 0) { + this.dateArr[4] = this.getCycleArr(rule, 12, false) + } else if (rule.indexOf('/') >= 0) { + this.dateArr[4] = this.getAverageArr(rule, 12) + } else if (rule !== '*') { + this.dateArr[4] = this.getAssignArr(rule) + } + }, + // 鑾峰彇"鏃�"鏁扮粍-涓昏涓烘棩鏈熻鍒� + getWeekArr(rule) { + // 鍙湁褰撴棩鏈熻鍒欑殑涓や釜鍊煎潎涓衡�溾�濇椂鍒欒〃杈炬棩鏈熸槸鏈夐�夐」鐨� + if (this.dayRule == '' && this.dayRuleSup == '') { + if (rule.indexOf('-') >= 0) { + this.dayRule = 'weekDay'; + this.dayRuleSup = this.getCycleArr(rule, 7, false) + } else if (rule.indexOf('#') >= 0) { + this.dayRule = 'assWeek'; + let matchRule = rule.match(/[0-9]{1}/g); + this.dayRuleSup = [Number(matchRule[1]), Number(matchRule[0])]; + this.dateArr[3] = [1]; + if (this.dayRuleSup[1] == 7) { + this.dayRuleSup[1] = 0; + } + } else if (rule.indexOf('L') >= 0) { + this.dayRule = 'lastWeek'; + this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]); + this.dateArr[3] = [31]; + if (this.dayRuleSup == 7) { + this.dayRuleSup = 0; + } + } else if (rule !== '*' && rule !== '?') { + this.dayRule = 'weekDay'; + this.dayRuleSup = this.getAssignArr(rule) + } + } + }, + // 鑾峰彇"鏃�"鏁扮粍-灏戦噺涓烘棩鏈熻鍒� + getDayArr(rule) { + this.dateArr[3] = this.getOrderArr(1, 31); + this.dayRule = ''; + this.dayRuleSup = ''; + if (rule.indexOf('-') >= 0) { + this.dateArr[3] = this.getCycleArr(rule, 31, false) + this.dayRuleSup = 'null'; + } else if (rule.indexOf('/') >= 0) { + this.dateArr[3] = this.getAverageArr(rule, 31) + this.dayRuleSup = 'null'; + } else if (rule.indexOf('W') >= 0) { + this.dayRule = 'workDay'; + this.dayRuleSup = Number(rule.match(/[0-9]{1,2}/g)[0]); + this.dateArr[3] = [this.dayRuleSup]; + } else if (rule.indexOf('L') >= 0) { + this.dayRule = 'lastDay'; + this.dayRuleSup = 'null'; + this.dateArr[3] = [31]; + } else if (rule !== '*' && rule !== '?') { + this.dateArr[3] = this.getAssignArr(rule) + this.dayRuleSup = 'null'; + } else if (rule == '*') { + this.dayRuleSup = 'null'; + } + }, + // 鑾峰彇"鏃�"鏁扮粍 + getHourArr(rule) { + this.dateArr[2] = this.getOrderArr(0, 23); + if (rule.indexOf('-') >= 0) { + this.dateArr[2] = this.getCycleArr(rule, 24, true) + } else if (rule.indexOf('/') >= 0) { + this.dateArr[2] = this.getAverageArr(rule, 23) + } else if (rule !== '*') { + this.dateArr[2] = this.getAssignArr(rule) + } + }, + // 鑾峰彇"鍒�"鏁扮粍 + getMinArr(rule) { + this.dateArr[1] = this.getOrderArr(0, 59); + if (rule.indexOf('-') >= 0) { + this.dateArr[1] = this.getCycleArr(rule, 60, true) + } else if (rule.indexOf('/') >= 0) { + this.dateArr[1] = this.getAverageArr(rule, 59) + } else if (rule !== '*') { + this.dateArr[1] = this.getAssignArr(rule) + } + }, + // 鑾峰彇"绉�"鏁扮粍 + getSecondArr(rule) { + this.dateArr[0] = this.getOrderArr(0, 59); + if (rule.indexOf('-') >= 0) { + this.dateArr[0] = this.getCycleArr(rule, 60, true) + } else if (rule.indexOf('/') >= 0) { + this.dateArr[0] = this.getAverageArr(rule, 59) + } else if (rule !== '*') { + this.dateArr[0] = this.getAssignArr(rule) + } + }, + // 鏍规嵁浼犺繘鏉ョ殑min-max杩斿洖涓�涓『搴忕殑鏁扮粍 + getOrderArr(min, max) { + let arr = []; + for (let i = min; i <= max; i++) { + arr.push(i); + } + return arr; + }, + // 鏍规嵁瑙勫垯涓寚瀹氱殑闆舵暎鍊艰繑鍥炰竴涓暟缁� + getAssignArr(rule) { + let arr = []; + let assiginArr = rule.split(','); + for (let i = 0; i < assiginArr.length; i++) { + arr[i] = Number(assiginArr[i]) + } + arr.sort(this.compare) + return arr; + }, + // 鏍规嵁涓�瀹氱畻鏈鍒欒绠楄繑鍥炰竴涓暟缁� + getAverageArr(rule, limit) { + let arr = []; + let agArr = rule.split('/'); + let min = Number(agArr[0]); + let step = Number(agArr[1]); + while (min <= limit) { + arr.push(min); + min += step; + } + return arr; + }, + // 鏍规嵁瑙勫垯杩斿洖涓�涓叿鏈夊懆鏈熸�х殑鏁扮粍 + getCycleArr(rule, limit, status) { + // status--琛ㄧず鏄惁浠�0寮�濮嬶紙鍒欎粠1寮�濮嬶級 + let arr = []; + let cycleArr = rule.split('-'); + let min = Number(cycleArr[0]); + let max = Number(cycleArr[1]); + if (min > max) { + max += limit; + } + for (let i = min; i <= max; i++) { + let add = 0; + if (status == false && i % limit == 0) { + add = limit; + } + arr.push(Math.round(i % limit + add)) + } + arr.sort(this.compare) + return arr; + }, + // 姣旇緝鏁板瓧澶у皬锛堢敤浜嶢rray.sort锛� + compare(value1, value2) { + if (value2 - value1 > 0) { + return -1; + } else { + return 1; + } + }, + // 鏍煎紡鍖栨棩鏈熸牸寮忓锛�2017-9-19 18:04:33 + formatDate(value, type) { + // 璁$畻鏃ユ湡鐩稿叧鍊� + let time = typeof value == 'number' ? new Date(value) : value; + let Y = time.getFullYear(); + let M = time.getMonth() + 1; + let D = time.getDate(); + let h = time.getHours(); + let m = time.getMinutes(); + let s = time.getSeconds(); + let week = time.getDay(); + // 濡傛灉浼犻�掍簡type鐨勮瘽 + if (type == undefined) { + return Y + '-' + (M < 10 ? '0' + M : M) + '-' + (D < 10 ? '0' + D : D) + ' ' + (h < 10 ? '0' + h : h) + ':' + (m < 10 ? '0' + m : m) + ':' + (s < 10 ? '0' + s : s); + } else if (type == 'week') { + // 鍦╭uartz涓� 1涓烘槦鏈熸棩 + return week + 1; + } + }, + // 妫�鏌ユ棩鏈熸槸鍚﹀瓨鍦� + checkDate(value) { + let time = new Date(value); + let format = this.formatDate(time) + return value === format; + } + }, + watch: { + 'ex': 'expressionChange' + }, + props: ['ex'], + mounted: function () { + // 鍒濆鍖� 鑾峰彇涓�娆$粨鏋� + this.expressionChange(); + } +} + +</script> diff --git a/src/components/Crontab/second.vue b/src/components/Crontab/second.vue new file mode 100644 index 0000000..e7b7761 --- /dev/null +++ b/src/components/Crontab/second.vue @@ -0,0 +1,117 @@ +<template> + <el-form size="small"> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 绉掞紝鍏佽鐨勯�氶厤绗, - * /] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min="0" :max="58" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : 1" :max="59" /> 绉� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 浠� + <el-input-number v-model='average01' :min="0" :max="58" /> 绉掑紑濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="59 - average01 || 0" /> 绉掓墽琛屼竴娆� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="item in 60" :key="item" :value="item-1">{{item-1}}</el-option> + </el-select> + </el-radio> + </el-form-item> + </el-form> +</template> + +<script> +export default { + data() { + return { + radioValue: 1, + cycle01: 1, + cycle02: 2, + average01: 0, + average02: 1, + checkboxList: [], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-second', + props: ['check', 'radioParent'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + switch (this.radioValue) { + case 1: + this.$emit('update', 'second', '*', 'second'); + break; + case 2: + this.$emit('update', 'second', this.cycleTotal); + break; + case 3: + this.$emit('update', 'second', this.averageTotal); + break; + case 4: + this.$emit('update', 'second', this.checkboxString); + break; + } + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '2') { + this.$emit('update', 'second', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '3') { + this.$emit('update', 'second', this.averageTotal); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '4') { + this.$emit('update', 'second', this.checkboxString); + } + } + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'checkboxString': 'checkboxChange', + radioParent() { + this.radioValue = this.radioParent + } + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, 0, 58) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : 1, 59) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, 0, 58) + const average02 = this.checkNum(this.average02, 1, 59 - average01 || 0) + return average01 + '/' + average02; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> diff --git a/src/components/Crontab/week.vue b/src/components/Crontab/week.vue new file mode 100644 index 0000000..1cec700 --- /dev/null +++ b/src/components/Crontab/week.vue @@ -0,0 +1,202 @@ +<template> + <el-form size='small'> + <el-form-item> + <el-radio v-model='radioValue' :label="1"> + 鍛紝鍏佽鐨勯�氶厤绗, - * ? / L #] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="2"> + 涓嶆寚瀹� + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="3"> + 鍛ㄦ湡浠庢槦鏈� + <el-select clearable v-model="cycle01"> + <el-option + v-for="(item,index) of weekList" + :key="index" + :label="item.value" + :value="item.key" + :disabled="item.key === 1" + >{{item.value}}</el-option> + </el-select> + - + <el-select clearable v-model="cycle02"> + <el-option + v-for="(item,index) of weekList" + :key="index" + :label="item.value" + :value="item.key" + :disabled="item.key < cycle01 && item.key !== 1" + >{{item.value}}</el-option> + </el-select> + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="4"> + 绗� + <el-input-number v-model='average01' :min="1" :max="4" /> 鍛ㄧ殑鏄熸湡 + <el-select clearable v-model="average02"> + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option> + </el-select> + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="5"> + 鏈湀鏈�鍚庝竴涓槦鏈� + <el-select clearable v-model="weekday"> + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="item.key">{{item.value}}</el-option> + </el-select> + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio v-model='radioValue' :label="6"> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple style="width:100%"> + <el-option v-for="(item,index) of weekList" :key="index" :label="item.value" :value="String(item.key)">{{item.value}}</el-option> + </el-select> + </el-radio> + </el-form-item> + + </el-form> +</template> + +<script> +export default { + data() { + return { + radioValue: 2, + weekday: 2, + cycle01: 2, + cycle02: 3, + average01: 1, + average02: 2, + checkboxList: [], + weekList: [ + { + key: 2, + value: '鏄熸湡涓�' + }, + { + key: 3, + value: '鏄熸湡浜�' + }, + { + key: 4, + value: '鏄熸湡涓�' + }, + { + key: 5, + value: '鏄熸湡鍥�' + }, + { + key: 6, + value: '鏄熸湡浜�' + }, + { + key: 7, + value: '鏄熸湡鍏�' + }, + { + key: 1, + value: '鏄熸湡鏃�' + } + ], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-week', + props: ['check', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + if (this.radioValue !== 2 && this.cron.day !== '?') { + this.$emit('update', 'day', '?', 'week'); + } + switch (this.radioValue) { + case 1: + this.$emit('update', 'week', '*'); + break; + case 2: + this.$emit('update', 'week', '?'); + break; + case 3: + this.$emit('update', 'week', this.cycleTotal); + break; + case 4: + this.$emit('update', 'week', this.averageTotal); + break; + case 5: + this.$emit('update', 'week', this.weekdayCheck + 'L'); + break; + case 6: + this.$emit('update', 'week', this.checkboxString); + break; + } + }, + + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '3') { + this.$emit('update', 'week', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '4') { + this.$emit('update', 'week', this.averageTotal); + } + }, + // 鏈�杩戝伐浣滄棩鍊煎彉鍖栨椂 + weekdayChange() { + if (this.radioValue == '5') { + this.$emit('update', 'week', this.weekday + 'L'); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '6') { + this.$emit('update', 'week', this.checkboxString); + } + }, + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'weekdayCheck': 'weekdayChange', + 'checkboxString': 'checkboxChange', + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + this.cycle01 = this.checkNum(this.cycle01, 1, 7) + this.cycle02 = this.checkNum(this.cycle02, 1, 7) + return this.cycle01 + '-' + this.cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + this.average01 = this.checkNum(this.average01, 1, 4) + this.average02 = this.checkNum(this.average02, 1, 7) + return this.average02 + '#' + this.average01; + }, + // 鏈�杩戠殑宸ヤ綔鏃ワ紙鏍煎紡锛� + weekdayCheck: function () { + this.weekday = this.checkNum(this.weekday, 1, 7) + return this.weekday; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str == '' ? '*' : str; + } + } +} +</script> diff --git a/src/components/Crontab/year.vue b/src/components/Crontab/year.vue new file mode 100644 index 0000000..5487a6c --- /dev/null +++ b/src/components/Crontab/year.vue @@ -0,0 +1,131 @@ +<template> + <el-form size="small"> + <el-form-item> + <el-radio :label="1" v-model='radioValue'> + 涓嶅~锛屽厑璁哥殑閫氶厤绗, - * /] + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio :label="2" v-model='radioValue'> + 姣忓勾 + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio :label="3" v-model='radioValue'> + 鍛ㄦ湡浠� + <el-input-number v-model='cycle01' :min='fullYear' :max="2098" /> - + <el-input-number v-model='cycle02' :min="cycle01 ? cycle01 + 1 : fullYear + 1" :max="2099" /> + </el-radio> + </el-form-item> + + <el-form-item> + <el-radio :label="4" v-model='radioValue'> + 浠� + <el-input-number v-model='average01' :min='fullYear' :max="2098"/> 骞村紑濮嬶紝姣� + <el-input-number v-model='average02' :min="1" :max="2099 - average01 || fullYear" /> 骞存墽琛屼竴娆� + </el-radio> + + </el-form-item> + + <el-form-item> + <el-radio :label="5" v-model='radioValue'> + 鎸囧畾 + <el-select clearable v-model="checkboxList" placeholder="鍙閫�" multiple> + <el-option v-for="item in 9" :key="item" :value="item - 1 + fullYear" :label="item -1 + fullYear" /> + </el-select> + </el-radio> + </el-form-item> + </el-form> +</template> + +<script> +export default { + data() { + return { + fullYear: 0, + radioValue: 1, + cycle01: 0, + cycle02: 0, + average01: 0, + average02: 1, + checkboxList: [], + checkNum: this.$options.propsData.check + } + }, + name: 'crontab-year', + props: ['check', 'month', 'cron'], + methods: { + // 鍗曢�夋寜閽�煎彉鍖栨椂 + radioChange() { + switch (this.radioValue) { + case 1: + this.$emit('update', 'year', ''); + break; + case 2: + this.$emit('update', 'year', '*'); + break; + case 3: + this.$emit('update', 'year', this.cycleTotal); + break; + case 4: + this.$emit('update', 'year', this.averageTotal); + break; + case 5: + this.$emit('update', 'year', this.checkboxString); + break; + } + }, + // 鍛ㄦ湡涓や釜鍊煎彉鍖栨椂 + cycleChange() { + if (this.radioValue == '3') { + this.$emit('update', 'year', this.cycleTotal); + } + }, + // 骞冲潎涓や釜鍊煎彉鍖栨椂 + averageChange() { + if (this.radioValue == '4') { + this.$emit('update', 'year', this.averageTotal); + } + }, + // checkbox鍊煎彉鍖栨椂 + checkboxChange() { + if (this.radioValue == '5') { + this.$emit('update', 'year', this.checkboxString); + } + } + }, + watch: { + 'radioValue': 'radioChange', + 'cycleTotal': 'cycleChange', + 'averageTotal': 'averageChange', + 'checkboxString': 'checkboxChange' + }, + computed: { + // 璁$畻涓や釜鍛ㄦ湡鍊� + cycleTotal: function () { + const cycle01 = this.checkNum(this.cycle01, this.fullYear, 2098) + const cycle02 = this.checkNum(this.cycle02, cycle01 ? cycle01 + 1 : this.fullYear + 1, 2099) + return cycle01 + '-' + cycle02; + }, + // 璁$畻骞冲潎鐢ㄥ埌鐨勫�� + averageTotal: function () { + const average01 = this.checkNum(this.average01, this.fullYear, 2098) + const average02 = this.checkNum(this.average02, 1, 2099 - average01 || this.fullYear) + return average01 + '/' + average02; + }, + // 璁$畻鍕鹃�夌殑checkbox鍊煎悎闆� + checkboxString: function () { + let str = this.checkboxList.join(); + return str; + } + }, + mounted: function () { + // 浠呰幏鍙栧綋鍓嶅勾浠� + this.fullYear = Number(new Date().getFullYear()); + this.cycle01 = this.fullYear + this.average01 = this.fullYear + } +} +</script> diff --git a/src/components/DictData/index.js b/src/components/DictData/index.js new file mode 100644 index 0000000..7b85d4a --- /dev/null +++ b/src/components/DictData/index.js @@ -0,0 +1,49 @@ +import Vue from 'vue' +import store from '@/store' +import DataDict from '@/utils/dict' +import { getDicts as getDicts } from '@/api/system/dict/data' + +function searchDictByKey(dict, key) { + if (key == null && key == "") { + return null + } + try { + for (let i = 0; i < dict.length; i++) { + if (dict[i].key == key) { + return dict[i].value + } + } + } catch (e) { + return null + } +} + +function install() { + Vue.use(DataDict, { + metas: { + '*': { + labelField: 'dictLabel', + valueField: 'dictValue', + request(dictMeta) { + const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) + if (storeDict) { + return new Promise(resolve => { resolve(storeDict) }) + } else { + return new Promise((resolve, reject) => { + getDicts(dictMeta.type).then(res => { + store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) + resolve(res.data) + }).catch(error => { + reject(error) + }) + }) + } + }, + }, + }, + }) +} + +export default { + install, +} \ No newline at end of file diff --git a/src/components/DictTag/index.vue b/src/components/DictTag/index.vue new file mode 100644 index 0000000..1ef13b9 --- /dev/null +++ b/src/components/DictTag/index.vue @@ -0,0 +1,92 @@ +<template> + <div> + <template v-for="(item, index) in options"> + <template v-if="values.includes(item.value)"> + <span + v-if="(item.raw.listClass == 'default' || item.raw.listClass == '') && (item.raw.cssClass == '' || item.raw.cssClass == null)" + :key="item.value" + :index="index" + :class="item.raw.cssClass" + >{{ item.label + " " }}</span + > + <el-tag + v-else + :disable-transitions="true" + :key="item.value" + :index="index" + :type="item.raw.listClass == 'primary' ? '' : item.raw.listClass" + :class="item.raw.cssClass" + > + {{ item.label + " " }} + </el-tag> + </template> + </template> + <template v-if="unmatch && showValue"> + {{ unmatchArray | handleArray }} + </template> + </div> +</template> + +<script> +export default { + name: "DictTag", + props: { + options: { + type: Array, + default: null, + }, + value: [Number, String, Array], + // 褰撴湭鎵惧埌鍖归厤鐨勬暟鎹椂锛屾樉绀簐alue + showValue: { + type: Boolean, + default: true, + } + }, + data() { + return { + unmatchArray: [], // 璁板綍鏈尮閰嶇殑椤� + } + }, + computed: { + values() { + if (this.value !== null && typeof this.value !== "undefined") { + return Array.isArray(this.value) ? this.value : [String(this.value)]; + } else { + return []; + } + }, + unmatch() { + this.unmatchArray = []; + if (this.value !== null && typeof this.value !== "undefined") { + // 浼犲叆鍊间负闈炴暟缁� + if (!Array.isArray(this.value)) { + if (this.options.some((v) => v.value == this.value)) return false; + this.unmatchArray.push(this.value); + return true; + } + // 浼犲叆鍊间负Array + this.value.forEach((item) => { + if (!this.options.some((v) => v.value == item)) + this.unmatchArray.push(item); + }); + return true; + } + // 娌℃湁value涓嶆樉绀� + return false; + }, + }, + filters: { + handleArray(array) { + if (array.length === 0) return ""; + return array.reduce((pre, cur) => { + return pre + " " + cur; + }) + } + } +}; +</script> +<style scoped> +.el-tag + .el-tag { + margin-left: 10px; +} +</style> diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue new file mode 100644 index 0000000..8981d76 --- /dev/null +++ b/src/components/Editor/index.vue @@ -0,0 +1,274 @@ +<template> + <div> + <el-upload + :action="uploadUrl" + :before-upload="handleBeforeUpload" + :on-success="handleUploadSuccess" + :on-error="handleUploadError" + name="file" + :show-file-list="false" + :headers="headers" + style="display: none" + ref="upload" + v-if="this.type == 'url'" + > + </el-upload> + <div class="editor" ref="editor" :style="styles"></div> + </div> +</template> + +<script> +import Quill from "quill"; +import "quill/dist/quill.core.css"; +import "quill/dist/quill.snow.css"; +import "quill/dist/quill.bubble.css"; +import { getToken } from "@/utils/auth"; + +export default { + name: "Editor", + props: { + /* 缂栬緫鍣ㄧ殑鍐呭 */ + value: { + type: String, + default: "", + }, + /* 楂樺害 */ + height: { + type: Number, + default: null, + }, + /* 鏈�灏忛珮搴� */ + minHeight: { + type: Number, + default: null, + }, + /* 鍙 */ + readOnly: { + type: Boolean, + default: false, + }, + /* 涓婁紶鏂囦欢澶у皬闄愬埗(MB) */ + fileSize: { + type: Number, + default: 5, + }, + /* 绫诲瀷锛坆ase64鏍煎紡銆乽rl鏍煎紡锛� */ + type: { + type: String, + default: "url", + } + }, + data() { + return { + uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃 + headers: { + Authorization: "Bearer " + getToken() + }, + Quill: null, + currentValue: "", + options: { + theme: "snow", + bounds: document.body, + debug: "warn", + modules: { + // 宸ュ叿鏍忛厤缃� + toolbar: [ + ["bold", "italic", "underline", "strike"], // 鍔犵矖 鏂滀綋 涓嬪垝绾� 鍒犻櫎绾� + ["blockquote", "code-block"], // 寮曠敤 浠g爜鍧� + [{ list: "ordered" }, { list: "bullet" }], // 鏈夊簭銆佹棤搴忓垪琛� + [{ indent: "-1" }, { indent: "+1" }], // 缂╄繘 + [{ size: ["small", false, "large", "huge"] }], // 瀛椾綋澶у皬 + [{ header: [1, 2, 3, 4, 5, 6, false] }], // 鏍囬 + [{ color: [] }, { background: [] }], // 瀛椾綋棰滆壊銆佸瓧浣撹儗鏅鑹� + [{ align: [] }], // 瀵归綈鏂瑰紡 + ["clean"], // 娓呴櫎鏂囨湰鏍煎紡 + ["link", "image", "video"] // 閾炬帴銆佸浘鐗囥�佽棰� + ], + }, + placeholder: "璇疯緭鍏ュ唴瀹�", + readOnly: this.readOnly, + }, + }; + }, + computed: { + styles() { + let style = {}; + if (this.minHeight) { + style.minHeight = `${this.minHeight}px`; + } + if (this.height) { + style.height = `${this.height}px`; + } + return style; + }, + }, + watch: { + value: { + handler(val) { + if (val !== this.currentValue) { + this.currentValue = val === null ? "" : val; + if (this.Quill) { + this.Quill.pasteHTML(this.currentValue); + } + } + }, + immediate: true, + }, + }, + mounted() { + this.init(); + }, + beforeDestroy() { + this.Quill = null; + }, + methods: { + init() { + const editor = this.$refs.editor; + this.Quill = new Quill(editor, this.options); + // 濡傛灉璁剧疆浜嗕笂浼犲湴鍧�鍒欒嚜瀹氫箟鍥剧墖涓婁紶浜嬩欢 + if (this.type == 'url') { + let toolbar = this.Quill.getModule("toolbar"); + toolbar.addHandler("image", (value) => { + if (value) { + this.$refs.upload.$children[0].$refs.input.click(); + } else { + this.quill.format("image", false); + } + }); + } + this.Quill.pasteHTML(this.currentValue); + this.Quill.on("text-change", (delta, oldDelta, source) => { + const html = this.$refs.editor.children[0].innerHTML; + const text = this.Quill.getText(); + const quill = this.Quill; + this.currentValue = html; + this.$emit("input", html); + this.$emit("on-change", { html, text, quill }); + }); + this.Quill.on("text-change", (delta, oldDelta, source) => { + this.$emit("on-text-change", delta, oldDelta, source); + }); + this.Quill.on("selection-change", (range, oldRange, source) => { + this.$emit("on-selection-change", range, oldRange, source); + }); + this.Quill.on("editor-change", (eventName, ...args) => { + this.$emit("on-editor-change", eventName, ...args); + }); + }, + // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏� + handleBeforeUpload(file) { + const type = ["image/jpeg", "image/jpg", "image/png", "image/svg"]; + const isJPG = type.includes(file.type); + // 妫�楠屾枃浠舵牸寮� + if (!isJPG) { + this.$message.error(`鍥剧墖鏍煎紡閿欒!`); + return false; + } + // 鏍℃鏂囦欢澶у皬 + if (this.fileSize) { + const isLt = file.size / 1024 / 1024 < this.fileSize; + if (!isLt) { + this.$message.error(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`); + return false; + } + } + return true; + }, + handleUploadSuccess(res, file) { + // 濡傛灉涓婁紶鎴愬姛 + if (res.code == 200) { + // 鑾峰彇瀵屾枃鏈粍浠跺疄渚� + let quill = this.Quill; + // 鑾峰彇鍏夋爣鎵�鍦ㄤ綅缃� + let length = quill.getSelection().index; + // 鎻掑叆鍥剧墖 res.url涓烘湇鍔″櫒杩斿洖鐨勫浘鐗囧湴鍧� + quill.insertEmbed(length, "image", process.env.VUE_APP_BASE_API + res.fileName); + // 璋冩暣鍏夋爣鍒版渶鍚� + quill.setSelection(length + 1); + } else { + this.$message.error("鍥剧墖鎻掑叆澶辫触"); + } + }, + handleUploadError() { + this.$message.error("鍥剧墖鎻掑叆澶辫触"); + }, + }, +}; +</script> + +<style> +.editor, .ql-toolbar { + white-space: pre-wrap !important; + line-height: normal !important; +} +.quill-img { + display: none; +} +.ql-snow .ql-tooltip[data-mode="link"]::before { + content: "璇疯緭鍏ラ摼鎺ュ湴鍧�:"; +} +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { + border-right: 0px; + content: "淇濆瓨"; + padding-right: 0px; +} +.ql-snow .ql-tooltip[data-mode="video"]::before { + content: "璇疯緭鍏ヨ棰戝湴鍧�:"; +} +.ql-snow .ql-picker.ql-size .ql-picker-label::before, +.ql-snow .ql-picker.ql-size .ql-picker-item::before { + content: "14px"; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before { + content: "10px"; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before { + content: "18px"; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before { + content: "32px"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label::before, +.ql-snow .ql-picker.ql-header .ql-picker-item::before { + content: "鏂囨湰"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + content: "鏍囬1"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + content: "鏍囬2"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + content: "鏍囬3"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + content: "鏍囬4"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + content: "鏍囬5"; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + content: "鏍囬6"; +} +.ql-snow .ql-picker.ql-font .ql-picker-label::before, +.ql-snow .ql-picker.ql-font .ql-picker-item::before { + content: "鏍囧噯瀛椾綋"; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before { + content: "琛嚎瀛椾綋"; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before { + content: "绛夊瀛椾綋"; +} +</style> diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue new file mode 100644 index 0000000..6c583cf --- /dev/null +++ b/src/components/FileUpload/index.vue @@ -0,0 +1,215 @@ +<template> + <div class="upload-file"> + <el-upload + multiple + :action="uploadFileUrl" + :before-upload="handleBeforeUpload" + :file-list="fileList" + :limit="limit" + :on-error="handleUploadError" + :on-exceed="handleExceed" + :on-success="handleUploadSuccess" + :show-file-list="false" + :headers="headers" + class="upload-file-uploader" + ref="fileUpload" + > + <!-- 涓婁紶鎸夐挳 --> + <el-button size="mini" type="primary">閫夊彇鏂囦欢</el-button> + <!-- 涓婁紶鎻愮ず --> + <div class="el-upload__tip" slot="tip" v-if="showTip"> + 璇蜂笂浼� + <template v-if="fileSize"> 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> + <template v-if="fileType"> 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> + 鐨勬枃浠� + </div> + </el-upload> + + <!-- 鏂囦欢鍒楄〃 --> + <transition-group class="upload-file-list el-upload-list el-upload-list--text" name="el-fade-in-linear" tag="ul"> + <li :key="file.url" class="el-upload-list__item ele-upload-list__item-content" v-for="(file, index) in fileList"> + <el-link :href="`${baseUrl}${file.url}`" :underline="false" target="_blank"> + <span class="el-icon-document"> {{ getFileName(file.name) }} </span> + </el-link> + <div class="ele-upload-list__item-content-action"> + <el-link :underline="false" @click="handleDelete(index)" type="danger">鍒犻櫎</el-link> + </div> + </li> + </transition-group> + </div> +</template> + +<script> +import { getToken } from "@/utils/auth"; + +export default { + name: "FileUpload", + props: { + // 鍊� + value: [String, Object, Array], + // 鏁伴噺闄愬埗 + limit: { + type: Number, + default: 5, + }, + // 澶у皬闄愬埗(MB) + fileSize: { + type: Number, + default: 5, + }, + // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg'] + fileType: { + type: Array, + default: () => ["doc", "xls", "ppt", "txt", "pdf"], + }, + // 鏄惁鏄剧ず鎻愮ず + isShowTip: { + type: Boolean, + default: true + } + }, + data() { + return { + number: 0, + uploadList: [], + baseUrl: process.env.VUE_APP_BASE_API, + uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鏂囦欢鏈嶅姟鍣ㄥ湴鍧� + headers: { + Authorization: "Bearer " + getToken(), + }, + fileList: [], + }; + }, + watch: { + value: { + handler(val) { + if (val) { + let temp = 1; + // 棣栧厛灏嗗�艰浆涓烘暟缁� + const list = Array.isArray(val) ? val : this.value.split(','); + // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁� + this.fileList = list.map(item => { + if (typeof item === "string") { + item = { name: item, url: item }; + } + item.uid = item.uid || new Date().getTime() + temp++; + return item; + }); + } else { + this.fileList = []; + return []; + } + }, + deep: true, + immediate: true + } + }, + computed: { + // 鏄惁鏄剧ず鎻愮ず + showTip() { + return this.isShowTip && (this.fileType || this.fileSize); + }, + }, + methods: { + // 涓婁紶鍓嶆牎妫�鏍煎紡鍜屽ぇ灏� + handleBeforeUpload(file) { + // 鏍℃鏂囦欢绫诲瀷 + if (this.fileType) { + const fileName = file.name.split('.'); + const fileExt = fileName[fileName.length - 1]; + const isTypeOk = this.fileType.indexOf(fileExt) >= 0; + if (!isTypeOk) { + this.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${this.fileType.join("/")}鏍煎紡鏂囦欢!`); + return false; + } + } + // 鏍℃鏂囦欢澶у皬 + if (this.fileSize) { + const isLt = file.size / 1024 / 1024 < this.fileSize; + if (!isLt) { + this.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`); + return false; + } + } + this.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��..."); + this.number++; + return true; + }, + // 鏂囦欢涓暟瓒呭嚭 + handleExceed() { + this.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${this.limit} 涓�!`); + }, + // 涓婁紶澶辫触 + handleUploadError(err) { + this.$modal.msgError("涓婁紶鏂囦欢澶辫触锛岃閲嶈瘯"); + this.$modal.closeLoading() + }, + // 涓婁紶鎴愬姛鍥炶皟 + handleUploadSuccess(res, file) { + if (res.code === 200) { + this.uploadList.push({ name: res.fileName, url: res.fileName }); + this.uploadedSuccessfully(); + } else { + this.number--; + this.$modal.closeLoading(); + this.$modal.msgError(res.msg); + this.$refs.fileUpload.handleRemove(file); + this.uploadedSuccessfully(); + } + }, + // 鍒犻櫎鏂囦欢 + handleDelete(index) { + this.fileList.splice(index, 1); + this.$emit("input", this.listToString(this.fileList)); + }, + // 涓婁紶缁撴潫澶勭悊 + uploadedSuccessfully() { + if (this.number > 0 && this.uploadList.length === this.number) { + this.fileList = this.fileList.concat(this.uploadList); + this.uploadList = []; + this.number = 0; + this.$emit("input", this.listToString(this.fileList)); + this.$modal.closeLoading(); + } + }, + // 鑾峰彇鏂囦欢鍚嶇О + getFileName(name) { + if (name.lastIndexOf("/") > -1) { + return name.slice(name.lastIndexOf("/") + 1); + } else { + return ""; + } + }, + // 瀵硅薄杞垚鎸囧畾瀛楃涓插垎闅� + listToString(list, separator) { + let strs = ""; + separator = separator || ","; + for (let i in list) { + strs += list[i].url + separator; + } + return strs != '' ? strs.substr(0, strs.length - 1) : ''; + } + } +}; +</script> + +<style scoped lang="scss"> +.upload-file-uploader { + margin-bottom: 5px; +} +.upload-file-list .el-upload-list__item { + border: 1px solid #e4e7ed; + line-height: 2; + margin-bottom: 10px; + position: relative; +} +.upload-file-list .ele-upload-list__item-content { + display: flex; + justify-content: space-between; + align-items: center; + color: inherit; +} +.ele-upload-list__item-content-action .el-link { + margin-right: 10px; +} +</style> diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue new file mode 100644 index 0000000..368b002 --- /dev/null +++ b/src/components/Hamburger/index.vue @@ -0,0 +1,44 @@ +<template> + <div style="padding: 0 15px;" @click="toggleClick"> + <svg + :class="{'is-active':isActive}" + class="hamburger" + viewBox="0 0 1024 1024" + xmlns="http://www.w3.org/2000/svg" + width="64" + height="64" + > + <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" /> + </svg> + </div> +</template> + +<script> +export default { + name: 'Hamburger', + props: { + isActive: { + type: Boolean, + default: false + } + }, + methods: { + toggleClick() { + this.$emit('toggleClick') + } + } +} +</script> + +<style scoped> +.hamburger { + display: inline-block; + vertical-align: middle; + width: 20px; + height: 20px; +} + +.hamburger.is-active { + transform: rotate(180deg); +} +</style> diff --git a/src/components/HeaderSearch/index.vue b/src/components/HeaderSearch/index.vue new file mode 100644 index 0000000..888be5d --- /dev/null +++ b/src/components/HeaderSearch/index.vue @@ -0,0 +1,198 @@ +<template> + <div :class="{'show':show}" class="header-search"> + <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" /> + <el-select + ref="headerSearchSelect" + v-model="search" + :remote-method="querySearch" + filterable + default-first-option + remote + placeholder="Search" + class="header-search-select" + @change="change" + > + <el-option v-for="option in options" :key="option.item.path" :value="option.item" :label="option.item.title.join(' > ')" /> + </el-select> + </div> +</template> + +<script> +// fuse is a lightweight fuzzy-search module +// make search results more in line with expectations +import Fuse from 'fuse.js/dist/fuse.min.js' +import path from 'path' + +export default { + name: 'HeaderSearch', + data() { + return { + search: '', + options: [], + searchPool: [], + show: false, + fuse: undefined + } + }, + computed: { + routes() { + return this.$store.getters.permission_routes + } + }, + watch: { + routes() { + this.searchPool = this.generateRoutes(this.routes) + }, + searchPool(list) { + this.initFuse(list) + }, + show(value) { + if (value) { + document.body.addEventListener('click', this.close) + } else { + document.body.removeEventListener('click', this.close) + } + } + }, + mounted() { + this.searchPool = this.generateRoutes(this.routes) + }, + methods: { + click() { + this.show = !this.show + if (this.show) { + this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus() + } + }, + close() { + this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur() + this.options = [] + this.show = false + }, + change(val) { + const path = val.path; + const query = val.query; + if(this.ishttp(val.path)) { + // http(s):// 璺緞鏂扮獥鍙f墦寮� + const pindex = path.indexOf("http"); + window.open(path.substr(pindex, path.length), "_blank"); + } else { + if (query) { + this.$router.push({ path: path, query: JSON.parse(query) }); + } else { + this.$router.push(path) + } + } + this.search = '' + this.options = [] + this.$nextTick(() => { + this.show = false + }) + }, + initFuse(list) { + this.fuse = new Fuse(list, { + shouldSort: true, + threshold: 0.4, + location: 0, + distance: 100, + minMatchCharLength: 1, + keys: [{ + name: 'title', + weight: 0.7 + }, { + name: 'path', + weight: 0.3 + }] + }) + }, + // Filter out the routes that can be displayed in the sidebar + // And generate the internationalized title + generateRoutes(routes, basePath = '/', prefixTitle = [], query = {}) { + let res = [] + + for (const router of routes) { + // skip hidden router + if (router.hidden) { continue } + + const data = { + path: !this.ishttp(router.path) ? path.resolve(basePath, router.path) : router.path, + title: [...prefixTitle] + } + + if (router.meta && router.meta.title) { + data.title = [...data.title, router.meta.title] + + if (router.redirect !== 'noRedirect') { + // only push the routes with title + // special case: need to exclude parent router without redirect + res.push(data) + } + } + + if (router.query) { + data.query = router.query + } + + // recursive child routes + if (router.children) { + const tempRoutes = this.generateRoutes(router.children, data.path, data.title, data.query) + if (tempRoutes.length >= 1) { + res = [...res, ...tempRoutes] + } + } + } + return res + }, + querySearch(query) { + if (query !== '') { + this.options = this.fuse.search(query) + } else { + this.options = [] + } + }, + ishttp(url) { + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 + } + } +} +</script> + +<style lang="scss" scoped> +.header-search { + font-size: 0 !important; + + .search-icon { + cursor: pointer; + font-size: 18px; + vertical-align: middle; + } + + .header-search-select { + font-size: 18px; + transition: width 0.2s; + width: 0; + overflow: hidden; + background: transparent; + border-radius: 0; + display: inline-block; + vertical-align: middle; + + ::v-deep .el-input__inner { + border-radius: 0; + border: 0; + padding-left: 0; + padding-right: 0; + box-shadow: none !important; + border-bottom: 1px solid #d9d9d9; + vertical-align: middle; + } + } + + &.show { + .header-search-select { + width: 210px; + margin-left: 10px; + } + } +} +</style> diff --git a/src/components/IconSelect/index.vue b/src/components/IconSelect/index.vue new file mode 100644 index 0000000..8dadc02 --- /dev/null +++ b/src/components/IconSelect/index.vue @@ -0,0 +1,104 @@ +<!-- @author zhengjie --> +<template> + <div class="icon-body"> + <el-input v-model="name" class="icon-search" clearable placeholder="璇疯緭鍏ュ浘鏍囧悕绉�" @clear="filterIcons" @input="filterIcons"> + <i slot="suffix" class="el-icon-search el-input__icon" /> + </el-input> + <div class="icon-list"> + <div class="list-container"> + <div v-for="(item, index) in iconList" class="icon-item-wrapper" :key="index" @click="selectedIcon(item)"> + <div :class="['icon-item', { active: activeIcon === item }]"> + <svg-icon :icon-class="item" class-name="icon" style="height: 25px;width: 16px;"/> + <span>{{ item }}</span> + </div> + </div> + </div> + </div> + </div> +</template> + +<script> +import icons from './requireIcons' +export default { + name: 'IconSelect', + props: { + activeIcon: { + type: String + } + }, + data() { + return { + name: '', + iconList: icons + } + }, + methods: { + filterIcons() { + this.iconList = icons + if (this.name) { + this.iconList = this.iconList.filter(item => item.includes(this.name)) + } + }, + selectedIcon(name) { + this.$emit('selected', name) + document.body.click() + }, + reset() { + this.name = '' + this.iconList = icons + } + } +} +</script> + +<style rel="stylesheet/scss" lang="scss" scoped> + .icon-body { + width: 100%; + padding: 10px; + .icon-search { + position: relative; + margin-bottom: 5px; + } + .icon-list { + height: 200px; + overflow: auto; + .list-container { + display: flex; + flex-wrap: wrap; + .icon-item-wrapper { + width: calc(100% / 3); + height: 25px; + line-height: 25px; + cursor: pointer; + display: flex; + .icon-item { + display: flex; + max-width: 100%; + height: 100%; + padding: 0 5px; + &:hover { + background: #ececec; + border-radius: 5px; + } + .icon { + flex-shrink: 0; + } + span { + display: inline-block; + vertical-align: -0.15em; + fill: currentColor; + padding-left: 2px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + } + .icon-item.active { + background: #ececec; + border-radius: 5px; + } + } + } + } + } +</style> diff --git a/src/components/IconSelect/requireIcons.js b/src/components/IconSelect/requireIcons.js new file mode 100644 index 0000000..99e5c54 --- /dev/null +++ b/src/components/IconSelect/requireIcons.js @@ -0,0 +1,11 @@ + +const req = require.context('../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const icons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default icons diff --git a/src/components/ImagePreview/index.vue b/src/components/ImagePreview/index.vue new file mode 100644 index 0000000..3c770c7 --- /dev/null +++ b/src/components/ImagePreview/index.vue @@ -0,0 +1,90 @@ +<template> + <el-image + :src="`${realSrc}`" + fit="cover" + :style="`width:${realWidth};height:${realHeight};`" + :preview-src-list="realSrcList" + > + <div slot="error" class="image-slot"> + <i class="el-icon-picture-outline"></i> + </div> + </el-image> +</template> + +<script> +import { isExternal } from "@/utils/validate"; + +export default { + name: "ImagePreview", + props: { + src: { + type: String, + default: "" + }, + width: { + type: [Number, String], + default: "" + }, + height: { + type: [Number, String], + default: "" + } + }, + computed: { + realSrc() { + if (!this.src) { + return; + } + let real_src = this.src.split(",")[0]; + if (isExternal(real_src)) { + return real_src; + } + return process.env.VUE_APP_BASE_API + real_src; + }, + realSrcList() { + if (!this.src) { + return; + } + let real_src_list = this.src.split(","); + let srcList = []; + real_src_list.forEach(item => { + if (isExternal(item)) { + return srcList.push(item); + } + return srcList.push(process.env.VUE_APP_BASE_API + item); + }); + return srcList; + }, + realWidth() { + return typeof this.width == "string" ? this.width : `${this.width}px`; + }, + realHeight() { + return typeof this.height == "string" ? this.height : `${this.height}px`; + } + }, +}; +</script> + +<style lang="scss" scoped> +.el-image { + border-radius: 5px; + background-color: #ebeef5; + box-shadow: 0 0 5px 1px #ccc; + ::v-deep .el-image__inner { + transition: all 0.3s; + cursor: pointer; + &:hover { + transform: scale(1.2); + } + } + ::v-deep .image-slot { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + color: #909399; + font-size: 30px; + } +} +</style> diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue new file mode 100644 index 0000000..b57a15e --- /dev/null +++ b/src/components/ImageUpload/index.vue @@ -0,0 +1,226 @@ +<template> + <div class="component-upload-image"> + <el-upload + multiple + :action="uploadImgUrl" + list-type="picture-card" + :on-success="handleUploadSuccess" + :before-upload="handleBeforeUpload" + :limit="limit" + :on-error="handleUploadError" + :on-exceed="handleExceed" + ref="imageUpload" + :on-remove="handleDelete" + :show-file-list="true" + :headers="headers" + :file-list="fileList" + :on-preview="handlePictureCardPreview" + :class="{hide: this.fileList.length >= this.limit}" + > + <i class="el-icon-plus"></i> + </el-upload> + + <!-- 涓婁紶鎻愮ず --> + <div class="el-upload__tip" slot="tip" v-if="showTip"> + 璇蜂笂浼� + <template v-if="fileSize"> 澶у皬涓嶈秴杩� <b style="color: #f56c6c">{{ fileSize }}MB</b> </template> + <template v-if="fileType"> 鏍煎紡涓� <b style="color: #f56c6c">{{ fileType.join("/") }}</b> </template> + 鐨勬枃浠� + </div> + + <el-dialog + :visible.sync="dialogVisible" + title="棰勮" + width="800" + append-to-body + > + <img + :src="dialogImageUrl" + style="display: block; max-width: 100%; margin: 0 auto" + /> + </el-dialog> + </div> +</template> + +<script> +import { getToken } from "@/utils/auth"; + +export default { + props: { + value: [String, Object, Array], + // 鍥剧墖鏁伴噺闄愬埗 + limit: { + type: Number, + default: 5, + }, + // 澶у皬闄愬埗(MB) + fileSize: { + type: Number, + default: 5, + }, + // 鏂囦欢绫诲瀷, 渚嬪['png', 'jpg', 'jpeg'] + fileType: { + type: Array, + default: () => ["png", "jpg", "jpeg"], + }, + // 鏄惁鏄剧ず鎻愮ず + isShowTip: { + type: Boolean, + default: true + } + }, + data() { + return { + number: 0, + uploadList: [], + dialogImageUrl: "", + dialogVisible: false, + hideUpload: false, + baseUrl: process.env.VUE_APP_BASE_API, + uploadImgUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 涓婁紶鐨勫浘鐗囨湇鍔″櫒鍦板潃 + headers: { + Authorization: "Bearer " + getToken(), + }, + fileList: [] + }; + }, + watch: { + value: { + handler(val) { + if (val) { + // 棣栧厛灏嗗�艰浆涓烘暟缁� + const list = Array.isArray(val) ? val : this.value.split(','); + // 鐒跺悗灏嗘暟缁勮浆涓哄璞℃暟缁� + this.fileList = list.map(item => { + if (typeof item === "string") { + if (item.indexOf(this.baseUrl) === -1) { + item = { name: this.baseUrl + item, url: this.baseUrl + item }; + } else { + item = { name: item, url: item }; + } + } + return item; + }); + } else { + this.fileList = []; + return []; + } + }, + deep: true, + immediate: true + } + }, + computed: { + // 鏄惁鏄剧ず鎻愮ず + showTip() { + return this.isShowTip && (this.fileType || this.fileSize); + }, + }, + methods: { + // 涓婁紶鍓峫oading鍔犺浇 + handleBeforeUpload(file) { + let isImg = false; + if (this.fileType.length) { + let fileExtension = ""; + if (file.name.lastIndexOf(".") > -1) { + fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); + } + isImg = this.fileType.some(type => { + if (file.type.indexOf(type) > -1) return true; + if (fileExtension && fileExtension.indexOf(type) > -1) return true; + return false; + }); + } else { + isImg = file.type.indexOf("image") > -1; + } + + if (!isImg) { + this.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${this.fileType.join("/")}鍥剧墖鏍煎紡鏂囦欢!`); + return false; + } + if (this.fileSize) { + const isLt = file.size / 1024 / 1024 < this.fileSize; + if (!isLt) { + this.$modal.msgError(`涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 ${this.fileSize} MB!`); + return false; + } + } + this.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��..."); + this.number++; + }, + // 鏂囦欢涓暟瓒呭嚭 + handleExceed() { + this.$modal.msgError(`涓婁紶鏂囦欢鏁伴噺涓嶈兘瓒呰繃 ${this.limit} 涓�!`); + }, + // 涓婁紶鎴愬姛鍥炶皟 + handleUploadSuccess(res, file) { + if (res.code === 200) { + this.uploadList.push({ name: res.fileName, url: res.fileName }); + this.uploadedSuccessfully(); + } else { + this.number--; + this.$modal.closeLoading(); + this.$modal.msgError(res.msg); + this.$refs.imageUpload.handleRemove(file); + this.uploadedSuccessfully(); + } + }, + // 鍒犻櫎鍥剧墖 + handleDelete(file) { + const findex = this.fileList.map(f => f.name).indexOf(file.name); + if(findex > -1) { + this.fileList.splice(findex, 1); + this.$emit("input", this.listToString(this.fileList)); + } + }, + // 涓婁紶澶辫触 + handleUploadError() { + this.$modal.msgError("涓婁紶鍥剧墖澶辫触锛岃閲嶈瘯"); + this.$modal.closeLoading(); + }, + // 涓婁紶缁撴潫澶勭悊 + uploadedSuccessfully() { + if (this.number > 0 && this.uploadList.length === this.number) { + this.fileList = this.fileList.concat(this.uploadList); + this.uploadList = []; + this.number = 0; + this.$emit("input", this.listToString(this.fileList)); + this.$modal.closeLoading(); + } + }, + // 棰勮 + handlePictureCardPreview(file) { + this.dialogImageUrl = file.url; + this.dialogVisible = true; + }, + // 瀵硅薄杞垚鎸囧畾瀛楃涓插垎闅� + listToString(list, separator) { + let strs = ""; + separator = separator || ","; + for (let i in list) { + if (list[i].url) { + strs += list[i].url.replace(this.baseUrl, "") + separator; + } + } + return strs != '' ? strs.substr(0, strs.length - 1) : ''; + } + } +}; +</script> +<style scoped lang="scss"> +// .el-upload--picture-card 鎺у埗鍔犲彿閮ㄥ垎 +::v-deep.hide .el-upload--picture-card { + display: none; +} +// 鍘绘帀鍔ㄧ敾鏁堟灉 +::v-deep .el-list-enter-active, +::v-deep .el-list-leave-active { + transition: all 0s; +} + +::v-deep .el-list-enter, .el-list-leave-active { + opacity: 0; + transform: translateY(0); +} +</style> + diff --git a/src/components/Pagination/index.vue b/src/components/Pagination/index.vue new file mode 100644 index 0000000..56f5a6b --- /dev/null +++ b/src/components/Pagination/index.vue @@ -0,0 +1,114 @@ +<template> + <div :class="{'hidden':hidden}" class="pagination-container"> + <el-pagination + :background="background" + :current-page.sync="currentPage" + :page-size.sync="pageSize" + :layout="layout" + :page-sizes="pageSizes" + :pager-count="pagerCount" + :total="total" + v-bind="$attrs" + @size-change="handleSizeChange" + @current-change="handleCurrentChange" + /> + </div> +</template> + +<script> +import { scrollTo } from '@/utils/scroll-to' + +export default { + name: 'Pagination', + props: { + total: { + required: true, + type: Number + }, + page: { + type: Number, + default: 1 + }, + limit: { + type: Number, + default: 20 + }, + pageSizes: { + type: Array, + default() { + return [10, 20, 30, 50] + } + }, + // 绉诲姩绔〉鐮佹寜閽殑鏁伴噺绔粯璁ゅ��5 + pagerCount: { + type: Number, + default: document.body.clientWidth < 992 ? 5 : 7 + }, + layout: { + type: String, + default: 'total, sizes, prev, pager, next, jumper' + }, + background: { + type: Boolean, + default: true + }, + autoScroll: { + type: Boolean, + default: true + }, + hidden: { + type: Boolean, + default: false + } + }, + data() { + return { + }; + }, + computed: { + currentPage: { + get() { + return this.page + }, + set(val) { + this.$emit('update:page', val) + } + }, + pageSize: { + get() { + return this.limit + }, + set(val) { + this.$emit('update:limit', val) + } + } + }, + methods: { + handleSizeChange(val) { + if (this.currentPage * val > this.total) { + this.currentPage = 1 + } + this.$emit('pagination', { page: this.currentPage, limit: val }) + if (this.autoScroll) { + scrollTo(0, 800) + } + }, + handleCurrentChange(val) { + this.$emit('pagination', { page: val, limit: this.pageSize }) + if (this.autoScroll) { + scrollTo(0, 800) + } + } + } +} +</script> + +<style scoped> +.pagination-container { + background: #fff; + padding: 32px 16px; +} +.pagination-container.hidden { + display: none; +} +</style> diff --git a/src/components/PanThumb/index.vue b/src/components/PanThumb/index.vue new file mode 100644 index 0000000..1bcf417 --- /dev/null +++ b/src/components/PanThumb/index.vue @@ -0,0 +1,142 @@ +<template> + <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item"> + <div class="pan-info"> + <div class="pan-info-roles-container"> + <slot /> + </div> + </div> + <!-- eslint-disable-next-line --> + <div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div> + </div> +</template> + +<script> +export default { + name: 'PanThumb', + props: { + image: { + type: String, + required: true + }, + zIndex: { + type: Number, + default: 1 + }, + width: { + type: String, + default: '150px' + }, + height: { + type: String, + default: '150px' + } + } +} +</script> + +<style scoped> +.pan-item { + width: 200px; + height: 200px; + border-radius: 50%; + display: inline-block; + position: relative; + cursor: default; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); +} + +.pan-info-roles-container { + padding: 20px; + text-align: center; +} + +.pan-thumb { + width: 100%; + height: 100%; + background-position: center center; + background-size: cover; + border-radius: 50%; + overflow: hidden; + position: absolute; + transform-origin: 95% 40%; + transition: all 0.3s ease-in-out; +} + +/* .pan-thumb:after { + content: ''; + width: 8px; + height: 8px; + position: absolute; + border-radius: 50%; + top: 40%; + left: 95%; + margin: -4px 0 0 -4px; + background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%); + box-shadow: 0 0 1px rgba(255, 255, 255, 0.9); +} */ + +.pan-info { + position: absolute; + width: inherit; + height: inherit; + border-radius: 50%; + overflow: hidden; + box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05); +} + +.pan-info h3 { + color: #fff; + text-transform: uppercase; + position: relative; + letter-spacing: 2px; + font-size: 18px; + margin: 0 60px; + padding: 22px 0 0 0; + height: 85px; + font-family: 'Open Sans', Arial, sans-serif; + text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.pan-info p { + color: #fff; + padding: 10px 5px; + font-style: italic; + margin: 0 30px; + font-size: 12px; + border-top: 1px solid rgba(255, 255, 255, 0.5); +} + +.pan-info p a { + display: block; + color: #333; + width: 80px; + height: 80px; + background: rgba(255, 255, 255, 0.3); + border-radius: 50%; + color: #fff; + font-style: normal; + font-weight: 700; + text-transform: uppercase; + font-size: 9px; + letter-spacing: 1px; + padding-top: 24px; + margin: 7px auto 0; + font-family: 'Open Sans', Arial, sans-serif; + opacity: 0; + transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s; + transform: translateX(60px) rotate(90deg); +} + +.pan-info p a:hover { + background: rgba(255, 255, 255, 0.5); +} + +.pan-item:hover .pan-thumb { + transform: rotate(-110deg); +} + +.pan-item:hover .pan-info p a { + opacity: 1; + transform: translateX(0px) rotate(0deg); +} +</style> diff --git a/src/components/ParentView/index.vue b/src/components/ParentView/index.vue new file mode 100644 index 0000000..7bf6148 --- /dev/null +++ b/src/components/ParentView/index.vue @@ -0,0 +1,3 @@ +<template > + <router-view /> +</template> diff --git a/src/components/RightPanel/index.vue b/src/components/RightPanel/index.vue new file mode 100644 index 0000000..5abeecb --- /dev/null +++ b/src/components/RightPanel/index.vue @@ -0,0 +1,106 @@ +<template> + <div ref="rightPanel" class="rightPanel-container"> + <div class="rightPanel-background" /> + <div class="rightPanel"> + <div class="rightPanel-items"> + <slot /> + </div> + </div> + </div> +</template> + +<script> +export default { + name: 'RightPanel', + props: { + clickNotClose: { + default: false, + type: Boolean + } + }, + computed: { + show: { + get() { + return this.$store.state.settings.showSettings + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'showSettings', + value: val + }) + } + } + }, + watch: { + show(value) { + if (value && !this.clickNotClose) { + this.addEventClick() + } + } + }, + mounted() { + this.addEventClick() + }, + beforeDestroy() { + const elx = this.$refs.rightPanel + elx.remove() + }, + methods: { + addEventClick() { + window.addEventListener('click', this.closeSidebar) + }, + closeSidebar(evt) { + const parent = evt.target.closest('.el-drawer__body') + if (!parent) { + this.show = false + window.removeEventListener('click', this.closeSidebar) + } + } + } +} +</script> + +<style lang="scss" scoped> +.rightPanel-background { + position: fixed; + top: 0; + left: 0; + opacity: 0; + transition: opacity .3s cubic-bezier(.7, .3, .1, 1); + background: rgba(0, 0, 0, .2); + z-index: -1; +} + +.rightPanel { + width: 100%; + max-width: 260px; + height: 100vh; + position: fixed; + top: 0; + right: 0; + box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05); + transition: all .25s cubic-bezier(.7, .3, .1, 1); + transform: translate(100%); + background: #fff; + z-index: 40000; +} + +.handle-button { + width: 48px; + height: 48px; + position: absolute; + left: -48px; + text-align: center; + font-size: 24px; + border-radius: 6px 0 0 6px !important; + z-index: 0; + pointer-events: auto; + cursor: pointer; + color: #fff; + line-height: 48px; + i { + font-size: 24px; + line-height: 48px; + } +} +</style> diff --git a/src/components/RightToolbar/index.vue b/src/components/RightToolbar/index.vue new file mode 100644 index 0000000..527e07c --- /dev/null +++ b/src/components/RightToolbar/index.vue @@ -0,0 +1,104 @@ +<template> + <div class="top-right-btn" :style="style"> + <el-row> + <el-tooltip class="item" effect="dark" :content="showSearch ? '闅愯棌鎼滅储' : '鏄剧ず鎼滅储'" placement="top" v-if="search"> + <el-button size="mini" circle icon="el-icon-search" @click="toggleSearch()" /> + </el-tooltip> + <el-tooltip class="item" effect="dark" content="鍒锋柊" placement="top"> + <el-button size="mini" circle icon="el-icon-refresh" @click="refresh()" /> + </el-tooltip> + <el-tooltip class="item" effect="dark" content="鏄鹃殣鍒�" placement="top" v-if="columns"> + <el-button size="mini" circle icon="el-icon-menu" @click="showColumn()" /> + </el-tooltip> + </el-row> + <el-dialog :title="title" :visible.sync="open" append-to-body> + <el-transfer + :titles="['鏄剧ず', '闅愯棌']" + v-model="value" + :data="columns" + @change="dataChange" + ></el-transfer> + </el-dialog> + </div> +</template> +<script> +export default { + name: "RightToolbar", + data() { + return { + // 鏄鹃殣鏁版嵁 + value: [], + // 寮瑰嚭灞傛爣棰� + title: "鏄剧ず/闅愯棌", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + }; + }, + props: { + showSearch: { + type: Boolean, + default: true, + }, + columns: { + type: Array, + }, + search: { + type: Boolean, + default: true, + }, + gutter: { + type: Number, + default: 10, + }, + }, + computed: { + style() { + const ret = {}; + if (this.gutter) { + ret.marginRight = `${this.gutter / 2}px`; + } + return ret; + } + }, + created() { + // 鏄鹃殣鍒楀垵濮嬮粯璁ら殣钘忓垪 + for (let item in this.columns) { + if (this.columns[item].visible === false) { + this.value.push(parseInt(item)); + } + } + }, + methods: { + // 鎼滅储 + toggleSearch() { + this.$emit("update:showSearch", !this.showSearch); + }, + // 鍒锋柊 + refresh() { + this.$emit("queryTable"); + }, + // 鍙充晶鍒楄〃鍏冪礌鍙樺寲 + dataChange(data) { + for (let item in this.columns) { + const key = this.columns[item].key; + this.columns[item].visible = !data.includes(key); + } + }, + // 鎵撳紑鏄鹃殣鍒梔ialog + showColumn() { + this.open = true; + }, + }, +}; +</script> +<style lang="scss" scoped> +::v-deep .el-transfer__button { + border-radius: 50%; + padding: 12px; + display: block; + margin-left: 0px; +} +::v-deep .el-transfer__button:first-child { + margin-bottom: 10px; +} +</style> diff --git a/src/components/RuoYi/Doc/index.vue b/src/components/RuoYi/Doc/index.vue new file mode 100644 index 0000000..75fa864 --- /dev/null +++ b/src/components/RuoYi/Doc/index.vue @@ -0,0 +1,21 @@ +<template> + <div> + <svg-icon icon-class="question" @click="goto" /> + </div> +</template> + +<script> +export default { + name: 'RuoYiDoc', + data() { + return { + url: 'http://doc.ruoyi.vip/ruoyi-vue' + } + }, + methods: { + goto() { + window.open(this.url) + } + } +} +</script> \ No newline at end of file diff --git a/src/components/RuoYi/Git/index.vue b/src/components/RuoYi/Git/index.vue new file mode 100644 index 0000000..bdafbae --- /dev/null +++ b/src/components/RuoYi/Git/index.vue @@ -0,0 +1,21 @@ +<template> + <div> + <svg-icon icon-class="github" @click="goto" /> + </div> +</template> + +<script> +export default { + name: 'RuoYiGit', + data() { + return { + url: 'https://gitee.com/y_project/RuoYi-Vue' + } + }, + methods: { + goto() { + window.open(this.url) + } + } +} +</script> \ No newline at end of file diff --git a/src/components/Screenfull/index.vue b/src/components/Screenfull/index.vue new file mode 100644 index 0000000..d4e539c --- /dev/null +++ b/src/components/Screenfull/index.vue @@ -0,0 +1,57 @@ +<template> + <div> + <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" /> + </div> +</template> + +<script> +import screenfull from 'screenfull' + +export default { + name: 'Screenfull', + data() { + return { + isFullscreen: false + } + }, + mounted() { + this.init() + }, + beforeDestroy() { + this.destroy() + }, + methods: { + click() { + if (!screenfull.isEnabled) { + this.$message({ message: '浣犵殑娴忚鍣ㄤ笉鏀寔鍏ㄥ睆', type: 'warning' }) + return false + } + screenfull.toggle() + }, + change() { + this.isFullscreen = screenfull.isFullscreen + }, + init() { + if (screenfull.isEnabled) { + screenfull.on('change', this.change) + } + }, + destroy() { + if (screenfull.isEnabled) { + screenfull.off('change', this.change) + } + } + } +} +</script> + +<style scoped> +.screenfull-svg { + display: inline-block; + cursor: pointer; + fill: #5a5e66;; + width: 20px; + height: 20px; + vertical-align: 10px; +} +</style> diff --git a/src/components/SizeSelect/index.vue b/src/components/SizeSelect/index.vue new file mode 100644 index 0000000..069b5de --- /dev/null +++ b/src/components/SizeSelect/index.vue @@ -0,0 +1,56 @@ +<template> + <el-dropdown trigger="click" @command="handleSetSize"> + <div> + <svg-icon class-name="size-icon" icon-class="size" /> + </div> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value"> + {{ item.label }} + </el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> +</template> + +<script> +export default { + data() { + return { + sizeOptions: [ + { label: 'Default', value: 'default' }, + { label: 'Medium', value: 'medium' }, + { label: 'Small', value: 'small' }, + { label: 'Mini', value: 'mini' } + ] + } + }, + computed: { + size() { + return this.$store.getters.size + } + }, + methods: { + handleSetSize(size) { + this.$ELEMENT.size = size + this.$store.dispatch('app/setSize', size) + this.refreshView() + this.$message({ + message: 'Switch Size Success', + type: 'success' + }) + }, + refreshView() { + // In order to make the cached page re-rendered + this.$store.dispatch('tagsView/delAllCachedViews', this.$route) + + const { fullPath } = this.$route + + this.$nextTick(() => { + this.$router.replace({ + path: '/redirect' + fullPath + }) + }) + } + } + +} +</script> diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue new file mode 100644 index 0000000..e4bf5ad --- /dev/null +++ b/src/components/SvgIcon/index.vue @@ -0,0 +1,61 @@ +<template> + <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> + <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> + <use :xlink:href="iconName" /> + </svg> +</template> + +<script> +import { isExternal } from '@/utils/validate' + +export default { + name: 'SvgIcon', + props: { + iconClass: { + type: String, + required: true + }, + className: { + type: String, + default: '' + } + }, + computed: { + isExternal() { + return isExternal(this.iconClass) + }, + iconName() { + return `#icon-${this.iconClass}` + }, + svgClass() { + if (this.className) { + return 'svg-icon ' + this.className + } else { + return 'svg-icon' + } + }, + styleExternalIcon() { + return { + mask: `url(${this.iconClass}) no-repeat 50% 50%`, + '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` + } + } + } +} +</script> + +<style scoped> +.svg-icon { + width: 1em; + height: 1em; + vertical-align: -0.15em; + fill: currentColor; + overflow: hidden; +} + +.svg-external-icon { + background-color: currentColor; + mask-size: cover!important; + display: inline-block; +} +</style> diff --git a/src/components/ThemePicker/index.vue b/src/components/ThemePicker/index.vue new file mode 100644 index 0000000..1714e1f --- /dev/null +++ b/src/components/ThemePicker/index.vue @@ -0,0 +1,173 @@ +<template> + <el-color-picker + v-model="theme" + :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]" + class="theme-picker" + popper-class="theme-picker-dropdown" + /> +</template> + +<script> +const version = require('element-ui/package.json').version // element-ui version from node_modules +const ORIGINAL_THEME = '#409EFF' // default color + +export default { + data() { + return { + chalk: '', // content of theme-chalk css + theme: '' + } + }, + computed: { + defaultTheme() { + return this.$store.state.settings.theme + } + }, + watch: { + defaultTheme: { + handler: function(val, oldVal) { + this.theme = val + }, + immediate: true + }, + async theme(val) { + await this.setTheme(val) + } + }, + created() { + if(this.defaultTheme !== ORIGINAL_THEME) { + this.setTheme(this.defaultTheme) + } + }, + + methods: { + async setTheme(val) { + const oldVal = this.chalk ? this.theme : ORIGINAL_THEME + if (typeof val !== 'string') return + const themeCluster = this.getThemeCluster(val.replace('#', '')) + const originalCluster = this.getThemeCluster(oldVal.replace('#', '')) + + const getHandler = (variable, id) => { + return () => { + const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', '')) + const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster) + + let styleTag = document.getElementById(id) + if (!styleTag) { + styleTag = document.createElement('style') + styleTag.setAttribute('id', id) + document.head.appendChild(styleTag) + } + styleTag.innerText = newStyle + } + } + + if (!this.chalk) { + const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css` + await this.getCSSString(url, 'chalk') + } + + const chalkHandler = getHandler('chalk', 'chalk-style') + + chalkHandler() + + const styles = [].slice.call(document.querySelectorAll('style')) + .filter(style => { + const text = style.innerText + return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text) + }) + styles.forEach(style => { + const { innerText } = style + if (typeof innerText !== 'string') return + style.innerText = this.updateStyle(innerText, originalCluster, themeCluster) + }) + + this.$emit('change', val) + }, + + updateStyle(style, oldCluster, newCluster) { + let newStyle = style + oldCluster.forEach((color, index) => { + newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index]) + }) + return newStyle + }, + + getCSSString(url, variable) { + return new Promise(resolve => { + const xhr = new XMLHttpRequest() + xhr.onreadystatechange = () => { + if (xhr.readyState === 4 && xhr.status === 200) { + this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '') + resolve() + } + } + xhr.open('GET', url) + xhr.send() + }) + }, + + getThemeCluster(theme) { + const tintColor = (color, tint) => { + let red = parseInt(color.slice(0, 2), 16) + let green = parseInt(color.slice(2, 4), 16) + let blue = parseInt(color.slice(4, 6), 16) + + if (tint === 0) { // when primary color is in its rgb space + return [red, green, blue].join(',') + } else { + red += Math.round(tint * (255 - red)) + green += Math.round(tint * (255 - green)) + blue += Math.round(tint * (255 - blue)) + + red = red.toString(16) + green = green.toString(16) + blue = blue.toString(16) + + return `#${red}${green}${blue}` + } + } + + const shadeColor = (color, shade) => { + let red = parseInt(color.slice(0, 2), 16) + let green = parseInt(color.slice(2, 4), 16) + let blue = parseInt(color.slice(4, 6), 16) + + red = Math.round((1 - shade) * red) + green = Math.round((1 - shade) * green) + blue = Math.round((1 - shade) * blue) + + red = red.toString(16) + green = green.toString(16) + blue = blue.toString(16) + + return `#${red}${green}${blue}` + } + + const clusters = [theme] + for (let i = 0; i <= 9; i++) { + clusters.push(tintColor(theme, Number((i / 10).toFixed(2)))) + } + clusters.push(shadeColor(theme, 0.1)) + return clusters + } + } +} +</script> + +<style> +.theme-message, +.theme-picker-dropdown { + z-index: 99999 !important; +} + +.theme-picker .el-color-picker__trigger { + height: 26px !important; + width: 26px !important; + padding: 2px; +} + +.theme-picker-dropdown .el-color-dropdown__link-btn { + display: none; +} +</style> diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue new file mode 100644 index 0000000..daee1b8 --- /dev/null +++ b/src/components/TopNav/index.vue @@ -0,0 +1,194 @@ +<template> + <el-menu + :default-active="activeMenu" + mode="horizontal" + @select="handleSelect" + > + <template v-for="(item, index) in topMenus"> + <el-menu-item :style="{'--theme': theme}" :index="item.path" :key="index" v-if="index < visibleNumber" + ><svg-icon + v-if="item.meta && item.meta.icon && item.meta.icon !== '#'" + :icon-class="item.meta.icon" + /> + {{ item.meta.title }}</el-menu-item + > + </template> + + <!-- 椤堕儴鑿滃崟瓒呭嚭鏁伴噺鎶樺彔 --> + <el-submenu :style="{'--theme': theme}" index="more" v-if="topMenus.length > visibleNumber"> + <template slot="title">鏇村鑿滃崟</template> + <template v-for="(item, index) in topMenus"> + <el-menu-item + :index="item.path" + :key="index" + v-if="index >= visibleNumber" + ><svg-icon :icon-class="item.meta.icon" /> + {{ item.meta.title }}</el-menu-item + > + </template> + </el-submenu> + </el-menu> +</template> + +<script> +import { constantRoutes } from "@/router"; + +// 闅愯棌渚ц竟鏍忚矾鐢� +const hideList = ['/index', '/user/profile']; + +export default { + data() { + return { + // 椤堕儴鏍忓垵濮嬫暟 + visibleNumber: 5, + // 褰撳墠婵�娲昏彍鍗曠殑 index + currentIndex: undefined + }; + }, + computed: { + theme() { + return this.$store.state.settings.theme; + }, + // 椤堕儴鏄剧ず鑿滃崟 + topMenus() { + let topMenus = []; + this.routers.map((menu) => { + if (menu.hidden !== true) { + // 鍏煎椤堕儴鏍忎竴绾ц彍鍗曞唴閮ㄨ烦杞� + if (menu.path === "/") { + topMenus.push(menu.children[0]); + } else { + topMenus.push(menu); + } + } + }); + return topMenus; + }, + // 鎵�鏈夌殑璺敱淇℃伅 + routers() { + return this.$store.state.permission.topbarRouters; + }, + // 璁剧疆瀛愯矾鐢� + childrenMenus() { + var childrenMenus = []; + this.routers.map((router) => { + for (var item in router.children) { + if (router.children[item].parentPath === undefined) { + if(router.path === "/") { + router.children[item].path = "/" + router.children[item].path; + } else { + if(!this.ishttp(router.children[item].path)) { + router.children[item].path = router.path + "/" + router.children[item].path; + } + } + router.children[item].parentPath = router.path; + } + childrenMenus.push(router.children[item]); + } + }); + return constantRoutes.concat(childrenMenus); + }, + // 榛樿婵�娲荤殑鑿滃崟 + activeMenu() { + const path = this.$route.path; + let activePath = path; + if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) { + const tmpPath = path.substring(1, path.length); + activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/")); + if (!this.$route.meta.link) { + this.$store.dispatch('app/toggleSideBarHide', false); + } + } else if(!this.$route.children) { + activePath = path; + this.$store.dispatch('app/toggleSideBarHide', true); + } + this.activeRoutes(activePath); + return activePath; + }, + }, + beforeMount() { + window.addEventListener('resize', this.setVisibleNumber) + }, + beforeDestroy() { + window.removeEventListener('resize', this.setVisibleNumber) + }, + mounted() { + this.setVisibleNumber(); + }, + methods: { + // 鏍规嵁瀹藉害璁$畻璁剧疆鏄剧ず鏍忔暟 + setVisibleNumber() { + const width = document.body.getBoundingClientRect().width / 3; + this.visibleNumber = parseInt(width / 85); + }, + // 鑿滃崟閫夋嫨浜嬩欢 + handleSelect(key, keyPath) { + this.currentIndex = key; + const route = this.routers.find(item => item.path === key); + if (this.ishttp(key)) { + // http(s):// 璺緞鏂扮獥鍙f墦寮� + window.open(key, "_blank"); + } else if (!route || !route.children) { + // 娌℃湁瀛愯矾鐢辫矾寰勫唴閮ㄦ墦寮� + const routeMenu = this.childrenMenus.find(item => item.path === key); + if (routeMenu && routeMenu.query) { + let query = JSON.parse(routeMenu.query); + this.$router.push({ path: key, query: query }); + } else { + this.$router.push({ path: key }); + } + this.$store.dispatch('app/toggleSideBarHide', true); + } else { + // 鏄剧ず宸︿晶鑱斿姩鑿滃崟 + this.activeRoutes(key); + this.$store.dispatch('app/toggleSideBarHide', false); + } + }, + // 褰撳墠婵�娲荤殑璺敱 + activeRoutes(key) { + var routes = []; + if (this.childrenMenus && this.childrenMenus.length > 0) { + this.childrenMenus.map((item) => { + if (key == item.parentPath || (key == "index" && "" == item.path)) { + routes.push(item); + } + }); + } + if(routes.length > 0) { + this.$store.commit("SET_SIDEBAR_ROUTERS", routes); + } else { + this.$store.dispatch('app/toggleSideBarHide', true); + } + }, + ishttp(url) { + return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1 + } + }, +}; +</script> + +<style lang="scss"> +.topmenu-container.el-menu--horizontal > .el-menu-item { + float: left; + height: 50px !important; + line-height: 50px !important; + color: #999093 !important; + padding: 0 5px !important; + margin: 0 10px !important; +} + +.topmenu-container.el-menu--horizontal > .el-menu-item.is-active, .el-menu--horizontal > .el-submenu.is-active .el-submenu__title { + border-bottom: 2px solid #{'var(--theme)'} !important; + color: #303133; +} + +/* submenu item */ +.topmenu-container.el-menu--horizontal > .el-submenu .el-submenu__title { + float: left; + height: 50px !important; + line-height: 50px !important; + color: #999093 !important; + padding: 0 5px !important; + margin: 0 10px !important; +} +</style> diff --git a/src/components/iFrame/index.vue b/src/components/iFrame/index.vue new file mode 100644 index 0000000..426857f --- /dev/null +++ b/src/components/iFrame/index.vue @@ -0,0 +1,36 @@ +<template> + <div v-loading="loading" :style="'height:' + height"> + <iframe + :src="src" + frameborder="no" + style="width: 100%; height: 100%" + scrolling="auto" + /> + </div> +</template> +<script> +export default { + props: { + src: { + type: String, + required: true + }, + }, + data() { + return { + height: document.documentElement.clientHeight - 94.5 + "px;", + loading: true, + url: this.src + }; + }, + mounted: function () { + setTimeout(() => { + this.loading = false; + }, 300); + const that = this; + window.onresize = function temp() { + that.height = document.documentElement.clientHeight - 94.5 + "px;"; + }; + } +}; +</script> diff --git a/src/directive/dialog/drag.js b/src/directive/dialog/drag.js new file mode 100644 index 0000000..2e82346 --- /dev/null +++ b/src/directive/dialog/drag.js @@ -0,0 +1,64 @@ +/** +* v-dialogDrag 寮圭獥鎷栨嫿 +* Copyright (c) 2019 ruoyi +*/ + +export default { + bind(el, binding, vnode, oldVnode) { + const value = binding.value + if (value == false) return + // 鑾峰彇鎷栨嫿鍐呭澶撮儴 + const dialogHeaderEl = el.querySelector('.el-dialog__header'); + const dragDom = el.querySelector('.el-dialog'); + dialogHeaderEl.style.cursor = 'move'; + // 鑾峰彇鍘熸湁灞炴�� ie dom鍏冪礌.currentStyle 鐏嫄璋锋瓕 window.getComputedStyle(dom鍏冪礌, null); + const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null); + dragDom.style.position = 'absolute'; + dragDom.style.marginTop = 0; + let width = dragDom.style.width; + if (width.includes('%')) { + width = +document.body.clientWidth * (+width.replace(/\%/g, '') / 100); + } else { + width = +width.replace(/\px/g, ''); + } + dragDom.style.left = `${(document.body.clientWidth - width) / 2}px`; + // 榧犳爣鎸変笅浜嬩欢 + dialogHeaderEl.onmousedown = (e) => { + // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂� (榧犳爣鐐瑰嚮浣嶇疆璺濈鍙绐楀彛鐨勮窛绂�) + const disX = e.clientX - dialogHeaderEl.offsetLeft; + const disY = e.clientY - dialogHeaderEl.offsetTop; + + // 鑾峰彇鍒扮殑鍊煎甫px 姝e垯鍖归厤鏇挎崲 + let styL, styT; + + // 娉ㄦ剰鍦╥e涓� 绗竴娆¤幏鍙栧埌鐨勫�间负缁勪欢鑷甫50% 绉诲姩涔嬪悗璧嬪�间负px + if (sty.left.includes('%')) { + styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100); + styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100); + } else { + styL = +sty.left.replace(/\px/g, ''); + styT = +sty.top.replace(/\px/g, ''); + }; + + // 榧犳爣鎷栨嫿浜嬩欢 + document.onmousemove = function (e) { + // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈 锛堝紑濮嬫嫋鎷借嚦缁撴潫鎷栨嫿鐨勮窛绂伙級 + const l = e.clientX - disX; + const t = e.clientY - disY; + + let finallyL = l + styL + let finallyT = t + styT + + // 绉诲姩褰撳墠鍏冪礌 + dragDom.style.left = `${finallyL}px`; + dragDom.style.top = `${finallyT}px`; + + }; + + document.onmouseup = function (e) { + document.onmousemove = null; + document.onmouseup = null; + }; + } + } +}; \ No newline at end of file diff --git a/src/directive/dialog/dragHeight.js b/src/directive/dialog/dragHeight.js new file mode 100644 index 0000000..d1590f8 --- /dev/null +++ b/src/directive/dialog/dragHeight.js @@ -0,0 +1,34 @@ +/** +* v-dialogDragWidth 鍙嫋鍔ㄥ脊绐楅珮搴︼紙鍙充笅瑙掞級 +* Copyright (c) 2019 ruoyi +*/ + +export default { + bind(el) { + const dragDom = el.querySelector('.el-dialog'); + const lineEl = document.createElement('div'); + lineEl.style = 'width: 6px; background: inherit; height: 10px; position: absolute; right: 0; bottom: 0; margin: auto; z-index: 1; cursor: nwse-resize;'; + lineEl.addEventListener('mousedown', + function(e) { + // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂� + const disX = e.clientX - el.offsetLeft; + const disY = e.clientY - el.offsetTop; + // 褰撳墠瀹藉害 楂樺害 + const curWidth = dragDom.offsetWidth; + const curHeight = dragDom.offsetHeight; + document.onmousemove = function(e) { + e.preventDefault(); // 绉诲姩鏃剁鐢ㄩ粯璁や簨浠� + // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈 + const xl = e.clientX - disX; + const yl = e.clientY - disY + dragDom.style.width = `${curWidth + xl}px`; + dragDom.style.height = `${curHeight + yl}px`; + }; + document.onmouseup = function(e) { + document.onmousemove = null; + document.onmouseup = null; + }; + }, false); + dragDom.appendChild(lineEl); + } +} \ No newline at end of file diff --git a/src/directive/dialog/dragWidth.js b/src/directive/dialog/dragWidth.js new file mode 100644 index 0000000..d5cda3a --- /dev/null +++ b/src/directive/dialog/dragWidth.js @@ -0,0 +1,30 @@ +/** +* v-dialogDragWidth 鍙嫋鍔ㄥ脊绐楀搴︼紙鍙充晶杈癸級 +* Copyright (c) 2019 ruoyi +*/ + +export default { + bind(el) { + const dragDom = el.querySelector('.el-dialog'); + const lineEl = document.createElement('div'); + lineEl.style = 'width: 5px; background: inherit; height: 80%; position: absolute; right: 0; top: 0; bottom: 0; margin: auto; z-index: 1; cursor: w-resize;'; + lineEl.addEventListener('mousedown', + function (e) { + // 榧犳爣鎸変笅锛岃绠楀綋鍓嶅厓绱犺窛绂诲彲瑙嗗尯鐨勮窛绂� + const disX = e.clientX - el.offsetLeft; + // 褰撳墠瀹藉害 + const curWidth = dragDom.offsetWidth; + document.onmousemove = function (e) { + e.preventDefault(); // 绉诲姩鏃剁鐢ㄩ粯璁や簨浠� + // 閫氳繃浜嬩欢濮旀墭锛岃绠楃Щ鍔ㄧ殑璺濈 + const l = e.clientX - disX; + dragDom.style.width = `${curWidth + l}px`; + }; + document.onmouseup = function (e) { + document.onmousemove = null; + document.onmouseup = null; + }; + }, false); + dragDom.appendChild(lineEl); + } +} \ No newline at end of file diff --git a/src/directive/index.js b/src/directive/index.js new file mode 100644 index 0000000..b9b07da --- /dev/null +++ b/src/directive/index.js @@ -0,0 +1,23 @@ +import hasRole from './permission/hasRole' +import hasPermi from './permission/hasPermi' +import dialogDrag from './dialog/drag' +import dialogDragWidth from './dialog/dragWidth' +import dialogDragHeight from './dialog/dragHeight' +import clipboard from './module/clipboard' + +const install = function(Vue) { + Vue.directive('hasRole', hasRole) + Vue.directive('hasPermi', hasPermi) + Vue.directive('clipboard', clipboard) + Vue.directive('dialogDrag', dialogDrag) + Vue.directive('dialogDragWidth', dialogDragWidth) + Vue.directive('dialogDragHeight', dialogDragHeight) +} + +if (window.Vue) { + window['hasRole'] = hasRole + window['hasPermi'] = hasPermi + Vue.use(install); // eslint-disable-line +} + +export default install diff --git a/src/directive/module/clipboard.js b/src/directive/module/clipboard.js new file mode 100644 index 0000000..635315a --- /dev/null +++ b/src/directive/module/clipboard.js @@ -0,0 +1,54 @@ +/** +* v-clipboard 鏂囧瓧澶嶅埗鍓创 +* Copyright (c) 2021 ruoyi +*/ + +import Clipboard from 'clipboard' +export default { + bind(el, binding, vnode) { + switch (binding.arg) { + case 'success': + el._vClipBoard_success = binding.value; + break; + case 'error': + el._vClipBoard_error = binding.value; + break; + default: { + const clipboard = new Clipboard(el, { + text: () => binding.value, + action: () => binding.arg === 'cut' ? 'cut' : 'copy' + }); + clipboard.on('success', e => { + const callback = el._vClipBoard_success; + callback && callback(e); + }); + clipboard.on('error', e => { + const callback = el._vClipBoard_error; + callback && callback(e); + }); + el._vClipBoard = clipboard; + } + } + }, + update(el, binding) { + if (binding.arg === 'success') { + el._vClipBoard_success = binding.value; + } else if (binding.arg === 'error') { + el._vClipBoard_error = binding.value; + } else { + el._vClipBoard.text = function () { return binding.value; }; + el._vClipBoard.action = () => binding.arg === 'cut' ? 'cut' : 'copy'; + } + }, + unbind(el, binding) { + if (!el._vClipboard) return + if (binding.arg === 'success') { + delete el._vClipBoard_success; + } else if (binding.arg === 'error') { + delete el._vClipBoard_error; + } else { + el._vClipBoard.destroy(); + delete el._vClipBoard; + } + } +} diff --git a/src/directive/permission/hasPermi.js b/src/directive/permission/hasPermi.js new file mode 100644 index 0000000..719536c --- /dev/null +++ b/src/directive/permission/hasPermi.js @@ -0,0 +1,28 @@ + /** + * v-hasPermi 鎿嶄綔鏉冮檺澶勭悊 + * Copyright (c) 2019 ruoyi + */ + +import store from '@/store' + +export default { + inserted(el, binding, vnode) { + const { value } = binding + const all_permission = "*:*:*"; + const permissions = store.getters && store.getters.permissions + + if (value && value instanceof Array && value.length > 0) { + const permissionFlag = value + + const hasPermissions = permissions.some(permission => { + return all_permission === permission || permissionFlag.includes(permission) + }) + + if (!hasPermissions) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + throw new Error(`璇疯缃搷浣滄潈闄愭爣绛惧�糮) + } + } +} diff --git a/src/directive/permission/hasRole.js b/src/directive/permission/hasRole.js new file mode 100644 index 0000000..eec4a5b --- /dev/null +++ b/src/directive/permission/hasRole.js @@ -0,0 +1,28 @@ + /** + * v-hasRole 瑙掕壊鏉冮檺澶勭悊 + * Copyright (c) 2019 ruoyi + */ + +import store from '@/store' + +export default { + inserted(el, binding, vnode) { + const { value } = binding + const super_admin = "admin"; + const roles = store.getters && store.getters.roles + + if (value && value instanceof Array && value.length > 0) { + const roleFlag = value + + const hasRole = roles.some(role => { + return super_admin === role || roleFlag.includes(role) + }) + + if (!hasRole) { + el.parentNode && el.parentNode.removeChild(el) + } + } else { + throw new Error(`璇疯缃鑹叉潈闄愭爣绛惧��"`) + } + } +} diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue new file mode 100644 index 0000000..a25c562 --- /dev/null +++ b/src/layout/components/AppMain.vue @@ -0,0 +1,75 @@ +<template> + <section class="app-main"> + <transition name="fade-transform" mode="out-in"> + <keep-alive :include="cachedViews"> + <router-view v-if="!$route.meta.link" :key="key" /> + </keep-alive> + </transition> + <iframe-toggle /> + </section> +</template> + +<script> +import iframeToggle from "./IframeToggle/index" + +export default { + name: 'AppMain', + components: { iframeToggle }, + computed: { + cachedViews() { + return this.$store.state.tagsView.cachedViews + }, + key() { + return this.$route.path + } + } +} +</script> + +<style lang="scss" scoped> +.app-main { + /* 50= navbar 50 */ + min-height: calc(100vh - 50px); + width: 100%; + position: relative; + overflow: hidden; +} + +.fixed-header + .app-main { + padding-top: 50px; +} + +.hasTagsView { + .app-main { + /* 84 = navbar + tags-view = 50 + 34 */ + min-height: calc(100vh - 84px); + } + + .fixed-header + .app-main { + padding-top: 84px; + } +} +</style> + +<style lang="scss"> +// fix css style bug in open el-dialog +.el-popup-parent--hidden { + .fixed-header { + padding-right: 6px; + } +} + +::-webkit-scrollbar { + width: 6px; + height: 6px; +} + +::-webkit-scrollbar-track { + background-color: #f1f1f1; +} + +::-webkit-scrollbar-thumb { + background-color: #c0c0c0; + border-radius: 3px; +} +</style> diff --git a/src/layout/components/IframeToggle/index.vue b/src/layout/components/IframeToggle/index.vue new file mode 100644 index 0000000..26e17c1 --- /dev/null +++ b/src/layout/components/IframeToggle/index.vue @@ -0,0 +1,24 @@ +<template> + <transition-group name="fade-transform" mode="out-in"> + <inner-link + v-for="(item, index) in iframeViews" + :key="item.path" + :iframeId="'iframe' + index" + v-show="$route.path === item.path" + :src="item.meta.link" + ></inner-link> + </transition-group> +</template> + +<script> +import InnerLink from "../InnerLink/index" + +export default { + components: { InnerLink }, + computed: { + iframeViews() { + return this.$store.state.tagsView.iframeViews + } + } +} +</script> diff --git a/src/layout/components/InnerLink/index.vue b/src/layout/components/InnerLink/index.vue new file mode 100644 index 0000000..badefc5 --- /dev/null +++ b/src/layout/components/InnerLink/index.vue @@ -0,0 +1,47 @@ +<template> + <div :style="'height:' + height" v-loading="loading" element-loading-text="姝e湪鍔犺浇椤甸潰锛岃绋嶅�欙紒"> + <iframe + :id="iframeId" + style="width: 100%; height: 100%" + :src="src" + frameborder="no" + ></iframe> + </div> +</template> + +<script> +export default { + props: { + src: { + type: String, + default: "/" + }, + iframeId: { + type: String + } + }, + data() { + return { + loading: false, + height: document.documentElement.clientHeight - 94.5 + "px;" + }; + }, + mounted() { + var _this = this; + const iframeId = ("#" + this.iframeId).replace(/\//g, "\\/"); + const iframe = document.querySelector(iframeId); + // iframe椤甸潰loading鎺у埗 + if (iframe.attachEvent) { + this.loading = true; + iframe.attachEvent("onload", function () { + _this.loading = false; + }); + } else { + this.loading = true; + iframe.onload = function () { + _this.loading = false; + }; + } + } +}; +</script> diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue new file mode 100644 index 0000000..e501a0b --- /dev/null +++ b/src/layout/components/Navbar.vue @@ -0,0 +1,192 @@ +<template> + <div class="navbar"> + <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> + + <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/> + <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/> + + <div class="right-menu"> + <template v-if="device!=='mobile'"> + <search id="header-search" class="right-menu-item" /> + + <screenfull id="screenfull" class="right-menu-item hover-effect" /> + + <el-tooltip content="甯冨眬澶у皬" effect="dark" placement="bottom"> + <size-select id="size-select" class="right-menu-item hover-effect" /> + </el-tooltip> + + </template> + + <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> + <div class="avatar-wrapper"> + <img :src="avatar" class="user-avatar"> + <i class="el-icon-caret-bottom" /> + </div> + <el-dropdown-menu slot="dropdown"> + <router-link to="/user/profile"> + <el-dropdown-item>涓汉涓績</el-dropdown-item> + </router-link> + <el-dropdown-item @click.native="setting = true"> + <span>甯冨眬璁剧疆</span> + </el-dropdown-item> + <el-dropdown-item divided @click.native="logout"> + <span>閫�鍑虹櫥褰�</span> + </el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </div> + </div> +</template> + +<script> +import { mapGetters } from 'vuex' +import Breadcrumb from '@/components/Breadcrumb' +import TopNav from '@/components/TopNav' +import Hamburger from '@/components/Hamburger' +import Screenfull from '@/components/Screenfull' +import SizeSelect from '@/components/SizeSelect' +import Search from '@/components/HeaderSearch' +import RuoYiGit from '@/components/RuoYi/Git' +import RuoYiDoc from '@/components/RuoYi/Doc' + +export default { + components: { + Breadcrumb, + TopNav, + Hamburger, + Screenfull, + SizeSelect, + Search, + RuoYiGit, + RuoYiDoc + }, + computed: { + ...mapGetters([ + 'sidebar', + 'avatar', + 'device' + ]), + setting: { + get() { + return this.$store.state.settings.showSettings + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'showSettings', + value: val + }) + } + }, + topNav: { + get() { + return this.$store.state.settings.topNav + } + } + }, + methods: { + toggleSideBar() { + this.$store.dispatch('app/toggleSideBar') + }, + async logout() { + this.$confirm('纭畾娉ㄩ攢骞堕��鍑虹郴缁熷悧锛�', '鎻愮ず', { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: 'warning' + }).then(() => { + this.$store.dispatch('LogOut').then(() => { + location.href = '/index'; + }) + }).catch(() => {}); + } + } +} +</script> + +<style lang="scss" scoped> +.navbar { + height: 50px; + overflow: hidden; + position: relative; + background: #fff; + box-shadow: 0 1px 4px rgba(0,21,41,.08); + + .hamburger-container { + line-height: 46px; + height: 100%; + float: left; + cursor: pointer; + transition: background .3s; + -webkit-tap-highlight-color:transparent; + + &:hover { + background: rgba(0, 0, 0, .025) + } + } + + .breadcrumb-container { + float: left; + } + + .topmenu-container { + position: absolute; + left: 50px; + } + + .errLog-container { + display: inline-block; + vertical-align: top; + } + + .right-menu { + float: right; + height: 100%; + line-height: 50px; + + &:focus { + outline: none; + } + + .right-menu-item { + display: inline-block; + padding: 0 8px; + height: 100%; + font-size: 18px; + color: #5a5e66; + vertical-align: text-bottom; + + &.hover-effect { + cursor: pointer; + transition: background .3s; + + &:hover { + background: rgba(0, 0, 0, .025) + } + } + } + + .avatar-container { + margin-right: 30px; + + .avatar-wrapper { + margin-top: 5px; + position: relative; + + .user-avatar { + cursor: pointer; + width: 40px; + height: 40px; + border-radius: 10px; + } + + .el-icon-caret-bottom { + cursor: pointer; + position: absolute; + right: -20px; + top: 25px; + font-size: 12px; + } + } + } + } +} +</style> diff --git a/src/layout/components/Settings/index.vue b/src/layout/components/Settings/index.vue new file mode 100644 index 0000000..8b49842 --- /dev/null +++ b/src/layout/components/Settings/index.vue @@ -0,0 +1,260 @@ +<template> + <el-drawer size="280px" :visible="visible" :with-header="false" :append-to-body="true" :show-close="false"> + <div class="drawer-container"> + <div> + <div class="setting-drawer-content"> + <div class="setting-drawer-title"> + <h3 class="drawer-title">涓婚椋庢牸璁剧疆</h3> + </div> + <div class="setting-drawer-block-checbox"> + <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')"> + <img src="@/assets/images/dark.svg" alt="dark"> + <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> + <i aria-label="鍥炬爣: check" class="anticon anticon-check"> + <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class=""> + <path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> + </svg> + </i> + </div> + </div> + <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')"> + <img src="@/assets/images/light.svg" alt="light"> + <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> + <i aria-label="鍥炬爣: check" class="anticon anticon-check"> + <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" focusable="false" class=""> + <path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> + </svg> + </i> + </div> + </div> + </div> + + <div class="drawer-item"> + <span>涓婚棰滆壊</span> + <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> + </div> + </div> + + <el-divider/> + + <h3 class="drawer-title">绯荤粺甯冨眬閰嶇疆</h3> + + <div class="drawer-item"> + <span>寮�鍚� TopNav</span> + <el-switch v-model="topNav" class="drawer-switch" /> + </div> + + <div class="drawer-item"> + <span>寮�鍚� Tags-Views</span> + <el-switch v-model="tagsView" class="drawer-switch" /> + </div> + + <div class="drawer-item"> + <span>鍥哄畾 Header</span> + <el-switch v-model="fixedHeader" class="drawer-switch" /> + </div> + + <div class="drawer-item"> + <span>鏄剧ず Logo</span> + <el-switch v-model="sidebarLogo" class="drawer-switch" /> + </div> + + <div class="drawer-item"> + <span>鍔ㄦ�佹爣棰�</span> + <el-switch v-model="dynamicTitle" class="drawer-switch" /> + </div> + + <el-divider/> + + <el-button size="small" type="primary" plain icon="el-icon-document-add" @click="saveSetting">淇濆瓨閰嶇疆</el-button> + <el-button size="small" plain icon="el-icon-refresh" @click="resetSetting">閲嶇疆閰嶇疆</el-button> + </div> + </div> + </el-drawer> +</template> + +<script> +import ThemePicker from '@/components/ThemePicker' + +export default { + components: { ThemePicker }, + data() { + return { + theme: this.$store.state.settings.theme, + sideTheme: this.$store.state.settings.sideTheme + }; + }, + computed: { + visible: { + get() { + return this.$store.state.settings.showSettings + } + }, + fixedHeader: { + get() { + return this.$store.state.settings.fixedHeader + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'fixedHeader', + value: val + }) + } + }, + topNav: { + get() { + return this.$store.state.settings.topNav + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'topNav', + value: val + }) + if (!val) { + this.$store.dispatch('app/toggleSideBarHide', false); + this.$store.commit("SET_SIDEBAR_ROUTERS", this.$store.state.permission.defaultRoutes); + } + } + }, + tagsView: { + get() { + return this.$store.state.settings.tagsView + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'tagsView', + value: val + }) + } + }, + sidebarLogo: { + get() { + return this.$store.state.settings.sidebarLogo + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'sidebarLogo', + value: val + }) + } + }, + dynamicTitle: { + get() { + return this.$store.state.settings.dynamicTitle + }, + set(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'dynamicTitle', + value: val + }) + } + }, + }, + methods: { + themeChange(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'theme', + value: val + }) + this.theme = val; + }, + handleTheme(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'sideTheme', + value: val + }) + this.sideTheme = val; + }, + saveSetting() { + this.$modal.loading("姝e湪淇濆瓨鍒版湰鍦帮紝璇风◢鍊�..."); + this.$cache.local.set( + "layout-setting", + `{ + "topNav":${this.topNav}, + "tagsView":${this.tagsView}, + "fixedHeader":${this.fixedHeader}, + "sidebarLogo":${this.sidebarLogo}, + "dynamicTitle":${this.dynamicTitle}, + "sideTheme":"${this.sideTheme}", + "theme":"${this.theme}" + }` + ); + setTimeout(this.$modal.closeLoading(), 1000) + }, + resetSetting() { + this.$modal.loading("姝e湪娓呴櫎璁剧疆缂撳瓨骞跺埛鏂帮紝璇风◢鍊�..."); + this.$cache.local.remove("layout-setting") + setTimeout("window.location.reload()", 1000) + } + } +} +</script> + +<style lang="scss" scoped> + .setting-drawer-content { + .setting-drawer-title { + margin-bottom: 12px; + color: rgba(0, 0, 0, .85); + font-size: 14px; + line-height: 22px; + font-weight: bold; + } + + .setting-drawer-block-checbox { + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 10px; + margin-bottom: 20px; + + .setting-drawer-block-checbox-item { + position: relative; + margin-right: 16px; + border-radius: 2px; + cursor: pointer; + + img { + width: 48px; + height: 48px; + } + + .setting-drawer-block-checbox-selectIcon { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + padding-top: 15px; + padding-left: 24px; + color: #1890ff; + font-weight: 700; + font-size: 14px; + } + } + } + } + + .drawer-container { + padding: 20px; + font-size: 14px; + line-height: 1.5; + word-wrap: break-word; + + .drawer-title { + margin-bottom: 12px; + color: rgba(0, 0, 0, .85); + font-size: 14px; + line-height: 22px; + } + + .drawer-item { + color: rgba(0, 0, 0, .65); + font-size: 14px; + padding: 12px 0; + } + + .drawer-switch { + float: right + } + } +</style> diff --git a/src/layout/components/Sidebar/FixiOSBug.js b/src/layout/components/Sidebar/FixiOSBug.js new file mode 100644 index 0000000..6823726 --- /dev/null +++ b/src/layout/components/Sidebar/FixiOSBug.js @@ -0,0 +1,25 @@ +export default { + computed: { + device() { + return this.$store.state.app.device + } + }, + mounted() { + // In order to fix the click on menu on the ios device will trigger the mouseleave bug + this.fixBugIniOS() + }, + methods: { + fixBugIniOS() { + const $subMenu = this.$refs.subMenu + if ($subMenu) { + const handleMouseleave = $subMenu.handleMouseleave + $subMenu.handleMouseleave = (e) => { + if (this.device === 'mobile') { + return + } + handleMouseleave(e) + } + } + } + } +} diff --git a/src/layout/components/Sidebar/Item.vue b/src/layout/components/Sidebar/Item.vue new file mode 100644 index 0000000..be3285d --- /dev/null +++ b/src/layout/components/Sidebar/Item.vue @@ -0,0 +1,33 @@ +<script> +export default { + name: 'MenuItem', + functional: true, + props: { + icon: { + type: String, + default: '' + }, + title: { + type: String, + default: '' + } + }, + render(h, context) { + const { icon, title } = context.props + const vnodes = [] + + if (icon) { + vnodes.push(<svg-icon icon-class={icon}/>) + } + + if (title) { + if (title.length > 5) { + vnodes.push(<span slot='title' title={(title)}>{(title)}</span>) + } else { + vnodes.push(<span slot='title'>{(title)}</span>) + } + } + return vnodes + } +} +</script> diff --git a/src/layout/components/Sidebar/Link.vue b/src/layout/components/Sidebar/Link.vue new file mode 100644 index 0000000..8b0bc93 --- /dev/null +++ b/src/layout/components/Sidebar/Link.vue @@ -0,0 +1,43 @@ +<template> + <component :is="type" v-bind="linkProps(to)"> + <slot /> + </component> +</template> + +<script> +import { isExternal } from '@/utils/validate' + +export default { + props: { + to: { + type: [String, Object], + required: true + } + }, + computed: { + isExternal() { + return isExternal(this.to) + }, + type() { + if (this.isExternal) { + return 'a' + } + return 'router-link' + } + }, + methods: { + linkProps(to) { + if (this.isExternal) { + return { + href: to, + target: '_blank', + rel: 'noopener' + } + } + return { + to: to + } + } + } +} +</script> diff --git a/src/layout/components/Sidebar/Logo.vue b/src/layout/components/Sidebar/Logo.vue new file mode 100644 index 0000000..2774cc8 --- /dev/null +++ b/src/layout/components/Sidebar/Logo.vue @@ -0,0 +1,93 @@ +<template> + <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> + <transition name="sidebarLogoFade"> + <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> + <img v-if="logo" :src="logo" class="sidebar-logo" /> + <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1> + </router-link> + <router-link v-else key="expand" class="sidebar-logo-link" to="/"> + <img v-if="logo" :src="logo" class="sidebar-logo" /> + <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1> + </router-link> + </transition> + </div> +</template> + +<script> +import logoImg from '@/assets/logo/logo.png' +import variables from '@/assets/styles/variables.scss' + +export default { + name: 'SidebarLogo', + props: { + collapse: { + type: Boolean, + required: true + } + }, + computed: { + variables() { + return variables; + }, + sideTheme() { + return this.$store.state.settings.sideTheme + } + }, + data() { + return { + title: process.env.VUE_APP_TITLE, + logo: logoImg + } + } +} +</script> + +<style lang="scss" scoped> +.sidebarLogoFade-enter-active { + transition: opacity 1.5s; +} + +.sidebarLogoFade-enter, +.sidebarLogoFade-leave-to { + opacity: 0; +} + +.sidebar-logo-container { + position: relative; + width: 100%; + height: 50px; + line-height: 50px; + background: #2b2f3a; + text-align: center; + overflow: hidden; + + & .sidebar-logo-link { + height: 100%; + width: 100%; + + & .sidebar-logo { + width: 32px; + height: 32px; + vertical-align: middle; + margin-right: 12px; + } + + & .sidebar-title { + display: inline-block; + margin: 0; + color: #fff; + font-weight: 600; + line-height: 50px; + font-size: 14px; + font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; + vertical-align: middle; + } + } + + &.collapse { + .sidebar-logo { + margin-right: 0px; + } + } +} +</style> diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue new file mode 100644 index 0000000..4853fbb --- /dev/null +++ b/src/layout/components/Sidebar/SidebarItem.vue @@ -0,0 +1,100 @@ +<template> + <div v-if="!item.hidden"> + <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> + <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path, onlyOneChild.query)"> + <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> + <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> + </el-menu-item> + </app-link> + </template> + + <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> + <template slot="title"> + <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> + </template> + <sidebar-item + v-for="child in item.children" + :key="child.path" + :is-nest="true" + :item="child" + :base-path="resolvePath(child.path)" + class="nest-menu" + /> + </el-submenu> + </div> +</template> + +<script> +import path from 'path' +import { isExternal } from '@/utils/validate' +import Item from './Item' +import AppLink from './Link' +import FixiOSBug from './FixiOSBug' + +export default { + name: 'SidebarItem', + components: { Item, AppLink }, + mixins: [FixiOSBug], + props: { + // route object + item: { + type: Object, + required: true + }, + isNest: { + type: Boolean, + default: false + }, + basePath: { + type: String, + default: '' + } + }, + data() { + this.onlyOneChild = null + return {} + }, + methods: { + hasOneShowingChild(children = [], parent) { + if (!children) { + children = []; + } + const showingChildren = children.filter(item => { + if (item.hidden) { + return false + } else { + // Temp set(will be used if only has one showing child) + this.onlyOneChild = item + return true + } + }) + + // When there is only one child router, the child router is displayed by default + if (showingChildren.length === 1) { + return true + } + + // Show parent if there are no child router to display + if (showingChildren.length === 0) { + this.onlyOneChild = { ... parent, path: '', noShowingChildren: true } + return true + } + + return false + }, + resolvePath(routePath, routeQuery) { + if (isExternal(routePath)) { + return routePath + } + if (isExternal(this.basePath)) { + return this.basePath + } + if (routeQuery) { + let query = JSON.parse(routeQuery); + return { path: path.resolve(this.basePath, routePath), query: query } + } + return path.resolve(this.basePath, routePath) + } + } +} +</script> diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue new file mode 100644 index 0000000..51d0839 --- /dev/null +++ b/src/layout/components/Sidebar/index.vue @@ -0,0 +1,57 @@ +<template> + <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground }"> + <logo v-if="showLogo" :collapse="isCollapse" /> + <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper"> + <el-menu + :default-active="activeMenu" + :collapse="isCollapse" + :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBackground : variables.menuLightBackground" + :text-color="settings.sideTheme === 'theme-dark' ? variables.menuColor : variables.menuLightColor" + :unique-opened="true" + :active-text-color="settings.theme" + :collapse-transition="false" + mode="vertical" + > + <sidebar-item + v-for="(route, index) in sidebarRouters" + :key="route.path + index" + :item="route" + :base-path="route.path" + /> + </el-menu> + </el-scrollbar> + </div> +</template> + +<script> +import { mapGetters, mapState } from "vuex"; +import Logo from "./Logo"; +import SidebarItem from "./SidebarItem"; +import variables from "@/assets/styles/variables.scss"; + +export default { + components: { SidebarItem, Logo }, + computed: { + ...mapState(["settings"]), + ...mapGetters(["sidebarRouters", "sidebar"]), + activeMenu() { + const route = this.$route; + const { meta, path } = route; + // if set path, the sidebar will highlight the path you set + if (meta.activeMenu) { + return meta.activeMenu; + } + return path; + }, + showLogo() { + return this.$store.state.settings.sidebarLogo; + }, + variables() { + return variables; + }, + isCollapse() { + return !this.sidebar.opened; + } + } +}; +</script> diff --git a/src/layout/components/TagsView/ScrollPane.vue b/src/layout/components/TagsView/ScrollPane.vue new file mode 100644 index 0000000..bb753a1 --- /dev/null +++ b/src/layout/components/TagsView/ScrollPane.vue @@ -0,0 +1,94 @@ +<template> + <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll"> + <slot /> + </el-scrollbar> +</template> + +<script> +const tagAndTagSpacing = 4 // tagAndTagSpacing + +export default { + name: 'ScrollPane', + data() { + return { + left: 0 + } + }, + computed: { + scrollWrapper() { + return this.$refs.scrollContainer.$refs.wrap + } + }, + mounted() { + this.scrollWrapper.addEventListener('scroll', this.emitScroll, true) + }, + beforeDestroy() { + this.scrollWrapper.removeEventListener('scroll', this.emitScroll) + }, + methods: { + handleScroll(e) { + const eventDelta = e.wheelDelta || -e.deltaY * 40 + const $scrollWrapper = this.scrollWrapper + $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4 + }, + emitScroll() { + this.$emit('scroll') + }, + moveToTarget(currentTag) { + const $container = this.$refs.scrollContainer.$el + const $containerWidth = $container.offsetWidth + const $scrollWrapper = this.scrollWrapper + const tagList = this.$parent.$refs.tag + + let firstTag = null + let lastTag = null + + // find first tag and last tag + if (tagList.length > 0) { + firstTag = tagList[0] + lastTag = tagList[tagList.length - 1] + } + + if (firstTag === currentTag) { + $scrollWrapper.scrollLeft = 0 + } else if (lastTag === currentTag) { + $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth + } else { + // find preTag and nextTag + const currentIndex = tagList.findIndex(item => item === currentTag) + const prevTag = tagList[currentIndex - 1] + const nextTag = tagList[currentIndex + 1] + + // the tag's offsetLeft after of nextTag + const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing + + // the tag's offsetLeft before of prevTag + const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing + + if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) { + $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth + } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) { + $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft + } + } + } + } +} +</script> + +<style lang="scss" scoped> +.scroll-container { + white-space: nowrap; + position: relative; + overflow: hidden; + width: 100%; + ::v-deep { + .el-scrollbar__bar { + bottom: 0px; + } + .el-scrollbar__wrap { + height: 49px; + } + } +} +</style> diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue new file mode 100644 index 0000000..96585a5 --- /dev/null +++ b/src/layout/components/TagsView/index.vue @@ -0,0 +1,332 @@ +<template> + <div id="tags-view-container" class="tags-view-container"> + <scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll"> + <router-link + v-for="tag in visitedViews" + ref="tag" + :key="tag.path" + :class="isActive(tag)?'active':''" + :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }" + tag="span" + class="tags-view-item" + :style="activeStyle(tag)" + @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''" + @contextmenu.prevent.native="openMenu(tag,$event)" + > + {{ tag.title }} + <span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" /> + </router-link> + </scroll-pane> + <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu"> + <li @click="refreshSelectedTag(selectedTag)"><i class="el-icon-refresh-right"></i> 鍒锋柊椤甸潰</li> + <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)"><i class="el-icon-close"></i> 鍏抽棴褰撳墠</li> + <li @click="closeOthersTags"><i class="el-icon-circle-close"></i> 鍏抽棴鍏朵粬</li> + <li v-if="!isFirstView()" @click="closeLeftTags"><i class="el-icon-back"></i> 鍏抽棴宸︿晶</li> + <li v-if="!isLastView()" @click="closeRightTags"><i class="el-icon-right"></i> 鍏抽棴鍙充晶</li> + <li @click="closeAllTags(selectedTag)"><i class="el-icon-circle-close"></i> 鍏ㄩ儴鍏抽棴</li> + </ul> + </div> +</template> + +<script> +import ScrollPane from './ScrollPane' +import path from 'path' + +export default { + components: { ScrollPane }, + data() { + return { + visible: false, + top: 0, + left: 0, + selectedTag: {}, + affixTags: [] + } + }, + computed: { + visitedViews() { + return this.$store.state.tagsView.visitedViews + }, + routes() { + return this.$store.state.permission.routes + }, + theme() { + return this.$store.state.settings.theme; + } + }, + watch: { + $route() { + this.addTags() + this.moveToCurrentTag() + }, + visible(value) { + if (value) { + document.body.addEventListener('click', this.closeMenu) + } else { + document.body.removeEventListener('click', this.closeMenu) + } + } + }, + mounted() { + this.initTags() + this.addTags() + }, + methods: { + isActive(route) { + return route.path === this.$route.path + }, + activeStyle(tag) { + if (!this.isActive(tag)) return {}; + return { + "background-color": this.theme, + "border-color": this.theme + }; + }, + isAffix(tag) { + return tag.meta && tag.meta.affix + }, + isFirstView() { + try { + return this.selectedTag.fullPath === '/index' || this.selectedTag.fullPath === this.visitedViews[1].fullPath + } catch (err) { + return false + } + }, + isLastView() { + try { + return this.selectedTag.fullPath === this.visitedViews[this.visitedViews.length - 1].fullPath + } catch (err) { + return false + } + }, + filterAffixTags(routes, basePath = '/') { + let tags = [] + routes.forEach(route => { + if (route.meta && route.meta.affix) { + const tagPath = path.resolve(basePath, route.path) + tags.push({ + fullPath: tagPath, + path: tagPath, + name: route.name, + meta: { ...route.meta } + }) + } + if (route.children) { + const tempTags = this.filterAffixTags(route.children, route.path) + if (tempTags.length >= 1) { + tags = [...tags, ...tempTags] + } + } + }) + return tags + }, + initTags() { + const affixTags = this.affixTags = this.filterAffixTags(this.routes) + for (const tag of affixTags) { + // Must have tag name + if (tag.name) { + this.$store.dispatch('tagsView/addVisitedView', tag) + } + } + }, + addTags() { + const { name } = this.$route + if (name) { + this.$store.dispatch('tagsView/addView', this.$route) + if (this.$route.meta.link) { + this.$store.dispatch('tagsView/addIframeView', this.$route) + } + } + return false + }, + moveToCurrentTag() { + const tags = this.$refs.tag + this.$nextTick(() => { + for (const tag of tags) { + if (tag.to.path === this.$route.path) { + this.$refs.scrollPane.moveToTarget(tag) + // when query is different then update + if (tag.to.fullPath !== this.$route.fullPath) { + this.$store.dispatch('tagsView/updateVisitedView', this.$route) + } + break + } + } + }) + }, + refreshSelectedTag(view) { + this.$tab.refreshPage(view); + if (this.$route.meta.link) { + this.$store.dispatch('tagsView/delIframeView', this.$route) + } + }, + closeSelectedTag(view) { + this.$tab.closePage(view).then(({ visitedViews }) => { + if (this.isActive(view)) { + this.toLastView(visitedViews, view) + } + }) + }, + closeRightTags() { + this.$tab.closeRightPage(this.selectedTag).then(visitedViews => { + if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) { + this.toLastView(visitedViews) + } + }) + }, + closeLeftTags() { + this.$tab.closeLeftPage(this.selectedTag).then(visitedViews => { + if (!visitedViews.find(i => i.fullPath === this.$route.fullPath)) { + this.toLastView(visitedViews) + } + }) + }, + closeOthersTags() { + this.$router.push(this.selectedTag.fullPath).catch(()=>{}); + this.$tab.closeOtherPage(this.selectedTag).then(() => { + this.moveToCurrentTag() + }) + }, + closeAllTags(view) { + this.$tab.closeAllPage().then(({ visitedViews }) => { + if (this.affixTags.some(tag => tag.path === this.$route.path)) { + return + } + this.toLastView(visitedViews, view) + }) + }, + toLastView(visitedViews, view) { + const latestView = visitedViews.slice(-1)[0] + if (latestView) { + this.$router.push(latestView.fullPath) + } else { + // now the default is to redirect to the home page if there is no tags-view, + // you can adjust it according to your needs. + if (view.name === 'Dashboard') { + // to reload home page + this.$router.replace({ path: '/redirect' + view.fullPath }) + } else { + this.$router.push('/') + } + } + }, + openMenu(tag, e) { + const menuMinWidth = 105 + const offsetLeft = this.$el.getBoundingClientRect().left // container margin left + const offsetWidth = this.$el.offsetWidth // container width + const maxLeft = offsetWidth - menuMinWidth // left boundary + const left = e.clientX - offsetLeft + 15 // 15: margin right + + if (left > maxLeft) { + this.left = maxLeft + } else { + this.left = left + } + + this.top = e.clientY + this.visible = true + this.selectedTag = tag + }, + closeMenu() { + this.visible = false + }, + handleScroll() { + this.closeMenu() + } + } +} +</script> + +<style lang="scss" scoped> +.tags-view-container { + height: 34px; + width: 100%; + background: #fff; + border-bottom: 1px solid #d8dce5; + box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04); + .tags-view-wrapper { + .tags-view-item { + display: inline-block; + position: relative; + cursor: pointer; + height: 26px; + line-height: 26px; + border: 1px solid #d8dce5; + color: #495060; + background: #fff; + padding: 0 8px; + font-size: 12px; + margin-left: 5px; + margin-top: 4px; + &:first-of-type { + margin-left: 15px; + } + &:last-of-type { + margin-right: 15px; + } + &.active { + background-color: #42b983; + color: #fff; + border-color: #42b983; + &::before { + content: ''; + background: #fff; + display: inline-block; + width: 8px; + height: 8px; + border-radius: 50%; + position: relative; + margin-right: 2px; + } + } + } + } + .contextmenu { + margin: 0; + background: #fff; + z-index: 3000; + position: absolute; + list-style-type: none; + padding: 5px 0; + border-radius: 4px; + font-size: 12px; + font-weight: 400; + color: #333; + box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3); + li { + margin: 0; + padding: 7px 16px; + cursor: pointer; + &:hover { + background: #eee; + } + } + } +} +</style> + +<style lang="scss"> +//reset element css of el-icon-close +.tags-view-wrapper { + .tags-view-item { + .el-icon-close { + width: 16px; + height: 16px; + vertical-align: 2px; + border-radius: 50%; + text-align: center; + transition: all .3s cubic-bezier(.645, .045, .355, 1); + transform-origin: 100% 50%; + &:before { + transform: scale(.6); + display: inline-block; + vertical-align: -3px; + } + &:hover { + background-color: #b4bccc; + color: #fff; + } + } + } +} +</style> diff --git a/src/layout/components/index.js b/src/layout/components/index.js new file mode 100644 index 0000000..104bd3a --- /dev/null +++ b/src/layout/components/index.js @@ -0,0 +1,5 @@ +export { default as AppMain } from './AppMain' +export { default as Navbar } from './Navbar' +export { default as Settings } from './Settings' +export { default as Sidebar } from './Sidebar/index.vue' +export { default as TagsView } from './TagsView/index.vue' diff --git a/src/layout/index.vue b/src/layout/index.vue new file mode 100644 index 0000000..dba4393 --- /dev/null +++ b/src/layout/index.vue @@ -0,0 +1,111 @@ +<template> + <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}"> + <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/> + <sidebar v-if="!sidebar.hide" class="sidebar-container"/> + <div :class="{hasTagsView:needTagsView,sidebarHide:sidebar.hide}" class="main-container"> + <div :class="{'fixed-header':fixedHeader}"> + <navbar/> + <tags-view v-if="needTagsView"/> + </div> + <app-main/> + <right-panel> + <settings/> + </right-panel> + </div> + </div> +</template> + +<script> +import RightPanel from '@/components/RightPanel' +import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' +import ResizeMixin from './mixin/ResizeHandler' +import { mapState } from 'vuex' +import variables from '@/assets/styles/variables.scss' + +export default { + name: 'Layout', + components: { + AppMain, + Navbar, + RightPanel, + Settings, + Sidebar, + TagsView + }, + mixins: [ResizeMixin], + computed: { + ...mapState({ + theme: state => state.settings.theme, + sideTheme: state => state.settings.sideTheme, + sidebar: state => state.app.sidebar, + device: state => state.app.device, + needTagsView: state => state.settings.tagsView, + fixedHeader: state => state.settings.fixedHeader + }), + classObj() { + return { + hideSidebar: !this.sidebar.opened, + openSidebar: this.sidebar.opened, + withoutAnimation: this.sidebar.withoutAnimation, + mobile: this.device === 'mobile' + } + }, + variables() { + return variables; + } + }, + methods: { + handleClickOutside() { + this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) + } + } +} +</script> + +<style lang="scss" scoped> + @import "~@/assets/styles/mixin.scss"; + @import "~@/assets/styles/variables.scss"; + + .app-wrapper { + @include clearfix; + position: relative; + height: 100%; + width: 100%; + + &.mobile.openSidebar { + position: fixed; + top: 0; + } + } + + .drawer-bg { + background: #000; + opacity: 0.3; + width: 100%; + top: 0; + height: 100%; + position: absolute; + z-index: 999; + } + + .fixed-header { + position: fixed; + top: 0; + right: 0; + z-index: 9; + width: calc(100% - #{$base-sidebar-width}); + transition: width 0.28s; + } + + .hideSidebar .fixed-header { + width: calc(100% - 54px); + } + + .sidebarHide .fixed-header { + width: 100%; + } + + .mobile .fixed-header { + width: 100%; + } +</style> diff --git a/src/layout/mixin/ResizeHandler.js b/src/layout/mixin/ResizeHandler.js new file mode 100644 index 0000000..e8d0df8 --- /dev/null +++ b/src/layout/mixin/ResizeHandler.js @@ -0,0 +1,45 @@ +import store from '@/store' + +const { body } = document +const WIDTH = 992 // refer to Bootstrap's responsive design + +export default { + watch: { + $route(route) { + if (this.device === 'mobile' && this.sidebar.opened) { + store.dispatch('app/closeSideBar', { withoutAnimation: false }) + } + } + }, + beforeMount() { + window.addEventListener('resize', this.$_resizeHandler) + }, + beforeDestroy() { + window.removeEventListener('resize', this.$_resizeHandler) + }, + mounted() { + const isMobile = this.$_isMobile() + if (isMobile) { + store.dispatch('app/toggleDevice', 'mobile') + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_isMobile() { + const rect = body.getBoundingClientRect() + return rect.width - 1 < WIDTH + }, + $_resizeHandler() { + if (!document.hidden) { + const isMobile = this.$_isMobile() + store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') + + if (isMobile) { + store.dispatch('app/closeSideBar', { withoutAnimation: true }) + } + } + } + } +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..0cb222b --- /dev/null +++ b/src/main.js @@ -0,0 +1,89 @@ +import Vue from 'vue' + +import Cookies from 'js-cookie' + +import Element from 'element-ui' +import './assets/styles/element-variables.scss' + +import '@/assets/styles/index.scss' // global css +import '@/assets/styles/ruoyi.scss' // ruoyi css +import App from './App' +import store from './store' +import router from './router' +import directive from './directive' // directive +import plugins from './plugins' // plugins +import { download,downloadFiles } from '@/utils/request' +import dataV from "@jiaminghi/data-view" + +import './assets/icons' // icon +import './permission' // permission control +import { getDicts } from "@/api/system/dict/data"; +import { getConfigKey } from "@/api/system/config"; +import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, handleTree } from "@/utils/ruoyi"; +// 鍒嗛〉缁勪欢 +import Pagination from "@/components/Pagination"; +// 鑷畾涔夎〃鏍煎伐鍏风粍浠� +import RightToolbar from "@/components/RightToolbar" +// 瀵屾枃鏈粍浠� +import Editor from "@/components/Editor" +// 鏂囦欢涓婁紶缁勪欢 +import FileUpload from "@/components/FileUpload" +// 鍥剧墖涓婁紶缁勪欢 +import ImageUpload from "@/components/ImageUpload" +// 鍥剧墖棰勮缁勪欢 +import ImagePreview from "@/components/ImagePreview" +// 瀛楀吀鏍囩缁勪欢 +import DictTag from '@/components/DictTag' +// 澶撮儴鏍囩缁勪欢 +import VueMeta from 'vue-meta' +// 瀛楀吀鏁版嵁缁勪欢 +import DictData from '@/components/DictData' + +// 鍏ㄥ眬鏂规硶鎸傝浇 +Vue.prototype.getDicts = getDicts +Vue.prototype.getConfigKey = getConfigKey +Vue.prototype.parseTime = parseTime +Vue.prototype.resetForm = resetForm +Vue.prototype.addDateRange = addDateRange +Vue.prototype.selectDictLabel = selectDictLabel +Vue.prototype.selectDictLabels = selectDictLabels +Vue.prototype.download = download +Vue.prototype.downloadFiles = downloadFiles +Vue.prototype.handleTree = handleTree + +// 鍏ㄥ眬缁勪欢鎸傝浇 +Vue.component('DictTag', DictTag) +Vue.component('Pagination', Pagination) +Vue.component('RightToolbar', RightToolbar) +Vue.component('Editor', Editor) +Vue.component('FileUpload', FileUpload) +Vue.component('ImageUpload', ImageUpload) +Vue.component('ImagePreview', ImagePreview) + +Vue.use(directive) +Vue.use(plugins) +Vue.use(VueMeta) +Vue.use(dataV) +DictData.install() + +/** + * If you don't want to use mock-server + * you want to use MockJs for mock api + * you can execute: mockXHR() + * + * Currently MockJs will be used in the production environment, + * please remove it before going online! ! ! + */ + +Vue.use(Element, { + size: Cookies.get('size') || 'medium' // set element-ui default size +}) + +Vue.config.productionTip = false + +new Vue({ + el: '#app', + router, + store, + render: h => h(App) +}) diff --git a/src/permission.js b/src/permission.js new file mode 100644 index 0000000..e1a14da --- /dev/null +++ b/src/permission.js @@ -0,0 +1,56 @@ +import router from './router' +import store from './store' +import { Message } from 'element-ui' +import NProgress from 'nprogress' +import 'nprogress/nprogress.css' +import { getToken } from '@/utils/auth' +import { isRelogin } from '@/utils/request' + +NProgress.configure({ showSpinner: false }) + +const whiteList = ['/login', '/register'] + +router.beforeEach((to, from, next) => { + NProgress.start() + if (getToken()) { + to.meta.title && store.dispatch('settings/setTitle', to.meta.title) + /* has token*/ + if (to.path === '/login') { + next({ path: '/' }) + NProgress.done() + } else { + if (store.getters.roles.length === 0) { + isRelogin.show = true + // 鍒ゆ柇褰撳墠鐢ㄦ埛鏄惁宸叉媺鍙栧畬user_info淇℃伅 + store.dispatch('GetInfo').then(() => { + isRelogin.show = false + store.dispatch('GenerateRoutes').then(accessRoutes => { + // 鏍规嵁roles鏉冮檺鐢熸垚鍙闂殑璺敱琛� + router.addRoutes(accessRoutes) // 鍔ㄦ�佹坊鍔犲彲璁块棶璺敱琛� + next({ ...to, replace: true }) // hack鏂规硶 纭繚addRoutes宸插畬鎴� + }) + }).catch(err => { + store.dispatch('LogOut').then(() => { + Message.error(err) + next({ path: '/' }) + }) + }) + } else { + next() + } + } + } else { + // 娌℃湁token + if (whiteList.indexOf(to.path) !== -1) { + // 鍦ㄥ厤鐧诲綍鐧藉悕鍗曪紝鐩存帴杩涘叆 + next() + } else { + next(`/login?redirect=${encodeURIComponent(to.fullPath)}`) // 鍚﹀垯鍏ㄩ儴閲嶅畾鍚戝埌鐧诲綍椤� + NProgress.done() + } + } +}) + +router.afterEach(() => { + NProgress.done() +}) diff --git a/src/plugins/auth.js b/src/plugins/auth.js new file mode 100644 index 0000000..6c6bc24 --- /dev/null +++ b/src/plugins/auth.js @@ -0,0 +1,60 @@ +import store from '@/store' + +function authPermission(permission) { + const all_permission = "*:*:*"; + const permissions = store.getters && store.getters.permissions + if (permission && permission.length > 0) { + return permissions.some(v => { + return all_permission === v || v === permission + }) + } else { + return false + } +} + +function authRole(role) { + const super_admin = "admin"; + const roles = store.getters && store.getters.roles + if (role && role.length > 0) { + return roles.some(v => { + return super_admin === v || v === role + }) + } else { + return false + } +} + +export default { + // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄� + hasPermi(permission) { + return authPermission(permission); + }, + // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽彧闇�鍖呭惈鍏朵腑涓�涓� + hasPermiOr(permissions) { + return permissions.some(item => { + return authPermission(item) + }) + }, + // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾鏉冮檺锛屽繀椤诲叏閮ㄦ嫢鏈� + hasPermiAnd(permissions) { + return permissions.every(item => { + return authPermission(item) + }) + }, + // 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愯鑹� + hasRole(role) { + return authRole(role); + }, + // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽彧闇�鍖呭惈鍏朵腑涓�涓� + hasRoleOr(roles) { + return roles.some(item => { + return authRole(item) + }) + }, + // 楠岃瘉鐢ㄦ埛鏄惁鍚湁鎸囧畾瑙掕壊锛屽繀椤诲叏閮ㄦ嫢鏈� + hasRoleAnd(roles) { + return roles.every(item => { + return authRole(item) + }) + } +} diff --git a/src/plugins/cache.js b/src/plugins/cache.js new file mode 100644 index 0000000..6b5c00b --- /dev/null +++ b/src/plugins/cache.js @@ -0,0 +1,77 @@ +const sessionCache = { + set (key, value) { + if (!sessionStorage) { + return + } + if (key != null && value != null) { + sessionStorage.setItem(key, value) + } + }, + get (key) { + if (!sessionStorage) { + return null + } + if (key == null) { + return null + } + return sessionStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + sessionStorage.removeItem(key); + } +} +const localCache = { + set (key, value) { + if (!localStorage) { + return + } + if (key != null && value != null) { + localStorage.setItem(key, value) + } + }, + get (key) { + if (!localStorage) { + return null + } + if (key == null) { + return null + } + return localStorage.getItem(key) + }, + setJSON (key, jsonValue) { + if (jsonValue != null) { + this.set(key, JSON.stringify(jsonValue)) + } + }, + getJSON (key) { + const value = this.get(key) + if (value != null) { + return JSON.parse(value) + } + }, + remove (key) { + localStorage.removeItem(key); + } +} + +export default { + /** + * 浼氳瘽绾х紦瀛� + */ + session: sessionCache, + /** + * 鏈湴缂撳瓨 + */ + local: localCache +} diff --git a/src/plugins/download.js b/src/plugins/download.js new file mode 100644 index 0000000..5b1568c --- /dev/null +++ b/src/plugins/download.js @@ -0,0 +1,73 @@ +import axios from 'axios' +import { Message } from 'element-ui' +import { saveAs } from 'file-saver' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { blobValidate } from "@/utils/ruoyi"; + +// const baseURL = process.env.VUE_APP_BASE_API +const baseURL = "http://127.0.0.1:8081" + +export default { + name(name, isDelete = true) { + var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + resource(resource) { + var url = baseURL + "/common/download/resource?resource=" + encodeURIComponent(resource); + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + const blob = new Blob([res.data]) + this.saveAs(blob, decodeURIComponent(res.headers['download-filename'])) + } else { + this.printErrMsg(res.data); + } + }) + }, + zip(url, name) { + var url = baseURL + url + axios({ + method: 'get', + url: url, + responseType: 'blob', + headers: { 'Authorization': 'Bearer ' + getToken() } + }).then((res) => { + const isBlob = blobValidate(res.data); + if (isBlob) { + const blob = new Blob([res.data], { type: 'application/zip' }) + this.saveAs(blob, name) + } else { + this.printErrMsg(res.data); + } + }) + }, + saveAs(text, name, opts) { + saveAs(text, name, opts); + }, + async printErrMsg(data) { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + Message.error(errMsg); + } +} + diff --git a/src/plugins/index.js b/src/plugins/index.js new file mode 100644 index 0000000..d000f2d --- /dev/null +++ b/src/plugins/index.js @@ -0,0 +1,20 @@ +import tab from './tab' +import auth from './auth' +import cache from './cache' +import modal from './modal' +import download from './download' + +export default { + install(Vue) { + // 椤电鎿嶄綔 + Vue.prototype.$tab = tab + // 璁よ瘉瀵硅薄 + Vue.prototype.$auth = auth + // 缂撳瓨瀵硅薄 + Vue.prototype.$cache = cache + // 妯℃�佹瀵硅薄 + Vue.prototype.$modal = modal + // 涓嬭浇鏂囦欢 + Vue.prototype.$download = download + } +} diff --git a/src/plugins/modal.js b/src/plugins/modal.js new file mode 100644 index 0000000..1c59188 --- /dev/null +++ b/src/plugins/modal.js @@ -0,0 +1,83 @@ +import { Message, MessageBox, Notification, Loading } from 'element-ui' + +let loadingInstance; + +export default { + // 娑堟伅鎻愮ず + msg(content) { + Message.info(content) + }, + // 閿欒娑堟伅 + msgError(content) { + Message.error(content) + }, + // 鎴愬姛娑堟伅 + msgSuccess(content) { + Message.success({ message: content, duration: 10000, showClose: true }) + }, + // 璀﹀憡娑堟伅 + msgWarning(content) { + Message.warning(content) + }, + // 寮瑰嚭鎻愮ず + alert(content) { + MessageBox.alert(content, "绯荤粺鎻愮ず") + }, + // 閿欒鎻愮ず + alertError(content) { + MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'error' }) + }, + // 鎴愬姛鎻愮ず + alertSuccess(content) { + MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'success' }) + }, + // 璀﹀憡鎻愮ず + alertWarning(content) { + MessageBox.alert(content, "绯荤粺鎻愮ず", { type: 'warning' }) + }, + // 閫氱煡鎻愮ず + notify(content) { + Notification.info(content) + }, + // 閿欒閫氱煡 + notifyError(content) { + Notification.error(content); + }, + // 鎴愬姛閫氱煡 + notifySuccess(content) { + Notification.success(content) + }, + // 璀﹀憡閫氱煡 + notifyWarning(content) { + Notification.warning(content) + }, + // 纭绐椾綋 + confirm(content) { + return MessageBox.confirm(content, "绯荤粺鎻愮ず", { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: "warning", + }) + }, + // 鎻愪氦鍐呭 + prompt(content) { + return MessageBox.prompt(content, "绯荤粺鎻愮ず", { + confirmButtonText: '纭畾', + cancelButtonText: '鍙栨秷', + type: "warning", + }) + }, + // 鎵撳紑閬僵灞� + loading(content) { + loadingInstance = Loading.service({ + lock: true, + text: content, + spinner: "el-icon-loading", + background: "rgba(0, 0, 0, 0.7)", + }) + }, + // 鍏抽棴閬僵灞� + closeLoading() { + loadingInstance.close(); + } +} diff --git a/src/plugins/tab.js b/src/plugins/tab.js new file mode 100644 index 0000000..b029c0e --- /dev/null +++ b/src/plugins/tab.js @@ -0,0 +1,71 @@ +import store from '@/store' +import router from '@/router'; + +export default { + // 鍒锋柊褰撳墠tab椤电 + refreshPage(obj) { + const { path, query, matched } = router.currentRoute; + if (obj === undefined) { + matched.forEach((m) => { + if (m.components && m.components.default && m.components.default.name) { + if (!['Layout', 'ParentView'].includes(m.components.default.name)) { + obj = { name: m.components.default.name, path: path, query: query }; + } + } + }); + } + return store.dispatch('tagsView/delCachedView', obj).then(() => { + const { path, query } = obj + router.replace({ + path: '/redirect' + path, + query: query + }) + }) + }, + // 鍏抽棴褰撳墠tab椤电锛屾墦寮�鏂伴〉绛� + closeOpenPage(obj) { + store.dispatch("tagsView/delView", router.currentRoute); + if (obj !== undefined) { + return router.push(obj); + } + }, + // 鍏抽棴鎸囧畾tab椤电 + closePage(obj) { + if (obj === undefined) { + return store.dispatch('tagsView/delView', router.currentRoute).then(({ visitedViews }) => { + const latestView = visitedViews.slice(-1)[0] + if (latestView) { + return router.push(latestView.fullPath) + } + return router.push('/'); + }); + } + return store.dispatch('tagsView/delView', obj); + }, + // 鍏抽棴鎵�鏈塼ab椤电 + closeAllPage() { + return store.dispatch('tagsView/delAllViews'); + }, + // 鍏抽棴宸︿晶tab椤电 + closeLeftPage(obj) { + return store.dispatch('tagsView/delLeftTags', obj || router.currentRoute); + }, + // 鍏抽棴鍙充晶tab椤电 + closeRightPage(obj) { + return store.dispatch('tagsView/delRightTags', obj || router.currentRoute); + }, + // 鍏抽棴鍏朵粬tab椤电 + closeOtherPage(obj) { + return store.dispatch('tagsView/delOthersViews', obj || router.currentRoute); + }, + // 娣诲姞tab椤电 + openPage(title, url, params) { + var obj = { path: url, meta: { title: title } } + store.dispatch('tagsView/addView', obj); + return router.push({ path: url, query: params }); + }, + // 淇敼tab椤电 + updatePage(obj) { + return store.dispatch('tagsView/updateVisitedView', obj); + } +} diff --git a/src/router/index.js b/src/router/index.js new file mode 100644 index 0000000..d0c95be --- /dev/null +++ b/src/router/index.js @@ -0,0 +1,184 @@ +import Vue from 'vue' +import Router from 'vue-router' + +Vue.use(Router) + +/* Layout */ +import Layout from '@/layout' + +/** + * Note: 璺敱閰嶇疆椤� + * + * hidden: true // 褰撹缃� true 鐨勬椂鍊欒璺敱涓嶄細鍐嶄晶杈规爮鍑虹幇 濡�401锛宭ogin绛夐〉闈紝鎴栬�呭涓�浜涚紪杈戦〉闈�/edit/1 + * alwaysShow: true // 褰撲綘涓�涓矾鐢变笅闈㈢殑 children 澹版槑鐨勮矾鐢卞ぇ浜�1涓椂锛岃嚜鍔ㄤ細鍙樻垚宓屽鐨勬ā寮�--濡傜粍浠堕〉闈� + * // 鍙湁涓�涓椂锛屼細灏嗛偅涓瓙璺敱褰撳仛鏍硅矾鐢辨樉绀哄湪渚ц竟鏍�--濡傚紩瀵奸〉闈� + * // 鑻ヤ綘鎯充笉绠¤矾鐢变笅闈㈢殑 children 澹版槑鐨勪釜鏁伴兘鏄剧ず浣犵殑鏍硅矾鐢� + * // 浣犲彲浠ヨ缃� alwaysShow: true锛岃繖鏍峰畠灏变細蹇界暐涔嬪墠瀹氫箟鐨勮鍒欙紝涓�鐩存樉绀烘牴璺敱 + * redirect: noRedirect // 褰撹缃� noRedirect 鐨勬椂鍊欒璺敱鍦ㄩ潰鍖呭睉瀵艰埅涓笉鍙鐐瑰嚮 + * name:'router-name' // 璁惧畾璺敱鐨勫悕瀛楋紝涓�瀹氳濉啓涓嶇劧浣跨敤<keep-alive>鏃朵細鍑虹幇鍚勭闂 + * query: '{"id": 1, "name": "ry"}' // 璁块棶璺敱鐨勯粯璁や紶閫掑弬鏁� + * roles: ['admin', 'common'] // 璁块棶璺敱鐨勮鑹叉潈闄� + * permissions: ['a:a:a', 'b:b:b'] // 璁块棶璺敱鐨勮彍鍗曟潈闄� + * meta : { + noCache: true // 濡傛灉璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive> 缂撳瓨(榛樿 false) + title: 'title' // 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛� + icon: 'svg-name' // 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg + breadcrumb: false // 濡傛灉璁剧疆涓篺alse锛屽垯涓嶄細鍦╞readcrumb闈㈠寘灞戜腑鏄剧ず + activeMenu: '/system/user' // 褰撹矾鐢辫缃簡璇ュ睘鎬э紝鍒欎細楂樹寒鐩稿搴旂殑渚ц竟鏍忋�� + } + */ + +// 鍏叡璺敱 +export const constantRoutes = [ + { + path: '/redirect', + component: Layout, + hidden: true, + children: [ + { + path: '/redirect/:path(.*)', + component: () => import('@/views/redirect') + } + ] + }, + { + path: '/login', + component: () => import('@/views/login'), + hidden: true + }, + { + path: '/register', + component: () => import('@/views/register'), + hidden: true + }, + { + path: '/404', + component: () => import('@/views/error/404'), + hidden: true + }, + { + path: '/401', + component: () => import('@/views/error/401'), + hidden: true + }, + { + path: '', + component: Layout, + redirect: 'index', + children: [ + { + path: 'index', + component: () => import('@/views/index'), + name: 'Index', + meta: { title: '棣栭〉', icon: 'dashboard', affix: true } + } + ] + }, + { + path: '/user', + component: Layout, + hidden: true, + redirect: 'noredirect', + children: [ + { + path: 'profile', + component: () => import('@/views/system/user/profile/index'), + name: 'Profile', + meta: { title: '涓汉涓績', icon: 'user' } + } + ] + } +] + +// 鍔ㄦ�佽矾鐢憋紝鍩轰簬鐢ㄦ埛鏉冮檺鍔ㄦ�佸幓鍔犺浇 +export const dynamicRoutes = [ + { + path: '/system/user-auth', + component: Layout, + hidden: true, + permissions: ['system:user:edit'], + children: [ + { + path: 'role/:userId(\\d+)', + component: () => import('@/views/system/user/authRole'), + name: 'AuthRole', + meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user' } + } + ] + }, + { + path: '/system/role-auth', + component: Layout, + hidden: true, + permissions: ['system:role:edit'], + children: [ + { + path: 'user/:roleId(\\d+)', + component: () => import('@/views/system/role/authUser'), + name: 'AuthUser', + meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role' } + } + ] + }, + { + path: '/system/dict-data', + component: Layout, + hidden: true, + permissions: ['system:dict:list'], + children: [ + { + path: 'index/:dictId(\\d+)', + component: () => import('@/views/system/dict/data'), + name: 'Data', + meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict' } + } + ] + }, + { + path: '/monitor/job-log', + component: Layout, + hidden: true, + permissions: ['monitor:job:list'], + children: [ + { + path: 'index/:jobId(\\d+)', + component: () => import('@/views/monitor/job/log'), + name: 'JobLog', + meta: { title: '璋冨害鏃ュ織', activeMenu: '/monitor/job' } + } + ] + }, + { + path: '/tool/gen-edit', + component: Layout, + hidden: true, + permissions: ['tool:gen:edit'], + children: [ + { + path: 'index/:tableId(\\d+)', + component: () => import('@/views/tool/gen/editTable'), + name: 'GenEdit', + meta: { title: '淇敼鐢熸垚閰嶇疆', activeMenu: '/tool/gen' } + } + ] + } +] + +// 闃叉杩炵画鐐瑰嚮澶氭璺敱鎶ラ敊 +let routerPush = Router.prototype.push; +let routerReplace = Router.prototype.replace; +// push +Router.prototype.push = function push(location) { + return routerPush.call(this, location).catch(err => err) +} +// replace +Router.prototype.replace = function push(location) { + return routerReplace.call(this, location).catch(err => err) +} + +export default new Router({ + mode: 'history', // 鍘绘帀url涓殑# + scrollBehavior: () => ({ y: 0 }), + base:process.env.NODE_ENV === "production" ? "/rYdist" : "/", + routes: constantRoutes +}) diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..6a0b09f --- /dev/null +++ b/src/settings.js @@ -0,0 +1,44 @@ +module.exports = { + /** + * 渚ц竟鏍忎富棰� 娣辫壊涓婚theme-dark锛屾祬鑹蹭富棰榯heme-light + */ + sideTheme: 'theme-dark', + + /** + * 鏄惁绯荤粺甯冨眬閰嶇疆 + */ + showSettings: false, + + /** + * 鏄惁鏄剧ず椤堕儴瀵艰埅 + */ + topNav: false, + + /** + * 鏄惁鏄剧ず tagsView + */ + tagsView: true, + + /** + * 鏄惁鍥哄畾澶撮儴 + */ + fixedHeader: false, + + /** + * 鏄惁鏄剧ずlogo + */ + sidebarLogo: true, + + /** + * 鏄惁鏄剧ず鍔ㄦ�佹爣棰� + */ + dynamicTitle: false, + + /** + * @type {string | array} 'production' | ['production', 'development'] + * @description Need show err logs component. + * The default is only used in the production env + * If you want to also use it in dev, you can pass ['production', 'development'] + */ + errorLog: 'production' +} diff --git a/src/store/getters.js b/src/store/getters.js new file mode 100644 index 0000000..8adb1b6 --- /dev/null +++ b/src/store/getters.js @@ -0,0 +1,19 @@ +const getters = { + sidebar: state => state.app.sidebar, + size: state => state.app.size, + device: state => state.app.device, + dict: state => state.dict.dict, + visitedViews: state => state.tagsView.visitedViews, + cachedViews: state => state.tagsView.cachedViews, + token: state => state.user.token, + avatar: state => state.user.avatar, + name: state => state.user.name, + introduction: state => state.user.introduction, + roles: state => state.user.roles, + permissions: state => state.user.permissions, + permission_routes: state => state.permission.routes, + topbarRouters:state => state.permission.topbarRouters, + defaultRoutes:state => state.permission.defaultRoutes, + sidebarRouters:state => state.permission.sidebarRouters, +} +export default getters diff --git a/src/store/index.js b/src/store/index.js new file mode 100644 index 0000000..97aaef8 --- /dev/null +++ b/src/store/index.js @@ -0,0 +1,25 @@ +import Vue from 'vue' +import Vuex from 'vuex' +import app from './modules/app' +import dict from './modules/dict' +import user from './modules/user' +import tagsView from './modules/tagsView' +import permission from './modules/permission' +import settings from './modules/settings' +import getters from './getters' + +Vue.use(Vuex) + +const store = new Vuex.Store({ + modules: { + app, + dict, + user, + tagsView, + permission, + settings + }, + getters +}) + +export default store diff --git a/src/store/modules/app.js b/src/store/modules/app.js new file mode 100644 index 0000000..3e22d1c --- /dev/null +++ b/src/store/modules/app.js @@ -0,0 +1,66 @@ +import Cookies from 'js-cookie' + +const state = { + sidebar: { + opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, + withoutAnimation: false, + hide: false + }, + device: 'desktop', + size: Cookies.get('size') || 'medium' +} + +const mutations = { + TOGGLE_SIDEBAR: state => { + if (state.sidebar.hide) { + return false; + } + state.sidebar.opened = !state.sidebar.opened + state.sidebar.withoutAnimation = false + if (state.sidebar.opened) { + Cookies.set('sidebarStatus', 1) + } else { + Cookies.set('sidebarStatus', 0) + } + }, + CLOSE_SIDEBAR: (state, withoutAnimation) => { + Cookies.set('sidebarStatus', 0) + state.sidebar.opened = false + state.sidebar.withoutAnimation = withoutAnimation + }, + TOGGLE_DEVICE: (state, device) => { + state.device = device + }, + SET_SIZE: (state, size) => { + state.size = size + Cookies.set('size', size) + }, + SET_SIDEBAR_HIDE: (state, status) => { + state.sidebar.hide = status + } +} + +const actions = { + toggleSideBar({ commit }) { + commit('TOGGLE_SIDEBAR') + }, + closeSideBar({ commit }, { withoutAnimation }) { + commit('CLOSE_SIDEBAR', withoutAnimation) + }, + toggleDevice({ commit }, device) { + commit('TOGGLE_DEVICE', device) + }, + setSize({ commit }, size) { + commit('SET_SIZE', size) + }, + toggleSideBarHide({ commit }, status) { + commit('SET_SIDEBAR_HIDE', status) + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/store/modules/dict.js b/src/store/modules/dict.js new file mode 100644 index 0000000..7a1b2f0 --- /dev/null +++ b/src/store/modules/dict.js @@ -0,0 +1,50 @@ +const state = { + dict: new Array() +} +const mutations = { + SET_DICT: (state, { key, value }) => { + if (key !== null && key !== "") { + state.dict.push({ + key: key, + value: value + }) + } + }, + REMOVE_DICT: (state, key) => { + try { + for (let i = 0; i < state.dict.length; i++) { + if (state.dict[i].key == key) { + state.dict.splice(i, 1) + return true + } + } + } catch (e) { + } + }, + CLEAN_DICT: (state) => { + state.dict = new Array() + } +} + +const actions = { + // 璁剧疆瀛楀吀 + setDict({ commit }, data) { + commit('SET_DICT', data) + }, + // 鍒犻櫎瀛楀吀 + removeDict({ commit }, key) { + commit('REMOVE_DICT', key) + }, + // 娓呯┖瀛楀吀 + cleanDict({ commit }) { + commit('CLEAN_DICT') + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/src/store/modules/permission.js b/src/store/modules/permission.js new file mode 100644 index 0000000..2287665 --- /dev/null +++ b/src/store/modules/permission.js @@ -0,0 +1,133 @@ +import auth from '@/plugins/auth' +import router, { constantRoutes, dynamicRoutes } from '@/router' +import { getRouters } from '@/api/menu' +import Layout from '@/layout/index' +import ParentView from '@/components/ParentView' +import InnerLink from '@/layout/components/InnerLink' + +const permission = { + state: { + routes: [], + addRoutes: [], + defaultRoutes: [], + topbarRouters: [], + sidebarRouters: [] + }, + mutations: { + SET_ROUTES: (state, routes) => { + state.addRoutes = routes + state.routes = constantRoutes.concat(routes) + }, + SET_DEFAULT_ROUTES: (state, routes) => { + state.defaultRoutes = constantRoutes.concat(routes) + }, + SET_TOPBAR_ROUTES: (state, routes) => { + state.topbarRouters = routes + }, + SET_SIDEBAR_ROUTERS: (state, routes) => { + state.sidebarRouters = routes + }, + }, + actions: { + // 鐢熸垚璺敱 + GenerateRoutes({ commit }) { + return new Promise(resolve => { + // 鍚戝悗绔姹傝矾鐢辨暟鎹� + getRouters().then(res => { + const sdata = JSON.parse(JSON.stringify(res.data)) + const rdata = JSON.parse(JSON.stringify(res.data)) + const sidebarRoutes = filterAsyncRouter(sdata) + const rewriteRoutes = filterAsyncRouter(rdata, false, true) + const asyncRoutes = filterDynamicRoutes(dynamicRoutes); + rewriteRoutes.push({ path: '*', redirect: '/404', hidden: true }) + router.addRoutes(asyncRoutes); + commit('SET_ROUTES', rewriteRoutes) + commit('SET_SIDEBAR_ROUTERS', constantRoutes.concat(sidebarRoutes)) + commit('SET_DEFAULT_ROUTES', sidebarRoutes) + commit('SET_TOPBAR_ROUTES', sidebarRoutes) + resolve(rewriteRoutes) + }) + }) + } + } +} + +// 閬嶅巻鍚庡彴浼犳潵鐨勮矾鐢卞瓧绗︿覆锛岃浆鎹负缁勪欢瀵硅薄 +function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { + return asyncRouterMap.filter(route => { + if (type && route.children) { + route.children = filterChildren(route.children) + } + if (route.component) { + // Layout ParentView 缁勪欢鐗规畩澶勭悊 + if (route.component === 'Layout') { + route.component = Layout + } else if (route.component === 'ParentView') { + route.component = ParentView + } else if (route.component === 'InnerLink') { + route.component = InnerLink + } else { + route.component = loadView(route.component) + } + } + if (route.children != null && route.children && route.children.length) { + route.children = filterAsyncRouter(route.children, route, type) + } else { + delete route['children'] + delete route['redirect'] + } + return true + }) +} + +function filterChildren(childrenMap, lastRouter = false) { + var children = [] + childrenMap.forEach((el, index) => { + if (el.children && el.children.length) { + if (el.component === 'ParentView' && !lastRouter) { + el.children.forEach(c => { + c.path = el.path + '/' + c.path + if (c.children && c.children.length) { + children = children.concat(filterChildren(c.children, c)) + return + } + children.push(c) + }) + return + } + } + if (lastRouter) { + el.path = lastRouter.path + '/' + el.path + } + children = children.concat(el) + }) + return children +} + +// 鍔ㄦ�佽矾鐢遍亶鍘嗭紝楠岃瘉鏄惁鍏峰鏉冮檺 +export function filterDynamicRoutes(routes) { + const res = [] + routes.forEach(route => { + if (route.permissions) { + if (auth.hasPermiOr(route.permissions)) { + res.push(route) + } + } else if (route.roles) { + if (auth.hasRoleOr(route.roles)) { + res.push(route) + } + } + }) + return res +} + +export const loadView = (view) => { + if (process.env.NODE_ENV === 'development') { + return (resolve) => require([`@/views/${view}`], resolve) + } else { + // 浣跨敤 import 瀹炵幇鐢熶骇鐜鐨勮矾鐢辨噿鍔犺浇 + return () => import(`@/views/${view}`) + } +} + +export default permission diff --git a/src/store/modules/settings.js b/src/store/modules/settings.js new file mode 100644 index 0000000..2455a1e --- /dev/null +++ b/src/store/modules/settings.js @@ -0,0 +1,42 @@ +import defaultSettings from '@/settings' + +const { sideTheme, showSettings, topNav, tagsView, fixedHeader, sidebarLogo, dynamicTitle } = defaultSettings + +const storageSetting = JSON.parse(localStorage.getItem('layout-setting')) || '' +const state = { + title: '', + theme: storageSetting.theme || '#409EFF', + sideTheme: storageSetting.sideTheme || sideTheme, + showSettings: showSettings, + topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav, + tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView, + fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader, + sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo, + dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle +} +const mutations = { + CHANGE_SETTING: (state, { key, value }) => { + if (state.hasOwnProperty(key)) { + state[key] = value + } + } +} + +const actions = { + // 淇敼甯冨眬璁剧疆 + changeSetting({ commit }, data) { + commit('CHANGE_SETTING', data) + }, + // 璁剧疆缃戦〉鏍囬 + setTitle({ commit }, title) { + state.title = title + } +} + +export default { + namespaced: true, + state, + mutations, + actions +} + diff --git a/src/store/modules/tagsView.js b/src/store/modules/tagsView.js new file mode 100644 index 0000000..5fc011c --- /dev/null +++ b/src/store/modules/tagsView.js @@ -0,0 +1,228 @@ +const state = { + visitedViews: [], + cachedViews: [], + iframeViews: [] +} + +const mutations = { + ADD_IFRAME_VIEW: (state, view) => { + if (state.iframeViews.some(v => v.path === view.path)) return + state.iframeViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_VISITED_VIEW: (state, view) => { + if (state.visitedViews.some(v => v.path === view.path)) return + state.visitedViews.push( + Object.assign({}, view, { + title: view.meta.title || 'no-name' + }) + ) + }, + ADD_CACHED_VIEW: (state, view) => { + if (state.cachedViews.includes(view.name)) return + if (view.meta && !view.meta.noCache) { + state.cachedViews.push(view.name) + } + }, + DEL_VISITED_VIEW: (state, view) => { + for (const [i, v] of state.visitedViews.entries()) { + if (v.path === view.path) { + state.visitedViews.splice(i, 1) + break + } + } + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_IFRAME_VIEW: (state, view) => { + state.iframeViews = state.iframeViews.filter(item => item.path !== view.path) + }, + DEL_CACHED_VIEW: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + index > -1 && state.cachedViews.splice(index, 1) + }, + + DEL_OTHERS_VISITED_VIEWS: (state, view) => { + state.visitedViews = state.visitedViews.filter(v => { + return v.meta.affix || v.path === view.path + }) + state.iframeViews = state.iframeViews.filter(item => item.path === view.path) + }, + DEL_OTHERS_CACHED_VIEWS: (state, view) => { + const index = state.cachedViews.indexOf(view.name) + if (index > -1) { + state.cachedViews = state.cachedViews.slice(index, index + 1) + } else { + state.cachedViews = [] + } + }, + DEL_ALL_VISITED_VIEWS: state => { + // keep affix tags + const affixTags = state.visitedViews.filter(tag => tag.meta.affix) + state.visitedViews = affixTags + state.iframeViews = [] + }, + DEL_ALL_CACHED_VIEWS: state => { + state.cachedViews = [] + }, + UPDATE_VISITED_VIEW: (state, view) => { + for (let v of state.visitedViews) { + if (v.path === view.path) { + v = Object.assign(v, view) + break + } + } + }, + DEL_RIGHT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx <= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + }, + DEL_LEFT_VIEWS: (state, view) => { + const index = state.visitedViews.findIndex(v => v.path === view.path) + if (index === -1) { + return + } + state.visitedViews = state.visitedViews.filter((item, idx) => { + if (idx >= index || (item.meta && item.meta.affix)) { + return true + } + const i = state.cachedViews.indexOf(item.name) + if (i > -1) { + state.cachedViews.splice(i, 1) + } + if(item.meta.link) { + const fi = state.iframeViews.findIndex(v => v.path === item.path) + state.iframeViews.splice(fi, 1) + } + return false + }) + } +} + +const actions = { + addView({ dispatch }, view) { + dispatch('addVisitedView', view) + dispatch('addCachedView', view) + }, + addIframeView({ commit }, view) { + commit('ADD_IFRAME_VIEW', view) + }, + addVisitedView({ commit }, view) { + commit('ADD_VISITED_VIEW', view) + }, + addCachedView({ commit }, view) { + commit('ADD_CACHED_VIEW', view) + }, + delView({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delVisitedView', view) + dispatch('delCachedView', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delVisitedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_VISITED_VIEW', view) + resolve([...state.visitedViews]) + }) + }, + delIframeView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_IFRAME_VIEW', view) + resolve([...state.iframeViews]) + }) + }, + delCachedView({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_CACHED_VIEW', view) + resolve([...state.cachedViews]) + }) + }, + delOthersViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delOthersVisitedViews', view) + dispatch('delOthersCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delOthersVisitedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_VISITED_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delOthersCachedViews({ commit, state }, view) { + return new Promise(resolve => { + commit('DEL_OTHERS_CACHED_VIEWS', view) + resolve([...state.cachedViews]) + }) + }, + delAllViews({ dispatch, state }, view) { + return new Promise(resolve => { + dispatch('delAllVisitedViews', view) + dispatch('delAllCachedViews', view) + resolve({ + visitedViews: [...state.visitedViews], + cachedViews: [...state.cachedViews] + }) + }) + }, + delAllVisitedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_VISITED_VIEWS') + resolve([...state.visitedViews]) + }) + }, + delAllCachedViews({ commit, state }) { + return new Promise(resolve => { + commit('DEL_ALL_CACHED_VIEWS') + resolve([...state.cachedViews]) + }) + }, + updateVisitedView({ commit }, view) { + commit('UPDATE_VISITED_VIEW', view) + }, + delRightTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_RIGHT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, + delLeftTags({ commit }, view) { + return new Promise(resolve => { + commit('DEL_LEFT_VIEWS', view) + resolve([...state.visitedViews]) + }) + }, +} + +export default { + namespaced: true, + state, + mutations, + actions +} diff --git a/src/store/modules/user.js b/src/store/modules/user.js new file mode 100644 index 0000000..cdbab1e --- /dev/null +++ b/src/store/modules/user.js @@ -0,0 +1,101 @@ +import { login, logout, getInfo } from '@/api/login' +import { getToken, setToken, removeToken } from '@/utils/auth' + +const user = { + state: { + token: getToken(), + id: '', + name: '', + avatar: '', + roles: [], + permissions: [] + }, + + mutations: { + SET_TOKEN: (state, token) => { + state.token = token + }, + SET_ID: (state, id) => { + state.id = id + }, + SET_NAME: (state, name) => { + state.name = name + }, + SET_AVATAR: (state, avatar) => { + state.avatar = avatar + }, + SET_ROLES: (state, roles) => { + state.roles = roles + }, + SET_PERMISSIONS: (state, permissions) => { + state.permissions = permissions + } + }, + + actions: { + // 鐧诲綍 + Login({ commit }, userInfo) { + const username = userInfo.username.trim() + const password = userInfo.password + const code = userInfo.code + const uuid = userInfo.uuid + return new Promise((resolve, reject) => { + login(username, password, code, uuid).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 鑾峰彇鐢ㄦ埛淇℃伅 + GetInfo({ commit, state }) { + return new Promise((resolve, reject) => { + getInfo().then(res => { + const user = res.user + const avatar = (user.avatar == "" || user.avatar == null) ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + if (res.roles && res.roles.length > 0) { // 楠岃瘉杩斿洖鐨剅oles鏄惁鏄竴涓潪绌烘暟缁� + commit('SET_ROLES', res.roles) + commit('SET_PERMISSIONS', res.permissions) + } else { + commit('SET_ROLES', ['ROLE_DEFAULT']) + } + commit('SET_ID', user.userId) + commit('SET_NAME', user.userName) + commit('SET_AVATAR', avatar) + resolve(res) + }).catch(error => { + reject(error) + }) + }) + }, + + // 閫�鍑虹郴缁� + LogOut({ commit, state }) { + return new Promise((resolve, reject) => { + logout(state.token).then(() => { + commit('SET_TOKEN', '') + commit('SET_ROLES', []) + commit('SET_PERMISSIONS', []) + removeToken() + resolve() + }).catch(error => { + reject(error) + }) + }) + }, + + // 鍓嶇 鐧诲嚭 + FedLogOut({ commit }) { + return new Promise(resolve => { + commit('SET_TOKEN', '') + removeToken() + resolve() + }) + } + } +} + +export default user diff --git a/src/utils/auth.js b/src/utils/auth.js new file mode 100644 index 0000000..08a43d6 --- /dev/null +++ b/src/utils/auth.js @@ -0,0 +1,15 @@ +import Cookies from 'js-cookie' + +const TokenKey = 'Admin-Token' + +export function getToken() { + return Cookies.get(TokenKey) +} + +export function setToken(token) { + return Cookies.set(TokenKey, token) +} + +export function removeToken() { + return Cookies.remove(TokenKey) +} diff --git a/src/utils/dict/Dict.js b/src/utils/dict/Dict.js new file mode 100644 index 0000000..104bd6e --- /dev/null +++ b/src/utils/dict/Dict.js @@ -0,0 +1,82 @@ +import Vue from 'vue' +import { mergeRecursive } from "@/utils/ruoyi"; +import DictMeta from './DictMeta' +import DictData from './DictData' + +const DEFAULT_DICT_OPTIONS = { + types: [], +} + +/** + * @classdesc 瀛楀吀 + * @property {Object} label 鏍囩瀵硅薄锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉� + * @property {Object} dict 瀛楁鏁扮粍锛屽唴閮ㄥ睘鎬у悕涓哄瓧鍏哥被鍨嬪悕绉� + * @property {Array.<DictMeta>} _dictMetas 瀛楀吀鍏冩暟鎹暟缁� + */ +export default class Dict { + constructor() { + this.owner = null + this.label = {} + this.type = {} + } + + init(options) { + if (options instanceof Array) { + options = { types: options } + } + const opts = mergeRecursive(DEFAULT_DICT_OPTIONS, options) + if (opts.types === undefined) { + throw new Error('need dict types') + } + const ps = [] + this._dictMetas = opts.types.map(t => DictMeta.parse(t)) + this._dictMetas.forEach(dictMeta => { + const type = dictMeta.type + Vue.set(this.label, type, {}) + Vue.set(this.type, type, []) + if (dictMeta.lazy) { + return + } + ps.push(loadDict(this, dictMeta)) + }) + return Promise.all(ps) + } + + /** + * 閲嶆柊鍔犺浇瀛楀吀 + * @param {String} type 瀛楀吀绫诲瀷 + */ + reloadDict(type) { + const dictMeta = this._dictMetas.find(e => e.type === type) + if (dictMeta === undefined) { + return Promise.reject(`the dict meta of ${type} was not found`) + } + return loadDict(this, dictMeta) + } +} + +/** + * 鍔犺浇瀛楀吀 + * @param {Dict} dict 瀛楀吀 + * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹� + * @returns {Promise} + */ +function loadDict(dict, dictMeta) { + return dictMeta.request(dictMeta) + .then(response => { + const type = dictMeta.type + let dicts = dictMeta.responseConverter(response, dictMeta) + if (!(dicts instanceof Array)) { + console.error('the return of responseConverter must be Array.<DictData>') + dicts = [] + } else if (dicts.filter(d => d instanceof DictData).length !== dicts.length) { + console.error('the type of elements in dicts must be DictData') + dicts = [] + } + dict.type[type].splice(0, Number.MAX_SAFE_INTEGER, ...dicts) + dicts.forEach(d => { + Vue.set(dict.label[type], d.value, d.label) + }) + return dicts + }) +} diff --git a/src/utils/dict/DictConverter.js b/src/utils/dict/DictConverter.js new file mode 100644 index 0000000..0cf5df8 --- /dev/null +++ b/src/utils/dict/DictConverter.js @@ -0,0 +1,17 @@ +import DictOptions from './DictOptions' +import DictData from './DictData' + +export default function(dict, dictMeta) { + const label = determineDictField(dict, dictMeta.labelField, ...DictOptions.DEFAULT_LABEL_FIELDS) + const value = determineDictField(dict, dictMeta.valueField, ...DictOptions.DEFAULT_VALUE_FIELDS) + return new DictData(dict[label], dict[value], dict) +} + +/** + * 纭畾瀛楀吀瀛楁 + * @param {DictData} dict + * @param {...String} fields + */ +function determineDictField(dict, ...fields) { + return fields.find(f => Object.prototype.hasOwnProperty.call(dict, f)) +} diff --git a/src/utils/dict/DictData.js b/src/utils/dict/DictData.js new file mode 100644 index 0000000..afc763e --- /dev/null +++ b/src/utils/dict/DictData.js @@ -0,0 +1,13 @@ +/** + * @classdesc 瀛楀吀鏁版嵁 + * @property {String} label 鏍囩 + * @property {*} value 鏍囩 + * @property {Object} raw 鍘熷鏁版嵁 + */ +export default class DictData { + constructor(label, value, raw) { + this.label = label + this.value = value + this.raw = raw + } +} diff --git a/src/utils/dict/DictMeta.js b/src/utils/dict/DictMeta.js new file mode 100644 index 0000000..9779daa --- /dev/null +++ b/src/utils/dict/DictMeta.js @@ -0,0 +1,38 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import DictOptions from './DictOptions' + +/** + * @classdesc 瀛楀吀鍏冩暟鎹� + * @property {String} type 绫诲瀷 + * @property {Function} request 璇锋眰 + * @property {String} label 鏍囩瀛楁 + * @property {String} value 鍊煎瓧娈� + */ +export default class DictMeta { + constructor(options) { + this.type = options.type + this.request = options.request + this.responseConverter = options.responseConverter + this.labelField = options.labelField + this.valueField = options.valueField + this.lazy = options.lazy === true + } +} + + +/** + * 瑙f瀽瀛楀吀鍏冩暟鎹� + * @param {Object} options + * @returns {DictMeta} + */ +DictMeta.parse= function(options) { + let opts = null + if (typeof options === 'string') { + opts = DictOptions.metas[options] || {} + opts.type = options + } else if (typeof options === 'object') { + opts = options + } + opts = mergeRecursive(DictOptions.metas['*'], opts) + return new DictMeta(opts) +} diff --git a/src/utils/dict/DictOptions.js b/src/utils/dict/DictOptions.js new file mode 100644 index 0000000..338a94e --- /dev/null +++ b/src/utils/dict/DictOptions.js @@ -0,0 +1,51 @@ +import { mergeRecursive } from "@/utils/ruoyi"; +import dictConverter from './DictConverter' + +export const options = { + metas: { + '*': { + /** + * 瀛楀吀璇锋眰锛屾柟娉曠鍚嶄负function(dictMeta: DictMeta): Promise + */ + request: (dictMeta) => { + console.log(`load dict ${dictMeta.type}`) + return Promise.resolve([]) + }, + /** + * 瀛楀吀鍝嶅簲鏁版嵁杞崲鍣紝鏂规硶绛惧悕涓篺unction(response: Object, dictMeta: DictMeta): DictData + */ + responseConverter, + labelField: 'label', + valueField: 'value', + }, + }, + /** + * 榛樿鏍囩瀛楁 + */ + DEFAULT_LABEL_FIELDS: ['label', 'name', 'title'], + /** + * 榛樿鍊煎瓧娈� + */ + DEFAULT_VALUE_FIELDS: ['value', 'id', 'uid', 'key'], +} + +/** + * 鏄犲皠瀛楀吀 + * @param {Object} response 瀛楀吀鏁版嵁 + * @param {DictMeta} dictMeta 瀛楀吀鍏冩暟鎹� + * @returns {DictData} + */ +function responseConverter(response, dictMeta) { + const dicts = response.content instanceof Array ? response.content : response + if (dicts === undefined) { + console.warn(`no dict data of "${dictMeta.type}" found in the response`) + return [] + } + return dicts.map(d => dictConverter(d, dictMeta)) +} + +export function mergeOptions(src) { + mergeRecursive(options, src) +} + +export default options diff --git a/src/utils/dict/index.js b/src/utils/dict/index.js new file mode 100644 index 0000000..215eb9e --- /dev/null +++ b/src/utils/dict/index.js @@ -0,0 +1,33 @@ +import Dict from './Dict' +import { mergeOptions } from './DictOptions' + +export default function(Vue, options) { + mergeOptions(options) + Vue.mixin({ + data() { + if (this.$options === undefined || this.$options.dicts === undefined || this.$options.dicts === null) { + return {} + } + const dict = new Dict() + dict.owner = this + return { + dict + } + }, + created() { + if (!(this.dict instanceof Dict)) { + return + } + options.onCreated && options.onCreated(this.dict) + this.dict.init(this.$options.dicts).then(() => { + options.onReady && options.onReady(this.dict) + this.$nextTick(() => { + this.$emit('dictReady', this.dict) + if (this.$options.methods && this.$options.methods.onDictReady instanceof Function) { + this.$options.methods.onDictReady.call(this, this.dict) + } + }) + }) + }, + }) +} diff --git a/src/utils/errorCode.js b/src/utils/errorCode.js new file mode 100644 index 0000000..d2111ee --- /dev/null +++ b/src/utils/errorCode.js @@ -0,0 +1,6 @@ +export default { + '401': '璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�', + '403': '褰撳墠鎿嶄綔娌℃湁鏉冮檺', + '404': '璁块棶璧勬簮涓嶅瓨鍦�', + 'default': '绯荤粺鏈煡閿欒锛岃鍙嶉缁欑鐞嗗憳' +} diff --git a/src/utils/generator/config.js b/src/utils/generator/config.js new file mode 100644 index 0000000..7abf227 --- /dev/null +++ b/src/utils/generator/config.js @@ -0,0 +1,438 @@ +export const formConf = { + formRef: 'elForm', + formModel: 'formData', + size: 'medium', + labelPosition: 'right', + labelWidth: 100, + formRules: 'rules', + gutter: 15, + disabled: false, + span: 24, + formBtns: true +} + +export const inputComponents = [ + { + label: '鍗曡鏂囨湰', + tag: 'el-input', + tagIcon: 'input', + placeholder: '璇疯緭鍏�', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '澶氳鏂囨湰', + tag: 'el-input', + tagIcon: 'textarea', + type: 'textarea', + placeholder: '璇疯緭鍏�', + defaultValue: undefined, + span: 24, + labelWidth: null, + autosize: { + minRows: 4, + maxRows: 4 + }, + style: { width: '100%' }, + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '瀵嗙爜', + tag: 'el-input', + tagIcon: 'password', + placeholder: '璇疯緭鍏�', + defaultValue: undefined, + span: 24, + 'show-password': true, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': '', + 'suffix-icon': '', + maxlength: null, + 'show-word-limit': false, + readonly: false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input' + }, + { + label: '璁℃暟鍣�', + tag: 'el-input-number', + tagIcon: 'number', + placeholder: '', + defaultValue: undefined, + span: 24, + labelWidth: null, + min: undefined, + max: undefined, + step: undefined, + 'step-strictly': false, + precision: undefined, + 'controls-position': '', + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/input-number' + } +] + +export const selectComponents = [ + { + label: '涓嬫媺閫夋嫨', + tag: 'el-select', + tagIcon: 'select', + placeholder: '璇烽�夋嫨', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: { width: '100%' }, + clearable: true, + disabled: false, + required: true, + filterable: false, + multiple: false, + options: [{ + label: '閫夐」涓�', + value: 1 + }, { + label: '閫夐」浜�', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/select' + }, + { + label: '绾ц仈閫夋嫨', + tag: 'el-cascader', + tagIcon: 'cascader', + placeholder: '璇烽�夋嫨', + defaultValue: [], + span: 24, + labelWidth: null, + style: { width: '100%' }, + props: { + props: { + multiple: false + } + }, + 'show-all-levels': true, + disabled: false, + clearable: true, + filterable: false, + required: true, + options: [{ + id: 1, + value: 1, + label: '閫夐」1', + children: [{ + id: 2, + value: 2, + label: '閫夐」1-1' + }] + }], + dataType: 'dynamic', + labelKey: 'label', + valueKey: 'value', + childrenKey: 'children', + separator: '/', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/cascader' + }, + { + label: '鍗曢�夋缁�', + tag: 'el-radio-group', + tagIcon: 'radio', + defaultValue: undefined, + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '閫夐」涓�', + value: 1 + }, { + label: '閫夐」浜�', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/radio' + }, + { + label: '澶氶�夋缁�', + tag: 'el-checkbox-group', + tagIcon: 'checkbox', + defaultValue: [], + span: 24, + labelWidth: null, + style: {}, + optionType: 'default', + border: false, + size: 'medium', + disabled: false, + required: true, + options: [{ + label: '閫夐」涓�', + value: 1 + }, { + label: '閫夐」浜�', + value: 2 + }], + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/checkbox' + }, + { + label: '寮�鍏�', + tag: 'el-switch', + tagIcon: 'switch', + defaultValue: false, + span: 24, + labelWidth: null, + style: {}, + disabled: false, + required: true, + 'active-text': '', + 'inactive-text': '', + 'active-color': null, + 'inactive-color': null, + 'active-value': true, + 'inactive-value': false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/switch' + }, + { + label: '婊戝潡', + tag: 'el-slider', + tagIcon: 'slider', + defaultValue: null, + span: 24, + labelWidth: null, + disabled: false, + required: true, + min: 0, + max: 100, + step: 1, + 'show-stops': false, + range: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/slider' + }, + { + label: '鏃堕棿閫夋嫨', + tag: 'el-time-picker', + tagIcon: 'time', + placeholder: '璇烽�夋嫨', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'picker-options': { + selectableRange: '00:00:00-23:59:59' + }, + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '鏃堕棿鑼冨洿', + tag: 'el-time-picker', + tagIcon: 'time-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + 'is-range': true, + 'range-separator': '鑷�', + 'start-placeholder': '寮�濮嬫椂闂�', + 'end-placeholder': '缁撴潫鏃堕棿', + format: 'HH:mm:ss', + 'value-format': 'HH:mm:ss', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/time-picker' + }, + { + label: '鏃ユ湡閫夋嫨', + tag: 'el-date-picker', + tagIcon: 'date', + placeholder: '璇烽�夋嫨', + defaultValue: null, + type: 'date', + span: 24, + labelWidth: null, + style: { width: '100%' }, + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '鏃ユ湡鑼冨洿', + tag: 'el-date-picker', + tagIcon: 'date-range', + defaultValue: null, + span: 24, + labelWidth: null, + style: { width: '100%' }, + type: 'daterange', + 'range-separator': '鑷�', + 'start-placeholder': '寮�濮嬫棩鏈�', + 'end-placeholder': '缁撴潫鏃ユ湡', + disabled: false, + clearable: true, + required: true, + format: 'yyyy-MM-dd', + 'value-format': 'yyyy-MM-dd', + readonly: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/date-picker' + }, + { + label: '璇勫垎', + tag: 'el-rate', + tagIcon: 'rate', + defaultValue: 0, + span: 24, + labelWidth: null, + style: {}, + max: 5, + 'allow-half': false, + 'show-text': false, + 'show-score': false, + disabled: false, + required: true, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/rate' + }, + { + label: '棰滆壊閫夋嫨', + tag: 'el-color-picker', + tagIcon: 'color', + defaultValue: null, + labelWidth: null, + 'show-alpha': false, + 'color-format': '', + disabled: false, + required: true, + size: 'medium', + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/color-picker' + }, + { + label: '涓婁紶', + tag: 'el-upload', + tagIcon: 'upload', + action: 'https://jsonplaceholder.typicode.com/posts/', + defaultValue: null, + labelWidth: null, + disabled: false, + required: true, + accept: '', + name: 'file', + 'auto-upload': true, + showTip: false, + buttonText: '鐐瑰嚮涓婁紶', + fileSize: 2, + sizeUnit: 'MB', + 'list-type': 'text', + multiple: false, + regList: [], + changeTag: true, + document: 'https://element.eleme.cn/#/zh-CN/component/upload' + } +] + +export const layoutComponents = [ + { + layout: 'rowFormItem', + tagIcon: 'row', + type: 'default', + justify: 'start', + align: 'top', + label: '琛屽鍣�', + layoutTree: true, + children: [], + document: 'https://element.eleme.cn/#/zh-CN/component/layout' + }, + { + layout: 'colFormItem', + label: '鎸夐挳', + changeTag: true, + labelWidth: null, + tag: 'el-button', + tagIcon: 'button', + span: 24, + default: '涓昏鎸夐挳', + type: 'primary', + icon: 'el-icon-search', + size: 'medium', + disabled: false, + document: 'https://element.eleme.cn/#/zh-CN/component/button' + } +] + +// 缁勪欢rule鐨勮Е鍙戞柟寮忥紝鏃犺Е鍙戞柟寮忕殑缁勪欢涓嶇敓鎴恟ule +export const trigger = { + 'el-input': 'blur', + 'el-input-number': 'blur', + 'el-select': 'change', + 'el-radio-group': 'change', + 'el-checkbox-group': 'change', + 'el-cascader': 'change', + 'el-time-picker': 'change', + 'el-date-picker': 'change', + 'el-rate': 'change' +} diff --git a/src/utils/generator/css.js b/src/utils/generator/css.js new file mode 100644 index 0000000..c1c62e6 --- /dev/null +++ b/src/utils/generator/css.js @@ -0,0 +1,18 @@ +const styles = { + 'el-rate': '.el-rate{display: inline-block; vertical-align: text-top;}', + 'el-upload': '.el-upload__tip{line-height: 1.2;}' +} + +function addCss(cssList, el) { + const css = styles[el.tag] + css && cssList.indexOf(css) === -1 && cssList.push(css) + if (el.children) { + el.children.forEach(el2 => addCss(cssList, el2)) + } +} + +export function makeUpCss(conf) { + const cssList = [] + conf.fields.forEach(el => addCss(cssList, el)) + return cssList.join('\n') +} diff --git a/src/utils/generator/drawingDefault.js b/src/utils/generator/drawingDefault.js new file mode 100644 index 0000000..09f133c --- /dev/null +++ b/src/utils/generator/drawingDefault.js @@ -0,0 +1,29 @@ +export default [ + { + layout: 'colFormItem', + tagIcon: 'input', + label: '鎵嬫満鍙�', + vModel: 'mobile', + formId: 6, + tag: 'el-input', + placeholder: '璇疯緭鍏ユ墜鏈哄彿', + defaultValue: '', + span: 24, + style: { width: '100%' }, + clearable: true, + prepend: '', + append: '', + 'prefix-icon': 'el-icon-mobile', + 'suffix-icon': '', + maxlength: 11, + 'show-word-limit': true, + readonly: false, + disabled: false, + required: true, + changeTag: true, + regList: [{ + pattern: '/^1(3|4|5|7|8|9)\\d{9}$/', + message: '鎵嬫満鍙锋牸寮忛敊璇�' + }] + } +] diff --git a/src/utils/generator/html.js b/src/utils/generator/html.js new file mode 100644 index 0000000..9bcc536 --- /dev/null +++ b/src/utils/generator/html.js @@ -0,0 +1,359 @@ +/* eslint-disable max-len */ +import { trigger } from './config' + +let confGlobal +let someSpanIsNot24 + +export function dialogWrapper(str) { + return `<el-dialog v-bind="$attrs" v-on="$listeners" @open="onOpen" @close="onClose" title="Dialog Title"> + ${str} + <div slot="footer"> + <el-button @click="close">鍙栨秷</el-button> + <el-button type="primary" @click="handleConfirm">纭畾</el-button> + </div> + </el-dialog>` +} + +export function vueTemplate(str) { + return `<template> + <div> + ${str} + </div> + </template>` +} + +export function vueScript(str) { + return `<script> + ${str} + </script>` +} + +export function cssStyle(cssStr) { + return `<style> + ${cssStr} + </style>` +} + +function buildFormTemplate(conf, child, type) { + let labelPosition = '' + if (conf.labelPosition !== 'right') { + labelPosition = `label-position="${conf.labelPosition}"` + } + const disabled = conf.disabled ? `:disabled="${conf.disabled}"` : '' + let str = `<el-form ref="${conf.formRef}" :model="${conf.formModel}" :rules="${conf.formRules}" size="${conf.size}" ${disabled} label-width="${conf.labelWidth}px" ${labelPosition}> + ${child} + ${buildFromBtns(conf, type)} + </el-form>` + if (someSpanIsNot24) { + str = `<el-row :gutter="${conf.gutter}"> + ${str} + </el-row>` + } + return str +} + +function buildFromBtns(conf, type) { + let str = '' + if (conf.formBtns && type === 'file') { + str = `<el-form-item size="large"> + <el-button type="primary" @click="submitForm">鎻愪氦</el-button> + <el-button @click="resetForm">閲嶇疆</el-button> + </el-form-item>` + if (someSpanIsNot24) { + str = `<el-col :span="24"> + ${str} + </el-col>` + } + } + return str +} + +// span涓嶄负24鐨勭敤el-col鍖呰9 +function colWrapper(element, str) { + if (someSpanIsNot24 || element.span !== 24) { + return `<el-col :span="${element.span}"> + ${str} + </el-col>` + } + return str +} + +const layouts = { + colFormItem(element) { + let labelWidth = '' + if (element.labelWidth && element.labelWidth !== confGlobal.labelWidth) { + labelWidth = `label-width="${element.labelWidth}px"` + } + const required = !trigger[element.tag] && element.required ? 'required' : '' + const tagDom = tags[element.tag] ? tags[element.tag](element) : null + let str = `<el-form-item ${labelWidth} label="${element.label}" prop="${element.vModel}" ${required}> + ${tagDom} + </el-form-item>` + str = colWrapper(element, str) + return str + }, + rowFormItem(element) { + const type = element.type === 'default' ? '' : `type="${element.type}"` + const justify = element.type === 'default' ? '' : `justify="${element.justify}"` + const align = element.type === 'default' ? '' : `align="${element.align}"` + const gutter = element.gutter ? `gutter="${element.gutter}"` : '' + const children = element.children.map(el => layouts[el.layout](el)) + let str = `<el-row ${type} ${justify} ${align} ${gutter}> + ${children.join('\n')} + </el-row>` + str = colWrapper(element, str) + return str + } +} + +const tags = { + 'el-button': el => { + const { + tag, disabled + } = attrBuilder(el) + const type = el.type ? `type="${el.type}"` : '' + const icon = el.icon ? `icon="${el.icon}"` : '' + const size = el.size ? `size="${el.size}"` : '' + let child = buildElButtonChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${type} ${icon} ${size} ${disabled}>${child}</${el.tag}>` + }, + 'el-input': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const maxlength = el.maxlength ? `:maxlength="${el.maxlength}"` : '' + const showWordLimit = el['show-word-limit'] ? 'show-word-limit' : '' + const readonly = el.readonly ? 'readonly' : '' + const prefixIcon = el['prefix-icon'] ? `prefix-icon='${el['prefix-icon']}'` : '' + const suffixIcon = el['suffix-icon'] ? `suffix-icon='${el['suffix-icon']}'` : '' + const showPassword = el['show-password'] ? 'show-password' : '' + const type = el.type ? `type="${el.type}"` : '' + const autosize = el.autosize && el.autosize.minRows + ? `:autosize="{minRows: ${el.autosize.minRows}, maxRows: ${el.autosize.maxRows}}"` + : '' + let child = buildElInputChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${vModel} ${type} ${placeholder} ${maxlength} ${showWordLimit} ${readonly} ${disabled} ${clearable} ${prefixIcon} ${suffixIcon} ${showPassword} ${autosize} ${width}>${child}</${el.tag}>` + }, + 'el-input-number': el => { + const { disabled, vModel, placeholder } = attrBuilder(el) + const controlsPosition = el['controls-position'] ? `controls-position=${el['controls-position']}` : '' + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const stepStrictly = el['step-strictly'] ? 'step-strictly' : '' + const precision = el.precision ? `:precision='${el.precision}'` : '' + + return `<${el.tag} ${vModel} ${placeholder} ${step} ${stepStrictly} ${precision} ${controlsPosition} ${min} ${max} ${disabled}></${el.tag}>` + }, + 'el-select': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const filterable = el.filterable ? 'filterable' : '' + const multiple = el.multiple ? 'multiple' : '' + let child = buildElSelectChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${vModel} ${placeholder} ${disabled} ${multiple} ${filterable} ${clearable} ${width}>${child}</${el.tag}>` + }, + 'el-radio-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + let child = buildElRadioGroupChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${vModel} ${size} ${disabled}>${child}</${el.tag}>` + }, + 'el-checkbox-group': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const min = el.min ? `:min="${el.min}"` : '' + const max = el.max ? `:max="${el.max}"` : '' + let child = buildElCheckboxGroupChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${vModel} ${min} ${max} ${size} ${disabled}>${child}</${el.tag}>` + }, + 'el-switch': el => { + const { disabled, vModel } = attrBuilder(el) + const activeText = el['active-text'] ? `active-text="${el['active-text']}"` : '' + const inactiveText = el['inactive-text'] ? `inactive-text="${el['inactive-text']}"` : '' + const activeColor = el['active-color'] ? `active-color="${el['active-color']}"` : '' + const inactiveColor = el['inactive-color'] ? `inactive-color="${el['inactive-color']}"` : '' + const activeValue = el['active-value'] !== true ? `:active-value='${JSON.stringify(el['active-value'])}'` : '' + const inactiveValue = el['inactive-value'] !== false ? `:inactive-value='${JSON.stringify(el['inactive-value'])}'` : '' + + return `<${el.tag} ${vModel} ${activeText} ${inactiveText} ${activeColor} ${inactiveColor} ${activeValue} ${inactiveValue} ${disabled}></${el.tag}>` + }, + 'el-cascader': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const options = el.options ? `:options="${el.vModel}Options"` : '' + const props = el.props ? `:props="${el.vModel}Props"` : '' + const showAllLevels = el['show-all-levels'] ? '' : ':show-all-levels="false"' + const filterable = el.filterable ? 'filterable' : '' + const separator = el.separator === '/' ? '' : `separator="${el.separator}"` + + return `<${el.tag} ${vModel} ${options} ${props} ${width} ${showAllLevels} ${placeholder} ${separator} ${filterable} ${clearable} ${disabled}></${el.tag}>` + }, + 'el-slider': el => { + const { disabled, vModel } = attrBuilder(el) + const min = el.min ? `:min='${el.min}'` : '' + const max = el.max ? `:max='${el.max}'` : '' + const step = el.step ? `:step='${el.step}'` : '' + const range = el.range ? 'range' : '' + const showStops = el['show-stops'] ? `:show-stops="${el['show-stops']}"` : '' + + return `<${el.tag} ${min} ${max} ${step} ${vModel} ${range} ${showStops} ${disabled}></${el.tag}>` + }, + 'el-time-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const isRange = el['is-range'] ? 'is-range' : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const pickerOptions = el['picker-options'] ? `:picker-options='${JSON.stringify(el['picker-options'])}'` : '' + + return `<${el.tag} ${vModel} ${isRange} ${format} ${valueFormat} ${pickerOptions} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${disabled}></${el.tag}>` + }, + 'el-date-picker': el => { + const { + disabled, vModel, clearable, placeholder, width + } = attrBuilder(el) + const startPlaceholder = el['start-placeholder'] ? `start-placeholder="${el['start-placeholder']}"` : '' + const endPlaceholder = el['end-placeholder'] ? `end-placeholder="${el['end-placeholder']}"` : '' + const rangeSeparator = el['range-separator'] ? `range-separator="${el['range-separator']}"` : '' + const format = el.format ? `format="${el.format}"` : '' + const valueFormat = el['value-format'] ? `value-format="${el['value-format']}"` : '' + const type = el.type === 'date' ? '' : `type="${el.type}"` + const readonly = el.readonly ? 'readonly' : '' + + return `<${el.tag} ${type} ${vModel} ${format} ${valueFormat} ${width} ${placeholder} ${startPlaceholder} ${endPlaceholder} ${rangeSeparator} ${clearable} ${readonly} ${disabled}></${el.tag}>` + }, + 'el-rate': el => { + const { disabled, vModel } = attrBuilder(el) + const max = el.max ? `:max='${el.max}'` : '' + const allowHalf = el['allow-half'] ? 'allow-half' : '' + const showText = el['show-text'] ? 'show-text' : '' + const showScore = el['show-score'] ? 'show-score' : '' + + return `<${el.tag} ${vModel} ${allowHalf} ${showText} ${showScore} ${disabled}></${el.tag}>` + }, + 'el-color-picker': el => { + const { disabled, vModel } = attrBuilder(el) + const size = `size="${el.size}"` + const showAlpha = el['show-alpha'] ? 'show-alpha' : '' + const colorFormat = el['color-format'] ? `color-format="${el['color-format']}"` : '' + + return `<${el.tag} ${vModel} ${size} ${showAlpha} ${colorFormat} ${disabled}></${el.tag}>` + }, + 'el-upload': el => { + const disabled = el.disabled ? ':disabled=\'true\'' : '' + const action = el.action ? `:action="${el.vModel}Action"` : '' + const multiple = el.multiple ? 'multiple' : '' + const listType = el['list-type'] !== 'text' ? `list-type="${el['list-type']}"` : '' + const accept = el.accept ? `accept="${el.accept}"` : '' + const name = el.name !== 'file' ? `name="${el.name}"` : '' + const autoUpload = el['auto-upload'] === false ? ':auto-upload="false"' : '' + const beforeUpload = `:before-upload="${el.vModel}BeforeUpload"` + const fileList = `:file-list="${el.vModel}fileList"` + const ref = `ref="${el.vModel}"` + let child = buildElUploadChild(el) + + if (child) child = `\n${child}\n` // 鎹㈣ + return `<${el.tag} ${ref} ${fileList} ${action} ${autoUpload} ${multiple} ${beforeUpload} ${listType} ${accept} ${name} ${disabled}>${child}</${el.tag}>` + } +} + +function attrBuilder(el) { + return { + vModel: `v-model="${confGlobal.formModel}.${el.vModel}"`, + clearable: el.clearable ? 'clearable' : '', + placeholder: el.placeholder ? `placeholder="${el.placeholder}"` : '', + width: el.style && el.style.width ? ':style="{width: \'100%\'}"' : '', + disabled: el.disabled ? ':disabled=\'true\'' : '' + } +} + +// el-buttin 瀛愮骇 +function buildElButtonChild(conf) { + const children = [] + if (conf.default) { + children.push(conf.default) + } + return children.join('\n') +} + +// el-input innerHTML +function buildElInputChild(conf) { + const children = [] + if (conf.prepend) { + children.push(`<template slot="prepend">${conf.prepend}</template>`) + } + if (conf.append) { + children.push(`<template slot="append">${conf.append}</template>`) + } + return children.join('\n') +} + +function buildElSelectChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + children.push(`<el-option v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.label" :value="item.value" :disabled="item.disabled"></el-option>`) + } + return children.join('\n') +} + +function buildElRadioGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-radio-button' : 'el-radio' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`) + } + return children.join('\n') +} + +function buildElCheckboxGroupChild(conf) { + const children = [] + if (conf.options && conf.options.length) { + const tag = conf.optionType === 'button' ? 'el-checkbox-button' : 'el-checkbox' + const border = conf.border ? 'border' : '' + children.push(`<${tag} v-for="(item, index) in ${conf.vModel}Options" :key="index" :label="item.value" :disabled="item.disabled" ${border}>{{item.label}}</${tag}>`) + } + return children.join('\n') +} + +function buildElUploadChild(conf) { + const list = [] + if (conf['list-type'] === 'picture-card') list.push('<i class="el-icon-plus"></i>') + else list.push(`<el-button size="small" type="primary" icon="el-icon-upload">${conf.buttonText}</el-button>`) + if (conf.showTip) list.push(`<div slot="tip" class="el-upload__tip">鍙兘涓婁紶涓嶈秴杩� ${conf.fileSize}${conf.sizeUnit} 鐨�${conf.accept}鏂囦欢</div>`) + return list.join('\n') +} + +export function makeUpHtml(conf, type) { + const htmlList = [] + confGlobal = conf + someSpanIsNot24 = conf.fields.some(item => item.span !== 24) + conf.fields.forEach(el => { + htmlList.push(layouts[el.layout](el)) + }) + const htmlStr = htmlList.join('\n') + + let temp = buildFormTemplate(conf, htmlStr, type) + if (type === 'dialog') { + temp = dialogWrapper(temp) + } + confGlobal = null + return temp +} diff --git a/src/utils/generator/icon.json b/src/utils/generator/icon.json new file mode 100644 index 0000000..2d9999a --- /dev/null +++ b/src/utils/generator/icon.json @@ -0,0 +1 @@ +["platform-eleme","eleme","delete-solid","delete","s-tools","setting","user-solid","user","phone","phone-outline","more","more-outline","star-on","star-off","s-goods","goods","warning","warning-outline","question","info","remove","circle-plus","success","error","zoom-in","zoom-out","remove-outline","circle-plus-outline","circle-check","circle-close","s-help","help","minus","plus","check","close","picture","picture-outline","picture-outline-round","upload","upload2","download","camera-solid","camera","video-camera-solid","video-camera","message-solid","bell","s-cooperation","s-order","s-platform","s-fold","s-unfold","s-operation","s-promotion","s-home","s-release","s-ticket","s-management","s-open","s-shop","s-marketing","s-flag","s-comment","s-finance","s-claim","s-custom","s-opportunity","s-data","s-check","s-grid","menu","share","d-caret","caret-left","caret-right","caret-bottom","caret-top","bottom-left","bottom-right","back","right","bottom","top","top-left","top-right","arrow-left","arrow-right","arrow-down","arrow-up","d-arrow-left","d-arrow-right","video-pause","video-play","refresh","refresh-right","refresh-left","finished","sort","sort-up","sort-down","rank","loading","view","c-scale-to-original","date","edit","edit-outline","folder","folder-opened","folder-add","folder-remove","folder-delete","folder-checked","tickets","document-remove","document-delete","document-copy","document-checked","document","document-add","printer","paperclip","takeaway-box","search","monitor","attract","mobile","scissors","umbrella","headset","brush","mouse","coordinate","magic-stick","reading","data-line","data-board","pie-chart","data-analysis","collection-tag","film","suitcase","suitcase-1","receiving","collection","files","notebook-1","notebook-2","toilet-paper","office-building","school","table-lamp","house","no-smoking","smoking","shopping-cart-full","shopping-cart-1","shopping-cart-2","shopping-bag-1","shopping-bag-2","sold-out","sell","present","box","bank-card","money","coin","wallet","discount","price-tag","news","guide","male","female","thumb","cpu","link","connection","open","turn-off","set-up","chat-round","chat-line-round","chat-square","chat-dot-round","chat-dot-square","chat-line-square","message","postcard","position","turn-off-microphone","microphone","close-notification","bangzhu","time","odometer","crop","aim","switch-button","full-screen","copy-document","mic","stopwatch","medal-1","medal","trophy","trophy-1","first-aid-kit","discover","place","location","location-outline","location-information","add-location","delete-location","map-location","alarm-clock","timer","watch-1","watch","lock","unlock","key","service","mobile-phone","bicycle","truck","ship","basketball","football","soccer","baseball","wind-power","light-rain","lightning","heavy-rain","sunrise","sunrise-1","sunset","sunny","cloudy","partly-cloudy","cloudy-and-sunny","moon","moon-night","dish","dish-1","food","chicken","fork-spoon","knife-fork","burger","tableware","sugar","dessert","ice-cream","hot-water","water-cup","coffee-cup","cold-drink","goblet","goblet-full","goblet-square","goblet-square-full","refrigerator","grape","watermelon","cherry","apple","pear","orange","coffee","ice-tea","ice-drink","milk-tea","potato-strips","lollipop","ice-cream-square","ice-cream-round"] \ No newline at end of file diff --git a/src/utils/generator/js.js b/src/utils/generator/js.js new file mode 100644 index 0000000..ee8668d --- /dev/null +++ b/src/utils/generator/js.js @@ -0,0 +1,235 @@ +import { exportDefault, titleCase } from '@/utils/index' +import { trigger } from './config' + +const units = { + KB: '1024', + MB: '1024 / 1024', + GB: '1024 / 1024 / 1024' +} +let confGlobal +const inheritAttrs = { + file: '', + dialog: 'inheritAttrs: false,' +} + + +export function makeUpJs(conf, type) { + confGlobal = conf = JSON.parse(JSON.stringify(conf)) + const dataList = [] + const ruleList = [] + const optionsList = [] + const propsList = [] + const methodList = mixinMethod(type) + const uploadVarList = [] + + conf.fields.forEach(el => { + buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + + const script = buildexport( + conf, + type, + dataList.join('\n'), + ruleList.join('\n'), + optionsList.join('\n'), + uploadVarList.join('\n'), + propsList.join('\n'), + methodList.join('\n') + ) + confGlobal = null + return script +} + +function buildAttributes(el, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) { + buildData(el, dataList) + buildRules(el, ruleList) + + if (el.options && el.options.length) { + buildOptions(el, optionsList) + if (el.dataType === 'dynamic') { + const model = `${el.vModel}Options` + const options = titleCase(model) + buildOptionMethod(`get${options}`, model, methodList) + } + } + + if (el.props && el.props.props) { + buildProps(el, propsList) + } + + if (el.action && el.tag === 'el-upload') { + uploadVarList.push( + `${el.vModel}Action: '${el.action}', + ${el.vModel}fileList: [],` + ) + methodList.push(buildBeforeUpload(el)) + if (!el['auto-upload']) { + methodList.push(buildSubmitUpload(el)) + } + } + + if (el.children) { + el.children.forEach(el2 => { + buildAttributes(el2, dataList, ruleList, optionsList, methodList, propsList, uploadVarList) + }) + } +} + +function mixinMethod(type) { + const list = []; const + minxins = { + file: confGlobal.formBtns ? { + submitForm: `submitForm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + // TODO 鎻愪氦琛ㄥ崟 + }) + },`, + resetForm: `resetForm() { + this.$refs['${confGlobal.formRef}'].resetFields() + },` + } : null, + dialog: { + onOpen: 'onOpen() {},', + onClose: `onClose() { + this.$refs['${confGlobal.formRef}'].resetFields() + },`, + close: `close() { + this.$emit('update:visible', false) + },`, + handleConfirm: `handleConfirm() { + this.$refs['${confGlobal.formRef}'].validate(valid => { + if(!valid) return + this.close() + }) + },` + } + } + + const methods = minxins[type] + if (methods) { + Object.keys(methods).forEach(key => { + list.push(methods[key]) + }) + } + + return list +} + +function buildData(conf, dataList) { + if (conf.vModel === undefined) return + let defaultValue + if (typeof (conf.defaultValue) === 'string' && !conf.multiple) { + defaultValue = `'${conf.defaultValue}'` + } else { + defaultValue = `${JSON.stringify(conf.defaultValue)}` + } + dataList.push(`${conf.vModel}: ${defaultValue},`) +} + +function buildRules(conf, ruleList) { + if (conf.vModel === undefined) return + const rules = [] + if (trigger[conf.tag]) { + if (conf.required) { + const type = Array.isArray(conf.defaultValue) ? 'type: \'array\',' : '' + let message = Array.isArray(conf.defaultValue) ? `璇疯嚦灏戦�夋嫨涓�涓�${conf.vModel}` : conf.placeholder + if (message === undefined) message = `${conf.label}涓嶈兘涓虹┖` + rules.push(`{ required: true, ${type} message: '${message}', trigger: '${trigger[conf.tag]}' }`) + } + if (conf.regList && Array.isArray(conf.regList)) { + conf.regList.forEach(item => { + if (item.pattern) { + rules.push(`{ pattern: ${eval(item.pattern)}, message: '${item.message}', trigger: '${trigger[conf.tag]}' }`) + } + }) + } + ruleList.push(`${conf.vModel}: [${rules.join(',')}],`) + } +} + +function buildOptions(conf, optionsList) { + if (conf.vModel === undefined) return + if (conf.dataType === 'dynamic') { conf.options = [] } + const str = `${conf.vModel}Options: ${JSON.stringify(conf.options)},` + optionsList.push(str) +} + +function buildProps(conf, propsList) { + if (conf.dataType === 'dynamic') { + conf.valueKey !== 'value' && (conf.props.props.value = conf.valueKey) + conf.labelKey !== 'label' && (conf.props.props.label = conf.labelKey) + conf.childrenKey !== 'children' && (conf.props.props.children = conf.childrenKey) + } + const str = `${conf.vModel}Props: ${JSON.stringify(conf.props.props)},` + propsList.push(str) +} + +function buildBeforeUpload(conf) { + const unitNum = units[conf.sizeUnit]; let rightSizeCode = ''; let acceptCode = ''; const + returnList = [] + if (conf.fileSize) { + rightSizeCode = `let isRightSize = file.size / ${unitNum} < ${conf.fileSize} + if(!isRightSize){ + this.$message.error('鏂囦欢澶у皬瓒呰繃 ${conf.fileSize}${conf.sizeUnit}') + }` + returnList.push('isRightSize') + } + if (conf.accept) { + acceptCode = `let isAccept = new RegExp('${conf.accept}').test(file.type) + if(!isAccept){ + this.$message.error('搴旇閫夋嫨${conf.accept}绫诲瀷鐨勬枃浠�') + }` + returnList.push('isAccept') + } + const str = `${conf.vModel}BeforeUpload(file) { + ${rightSizeCode} + ${acceptCode} + return ${returnList.join('&&')} + },` + return returnList.length ? str : '' +} + +function buildSubmitUpload(conf) { + const str = `submitUpload() { + this.$refs['${conf.vModel}'].submit() + },` + return str +} + +function buildOptionMethod(methodName, model, methodList) { + const str = `${methodName}() { + // TODO 鍙戣捣璇锋眰鑾峰彇鏁版嵁 + this.${model} + },` + methodList.push(str) +} + +function buildexport(conf, type, data, rules, selectOptions, uploadVar, props, methods) { + const str = `${exportDefault}{ + ${inheritAttrs[type]} + components: {}, + props: [], + data () { + return { + ${conf.formModel}: { + ${data} + }, + ${conf.formRules}: { + ${rules} + }, + ${uploadVar} + ${selectOptions} + ${props} + } + }, + computed: {}, + watch: {}, + created () {}, + mounted () {}, + methods: { + ${methods} + } +}` + return str +} diff --git a/src/utils/generator/render.js b/src/utils/generator/render.js new file mode 100644 index 0000000..e8640f0 --- /dev/null +++ b/src/utils/generator/render.js @@ -0,0 +1,126 @@ +import { makeMap } from '@/utils/index' + +// 鍙傝�僪ttps://github.com/vuejs/vue/blob/v2.6.10/src/platforms/web/server/util.js +const isAttr = makeMap( + 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' + + 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' + + 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' + + 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' + + 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' + + 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' + + 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' + + 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' + + 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' + + 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' + + 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' + + 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' + + 'target,title,type,usemap,value,width,wrap' +) + +function vModel(self, dataObject, defaultValue) { + dataObject.props.value = defaultValue + + dataObject.on.input = val => { + self.$emit('input', val) + } +} + +const componentChild = { + 'el-button': { + default(h, conf, key) { + return conf[key] + }, + }, + 'el-input': { + prepend(h, conf, key) { + return <template slot="prepend">{conf[key]}</template> + }, + append(h, conf, key) { + return <template slot="append">{conf[key]}</template> + } + }, + 'el-select': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + list.push(<el-option label={item.label} value={item.value} disabled={item.disabled}></el-option>) + }) + return list + } + }, + 'el-radio-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') list.push(<el-radio-button label={item.value}>{item.label}</el-radio-button>) + else list.push(<el-radio label={item.value} border={conf.border}>{item.label}</el-radio>) + }) + return list + } + }, + 'el-checkbox-group': { + options(h, conf, key) { + const list = [] + conf.options.forEach(item => { + if (conf.optionType === 'button') { + list.push(<el-checkbox-button label={item.value}>{item.label}</el-checkbox-button>) + } else { + list.push(<el-checkbox label={item.value} border={conf.border}>{item.label}</el-checkbox>) + } + }) + return list + } + }, + 'el-upload': { + 'list-type': (h, conf, key) => { + const list = [] + if (conf['list-type'] === 'picture-card') { + list.push(<i class="el-icon-plus"></i>) + } else { + list.push(<el-button size="small" type="primary" icon="el-icon-upload">{conf.buttonText}</el-button>) + } + if (conf.showTip) { + list.push(<div slot="tip" class="el-upload__tip">鍙兘涓婁紶涓嶈秴杩� {conf.fileSize}{conf.sizeUnit} 鐨剓conf.accept}鏂囦欢</div>) + } + return list + } + } +} + +export default { + render(h) { + const dataObject = { + attrs: {}, + props: {}, + on: {}, + style: {} + } + const confClone = JSON.parse(JSON.stringify(this.conf)) + const children = [] + + const childObjs = componentChild[confClone.tag] + if (childObjs) { + Object.keys(childObjs).forEach(key => { + const childFunc = childObjs[key] + if (confClone[key]) { + children.push(childFunc(h, confClone, key)) + } + }) + } + + Object.keys(confClone).forEach(key => { + const val = confClone[key] + if (key === 'vModel') { + vModel(this, dataObject, confClone.defaultValue) + } else if (dataObject[key]) { + dataObject[key] = val + } else if (!isAttr(key)) { + dataObject.props[key] = val + } else { + dataObject.attrs[key] = val + } + }) + return h(this.conf.tag, dataObject, children) + }, + props: ['conf'] +} diff --git a/src/utils/index.js b/src/utils/index.js new file mode 100644 index 0000000..4e65504 --- /dev/null +++ b/src/utils/index.js @@ -0,0 +1,390 @@ +import { parseTime } from './ruoyi' + +/** + * 琛ㄦ牸鏃堕棿鏍煎紡鍖� + */ +export function formatDate(cellValue) { + if (cellValue == null || cellValue == "") return ""; + var date = new Date(cellValue) + var year = date.getFullYear() + var month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 + var day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate() + var hours = date.getHours() < 10 ? '0' + date.getHours() : date.getHours() + var minutes = date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() + var seconds = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds() + return year + '-' + month + '-' + day + ' ' + hours + ':' + minutes + ':' + seconds +} + +/** + * @param {number} time + * @param {string} option + * @returns {string} + */ +export function formatTime(time, option) { + if (('' + time).length === 10) { + time = parseInt(time) * 1000 + } else { + time = +time + } + const d = new Date(time) + const now = Date.now() + + const diff = (now - d) / 1000 + + if (diff < 30) { + return '鍒氬垰' + } else if (diff < 3600) { + // less 1 hour + return Math.ceil(diff / 60) + '鍒嗛挓鍓�' + } else if (diff < 3600 * 24) { + return Math.ceil(diff / 3600) + '灏忔椂鍓�' + } else if (diff < 3600 * 24 * 2) { + return '1澶╁墠' + } + if (option) { + return parseTime(time, option) + } else { + return ( + d.getMonth() + + 1 + + '鏈�' + + d.getDate() + + '鏃�' + + d.getHours() + + '鏃�' + + d.getMinutes() + + '鍒�' + ) + } +} + +/** + * @param {string} url + * @returns {Object} + */ +export function getQueryObject(url) { + url = url == null ? window.location.href : url + const search = url.substring(url.lastIndexOf('?') + 1) + const obj = {} + const reg = /([^?&=]+)=([^?&=]*)/g + search.replace(reg, (rs, $1, $2) => { + const name = decodeURIComponent($1) + let val = decodeURIComponent($2) + val = String(val) + obj[name] = val + return rs + }) + return obj +} + +/** + * @param {string} input value + * @returns {number} output value + */ +export function byteLength(str) { + // returns the byte length of an utf8 string + let s = str.length + for (var i = str.length - 1; i >= 0; i--) { + const code = str.charCodeAt(i) + if (code > 0x7f && code <= 0x7ff) s++ + else if (code > 0x7ff && code <= 0xffff) s += 2 + if (code >= 0xDC00 && code <= 0xDFFF) i-- + } + return s +} + +/** + * @param {Array} actual + * @returns {Array} + */ +export function cleanArray(actual) { + const newArray = [] + for (let i = 0; i < actual.length; i++) { + if (actual[i]) { + newArray.push(actual[i]) + } + } + return newArray +} + +/** + * @param {Object} json + * @returns {Array} + */ +export function param(json) { + if (!json) return '' + return cleanArray( + Object.keys(json).map(key => { + if (json[key] === undefined) return '' + return encodeURIComponent(key) + '=' + encodeURIComponent(json[key]) + }) + ).join('&') +} + +/** + * @param {string} url + * @returns {Object} + */ +export function param2Obj(url) { + const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ') + if (!search) { + return {} + } + const obj = {} + const searchArr = search.split('&') + searchArr.forEach(v => { + const index = v.indexOf('=') + if (index !== -1) { + const name = v.substring(0, index) + const val = v.substring(index + 1, v.length) + obj[name] = val + } + }) + return obj +} + +/** + * @param {string} val + * @returns {string} + */ +export function html2Text(val) { + const div = document.createElement('div') + div.innerHTML = val + return div.textContent || div.innerText +} + +/** + * Merges two objects, giving the last one precedence + * @param {Object} target + * @param {(Object|Array)} source + * @returns {Object} + */ +export function objectMerge(target, source) { + if (typeof target !== 'object') { + target = {} + } + if (Array.isArray(source)) { + return source.slice() + } + Object.keys(source).forEach(property => { + const sourceProperty = source[property] + if (typeof sourceProperty === 'object') { + target[property] = objectMerge(target[property], sourceProperty) + } else { + target[property] = sourceProperty + } + }) + return target +} + +/** + * @param {HTMLElement} element + * @param {string} className + */ +export function toggleClass(element, className) { + if (!element || !className) { + return + } + let classString = element.className + const nameIndex = classString.indexOf(className) + if (nameIndex === -1) { + classString += '' + className + } else { + classString = + classString.substr(0, nameIndex) + + classString.substr(nameIndex + className.length) + } + element.className = classString +} + +/** + * @param {string} type + * @returns {Date} + */ +export function getTime(type) { + if (type === 'start') { + return new Date().getTime() - 3600 * 1000 * 24 * 90 + } else { + return new Date(new Date().toDateString()) + } +} + +/** + * @param {Function} func + * @param {number} wait + * @param {boolean} immediate + * @return {*} + */ +export function debounce(func, wait, immediate) { + let timeout, args, context, timestamp, result + + const later = function() { + // 鎹笂涓�娆¤Е鍙戞椂闂撮棿闅� + const last = +new Date() - timestamp + + // 涓婃琚寘瑁呭嚱鏁拌璋冪敤鏃堕棿闂撮殧 last 灏忎簬璁惧畾鏃堕棿闂撮殧 wait + if (last < wait && last > 0) { + timeout = setTimeout(later, wait - last) + } else { + timeout = null + // 濡傛灉璁惧畾涓篿mmediate===true锛屽洜涓哄紑濮嬭竟鐣屽凡缁忚皟鐢ㄨ繃浜嗘澶勬棤闇�璋冪敤 + if (!immediate) { + result = func.apply(context, args) + if (!timeout) context = args = null + } + } + } + + return function(...args) { + context = this + timestamp = +new Date() + const callNow = immediate && !timeout + // 濡傛灉寤舵椂涓嶅瓨鍦紝閲嶆柊璁惧畾寤舵椂 + if (!timeout) timeout = setTimeout(later, wait) + if (callNow) { + result = func.apply(context, args) + context = args = null + } + + return result + } +} + +/** + * This is just a simple version of deep copy + * Has a lot of edge cases bug + * If you want to use a perfect deep copy, use lodash's _.cloneDeep + * @param {Object} source + * @returns {Object} + */ +export function deepClone(source) { + if (!source && typeof source !== 'object') { + throw new Error('error arguments', 'deepClone') + } + const targetObj = source.constructor === Array ? [] : {} + Object.keys(source).forEach(keys => { + if (source[keys] && typeof source[keys] === 'object') { + targetObj[keys] = deepClone(source[keys]) + } else { + targetObj[keys] = source[keys] + } + }) + return targetObj +} + +/** + * @param {Array} arr + * @returns {Array} + */ +export function uniqueArr(arr) { + return Array.from(new Set(arr)) +} + +/** + * @returns {string} + */ +export function createUniqueString() { + const timestamp = +new Date() + '' + const randomNum = parseInt((1 + Math.random()) * 65536) + '' + return (+(randomNum + timestamp)).toString(32) +} + +/** + * Check if an element has a class + * @param {HTMLElement} elm + * @param {string} cls + * @returns {boolean} + */ +export function hasClass(ele, cls) { + return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) +} + +/** + * Add class to element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function addClass(ele, cls) { + if (!hasClass(ele, cls)) ele.className += ' ' + cls +} + +/** + * Remove class from element + * @param {HTMLElement} elm + * @param {string} cls + */ +export function removeClass(ele, cls) { + if (hasClass(ele, cls)) { + const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') + ele.className = ele.className.replace(reg, ' ') + } +} + +export function makeMap(str, expectsLowerCase) { + const map = Object.create(null) + const list = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase + ? val => map[val.toLowerCase()] + : val => map[val] +} + +export const exportDefault = 'export default ' + +export const beautifierConf = { + html: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'separate', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: false, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + }, + js: { + indent_size: '2', + indent_char: ' ', + max_preserve_newlines: '-1', + preserve_newlines: false, + keep_array_indentation: false, + break_chained_methods: false, + indent_scripts: 'normal', + brace_style: 'end-expand', + space_before_conditional: true, + unescape_strings: false, + jslint_happy: true, + end_with_newline: true, + wrap_line_length: '110', + indent_inner_html: true, + comma_first: false, + e4x: true, + indent_empty_lines: true + } +} + +// 棣栧瓧姣嶅ぇ灏� +export function titleCase(str) { + return str.replace(/( |^)[a-z]/g, L => L.toUpperCase()) +} + +// 涓嬪垝杞┘宄� +export function camelCase(str) { + return str.replace(/_[a-z]/g, str1 => str1.substr(-1).toUpperCase()) +} + +export function isNumberStr(str) { + return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) +} + diff --git a/src/utils/jsencrypt.js b/src/utils/jsencrypt.js new file mode 100644 index 0000000..78d9523 --- /dev/null +++ b/src/utils/jsencrypt.js @@ -0,0 +1,30 @@ +import JSEncrypt from 'jsencrypt/bin/jsencrypt.min' + +// 瀵嗛挜瀵圭敓鎴� http://web.chacuo.net/netrsakeypair + +const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' + + 'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==' + +const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' + + '7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' + + 'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' + + 'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' + + 'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' + + 'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' + + 'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' + + 'UP8iWi1Qw0Y=' + +// 鍔犲瘑 +export function encrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPublicKey(publicKey) // 璁剧疆鍏挜 + return encryptor.encrypt(txt) // 瀵规暟鎹繘琛屽姞瀵� +} + +// 瑙e瘑 +export function decrypt(txt) { + const encryptor = new JSEncrypt() + encryptor.setPrivateKey(privateKey) // 璁剧疆绉侀挜 + return encryptor.decrypt(txt) // 瀵规暟鎹繘琛岃В瀵� +} + diff --git a/src/utils/permission.js b/src/utils/permission.js new file mode 100644 index 0000000..1730e33 --- /dev/null +++ b/src/utils/permission.js @@ -0,0 +1,51 @@ +import store from '@/store' + +/** + * 瀛楃鏉冮檺鏍¢獙 + * @param {Array} value 鏍¢獙鍊� + * @returns {Boolean} + */ +export function checkPermi(value) { + if (value && value instanceof Array && value.length > 0) { + const permissions = store.getters && store.getters.permissions + const permissionDatas = value + const all_permission = "*:*:*"; + + const hasPermission = permissions.some(permission => { + return all_permission === permission || permissionDatas.includes(permission) + }) + + if (!hasPermission) { + return false + } + return true + } else { + console.error(`need roles! Like checkPermi="['system:user:add','system:user:edit']"`) + return false + } +} + +/** + * 瑙掕壊鏉冮檺鏍¢獙 + * @param {Array} value 鏍¢獙鍊� + * @returns {Boolean} + */ +export function checkRole(value) { + if (value && value instanceof Array && value.length > 0) { + const roles = store.getters && store.getters.roles + const permissionRoles = value + const super_admin = "admin"; + + const hasRole = roles.some(role => { + return super_admin === role || permissionRoles.includes(role) + }) + + if (!hasRole) { + return false + } + return true + } else { + console.error(`need roles! Like checkRole="['admin','editor']"`) + return false + } +} \ No newline at end of file diff --git a/src/utils/request.js b/src/utils/request.js new file mode 100644 index 0000000..6b75ef5 --- /dev/null +++ b/src/utils/request.js @@ -0,0 +1,181 @@ +import axios from 'axios' +import { Notification, MessageBox, Message, Loading } from 'element-ui' +import store from '@/store' +import { getToken } from '@/utils/auth' +import errorCode from '@/utils/errorCode' +import { tansParams, blobValidate } from "@/utils/ruoyi"; +import cache from '@/plugins/cache' +import { saveAs } from 'file-saver' + +let downloadLoadingInstance; +// 鏄惁鏄剧ず閲嶆柊鐧诲綍 +export let isRelogin = { show: false }; + +axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8' +// const baseURL = VUE_BASE_URL+"/"; +// 鍒涘缓axios瀹炰緥 +const service = axios.create({ + // axios涓姹傞厤缃湁baseURL閫夐」锛岃〃绀鸿姹俇RL鍏叡閮ㄥ垎 + baseURL: process.env.VUE_APP_BASE_API, + // baseURL: 'http://127.0.0.1:8095/', + // 瓒呮椂 + timeout: 10000 +}) + +// request鎷︽埅鍣� +service.interceptors.request.use(config => { + // 鏄惁闇�瑕佽缃� token + const isToken = (config.headers || {}).isToken === false + // 鏄惁闇�瑕侀槻姝㈡暟鎹噸澶嶆彁浜� + const isRepeatSubmit = (config.headers || {}).repeatSubmit === false + if (getToken() && !isToken) { + config.headers['Authorization'] = 'Bearer ' + getToken() // 璁╂瘡涓姹傛惡甯﹁嚜瀹氫箟token 璇锋牴鎹疄闄呮儏鍐佃嚜琛屼慨鏀� + } + // get璇锋眰鏄犲皠params鍙傛暟 + if (config.method === 'get' && config.params) { + let url = config.url + '?' + tansParams(config.params); + url = url.slice(0, -1); + config.params = {}; + config.url = url; + } + if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) { + const requestObj = { + url: config.url, + data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data, + time: new Date().getTime() + } + const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 璇锋眰鏁版嵁澶у皬 + const limitSize = 5 * 1024 * 1024; // 闄愬埗瀛樻斁鏁版嵁5M + if (requestSize >= limitSize) { + console.warn(`[${config.url}]: ` + '璇锋眰鏁版嵁澶у皬瓒呭嚭鍏佽鐨�5M闄愬埗锛屾棤娉曡繘琛岄槻閲嶅鎻愪氦楠岃瘉銆�') + return config; + } + const sessionObj = cache.session.getJSON('sessionObj') + if (sessionObj === undefined || sessionObj === null || sessionObj === '') { + cache.session.setJSON('sessionObj', requestObj) + } else { + const s_url = sessionObj.url; // 璇锋眰鍦板潃 + const s_data = sessionObj.data; // 璇锋眰鏁版嵁 + const s_time = sessionObj.time; // 璇锋眰鏃堕棿 + const interval = 1000; // 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦 + if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) { + const message = '鏁版嵁姝e湪澶勭悊锛岃鍕块噸澶嶆彁浜�'; + console.warn(`[${s_url}]: ` + message) + return Promise.reject(new Error(message)) + } else { + cache.session.setJSON('sessionObj', requestObj) + } + } + } + return config +}, error => { + console.log(error) + Promise.reject(error) +}) + +// 鍝嶅簲鎷︽埅鍣� +service.interceptors.response.use(res => { + // 鏈缃姸鎬佺爜鍒欓粯璁ゆ垚鍔熺姸鎬� + const code = res.data.code || 200; + // 鑾峰彇閿欒淇℃伅 + const msg = errorCode[code] || res.data.msg || errorCode['default'] + // 浜岃繘鍒舵暟鎹垯鐩存帴杩斿洖 + if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') { + return res.data + } + if (code === 401) { + if (!isRelogin.show) { + isRelogin.show = true; + MessageBox.confirm('鐧诲綍鐘舵�佸凡杩囨湡锛屾偍鍙互缁х画鐣欏湪璇ラ〉闈紝鎴栬�呴噸鏂扮櫥褰�', '绯荤粺鎻愮ず', { confirmButtonText: '閲嶆柊鐧诲綍', cancelButtonText: '鍙栨秷', type: 'warning' }).then(() => { + isRelogin.show = false; + store.dispatch('LogOut').then(() => { + location.href = '/index'; + }) + }).catch(() => { + isRelogin.show = false; + }); + } + return Promise.reject('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�') + } else if (code === 500) { + Message({ message: msg, type: 'error' }) + return Promise.reject(new Error(msg)) + } else if (code === 601) { + Message({ message: msg, type: 'warning' }) + return Promise.reject('error') + } else if (code !== 200) { + Notification.error({ title: msg }) + return Promise.reject('error') + } else { + return res.data + } + }, + error => { + console.log('err' + error) + let { message } = error; + if (message == "Network Error") { + message = "鍚庣鎺ュ彛杩炴帴寮傚父"; + } else if (message.includes("timeout")) { + message = "绯荤粺鎺ュ彛璇锋眰瓒呮椂"; + } else if (message.includes("Request failed with status code")) { + message = "绯荤粺鎺ュ彛" + message.substr(message.length - 3) + "寮傚父"; + } + Message({ message: message, type: 'error', duration: 5 * 1000 }) + return Promise.reject(error) + } +) + +// 閫氱敤涓嬭浇鏂规硶 +export function download(url, params, filename, config) { + downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) + return service.post(url, params, { + transformRequest: [(params) => { return tansParams(params) }], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob', + ...config + }).then(async (data) => { + const isBlob = blobValidate(data); + if (isBlob) { + const blob = new Blob([data]) + saveAs(blob, filename) + } else { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + Message.error(errMsg); + } + downloadLoadingInstance.close(); + }).catch((r) => { + console.error(r) + Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒') + downloadLoadingInstance.close(); + }) +} + +// 閫氱敤涓嬭浇鏂规硶 +export function downloadFiles(url, params, filename, config) { + downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", }) + return service.post(url, params, { + transformRequest: [(params) => { return tansParams(params) }], + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + responseType: 'blob', + ...config + }).then(async (data) => { + const isBlob = blobValidate(data); + if (!isBlob) { + const blob = new Blob([data]) + saveAs(blob, filename) + } else { + const resText = await data.text(); + const rspObj = JSON.parse(resText); + const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default'] + Message.error(errMsg); + } + downloadLoadingInstance.close(); + }).catch((r) => { + console.error(r) + Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒') + downloadLoadingInstance.close(); + }) +} + +export default service diff --git a/src/utils/ruoyi.js b/src/utils/ruoyi.js new file mode 100644 index 0000000..44bf9c4 --- /dev/null +++ b/src/utils/ruoyi.js @@ -0,0 +1,233 @@ + + +/** + * 閫氱敤js鏂规硶灏佽澶勭悊 + * Copyright (c) 2019 ruoyi + */ + +// 鏃ユ湡鏍煎紡鍖� +export function parseTime(time, pattern) { + if (arguments.length === 0 || !time) { + return null + } + const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}' + let date + if (typeof time === 'object') { + date = time + } else { + if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { + time = parseInt(time) + } else if (typeof time === 'string') { + time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), ''); + } + if ((typeof time === 'number') && (time.toString().length === 10)) { + time = time * 1000 + } + date = new Date(time) + } + const formatObj = { + y: date.getFullYear(), + m: date.getMonth() + 1, + d: date.getDate(), + h: date.getHours(), + i: date.getMinutes(), + s: date.getSeconds(), + a: date.getDay() + } + const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => { + let value = formatObj[key] + // Note: getDay() returns 0 on Sunday + if (key === 'a') { return ['鏃�', '涓�', '浜�', '涓�', '鍥�', '浜�', '鍏�'][value] } + if (result.length > 0 && value < 10) { + value = '0' + value + } + return value || 0 + }) + return time_str +} + +// 琛ㄥ崟閲嶇疆 +export function resetForm(refName) { + if (this.$refs[refName]) { + this.$refs[refName].resetFields(); + } +} + +// 娣诲姞鏃ユ湡鑼冨洿 +export function addDateRange(params, dateRange, propName) { + let search = params; + search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {}; + dateRange = Array.isArray(dateRange) ? dateRange : []; + if (typeof (propName) === 'undefined') { + search.params['beginTime'] = dateRange[0]; + search.params['endTime'] = dateRange[1]; + } else { + search.params['begin' + propName] = dateRange[0]; + search.params['end' + propName] = dateRange[1]; + } + return search; +} + +// 鍥炴樉鏁版嵁瀛楀吀 +export function selectDictLabel(datas, value) { + if (value === undefined) { + return ""; + } + var actions = []; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + value)) { + actions.push(datas[key].label); + return true; + } + }) + if (actions.length === 0) { + actions.push(value); + } + return actions.join(''); +} + +// 鍥炴樉鏁版嵁瀛楀吀锛堝瓧绗︿覆銆佹暟缁勶級 +export function selectDictLabels(datas, value, separator) { + if (value === undefined || value.length ===0) { + return ""; + } + if (Array.isArray(value)) { + value = value.join(","); + } + var actions = []; + var currentSeparator = undefined === separator ? "," : separator; + var temp = value.split(currentSeparator); + Object.keys(value.split(currentSeparator)).some((val) => { + var match = false; + Object.keys(datas).some((key) => { + if (datas[key].value == ('' + temp[val])) { + actions.push(datas[key].label + currentSeparator); + match = true; + } + }) + if (!match) { + actions.push(temp[val] + currentSeparator); + } + }) + return actions.join('').substring(0, actions.join('').length - 1); +} + +// 瀛楃涓叉牸寮忓寲(%s ) +export function sprintf(str) { + var args = arguments, flag = true, i = 1; + str = str.replace(/%s/g, function () { + var arg = args[i++]; + if (typeof arg === 'undefined') { + flag = false; + return ''; + } + return arg; + }); + return flag ? str : ''; +} + +// 杞崲瀛楃涓诧紝undefined,null绛夎浆鍖栦负"" +export function parseStrEmpty(str) { + if (!str || str == "undefined" || str == "null") { + return ""; + } + return str; +} + +// 鏁版嵁鍚堝苟 +export function mergeRecursive(source, target) { + for (var p in target) { + try { + if (target[p].constructor == Object) { + source[p] = mergeRecursive(source[p], target[p]); + } else { + source[p] = target[p]; + } + } catch (e) { + source[p] = target[p]; + } + } + return source; +}; + +/** + * 鏋勯�犳爲鍨嬬粨鏋勬暟鎹� + * @param {*} data 鏁版嵁婧� + * @param {*} id id瀛楁 榛樿 'id' + * @param {*} parentId 鐖惰妭鐐瑰瓧娈� 榛樿 'parentId' + * @param {*} children 瀛╁瓙鑺傜偣瀛楁 榛樿 'children' + */ +export function handleTree(data, id, parentId, children) { + let config = { + id: id || 'id', + parentId: parentId || 'parentId', + childrenList: children || 'children' + }; + + var childrenListMap = {}; + var nodeIds = {}; + var tree = []; + + for (let d of data) { + let parentId = d[config.parentId]; + if (childrenListMap[parentId] == null) { + childrenListMap[parentId] = []; + } + nodeIds[d[config.id]] = d; + childrenListMap[parentId].push(d); + } + + for (let d of data) { + let parentId = d[config.parentId]; + if (nodeIds[parentId] == null) { + tree.push(d); + } + } + + for (let t of tree) { + adaptToChildrenList(t); + } + + function adaptToChildrenList(o) { + if (childrenListMap[o[config.id]] !== null) { + o[config.childrenList] = childrenListMap[o[config.id]]; + } + if (o[config.childrenList]) { + for (let c of o[config.childrenList]) { + adaptToChildrenList(c); + } + } + } + return tree; +} + +/** +* 鍙傛暟澶勭悊 +* @param {*} params 鍙傛暟 +*/ +export function tansParams(params) { + let result = '' + for (const propName of Object.keys(params)) { + const value = params[propName]; + var part = encodeURIComponent(propName) + "="; + if (value !== null && value !== "" && typeof (value) !== "undefined") { + if (typeof value === 'object') { + for (const key of Object.keys(value)) { + if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') { + let params = propName + '[' + key + ']'; + var subPart = encodeURIComponent(params) + "="; + result += subPart + encodeURIComponent(value[key]) + "&"; + } + } + } else { + result += part + encodeURIComponent(value) + "&"; + } + } + } + return result +} + +// 楠岃瘉鏄惁涓篵lob鏍煎紡 +export function blobValidate(data) { + return data.type !== 'application/json' +} diff --git a/src/utils/scroll-to.js b/src/utils/scroll-to.js new file mode 100644 index 0000000..c5d8e04 --- /dev/null +++ b/src/utils/scroll-to.js @@ -0,0 +1,58 @@ +Math.easeInOutQuad = function(t, b, c, d) { + t /= d / 2 + if (t < 1) { + return c / 2 * t * t + b + } + t-- + return -c / 2 * (t * (t - 2) - 1) + b +} + +// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts +var requestAnimFrame = (function() { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) } +})() + +/** + * Because it's so fucking difficult to detect the scrolling element, just move them all + * @param {number} amount + */ +function move(amount) { + document.documentElement.scrollTop = amount + document.body.parentNode.scrollTop = amount + document.body.scrollTop = amount +} + +function position() { + return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop +} + +/** + * @param {number} to + * @param {number} duration + * @param {Function} callback + */ +export function scrollTo(to, duration, callback) { + const start = position() + const change = to - start + const increment = 20 + let currentTime = 0 + duration = (typeof (duration) === 'undefined') ? 500 : duration + var animateScroll = function() { + // increment the time + currentTime += increment + // find the value with the quadratic in-out easing function + var val = Math.easeInOutQuad(currentTime, start, change, duration) + // move the document.body + move(val) + // do the animation unless its over + if (currentTime < duration) { + requestAnimFrame(animateScroll) + } else { + if (callback && typeof (callback) === 'function') { + // the animation is done so lets callback + callback() + } + } + } + animateScroll() +} diff --git a/src/utils/validate.js b/src/utils/validate.js new file mode 100644 index 0000000..adfa254 --- /dev/null +++ b/src/utils/validate.js @@ -0,0 +1,83 @@ +/** + * @param {string} path + * @returns {Boolean} + */ +export function isExternal(path) { + return /^(https?:|mailto:|tel:)/.test(path) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUsername(str) { + const valid_map = ['admin', 'editor'] + return valid_map.indexOf(str.trim()) >= 0 +} + +/** + * @param {string} url + * @returns {Boolean} + */ +export function validURL(url) { + const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/ + return reg.test(url) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validLowerCase(str) { + const reg = /^[a-z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validUpperCase(str) { + const reg = /^[A-Z]+$/ + return reg.test(str) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function validAlphabets(str) { + const reg = /^[A-Za-z]+$/ + return reg.test(str) +} + +/** + * @param {string} email + * @returns {Boolean} + */ +export function validEmail(email) { + const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ + return reg.test(email) +} + +/** + * @param {string} str + * @returns {Boolean} + */ +export function isString(str) { + if (typeof str === 'string' || str instanceof String) { + return true + } + return false +} + +/** + * @param {Array} arg + * @returns {Boolean} + */ +export function isArray(arg) { + if (typeof Array.isArray === 'undefined') { + return Object.prototype.toString.call(arg) === '[object Array]' + } + return Array.isArray(arg) +} diff --git a/src/views/components/icons/element-icons.js b/src/views/components/icons/element-icons.js new file mode 100644 index 0000000..9ea4d63 --- /dev/null +++ b/src/views/components/icons/element-icons.js @@ -0,0 +1,3 @@ +const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round'] + +export default elementIcons diff --git a/src/views/components/icons/index.vue b/src/views/components/icons/index.vue new file mode 100644 index 0000000..d3c9a71 --- /dev/null +++ b/src/views/components/icons/index.vue @@ -0,0 +1,87 @@ +<template> + <div class="icons-container"> + <aside> + <a href="#" target="_blank">Add and use + </a> + </aside> + <el-tabs type="border-card"> + <el-tab-pane label="Icons"> + <div v-for="item of svgIcons" :key="item"> + <el-tooltip placement="top"> + <div slot="content"> + {{ generateIconCode(item) }} + </div> + <div class="icon-item"> + <svg-icon :icon-class="item" class-name="disabled" /> + <span>{{ item }}</span> + </div> + </el-tooltip> + </div> + </el-tab-pane> + <el-tab-pane label="Element-UI Icons"> + <div v-for="item of elementIcons" :key="item"> + <el-tooltip placement="top"> + <div slot="content"> + {{ generateElementIconCode(item) }} + </div> + <div class="icon-item"> + <i :class="'el-icon-' + item" /> + <span>{{ item }}</span> + </div> + </el-tooltip> + </div> + </el-tab-pane> + </el-tabs> + </div> +</template> + +<script> +import svgIcons from './svg-icons' +import elementIcons from './element-icons' + +export default { + name: 'Icons', + data() { + return { + svgIcons, + elementIcons + } + }, + methods: { + generateIconCode(symbol) { + return `<svg-icon icon-class="${symbol}" />` + }, + generateElementIconCode(symbol) { + return `<i class="el-icon-${symbol}" />` + } + } +} +</script> + +<style lang="scss" scoped> +.icons-container { + margin: 10px 20px 0; + overflow: hidden; + + .icon-item { + margin: 20px; + height: 85px; + text-align: center; + width: 100px; + float: left; + font-size: 30px; + color: #24292e; + cursor: pointer; + } + + span { + display: block; + font-size: 16px; + margin-top: 10px; + } + + .disabled { + pointer-events: none; + } +} +</style> diff --git a/src/views/components/icons/svg-icons.js b/src/views/components/icons/svg-icons.js new file mode 100644 index 0000000..724cd8e --- /dev/null +++ b/src/views/components/icons/svg-icons.js @@ -0,0 +1,10 @@ +const req = require.context('../../../assets/icons/svg', false, /\.svg$/) +const requireAll = requireContext => requireContext.keys() + +const re = /\.\/(.*)\.svg/ + +const svgIcons = requireAll(req).map(i => { + return i.match(re)[1] +}) + +export default svgIcons diff --git a/src/views/dashboard/BarChart.vue b/src/views/dashboard/BarChart.vue new file mode 100644 index 0000000..cd33d2d --- /dev/null +++ b/src/views/dashboard/BarChart.vue @@ -0,0 +1,102 @@ +<template> + <div :class="className" :style="{height:height,width:width}" /> +</template> + +<script> +import * as echarts from 'echarts'; +require('echarts/theme/macarons') // echarts theme +import resize from './mixins/resize' + +const animationDuration = 6000 + +export default { + mixins: [resize], + props: { + className: { + type: String, + default: 'chart' + }, + width: { + type: String, + default: '100%' + }, + height: { + type: String, + default: '300px' + } + }, + data() { + return { + chart: null + } + }, + mounted() { + this.$nextTick(() => { + this.initChart() + }) + }, + beforeDestroy() { + if (!this.chart) { + return + } + this.chart.dispose() + this.chart = null + }, + methods: { + initChart() { + this.chart = echarts.init(this.$el, 'macarons') + + this.chart.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { // 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥 + type: 'shadow' // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow' + } + }, + grid: { + top: 10, + left: '2%', + right: '2%', + bottom: '3%', + containLabel: true + }, + xAxis: [{ + type: 'category', + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + axisTick: { + alignWithLabel: true + } + }], + yAxis: [{ + type: 'value', + axisTick: { + show: false + } + }], + series: [{ + name: 'pageA', + type: 'bar', + stack: 'vistors', + barWidth: '60%', + data: [79, 52, 200, 334, 390, 330, 220], + animationDuration + }, { + name: 'pageB', + type: 'bar', + stack: 'vistors', + barWidth: '60%', + data: [80, 52, 200, 334, 390, 330, 220], + animationDuration + }, { + name: 'pageC', + type: 'bar', + stack: 'vistors', + barWidth: '60%', + data: [30, 52, 200, 334, 390, 330, 220], + animationDuration + }] + }) + } + } +} +</script> diff --git a/src/views/dashboard/LineChart.vue b/src/views/dashboard/LineChart.vue new file mode 100644 index 0000000..ddd1063 --- /dev/null +++ b/src/views/dashboard/LineChart.vue @@ -0,0 +1,135 @@ +<template> + <div :class="className" :style="{height:height,width:width}" /> +</template> + +<script> +import * as echarts from 'echarts'; +require('echarts/theme/macarons') // echarts theme +import resize from './mixins/resize' + +export default { + mixins: [resize], + props: { + className: { + type: String, + default: 'chart' + }, + width: { + type: String, + default: '100%' + }, + height: { + type: String, + default: '350px' + }, + autoResize: { + type: Boolean, + default: true + }, + chartData: { + type: Object, + required: true + } + }, + data() { + return { + chart: null + } + }, + watch: { + chartData: { + deep: true, + handler(val) { + this.setOptions(val) + } + } + }, + mounted() { + this.$nextTick(() => { + this.initChart() + }) + }, + beforeDestroy() { + if (!this.chart) { + return + } + this.chart.dispose() + this.chart = null + }, + methods: { + initChart() { + this.chart = echarts.init(this.$el, 'macarons') + this.setOptions(this.chartData) + }, + setOptions({ expectedData, actualData } = {}) { + this.chart.setOption({ + xAxis: { + data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'], + boundaryGap: false, + axisTick: { + show: false + } + }, + grid: { + left: 10, + right: 10, + bottom: 20, + top: 30, + containLabel: true + }, + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'cross' + }, + padding: [5, 10] + }, + yAxis: { + axisTick: { + show: false + } + }, + legend: { + data: ['expected', 'actual'] + }, + series: [{ + name: 'expected', itemStyle: { + normal: { + color: '#FF005A', + lineStyle: { + color: '#FF005A', + width: 2 + } + } + }, + smooth: true, + type: 'line', + data: expectedData, + animationDuration: 2800, + animationEasing: 'cubicInOut' + }, + { + name: 'actual', + smooth: true, + type: 'line', + itemStyle: { + normal: { + color: '#3888fa', + lineStyle: { + color: '#3888fa', + width: 2 + }, + areaStyle: { + color: '#f3f8ff' + } + } + }, + data: actualData, + animationDuration: 2800, + animationEasing: 'quadraticOut' + }] + }) + } + } +} +</script> diff --git a/src/views/dashboard/PanelGroup.vue b/src/views/dashboard/PanelGroup.vue new file mode 100644 index 0000000..1a1081f --- /dev/null +++ b/src/views/dashboard/PanelGroup.vue @@ -0,0 +1,181 @@ +<template> + <el-row :gutter="40" class="panel-group"> + <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> + <div class="card-panel" @click="handleSetLineChartData('newVisitis')"> + <div class="card-panel-icon-wrapper icon-people"> + <svg-icon icon-class="peoples" class-name="card-panel-icon" /> + </div> + <div class="card-panel-description"> + <div class="card-panel-text"> + 璁垮 + </div> + <count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" /> + </div> + </div> + </el-col> + <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> + <div class="card-panel" @click="handleSetLineChartData('messages')"> + <div class="card-panel-icon-wrapper icon-message"> + <svg-icon icon-class="message" class-name="card-panel-icon" /> + </div> + <div class="card-panel-description"> + <div class="card-panel-text"> + 娑堟伅 + </div> + <count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" /> + </div> + </div> + </el-col> + <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> + <div class="card-panel" @click="handleSetLineChartData('purchases')"> + <div class="card-panel-icon-wrapper icon-money"> + <svg-icon icon-class="money" class-name="card-panel-icon" /> + </div> + <div class="card-panel-description"> + <div class="card-panel-text"> + 閲戦 + </div> + <count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" /> + </div> + </div> + </el-col> + <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> + <div class="card-panel" @click="handleSetLineChartData('shoppings')"> + <div class="card-panel-icon-wrapper icon-shopping"> + <svg-icon icon-class="shopping" class-name="card-panel-icon" /> + </div> + <div class="card-panel-description"> + <div class="card-panel-text"> + 璁㈠崟 + </div> + <count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" /> + </div> + </div> + </el-col> + </el-row> +</template> + +<script> +import CountTo from 'vue-count-to' + +export default { + components: { + CountTo + }, + methods: { + handleSetLineChartData(type) { + this.$emit('handleSetLineChartData', type) + } + } +} +</script> + +<style lang="scss" scoped> +.panel-group { + margin-top: 18px; + + .card-panel-col { + margin-bottom: 32px; + } + + .card-panel { + height: 108px; + cursor: pointer; + font-size: 12px; + position: relative; + overflow: hidden; + color: #666; + background: #fff; + box-shadow: 4px 4px 40px rgba(0, 0, 0, .05); + border-color: rgba(0, 0, 0, .05); + + &:hover { + .card-panel-icon-wrapper { + color: #fff; + } + + .icon-people { + background: #40c9c6; + } + + .icon-message { + background: #36a3f7; + } + + .icon-money { + background: #f4516c; + } + + .icon-shopping { + background: #34bfa3 + } + } + + .icon-people { + color: #40c9c6; + } + + .icon-message { + color: #36a3f7; + } + + .icon-money { + color: #f4516c; + } + + .icon-shopping { + color: #34bfa3 + } + + .card-panel-icon-wrapper { + float: left; + margin: 14px 0 0 14px; + padding: 16px; + transition: all 0.38s ease-out; + border-radius: 6px; + } + + .card-panel-icon { + float: left; + font-size: 48px; + } + + .card-panel-description { + float: right; + font-weight: bold; + margin: 26px; + margin-left: 0px; + + .card-panel-text { + line-height: 18px; + color: rgba(0, 0, 0, 0.45); + font-size: 16px; + margin-bottom: 12px; + } + + .card-panel-num { + font-size: 20px; + } + } + } +} + +@media (max-width:550px) { + .card-panel-description { + display: none; + } + + .card-panel-icon-wrapper { + float: none !important; + width: 100%; + height: 100%; + margin: 0 !important; + + .svg-icon { + display: block; + margin: 14px auto !important; + float: none !important; + } + } +} +</style> diff --git a/src/views/dashboard/PieChart.vue b/src/views/dashboard/PieChart.vue new file mode 100644 index 0000000..c360057 --- /dev/null +++ b/src/views/dashboard/PieChart.vue @@ -0,0 +1,79 @@ +<template> + <div :class="className" :style="{height:height,width:width}" /> +</template> + +<script> +import * as echarts from 'echarts'; +require('echarts/theme/macarons') // echarts theme +import resize from './mixins/resize' + +export default { + mixins: [resize], + props: { + className: { + type: String, + default: 'chart' + }, + width: { + type: String, + default: '100%' + }, + height: { + type: String, + default: '300px' + } + }, + data() { + return { + chart: null + } + }, + mounted() { + this.$nextTick(() => { + this.initChart() + }) + }, + beforeDestroy() { + if (!this.chart) { + return + } + this.chart.dispose() + this.chart = null + }, + methods: { + initChart() { + this.chart = echarts.init(this.$el, 'macarons') + + this.chart.setOption({ + tooltip: { + trigger: 'item', + formatter: '{a} <br/>{b} : {c} ({d}%)' + }, + legend: { + left: 'center', + bottom: '10', + data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts'] + }, + series: [ + { + name: 'WEEKLY WRITE ARTICLES', + type: 'pie', + roseType: 'radius', + radius: [15, 95], + center: ['50%', '38%'], + data: [ + { value: 320, name: 'Industries' }, + { value: 240, name: 'Technology' }, + { value: 149, name: 'Forex' }, + { value: 100, name: 'Gold' }, + { value: 59, name: 'Forecasts' } + ], + animationEasing: 'cubicInOut', + animationDuration: 2600 + } + ] + }) + } + } +} +</script> diff --git a/src/views/dashboard/RaddarChart.vue b/src/views/dashboard/RaddarChart.vue new file mode 100644 index 0000000..b1790ca --- /dev/null +++ b/src/views/dashboard/RaddarChart.vue @@ -0,0 +1,116 @@ +<template> + <div :class="className" :style="{height:height,width:width}" /> +</template> + +<script> +import * as echarts from 'echarts'; +require('echarts/theme/macarons') // echarts theme +import resize from './mixins/resize' + +const animationDuration = 3000 + +export default { + mixins: [resize], + props: { + className: { + type: String, + default: 'chart' + }, + width: { + type: String, + default: '100%' + }, + height: { + type: String, + default: '300px' + } + }, + data() { + return { + chart: null + } + }, + mounted() { + this.$nextTick(() => { + this.initChart() + }) + }, + beforeDestroy() { + if (!this.chart) { + return + } + this.chart.dispose() + this.chart = null + }, + methods: { + initChart() { + this.chart = echarts.init(this.$el, 'macarons') + + this.chart.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { // 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥 + type: 'shadow' // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow' + } + }, + radar: { + radius: '66%', + center: ['50%', '42%'], + splitNumber: 8, + splitArea: { + areaStyle: { + color: 'rgba(127,95,132,.3)', + opacity: 1, + shadowBlur: 45, + shadowColor: 'rgba(0,0,0,.5)', + shadowOffsetX: 0, + shadowOffsetY: 15 + } + }, + indicator: [ + { name: 'Sales', max: 10000 }, + { name: 'Administration', max: 20000 }, + { name: 'Information Techology', max: 20000 }, + { name: 'Customer Support', max: 20000 }, + { name: 'Development', max: 20000 }, + { name: 'Marketing', max: 20000 } + ] + }, + legend: { + left: 'center', + bottom: '10', + data: ['Allocated Budget', 'Expected Spending', 'Actual Spending'] + }, + series: [{ + type: 'radar', + symbolSize: 0, + areaStyle: { + normal: { + shadowBlur: 13, + shadowColor: 'rgba(0,0,0,.2)', + shadowOffsetX: 0, + shadowOffsetY: 10, + opacity: 1 + } + }, + data: [ + { + value: [5000, 7000, 12000, 11000, 15000, 14000], + name: 'Allocated Budget' + }, + { + value: [4000, 9000, 15000, 15000, 13000, 11000], + name: 'Expected Spending' + }, + { + value: [5500, 11000, 12000, 15000, 12000, 12000], + name: 'Actual Spending' + } + ], + animationDuration: animationDuration + }] + }) + } + } +} +</script> diff --git a/src/views/dashboard/mixins/resize.js b/src/views/dashboard/mixins/resize.js new file mode 100644 index 0000000..b1e76e9 --- /dev/null +++ b/src/views/dashboard/mixins/resize.js @@ -0,0 +1,56 @@ +import { debounce } from '@/utils' + +export default { + data() { + return { + $_sidebarElm: null, + $_resizeHandler: null + } + }, + mounted() { + this.initListener() + }, + activated() { + if (!this.$_resizeHandler) { + // avoid duplication init + this.initListener() + } + + // when keep-alive chart activated, auto resize + this.resize() + }, + beforeDestroy() { + this.destroyListener() + }, + deactivated() { + this.destroyListener() + }, + methods: { + // use $_ for mixins properties + // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential + $_sidebarResizeHandler(e) { + if (e.propertyName === 'width') { + this.$_resizeHandler() + } + }, + initListener() { + this.$_resizeHandler = debounce(() => { + this.resize() + }, 100) + window.addEventListener('resize', this.$_resizeHandler) + + this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0] + this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler) + }, + destroyListener() { + window.removeEventListener('resize', this.$_resizeHandler) + this.$_resizeHandler = null + + this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler) + }, + resize() { + const { chart } = this + chart && chart.resize() + } + } +} diff --git a/src/views/error/401.vue b/src/views/error/401.vue new file mode 100644 index 0000000..448b6ec --- /dev/null +++ b/src/views/error/401.vue @@ -0,0 +1,88 @@ +<template> + <div class="errPage-container"> + <el-button icon="arrow-left" class="pan-back-btn" @click="back"> + 杩斿洖 + </el-button> + <el-row> + <el-col :span="12"> + <h1 class="text-jumbo text-ginormous"> + 401閿欒! + </h1> + <h2>鎮ㄦ病鏈夎闂潈闄愶紒</h2> + <h6>瀵逛笉璧凤紝鎮ㄦ病鏈夎闂潈闄愶紝璇蜂笉瑕佽繘琛岄潪娉曟搷浣滐紒鎮ㄥ彲浠ヨ繑鍥炰富椤甸潰</h6> + <ul class="list-unstyled"> + <li class="link-type"> + <router-link to="/"> + 鍥為椤� + </router-link> + </li> + </ul> + </el-col> + <el-col :span="12"> + <img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream."> + </el-col> + </el-row> + </div> +</template> + +<script> +import errGif from '@/assets/401_images/401.gif' + +export default { + name: 'Page401', + data() { + return { + errGif: errGif + '?' + +new Date() + } + }, + methods: { + back() { + if (this.$route.query.noGoBack) { + this.$router.push({ path: '/' }) + } else { + this.$router.go(-1) + } + } + } +} +</script> + +<style lang="scss" scoped> + .errPage-container { + width: 800px; + max-width: 100%; + margin: 100px auto; + .pan-back-btn { + background: #008489; + color: #fff; + border: none!important; + } + .pan-gif { + margin: 0 auto; + display: block; + } + .pan-img { + display: block; + margin: 0 auto; + width: 100%; + } + .text-jumbo { + font-size: 60px; + font-weight: 700; + color: #484848; + } + .list-unstyled { + font-size: 14px; + li { + padding-bottom: 5px; + } + a { + color: #008489; + text-decoration: none; + &:hover { + text-decoration: underline; + } + } + } + } +</style> diff --git a/src/views/error/404.vue b/src/views/error/404.vue new file mode 100644 index 0000000..96f075c --- /dev/null +++ b/src/views/error/404.vue @@ -0,0 +1,233 @@ +<template> + <div class="wscn-http404-container"> + <div class="wscn-http404"> + <div class="pic-404"> + <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404"> + <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404"> + <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404"> + <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404"> + </div> + <div class="bullshit"> + <div class="bullshit__oops"> + 404閿欒! + </div> + <div class="bullshit__headline"> + {{ message }} + </div> + <div class="bullshit__info"> + 瀵逛笉璧凤紝鎮ㄦ鍦ㄥ鎵剧殑椤甸潰涓嶅瓨鍦ㄣ�傚皾璇曟鏌RL鐨勯敊璇紝鐒跺悗鎸夋祻瑙堝櫒涓婄殑鍒锋柊鎸夐挳鎴栧皾璇曞湪鎴戜滑鐨勫簲鐢ㄧ▼搴忎腑鎵惧埌鍏朵粬鍐呭銆� + </div> + <router-link to="/" class="bullshit__return-home"> + 杩斿洖棣栭〉 + </router-link> + </div> + </div> + </div> +</template> + +<script> + +export default { + name: 'Page404', + computed: { + message() { + return '鎵句笉鍒扮綉椤碉紒' + } + } +} +</script> + +<style lang="scss" scoped> +.wscn-http404-container{ + transform: translate(-50%,-50%); + position: absolute; + top: 40%; + left: 50%; +} +.wscn-http404 { + position: relative; + width: 1200px; + padding: 0 50px; + overflow: hidden; + .pic-404 { + position: relative; + float: left; + width: 600px; + overflow: hidden; + &__parent { + width: 100%; + } + &__child { + position: absolute; + &.left { + width: 80px; + top: 17px; + left: 220px; + opacity: 0; + animation-name: cloudLeft; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: forwards; + animation-delay: 1s; + } + &.mid { + width: 46px; + top: 10px; + left: 420px; + opacity: 0; + animation-name: cloudMid; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: forwards; + animation-delay: 1.2s; + } + &.right { + width: 62px; + top: 100px; + left: 500px; + opacity: 0; + animation-name: cloudRight; + animation-duration: 2s; + animation-timing-function: linear; + animation-fill-mode: forwards; + animation-delay: 1s; + } + @keyframes cloudLeft { + 0% { + top: 17px; + left: 220px; + opacity: 0; + } + 20% { + top: 33px; + left: 188px; + opacity: 1; + } + 80% { + top: 81px; + left: 92px; + opacity: 1; + } + 100% { + top: 97px; + left: 60px; + opacity: 0; + } + } + @keyframes cloudMid { + 0% { + top: 10px; + left: 420px; + opacity: 0; + } + 20% { + top: 40px; + left: 360px; + opacity: 1; + } + 70% { + top: 130px; + left: 180px; + opacity: 1; + } + 100% { + top: 160px; + left: 120px; + opacity: 0; + } + } + @keyframes cloudRight { + 0% { + top: 100px; + left: 500px; + opacity: 0; + } + 20% { + top: 120px; + left: 460px; + opacity: 1; + } + 80% { + top: 180px; + left: 340px; + opacity: 1; + } + 100% { + top: 200px; + left: 300px; + opacity: 0; + } + } + } + } + .bullshit { + position: relative; + float: left; + width: 300px; + padding: 30px 0; + overflow: hidden; + &__oops { + font-size: 32px; + font-weight: bold; + line-height: 40px; + color: #1482f0; + opacity: 0; + margin-bottom: 20px; + animation-name: slideUp; + animation-duration: 0.5s; + animation-fill-mode: forwards; + } + &__headline { + font-size: 20px; + line-height: 24px; + color: #222; + font-weight: bold; + opacity: 0; + margin-bottom: 10px; + animation-name: slideUp; + animation-duration: 0.5s; + animation-delay: 0.1s; + animation-fill-mode: forwards; + } + &__info { + font-size: 13px; + line-height: 21px; + color: grey; + opacity: 0; + margin-bottom: 30px; + animation-name: slideUp; + animation-duration: 0.5s; + animation-delay: 0.2s; + animation-fill-mode: forwards; + } + &__return-home { + display: block; + float: left; + width: 110px; + height: 36px; + background: #1482f0; + border-radius: 100px; + text-align: center; + color: #ffffff; + opacity: 0; + font-size: 14px; + line-height: 36px; + cursor: pointer; + animation-name: slideUp; + animation-duration: 0.5s; + animation-delay: 0.3s; + animation-fill-mode: forwards; + } + @keyframes slideUp { + 0% { + transform: translateY(60px); + opacity: 0; + } + 100% { + transform: translateY(0); + opacity: 1; + } + } + } +} +</style> diff --git a/src/views/index.vue b/src/views/index.vue new file mode 100644 index 0000000..442f054 --- /dev/null +++ b/src/views/index.vue @@ -0,0 +1,897 @@ +<template> + <div class="app-container home"> + <el-row :gutter="20"> + </el-row> + <el-row :gutter="20"> + <el-col :sm="24" :lg="12" style="padding-left: 20px"> + <h2>鏁板瓧鍖栧悗鍙扮鐞嗙鐞嗙郴缁�</h2> + <p> + 鏁板瓧鍖栧悗鍙扮鐞嗙郴缁燂紝鏄竴濂楁暟瀛楀寲绠$悊鏁版嵁璧勪骇鍙婄郴缁熻繍缁寸殑鍚庡彴绯荤粺銆傜郴缁熶娇鐢ㄤ簡鍏堣繘鐨勬妧鏈灦鏋勶紝閫氳繃Web娴忚鍣ㄨ闂郴缁燂紝绯荤粺鐢辩郴缁熺鐞嗐�佺郴缁熺洃鎺т袱澶ф牳蹇冩ā鍧楃粍鎴愶紝杈呬互鏁板瓧鍖栬祫浜х殑淇℃伅绠$悊缁存姢锛屾槸涓�涓鐢ㄩ�斿缁村害鐨勫悗鍙扮鐞嗙郴缁熴�傜畝鍗曞鏄撲笂鎵嬶紝鍑洪敊姒傜巼浣庛�傚悗缁郴缁熶細闄嗙画鏇存柊涓�浜涘疄鐢ㄥ姛鑳姐�� + </p> + <p> + <b>褰撳墠鐗堟湰:</b> <span>v{{ version }}</span> + </p> + </el-col> + </el-row> + <el-divider /> + <el-row :gutter="20"> + <el-col :xs="24" :sm="24" :md="12" :lg="8"> + <el-card class="update-log"> + <div slot="header" class="clearfix"> + <span>鑱旂郴淇℃伅</span> + </div> + <div class="body"> + <p> + <i class="el-icon-s-promotion"></i> 瀹樼綉锛�<el-link + href="http://www.xxx.com" + target="_blank" + >http://www.xxx.com</el-link + > + </p> + </div> + </el-card> + </el-col> + <el-col :xs="24" :sm="24" :md="12" :lg="8"> + <el-card class="update-log"> + <div slot="header" class="clearfix"> + <span>鏇存柊鏃ュ織</span> + </div> + <el-collapse accordion> + <el-collapse-item title="v3.8.6 - 2023-06-30"> + <ol> + <li>鏀寔鐧诲綍IP榛戝悕鍗曢檺鍒�</li> + <li>鏂板鐩戞帶椤甸潰鍥炬爣鏄剧ず</li> + <li>鎿嶄綔鏃ュ織鏂板娑堣�楁椂闂村睘鎬�</li> + <li>灞忚斀瀹氭椂浠诲姟bean杩濊鐨勫瓧绗�</li> + <li>鏃ュ織绠$悊浣跨敤绱㈠紩鎻愬崌鏌ヨ鎬ц兘</li> + <li>鏃ュ織娉ㄨВ鏀寔鎺掗櫎鎸囧畾鐨勮姹傚弬鏁�</li> + <li>鏀寔鑷畾涔夐殣钘忓睘鎬у垪杩囨护瀛愬璞�</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈�6.4.3</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈�1.2.16</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増2.0.34</li> + <li>鍗囩骇spring-boot鍒版渶鏂扮増鏈�2.5.15</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.13</li> + <li>绉婚櫎apache/commons-fileupload渚濊禆</li> + <li>淇椤甸潰鍒囨崲鏃跺竷灞�閿欎贡鐨勯棶棰�</li> + <li>淇鍖垮悕娉ㄨВAnonymous绌烘寚閽堥棶棰�</li> + <li>淇璺敱璺宠浆琚樆姝㈡椂鍐呴儴浜х敓鎶ラ敊淇℃伅闂</li> + <li>淇isMatchedIp鐨勫弬鏁板垽鏂骇鐢熺┖鎸囬拡鐨勯棶棰�</li> + <li>淇鐢ㄦ埛澶氳鑹叉暟鎹潈闄愬彲鑳藉嚭鐜版潈闄愭姮鍗囩殑鎯呭喌</li> + <li>淇寮�鍚疶opNav鍚庝竴绾ц彍鍗曡矾鐢卞弬鏁拌缃棤鏁堥棶棰�</li> + <li>淇DictTag缁勪欢value娌℃湁鍖归厤鐨勫�兼椂鍒欏睍绀簐alue</li> + <li>浼樺寲鏂囦欢涓嬭浇鍑虹幇鐨勫紓甯�</li> + <li>浼樺寲閫夋嫨鍥炬爣缁勪欢楂樹寒鍥炴樉</li> + <li>浼樺寲寮圭獥鍚庡鑸爮鍋忕Щ鐨勯棶棰�</li> + <li>浼樺寲淇敼瀵嗙爜鏃ュ織瀛樺偍鏄庢枃闂</li> + <li>浼樺寲椤电鏍忓叧闂叾浠栧嚭鐜扮殑寮傚父闂</li> + <li>浼樺寲椤电鍏抽棴宸︿晶閫夐」鎺掗櫎棣栭〉閫夐」</li> + <li>浼樺寲鍏抽棴褰撳墠tab椤佃烦杞渶鍙充晶tab椤�</li> + <li>浼樺寲缂撳瓨鍒楄〃娓呴櫎鎿嶄綔鎻愮ず涓嶅彉鐨勯棶棰�</li> + <li>浼樺寲瀛楃鏈娇鐢ㄤ笅鍒掔嚎涓嶈繘琛岄┘宄板紡澶勭悊</li> + <li>浼樺寲鐢ㄦ埛瀵煎叆鏇存柊鏃堕渶鑾峰彇鐢ㄦ埛缂栧彿闂</li> + <li>浼樺寲渚ц竟鏍忕殑骞冲彴鏍囬涓嶸UE_APP_TITLE淇濇寔鍚屾</li> + <li>浼樺寲瀵煎嚭Excel鏃惰缃甦ictType灞炴�ч噸澶嶆煡缂撳瓨闂</li> + <li>杩炴帴姹燚ruid鏀寔鏂扮殑閰嶇疆connectTimeout鍜宻ocketTimeout</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.5 - 2023-01-01"> + <ol> + <li>瀹氭椂浠诲姟杩濊鐨勫瓧绗�</li> + <li>閲嶇疆鏃跺彇娑堥儴闂ㄩ�変腑</li> + <li>鏂板杩斿洖璀﹀憡娑堟伅鎻愮ず</li> + <li>蹇界暐涓嶅繀瑕佺殑灞炴�ф暟鎹繑鍥�</li> + <li>淇敼鍙傛暟閿悕鏃剁Щ闄ゅ墠缂撳瓨閰嶇疆</li> + <li>瀵煎叆鏇存柊鐢ㄦ埛鏁版嵁鍓嶆牎楠屾暟鎹潈闄�</li> + <li>鍏煎Excel涓嬫媺妗嗗唴瀹硅繃澶氭棤娉曟樉绀虹殑闂</li> + <li>鍗囩骇echarts鍒版渶鏂扮増鏈�5.4.0</li> + <li>鍗囩骇core-js鍒版渶鏂扮増鏈�3.25.3</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈�6.4.0</li> + <li>鍗囩骇kaptcha鍒版渶鏂扮増2.3.3</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈�1.2.15</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増2.0.20</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.4.6</li> + <li>浼樺寲寮圭獥鍐呭杩囧灞曠ず涓嶅叏闂</li> + <li>浼樺寲swagger-ui闈欐�佽祫婧愪娇鐢ㄧ紦瀛�</li> + <li>寮�鍚疶opNav娌℃湁瀛愯彍鍗曢殣钘忎晶杈规爮</li> + <li>鍒犻櫎fuse鏃犳晥閫夐」maxPatternLength</li> + <li>浼樺寲瀵煎嚭瀵硅薄鐨勫瓙鍒楄〃涓虹┖浼氬嚭鐜癧]闂</li> + <li>浼樺寲缂栬緫澶村儚鏃堕�忔槑閮ㄥ垎浼氬彉鎴愰粦鑹查棶棰�</li> + <li>浼樺寲灏忓睆骞曚笂淇敼澶村儚鐣岄潰甯冨眬閿欎綅鐨勯棶棰�</li> + <li>淇浠g爜鐢熸垚鍕鹃�夊睘鎬ф棤鏁堥棶棰�</li> + <li>淇鏂囦欢涓婁紶缁勪欢鏍煎紡楠岃瘉闂</li> + <li>淇鍥炴樉鏁版嵁瀛楀吀鏁扮粍寮傚父闂</li> + <li>淇sheet瓒呭嚭鏈�澶ц鏁板紓甯搁棶棰�</li> + <li>淇Log娉ㄨВGET璇锋眰璁板綍涓嶅埌鍙傛暟闂</li> + <li>淇璋冨害鏃ュ織鐐瑰嚮澶氭鏁版嵁涓嶅彉鍖栫殑闂</li> + <li>淇涓婚棰滆壊鍦―rawer缁勪欢涓嶄細鍔犺浇闂</li> + <li>淇鏂囦欢鍚嶅寘鍚壒娈婂瓧绗︾殑鏂囦欢鏃犳硶涓嬭浇闂</li> + <li>淇table涓洿澶氭寜閽垏鎹富棰樿壊鏈敓鏁堜慨澶嶉棶棰�</li> + <li>淇鏌愪簺鐗规�х殑鐜鐢熸垚浠g爜鍙樹贡鐮乀XT鏂囦欢闂</li> + <li>淇浠g爜鐢熸垚鍥剧墖/鏂囦欢/鍗曢�夋椂閫夋嫨蹇呭~鏃犳硶鏍¢獙闂</li> + <li>淇鏌愪簺鐗规�х殑鎯呭喌鐢ㄦ埛缂栬緫瀵硅瘽妗嗕腑瑙掕壊鍜岄儴闂ㄦ棤娉曚慨鏀归棶棰�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.4 - 2022-09-26"> + <ol> + <li>鏁版嵁閫昏緫鍒犻櫎涓嶈繘琛屽敮涓�楠岃瘉</li> + <li>Excel娉ㄨВ鏀寔瀵煎嚭瀵硅薄鐨勫瓙鍒楄〃鏂规硶</li> + <li>Excel娉ㄨВ鏀寔鑷畾涔夐殣钘忓睘鎬у垪</li> + <li>Excel娉ㄨВ鏀寔backgroundColor灞炴�ц缃儗鏅壊</li> + <li>鏀寔閰嶇疆瀵嗙爜鏈�澶ч敊璇鏁�/閿佸畾鏃堕棿</li> + <li>鐧诲綍鏃ュ織鏂板瑙i攣璐︽埛鍔熻兘</li> + <li>閫氱敤涓嬭浇鏂规硶鏂板config閰嶇疆閫夐」</li> + <li>鏀寔澶氭潈闄愬瓧绗﹀尮閰嶈鑹叉暟鎹潈闄�</li> + <li>椤甸潰鍐呭祵iframe鍒囨崲tab涓嶅埛鏂版暟鎹�</li> + <li>鎿嶄綔鏃ュ織璁板綍鏀寔鎺掗櫎鏁忔劅灞炴�у瓧娈�</li> + <li>淇澶氭枃浠朵笂浼犳姤閿欏嚭鐜扮殑寮傚父闂</li> + <li>淇鍥剧墖棰勮缁勪欢src灞炴�т负null鍊兼帶鍒跺彴鎶ラ敊闂</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈�6.2.2</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増2.0.14</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.4.3</li> + <li>鍗囩骇core-js鍒版渶鏂扮増鏈�3.25.2</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.10</li> + <li>浼樺寲浠诲姟杩囨湡涓嶆墽琛岃皟搴�</li> + <li>浼樺寲瀛楀吀鏁版嵁浣跨敤store瀛樺彇</li> + <li>浼樺寲淇敼璧勬枡澶村儚琚鐩栫殑闂</li> + <li>浼樺寲淇敼鐢ㄦ埛鐧诲綍璐﹀彿閲嶅楠岃瘉</li> + <li>浼樺寲浠g爜鐢熸垚鍚屾鍚庡�糔ULL闂</li> + <li>浼樺寲瀹氭椂浠诲姟鏀寔鎵ц鐖剁被鏂规硶</li> + <li>浼樺寲鐢ㄦ埛涓汉淇℃伅鎺ュ彛闃叉淇敼閮ㄩ棬</li> + <li>浼樺寲甯冨眬璁剧疆浣跨敤el-drawer鎶藉眽鏄剧ず</li> + <li>浼樺寲娌℃湁鏉冮檺鐨勭敤鎴风紪杈戦儴闂ㄧ己灏戞暟鎹�</li> + <li>浼樺寲鏃ュ織娉ㄨВ璁板綍闄愬埗璇锋眰鍦板潃鐨勯暱搴�</li> + <li>浼樺寲excel/scale灞炴�у鍑哄崟鍏冩牸鏁板�肩被鍨�</li> + <li>浼樺寲鏃ュ織鎿嶄綔涓噸缃寜閽椂閲嶅鏌ヨ鐨勯棶棰�</li> + <li>浼樺寲澶氫釜鐩稿悓瑙掕壊鏁版嵁瀵艰嚧鏉冮檺SQL閲嶅闂</li> + <li>浼樺寲琛ㄦ牸涓婂彸渚у伐鍏锋潯锛堟悳绱㈡寜閽樉闅�&鍙充晶鏍峰紡鍑稿嚭锛�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.3 - 2022-06-27"> + <ol> + <li>鏂板缂撳瓨鍒楄〃鑿滃崟鍔熻兘</li> + <li>浠g爜鐢熸垚鏍戣〃鏂板(灞曞紑/鎶樺彔)</li> + <li>Excel娉ㄨВ鏀寔color瀛椾綋棰滆壊</li> + <li>鏂板Anonymous鍖垮悕璁块棶涓嶉壌鏉冩敞瑙�</li> + <li>鐢ㄦ埛澶村儚涓婁紶闄愬埗鍙兘涓哄浘鐗囨牸寮�</li> + <li>鎺ュ彛浣跨敤娉涘瀷浣垮叾鐪嬪埌鍝嶅簲灞炴�у瓧娈�</li> + <li>妫�鏌ュ畾鏃朵换鍔ean鎵�鍦ㄥ寘鍚嶆槸鍚︿负鐧藉悕鍗曢厤缃�</li> + <li>娣诲姞椤电openPage鏀寔浼犻�掑弬鏁�</li> + <li>鐢ㄦ埛缂撳瓨淇℃伅娣诲姞閮ㄩ棬ancestors绁栫骇鍒楄〃</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.8</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈�6.1.6</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈�1.2.11</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増2.0.8</li> + <li>鍗囩骇spring-boot鍒版渶鏂扮増鏈�2.5.14</li> + <li>闄嶇骇jsencrypt鐗堟湰鍏煎IE娴忚鍣�</li> + <li>鍒犻櫎澶氫綑鐨剆alt瀛楁</li> + <li>鏂板鑾峰彇涓嶅甫鍚庣紑鏂囦欢鍚嶇О鏂规硶</li> + <li>鏂板鑾峰彇閰嶇疆鏂囦欢涓殑灞炴�у�兼柟娉�</li> + <li>鏂板鍐呭缂栫爜/瑙g爜鏂逛究鎻掍欢闆嗘垚浣跨敤</li> + <li>瀛楀吀绫诲瀷蹇呴』浠ュ瓧姣嶅紑澶达紝涓斿彧鑳戒负锛堝皬鍐欏瓧姣嶏紝鏁板瓧锛屼笅婊戠嚎锛�</li> + <li>浼樺寲璁剧疆鍒嗛〉鍙傛暟榛樿鍊�</li> + <li>浼樺寲瀵圭┖瀛楃涓插弬鏁板鐞嗙殑杩囨护</li> + <li>浼樺寲鏄剧ず椤哄簭orderNum绫诲瀷涓烘暣鍨�</li> + <li>浼樺寲琛ㄥ崟鏋勫缓鎸夐挳涓嶆樉绀烘鍒欐牎楠�</li> + <li>浼樺寲瀛楀吀鏁版嵁鍥炴樉鏍峰紡涓嬫媺妗嗘樉绀哄��</li> + <li>浼樺寲R鍝嶅簲鎴愬姛鐘舵�佺爜涓庡叏灞�淇濇寔涓�鑷�</li> + <li>浼樺寲druid寮�鍚痺all杩囨护鍣ㄥ嚭鐜扮殑寮傚父闂</li> + <li>浼樺寲鐢ㄦ埛绠$悊宸︿晶鏍戝瀷缁勪欢澧炲姞閫変腑楂樹寒淇濇寔</li> + <li>浼樺寲鏂板鐢ㄦ埛涓庤鑹蹭俊鎭�&鐢ㄦ埛涓庡矖浣嶄俊鎭�昏緫</li> + <li>浼樺寲榛樿涓嶅惎鐢ㄥ帇缂╂枃浠剁紦瀛橀槻姝ode_modules杩囧ぇ</li> + <li>淇瀛楀吀鏁版嵁鏄剧ず涓嶅叏闂</li> + <li>淇鎿嶄綔鏃ュ織鏌ヨ绫诲瀷鏉′欢涓�0鏃朵細鏌ュ埌鎵�鏈夋暟鎹�</li> + <li>淇Excel娉ㄨВprompt/combo鍚屾椂浣跨敤涓嶇敓鏁堥棶棰�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.2 - 2022-04-01"> + <ol> + <li>鍓嶇鏀寔璁剧疆鏄惁闇�瑕侀槻姝㈡暟鎹噸澶嶆彁浜�</li> + <li>寮�鍚疶opNav娌℃湁瀛愯彍鍗曟儏鍐甸殣钘忎晶杈规爮</li> + <li>渚ц竟鏍忚彍鍗曞悕绉拌繃闀挎偓鍋滄樉绀烘爣棰�</li> + <li>鐢ㄦ埛璁块棶鎺у埗鏃舵牎楠屾暟鎹潈闄愶紝闃叉瓒婃潈</li> + <li>瀵煎嚭Excel鏃跺睆钄藉叕寮忥紝闃叉CSV娉ㄥ叆椋庨櫓</li> + <li>缁勪欢ImagePreview鏀寔澶氬浘棰勮鏄剧ず</li> + <li>缁勪欢ImageUpload鏀寔澶氬浘鍚屾椂閫夋嫨涓婁紶</li> + <li>缁勪欢FileUpload鏀寔澶氭枃浠跺悓鏃堕�夋嫨涓婁紶</li> + <li>鏈嶅姟鐩戞帶鏂板杩愯鍙傛暟淇℃伅鏄剧ず</li> + <li>瀹氭椂浠诲姟鐩爣瀛楃涓茶繃婊ょ壒娈婂瓧绗�</li> + <li>瀹氭椂浠诲姟鐩爣瀛楃涓查獙璇佸寘鍚嶇櫧鍚嶅崟</li> + <li>浠g爜鐢熸垚鍒楄〃鍥剧墖鏀寔棰勮</li> + <li>浠g爜鐢熸垚缂栬緫淇敼鎵撳紑鏂伴〉绛�</li> + <li>浠g爜鐢熸垚鏂板Java绫诲瀷Boolean</li> + <li>浠g爜鐢熸垚瀛愯〃鏀寔鏃ユ湡/瀛楀吀閰嶇疆</li> + <li>浠g爜鐢熸垚鍚屾淇濈暀蹇呭~/绫诲瀷閫夐」</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈�6.1.2</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.80</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.4.1</li> + <li>鍗囩骇spring-boot鍒版渶鏂扮増鏈�2.5.11</li> + <li>鍗囩骇spring-boot-mybatis鍒版渶鏂扮増2.2.2</li> + <li>娣诲姞閬楁紡鐨勫垎椤靛弬鏁板悎鐞嗗寲灞炴��</li> + <li>淇敼npm鍗冲皢杩囨湡鐨勬敞鍐屾簮鍦板潃</li> + <li>淇鍒嗛〉缁勪欢璇锋眰涓ゆ闂</li> + <li>淇閫氱敤鏂囦欢涓嬭浇鎺ュ彛璺ㄥ煙闂</li> + <li>淇Xss娉ㄨВ瀛楁鍊间负绌烘椂鐨勫紓甯搁棶棰�</li> + <li>淇閫夐」鍗$偣鍑诲彸閿埛鏂颁涪澶卞弬鏁伴棶棰�</li> + <li>淇琛ㄥ崟娓呴櫎鍏冪礌浣嶇疆鏈瀭鐩村眳涓棶棰�</li> + <li>淇鏈嶅姟鐩戞帶涓繍琛屽弬鏁版樉绀烘潯浠堕敊璇�</li> + <li>淇瀵煎叆Excel鏃跺瓧鍏稿瓧娈电被鍨嬩负Long杞箟涓虹┖闂</li> + <li>淇鐧诲綍瓒呮椂鍒锋柊椤甸潰璺宠浆鐧诲綍椤甸潰杩樻彁绀洪噸鏂扮櫥褰曢棶棰�</li> + <li>浼樺寲鍔犺浇瀛楀吀缂撳瓨鏁版嵁</li> + <li>浼樺寲IP鍦板潃鑾峰彇鍒板涓殑闂</li> + <li>浼樺寲浠诲姟闃熷垪婊℃椂浠诲姟鎷掔粷绛栫暐</li> + <li>浼樺寲鏂囦欢涓婁紶鍏煎Weblogic鐜</li> + <li>浼樺寲瀹氭椂浠诲姟榛樿淇濆瓨鍒板唴瀛樹腑鎵ц</li> + <li>浼樺寲閮ㄩ棬淇敼缂╂斁鍚庡嚭鐜扮殑閿欎綅闂</li> + <li>浼樺寲Excel鏍煎紡鍖栦笉鍚岀被鍨嬬殑鏃ユ湡瀵硅薄</li> + <li>浼樺寲鑿滃崟琛ㄥ叧閿瓧瀵艰嚧鐨勬彃浠舵姤閿欓棶棰�</li> + <li>浼樺寲Oracle鐢ㄦ埛澶村儚鍒椾负绌烘椂涓嶆樉绀洪棶棰�</li> + <li>浼樺寲椤甸潰鑻ユ湭鍖归厤鍒板瓧鍏告爣绛惧垯杩斿洖鍘熷瓧鍏稿��</li> + <li>浼樺寲淇鐧诲綍澶辨晥鍚庡娆¤姹傛彁绀哄娆″脊绐楅棶棰�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.1 - 2022-01-01"> + <ol> + <li>鏂板Vue3鍓嶇浠g爜鐢熸垚妯℃澘</li> + <li>鏂板鍥剧墖棰勮缁勪欢</li> + <li>鏂板鍘嬬缉鎻掍欢瀹炵幇鎵撳寘Gzip</li> + <li>鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇</li> + <li>鑷畾涔夋枃瀛楀鍒跺壀璐存寚浠�</li> + <li>浠g爜鐢熸垚棰勮鏀寔澶嶅埗鍐呭</li> + <li>璺敱鏀寔鍗曠嫭閰嶇疆鑿滃崟鎴栬鑹叉潈闄�</li> + <li>鐢ㄦ埛绠$悊閮ㄩ棬鏌ヨ閫夋嫨鑺傜偣鍚庡垎椤靛弬鏁板垵濮�</li> + <li>淇鐢ㄦ埛鍒嗛厤瑙掕壊灞炴�ч敊璇�</li> + <li>淇鎵撳寘鍚庡瓧浣撳浘鏍囧伓鐜扮殑涔辩爜闂</li> + <li>淇鑿滃崟绠$悊閲嶇疆琛ㄥ崟鍑虹幇鐨勯敊璇�</li> + <li>淇鐗堟湰宸紓瀵艰嚧鐨勬噿鍔犺浇鎶ラ敊闂</li> + <li>淇Cron缁勪欢涓懆鍥炴樉闂</li> + <li>淇瀹氭椂浠诲姟澶氬弬鏁伴�楀彿鍒嗛殧鐨勯棶棰�</li> + <li>淇鏍规嵁ID鏌ヨ鍒楄〃鍙兘鍑虹幇鐨勪富閿孩鍑洪棶棰�</li> + <li>淇tomcat閰嶇疆鍙傛暟宸茶繃鏈熼棶棰�</li> + <li>鍗囩骇clipboard鍒版渶鏂扮増鏈�2.0.8</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.8.6</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.79</li> + <li>鍗囩骇spring-boot鍒版渶鏂扮増鏈�2.5.8</li> + <li>鍗囩骇log4j2鍒�2.17.1锛岄槻姝㈡紡娲為闄�</li> + <li>浼樺寲涓嬭浇瑙f瀽blob寮傚父鎻愮ず</li> + <li>浼樺寲浠g爜鐢熸垚瀛楀吀缁勯噸澶嶉棶棰�</li> + <li>浼樺寲鏌ヨ鐢ㄦ埛鐨勮鑹茬粍&宀椾綅缁勪唬鐮�</li> + <li>浼樺寲瀹氭椂浠诲姟cron琛ㄨ揪寮忓皬鏃惰缃�24</li> + <li>浼樺寲鐢ㄦ埛瀵煎叆鎻愮ず婧㈠嚭鍒欐樉绀烘粴鍔ㄦ潯</li> + <li>浼樺寲闃查噸澶嶆彁浜ゆ爣璇嗙粍鍚堜负(key+url+header)</li> + <li>浼樺寲鍒嗛〉鏂规硶璁剧疆鎴愰�氱敤鏂逛究鐏垫椿璋冪敤</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.8.0 - 2021-12-01"> + <ol> + <li>鏂板閰嶅骞跺悓姝ョ殑Vue3鍓嶇鐗堟湰</li> + <li>鏂板閫氱敤鏂规硶绠�鍖栨ā鎬�/缂撳瓨/涓嬭浇/鏉冮檺/椤电浣跨敤</li> + <li>浼樺寲瀵煎嚭鏁版嵁/浣跨敤閫氱敤涓嬭浇鏂规硶</li> + <li>Excel娉ㄨВ鏀寔鑷畾涔夋暟鎹鐞嗗櫒</li> + <li>Excel娉ㄨВ鏀寔瀵煎叆瀵煎嚭鏍囬淇℃伅</li> + <li>Excel瀵煎叆鏀寔@Excels娉ㄨВ</li> + <li>鏂板缁勪欢data-dict锛岀畝鍖栨暟鎹瓧鍏镐娇鐢�</li> + <li>鏂板Jaxb渚濊禆锛岄槻姝dk8浠ヤ笂鍑虹幇鐨勫吋瀹归敊璇�</li> + <li>鐢熶骇鐜浣跨敤璺敱鎳掑姞杞芥彁鍗囬〉闈㈠搷搴旈�熷害</li> + <li>淇浜旂骇浠ヤ笂鑿滃崟鍑虹幇鐨�404闂</li> + <li>闃查噸鎻愪氦娉ㄨВ鏀寔閰嶇疆闂撮殧鏃堕棿/鎻愮ず娑堟伅</li> + <li>鏃ュ織娉ㄨВ鏂板鏄惁淇濆瓨鍝嶅簲鍙傛暟</li> + <li>浠诲姟灞忚斀杩濊瀛楃&鍙傛暟蹇界暐鍙屽紩鍙蜂腑鐨勯�楀彿</li> + <li>鍗囩骇SpringBoot鍒版渶鏂扮増鏈�2.5.6</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.4.0</li> + <li>鍗囩骇spring-boot-mybatis鍒版渶鏂扮増2.2.0</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.8.2</li> + <li>鍗囩骇druid鍒版渶鏂扮増1.2.8</li> + <li>鍗囩骇velocity鍒版渶鏂扮増鏈�2.3</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.78</li> + <li>鍗囩骇axios鍒版渶鏂扮増鏈�0.24.0</li> + <li>鍗囩骇dart-sass鍒扮増鏈�1.32.13</li> + <li>鍗囩骇core-js鍒版渶鏂扮増鏈�3.19.1</li> + <li>鍗囩骇jsencrypt鍒版渶鏂扮増鏈�3.2.1</li> + <li>鍗囩骇js-cookie鍒版渶鏂扮増鏈�3.0.1</li> + <li>鍗囩骇file-saver鍒版渶鏂扮増鏈�2.0.5</li> + <li>鍗囩骇sass-loader鍒版渶鏂扮増鏈�10.1.1</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.6</li> + <li>鏂板sendGet鏃犲弬璇锋眰鏂规硶</li> + <li>绂佺敤el-tag缁勪欢鐨勬笎鍙樺姩鐢�</li> + <li>浠g爜鐢熸垚鐐瑰嚮棰勮閲嶇疆婵�娲籺ab</li> + <li>AjaxResult閲嶅啓put鏂规硶锛屼互鏂逛究閾惧紡璋冪敤</li> + <li>浼樺寲鐧诲綍/楠岃瘉鐮佽姹俬eaders涓嶈缃畉oken</li> + <li>浼樺寲鐢ㄦ埛涓汉淇℃伅鎺ュ彛闃叉淇敼鐢ㄦ埛鍚�</li> + <li>浼樺寲Cron琛ㄨ揪寮忕敓鎴愬櫒鍏抽棴鏃堕攢姣侀伩鍏嶇紦瀛�</li> + <li>浼樺寲娉ㄥ唽鎴愬姛鎻愮ず娑堟伅绫诲瀷success</li> + <li>浼樺寲aop璇硶锛屼娇鐢╯pring鑷姩娉ㄥ叆娉ㄨВ</li> + <li>浼樺寲璁板綍鐧诲綍淇℃伅锛岀Щ闄や笉蹇呰鐨勪慨鏀�</li> + <li>浼樺寲mybatis鍏ㄥ眬榛樿鐨勬墽琛屽櫒</li> + <li>浼樺寲Excel瀵煎叆鍥剧墖鍙兘鍑虹幇鐨勫紓甯�</li> + <li>淇浠g爜鐢熸垚妯℃澘涓诲瓙琛ㄥ垹闄ょ己灏戜簨鍔�</li> + <li>淇鏃ュ織璁板綍鍙兘鍑虹幇鐨勮浆鎹㈠紓甯�</li> + <li>淇浠g爜鐢熸垚澶嶉�夋瀛楀吀閬楁紡闂</li> + <li>淇鍏抽棴xss鍔熻兘瀵艰嚧鍙噸澶嶈RepeatableFilter澶辨晥</li> + <li>淇瀛楃涓叉棤娉曡鍙嶈浆涔夐棶棰�</li> + <li>淇鍚庣涓诲瓙琛ㄤ唬鐮佹ā鏉挎柟娉曞悕鐢熸垚閿欒闂</li> + <li>淇xss杩囨护鍚庢牸寮忓嚭鐜扮殑寮傚父</li> + <li>淇swagger娌℃湁鎸囧畾dataTypeClass瀵艰嚧鍚姩鍑虹幇warn鏃ュ織</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.7.0 - 2021-09-13"> + <ol> + <li>鍙傛暟绠$悊鏀寔閰嶇疆楠岃瘉鐮佸紑鍏�</li> + <li>鏂板鏄惁寮�鍚敤鎴锋敞鍐屽姛鑳�</li> + <li>瀹氭椂浠诲姟鏀寔鍦ㄧ嚎鐢熸垚cron琛ㄨ揪寮�</li> + <li>鑿滃崟绠$悊鏀寔閰嶇疆璺敱鍙傛暟</li> + <li>鏀寔鑷畾涔夋敞瑙e疄鐜版帴鍙i檺娴�</li> + <li>Excel娉ㄨВ鏀寔Image鍥剧墖瀵煎叆</li> + <li>鑷畾涔夊脊灞傛孩鍑烘粴鍔ㄦ牱寮�</li> + <li>鑷畾涔夊彲鎷栧姩寮圭獥瀹藉害鎸囦护</li> + <li>鑷畾涔夊彲鎷栧姩寮圭獥楂樺害鎸囦护</li> + <li>淇浠绘剰璐︽埛瓒婃潈闂</li> + <li>淇敼鏃舵鏌ョ敤鎴锋暟鎹潈闄愯寖鍥�</li> + <li>淇淇濆瓨閰嶇疆涓婚棰滆壊澶辨晥闂</li> + <li>鏂板鏆楄壊鑿滃崟椋庢牸涓婚</li> + <li>鑿滃崟&閮ㄩ棬鏂板灞曞紑/鎶樺彔鍔熻兘</li> + <li>椤电鏂板鍏抽棴宸︿晶&娣诲姞鍥炬爣</li> + <li>椤堕儴鑿滃崟鎺掗櫎闅愯棌鐨勯粯璁よ矾鐢�</li> + <li>椤堕儴鑿滃崟鍚屾绯荤粺涓婚鏍峰紡</li> + <li>璺宠浆璺敱楂樹寒鐩稿搴旂殑鑿滃崟鏍�</li> + <li>浠g爜鐢熸垚涓诲瓙琛ㄥ閫夎鏁版嵁</li> + <li>鏃ユ湡鑼冨洿鏀寔娣诲姞澶氱粍</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.5</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.8.0</li> + <li>鍗囩骇commons.io鍒版渶鏂扮増鏈瑅2.11.0</li> + <li>瀹氭椂浠诲姟灞忚斀ldap杩滅▼璋冪敤</li> + <li>瀹氭椂浠诲姟灞忚斀http(s)杩滅▼璋冪敤</li> + <li>琛ュ厖瀹氭椂浠诲姟琛ㄥ瓧娈垫敞閲�</li> + <li>瀹氭椂浠诲姟瀵规鏌ュ紓甯歌繘琛屼簨鍔″洖婊�</li> + <li>鍚敤鐖堕儴闂ㄧ姸鎬佹帓闄ら《绾ц妭鐐�</li> + <li>瀵屾枃鏈柊澧炰笂浼犳枃浠跺ぇ灏忛檺鍒�</li> + <li>榛樿棣栭〉浣跨敤keep-alive缂撳瓨</li> + <li>淇敼浠g爜鐢熸垚瀛楀吀鍥炴樉鏍峰紡</li> + <li>鑷畾涔夊垎椤靛悎鐞嗗寲浼犲叆鍙傛暟</li> + <li>淇瀛楀吀缁勪欢鍊间负鏁村舰涓嶆樉绀洪棶棰�</li> + <li>淇瀹氭椂浠诲姟鏃ュ織鎵ц鐘舵�佹樉绀�</li> + <li>瑙掕壊&鑿滃崟鏂板瀛楁灞炴�ф彁绀轰俊鎭�</li> + <li>淇瑙掕壊鍒嗛厤鐢ㄦ埛椤甸潰鍙傛暟绫诲瀷閿欒鎻愰啋</li> + <li>浼樺寲甯冨眬璁剧疆鍔ㄧ敾鐗规晥</li> + <li>浼樺寲寮傚父澶勭悊淇℃伅</li> + <li>浼樺寲閿欒token瀵艰嚧鐨勮В鏋愬紓甯�</li> + <li>瀵嗙爜妗嗘柊澧炴樉绀哄垏鎹㈠瘑鐮佸浘鏍�</li> + <li>瀹氭椂浠诲姟鏂板鏇村鎿嶄綔</li> + <li>鏇村鎿嶄綔鎸夐挳娣诲姞鏉冮檺鎺у埗</li> + <li>瀵煎叆鐢ㄦ埛鏍峰紡浼樺寲</li> + <li>鎻愬彇閫氱敤鏂规硶鍒板熀绫绘帶鍒跺櫒</li> + <li>浼樺寲浣跨敤鏉冮檺宸ュ叿鑾峰彇鐢ㄦ埛淇℃伅</li> + <li>浼樺寲鐢ㄦ埛涓嶈兘鍒犻櫎鑷繁</li> + <li>浼樺寲XSS璺ㄧ珯鑴氭湰杩囨护</li> + <li>浼樺寲浠g爜鐢熸垚妯℃澘</li> + <li>楠岃瘉鐮侀粯璁�20s瓒呮椂</li> + <li>BLOB涓嬭浇鏃舵竻闄RL瀵硅薄寮曠敤</li> + <li>浠g爜鐢熸垚瀵煎叆琛ㄦ寜鍒涘缓鏃堕棿鎺掑簭</li> + <li>淇浠g爜鐢熸垚椤甸潰鏁版嵁缂栬緫淇濆瓨涔嬪悗鎬绘槸璺宠浆绗竴椤电殑闂</li> + <li>淇甯afari娴忚鍣ㄦ棤娉曟牸寮忓寲utc鏃ユ湡鏍煎紡yyyy-MM-dd'T'HH:mm:ss.SSS闂</li> + <li>澶氬浘涓婁紶缁勪欢绉婚櫎澶氫綑鐨刟pi鍦板潃&楠岃瘉澶辫触瀵艰嚧鍥剧墖鍒犻櫎闂&鏃犳硶鍒犻櫎鐩稿簲鍥剧墖淇</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.6.0 - 2021-07-12"> + <ol> + <li>瑙掕壊绠$悊鏂板鍒嗛厤鐢ㄦ埛鍔熻兘</li> + <li>鐢ㄦ埛绠$悊鏂板鍒嗛厤瑙掕壊鍔熻兘</li> + <li>鏃ュ織鍒楄〃鏀寔鎺掑簭鎿嶄綔</li> + <li>浼樺寲鍙傛暟&瀛楀吀缂撳瓨鎿嶄綔</li> + <li>绯荤粺甯冨眬閰嶇疆鏀寔鍔ㄦ�佹爣棰樺紑鍏�</li> + <li>鑿滃崟璺敱閰嶇疆鏀寔鍐呴摼璁块棶</li> + <li>榛樿璁块棶鍚庣棣栭〉鏂板鎻愮ず璇�</li> + <li>瀵屾枃鏈粯璁や笂浼犺繑鍥瀠rl绫诲瀷</li> + <li>鏂板鑷畾涔夊脊绐楁嫋鎷芥寚浠�</li> + <li>鍏ㄥ眬娉ㄥ唽甯哥敤閫氱敤缁勪欢</li> + <li>鍏ㄥ眬鎸傝浇瀛楀吀鏍囩缁勪欢</li> + <li>ImageUpload缁勪欢鏀寔澶氬浘鐗囦笂浼�</li> + <li>FileUpload缁勪欢鏀寔澶氭枃浠朵笂浼�</li> + <li>鏂囦欢涓婁紶缁勪欢娣诲姞鏁伴噺闄愬埗灞炴��</li> + <li>瀵屾枃鏈紪杈戠粍浠舵坊鍔犵被鍨嬪睘鎬�</li> + <li>瀵屾枃鏈粍浠跺伐鍏锋爮閰嶇疆瑙嗛</li> + <li>灏佽閫氱敤iframe缁勪欢</li> + <li>闄愬埗瓒呯骇绠$悊鍛樹笉鍏佽鎿嶄綔</li> + <li>鐢ㄦ埛淇℃伅闀垮害鏍¢獙闄愬埗</li> + <li>鍒嗛〉缁勪欢鏂板pagerCount灞炴��</li> + <li>娣诲姞bat鑴氭湰鎵ц搴旂敤</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.7.4</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.2</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.3.1</li> + <li>鍗囩骇commons.io鍒版渶鏂扮増鏈瑅2.10.0</li> + <li>鍗囩骇commons.fileupload鍒版渶鏂扮増鏈瑅1.4</li> + <li>鍗囩骇swagger鍒版渶鏂扮増鏈瑅3.0.0</li> + <li>淇鍏抽棴confirm鎻愮ず妗嗘帶鍒跺彴鎶ラ敊闂</li> + <li>淇瀛樺湪鐨凷QL娉ㄥ叆婕忔礊闂</li> + <li>瀹氭椂浠诲姟灞忚斀rmi杩滅▼璋冪敤</li> + <li>淇鐢ㄦ埛鎼滅储鍒嗛〉鍙橀噺閿欒</li> + <li>淇瀵煎嚭瑙掕壊鏁版嵁鑼冨洿缈昏瘧缂哄皯浠呮湰浜�</li> + <li>淇琛ㄥ崟鏋勫缓閫夋嫨涓嬫媺閫夋嫨鎺у埗鍙版姤閿欓棶棰�</li> + <li>浼樺寲鍥剧墖宸ュ叿绫昏鍙栨枃浠�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.5.0 - 2021-05-25"> + <ol> + <li>鏂板鑿滃崟瀵艰埅鏄剧ず椋庢牸TopNav锛坒alse涓哄乏渚у鑸彍鍗曪紝true涓洪《閮ㄥ鑸彍鍗曪級</li> + <li>甯冨眬璁剧疆鏀寔淇濆瓨&閲嶇疆閰嶇疆</li> + <li>淇鏍戣〃鏁版嵁鏄剧ず涓嶅叏&鍔犺浇鎱㈤棶棰�</li> + <li>鏂板IE娴忚鍣ㄧ増鏈繃浣庢彁绀洪〉闈�</li> + <li>鐢ㄦ埛鐧诲綍鍚庤褰曟渶鍚庣櫥褰旾P&鏃堕棿</li> + <li>椤甸潰瀵煎嚭鎸夐挳鐐瑰嚮涔嬪悗娣诲姞閬僵</li> + <li>瀵屾枃鏈紪杈戝櫒鏀寔鑷畾涔変笂浼犲湴鍧�</li> + <li>瀵屾枃鏈紪杈戠粍浠舵柊澧瀝eadOnly灞炴��</li> + <li>椤电TagsView鏂板鍏抽棴鍙充晶鍔熻兘</li> + <li>鏄鹃殣鍒楃粍浠跺姞杞藉垵濮嬮粯璁ら殣钘忓垪</li> + <li>鍏抽棴澶村儚涓婁紶绐楀彛杩樺師榛樿鍥剧墖</li> + <li>涓汉淇℃伅娣诲姞鎵嬫満&閭閲嶅楠岃瘉</li> + <li>浠g爜鐢熸垚妯℃澘瀵煎嚭鎸夐挳鐐瑰嚮鍚庢坊鍔犻伄缃�</li> + <li>浠g爜鐢熸垚妯℃澘鏍戣〃鎿嶄綔鍒楁坊鍔犳柊澧炴寜閽�</li> + <li>浠g爜鐢熸垚妯℃澘淇涓诲瓙琛ㄥ瓧娈甸噸鍚嶉棶棰�</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.76</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈瑅1.2.6</li> + <li>鍗囩骇mybatis鍒版渶鏂扮増3.5.6 闃绘杩滅▼浠g爜鎵ц婕忔礊</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.6.0</li> + <li>velocity鍓旈櫎commons-collections鐗堟湰锛岄槻姝�3.2.1鐗堟湰鐨勫弽搴忓垪鍖栨紡娲�</li> + <li>鏁版嵁鐩戞帶椤甸粯璁よ处鎴峰瘑鐮侀槻姝㈣秺鏉冭闂�</li> + <li>淇firefox涓嬭〃鍗曟瀯寤烘嫋鎷戒細鏂版墦鍗′竴涓�夐」鍗�</li> + <li>淇鍚庣瀵煎叆琛ㄦ潈闄愭爣璇�</li> + <li>淇鍓嶇鎿嶄綔鏃ュ織&鐧诲綍鏃ュ織鏉冮檺鏍囪瘑</li> + <li>璁剧疆Redis閰嶇疆HashKey搴忓垪鍖�</li> + <li>鍒犻櫎鎿嶄綔鏃ュ織璁板綍淇℃伅</li> + <li>涓婁紶濯掍綋绫诲瀷娣诲姞瑙嗛鏍煎紡</li> + <li>淇璇锋眰褰㈠弬鏈紶鍊艰褰曟棩蹇楀紓甯搁棶棰�</li> + <li>浼樺寲xss鏍¢獙json璇锋眰鏉′欢</li> + <li>鏍戠骇缁撴瀯鏇存柊瀛愯妭鐐逛娇鐢╮eplaceFirst</li> + <li>浼樺寲ExcelUtil绌哄�煎鐞�</li> + <li>鏃ュ織璁板綍杩囨护BindingResult瀵硅薄锛岄槻姝㈠紓甯�</li> + <li>淇敼涓婚鍚巑ini绫诲瀷鎸夐挳鏃犳晥闂</li> + <li>浼樺寲閫氱敤涓嬭浇瀹屾垚鍚庡垹闄よ妭鐐�</li> + <li>閫氱敤Controller娣诲姞鍝嶅簲杩斿洖娑堟伅</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.4.0 - 2021-02-22"> + <ol> + <li>浠g爜鐢熸垚妯℃澘鏀寔涓诲瓙琛�</li> + <li>琛ㄦ牸鍙充晶宸ュ叿鏍忕粍浠舵敮鎸佹樉闅愬垪</li> + <li>鍥剧墖缁勪欢娣诲姞棰勮&绉婚櫎鍔熻兘</li> + <li>Excel娉ㄨВ鏀寔Image鍥剧墖瀵煎嚭</li> + <li>鎿嶄綔鎸夐挳缁勮皟鏁翠负鏈寸礌鎸夐挳鏍峰紡</li> + <li>浠g爜鐢熸垚鏀寔鏂囦欢涓婁紶缁勪欢</li> + <li>浠g爜鐢熸垚鏃ユ湡鎺т欢鍖哄垎鑼冨洿</li> + <li>浠g爜鐢熸垚鏁版嵁搴撴枃鏈被鍨嬬敓鎴愯〃鍗曟枃鏈煙</li> + <li>鐢ㄦ埛鎵嬫満閭&鑿滃崟缁勪欢淇敼鍏佽绌哄瓧绗︿覆</li> + <li>鍗囩骇SpringBoot鍒版渶鏂扮増鏈�2.2.13 鎻愬崌鍚姩閫熷害</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈瑅1.2.4</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.75</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.15.0</li> + <li>淇IE11娴忚鍣ㄦ姤閿欓棶棰�</li> + <li>浼樺寲澶氱骇鑿滃崟涔嬮棿鍒囨崲鏃犳硶缂撳瓨鐨勯棶棰�</li> + <li>淇鍥涚骇鑿滃崟鏃犳硶鏄剧ず闂</li> + <li>淇渚ц竟鏍忛潤鎬佽矾鐢变涪澶遍棶棰�</li> + <li>淇瑙掕壊绠$悊-缂栬緫瑙掕壊-鍔熻兘鏉冮檺鏄剧ず寮傚父</li> + <li>閰嶇疆鏂囦欢鏂板redis鏁版嵁搴撶储寮曞睘鎬�</li> + <li>鏉冮檺宸ュ叿绫诲鍔燼dmin鍒ゆ柇</li> + <li>瑙掕壊闈炶嚜瀹氫箟鏉冮檺鑼冨洿娓呯┖閫夋嫨鍊�</li> + <li>淇瀵煎叆鏁版嵁涓鸿礋娴偣鏁版椂涓㈠け绮惧害闂</li> + <li>绉婚櫎path-to-regexp姝e垯鍖归厤鎻掍欢</li> + <li>淇鐢熸垚鏍戣〃浠g爜寮傚父</li> + <li>淇敼ip瀛楁闀垮害闃叉ipv6鍦板潃闀垮害涓嶅</li> + <li>闃叉get璇锋眰鍙傛暟鍊间负false鎴�0绛夌壒娈婂�间細瀵艰嚧鏃犳硶姝g‘鐨勪紶鍙�</li> + <li>鐧诲綍鍚巔ush娣诲姞catch闃叉鍑虹幇妫�鏌ラ敊璇�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.3.0 - 2020-12-14"> + <ol> + <li>鏂板缂撳瓨鐩戞帶鍔熻兘</li> + <li>鏀寔涓婚椋庢牸閰嶇疆</li> + <li>淇澶氱骇鑿滃崟涔嬮棿鍒囨崲鏃犳硶缂撳瓨鐨勯棶棰�</li> + <li>澶氱骇鑿滃崟鑷姩閰嶇疆缁勪欢</li> + <li>浠g爜鐢熸垚棰勮鏀寔楂樹寒鏄剧ず</li> + <li>鏀寔Get璇锋眰鏄犲皠Params鍙傛暟</li> + <li>鍒犻櫎鐢ㄦ埛鍜岃鑹茶В缁戝叧鑱�</li> + <li>鍘婚櫎鐢ㄦ埛鎵嬫満閭閮ㄩ棬蹇呭~楠岃瘉</li> + <li>Excel鏀寔娉ㄨВalign瀵归綈鏂瑰紡</li> + <li>Excel鏀寔瀵煎叆Boolean鍨嬫暟鎹�</li> + <li>浼樺寲澶村儚鏍峰紡锛岄紶鏍囩Щ鍏ユ偓鍋滈伄缃�</li> + <li>浠g爜鐢熸垚棰勮鎻愪緵婊氬姩鏈哄埗</li> + <li>浠g爜鐢熸垚鍒犻櫎澶氫綑鐨勬暟瀛梖loat绫诲瀷</li> + <li>淇杞崲瀛楃涓茬殑鐩爣瀛楃闆嗗睘鎬�</li> + <li>鍥炴樉鏁版嵁瀛楀吀闃叉绌哄�兼姤閿�</li> + <li>鏃ュ織璁板綍澧炲姞杩囨护澶氭枃浠跺満鏅�</li> + <li>淇敼缂撳瓨Set鏂规硶鍙兘瀵艰嚧宓屽鐨勯棶棰�</li> + <li>绉婚櫎鍓嶇涓�浜涘浣欑殑渚濊禆</li> + <li>闃叉瀹夊叏鎵弿YUI鍑虹幇鐨勯闄╂彁绀�</li> + <li>淇敼node-sass涓篸art-sass</li> + <li>鍗囩骇SpringBoot鍒版渶鏂扮増鏈�2.1.18</li> + <li>鍗囩骇poi鍒版渶鏂扮増鏈�4.1.2</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.3.6</li> + <li>鍗囩骇bitwalker鍒版渶鏂扮増鏈�1.21</li> + <li>鍗囩骇axios鍒版渶鏂扮増鏈�0.21.0</li> + <li>鍗囩骇element-ui鍒版渶鏂扮増鏈�2.14.1</li> + <li>鍗囩骇vue鍒版渶鏂扮増鏈�2.6.12</li> + <li>鍗囩骇vuex鍒版渶鏂扮増鏈�3.6.0</li> + <li>鍗囩骇vue-cli鍒扮増鏈�4.5.9</li> + <li>鍗囩骇vue-router鍒版渶鏂扮増鏈�3.4.9</li> + <li>鍗囩骇vue-cli鍒版渶鏂扮増鏈�4.4.6</li> + <li>鍗囩骇vue-cropper鍒版渶鏂扮増鏈�0.5.5</li> + <li>鍗囩骇clipboard鍒版渶鏂扮増鏈�2.0.6</li> + <li>鍗囩骇core-js鍒版渶鏂扮増鏈�3.8.1</li> + <li>鍗囩骇echarts鍒版渶鏂扮増鏈�4.9.0</li> + <li>鍗囩骇file-saver鍒版渶鏂扮増鏈�2.0.4</li> + <li>鍗囩骇fuse.js鍒版渶鏂扮増鏈�6.4.3</li> + <li>鍗囩骇js-beautify鍒版渶鏂扮増鏈�1.13.0</li> + <li>鍗囩骇js-cookie鍒版渶鏂扮増鏈�2.2.1</li> + <li>鍗囩骇path-to-regexp鍒版渶鏂扮増鏈�6.2.0</li> + <li>鍗囩骇quill鍒版渶鏂扮増鏈�1.3.7</li> + <li>鍗囩骇screenfull鍒版渶鏂扮増鏈�5.0.2</li> + <li>鍗囩骇sortablejs鍒版渶鏂扮増鏈�1.10.2</li> + <li>鍗囩骇vuedraggable鍒版渶鏂扮増鏈�2.24.3</li> + <li>鍗囩骇chalk鍒版渶鏂扮増鏈�4.1.0</li> + <li>鍗囩骇eslint鍒版渶鏂扮増鏈�7.15.0</li> + <li>鍗囩骇eslint-plugin-vue鍒版渶鏂扮増鏈�7.2.0</li> + <li>鍗囩骇lint-staged鍒版渶鏂扮増鏈�10.5.3</li> + <li>鍗囩骇runjs鍒版渶鏂扮増鏈�4.4.2</li> + <li>鍗囩骇sass-loader鍒版渶鏂扮増鏈�10.1.0</li> + <li>鍗囩骇script-ext-html-webpack-plugin鍒版渶鏂扮増鏈�2.1.5</li> + <li>鍗囩骇svg-sprite-loader鍒版渶鏂扮増鏈�5.1.1</li> + <li>鍗囩骇vue-template-compiler鍒版渶鏂扮増鏈�2.6.12</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.2.1 - 2020-11-18"> + <ol> + <li>闃绘浠绘剰鏂囦欢涓嬭浇婕忔礊</li> + <li>浠g爜鐢熸垚鏀寔涓婁紶鎺т欢</li> + <li>鏂板鍥剧墖涓婁紶缁勪欢</li> + <li>璋冩暣榛樿棣栭〉</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈瑅1.2.2</li> + <li>mapperLocations閰嶇疆鏀寔鍒嗛殧绗�</li> + <li>鏉冮檺淇℃伅璋冩暣</li> + <li>璋冩暣sql榛樿鏃堕棿</li> + <li>瑙e喅浠g爜鐢熸垚娌℃湁bit绫诲瀷鐨勯棶棰�</li> + <li>鍗囩骇pagehelper鍒版渶鏂扮増1.3.0</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v3.2.0 - 2020-10-10"> + <ol> + <li>鍗囩骇springboot鐗堟湰鍒�2.1.17 鎻愬崌瀹夊叏鎬�</li> + <li>鍗囩骇oshi鍒版渶鏂扮増鏈瑅5.2.5</li> + <li>鍗囩骇druid鍒版渶鏂扮増鏈瑅1.2.1</li> + <li>鍗囩骇jjwt鍒扮増鏈�0.9.1</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.74</li> + <li>淇敼sass涓簄ode-sass锛岄伩鍏峞l-icon鍥炬爣涔辩爜</li> + <li>浠g爜鐢熸垚鏀寔鍚屾鏁版嵁搴�</li> + <li>浠g爜鐢熸垚鏀寔瀵屾枃鏈帶浠�</li> + <li>浠g爜鐢熸垚椤甸潰鏃朵笉蹇界暐remark灞炴��</li> + <li>浠g爜鐢熸垚娣诲姞select蹇呭~閫夐」</li> + <li>Excel瀵煎嚭绫诲瀷NUMERIC鏀寔绮惧害娴偣绫诲瀷</li> + <li>Excel瀵煎嚭targetAttr浼樺寲鑾峰彇鍊硷紝闃叉get鏂规硶涓嶈鑼�</li> + <li>Excel娉ㄨВ鏀寔鑷姩缁熻鏁版嵁鎬诲拰</li> + <li>Excel娉ㄨВ鏀寔璁剧疆BigDecimal绮惧害&鑸嶅叆瑙勫垯</li> + <li>鑿滃崟&鏁版嵁鏉冮檺鏂板锛堝睍寮�/鎶樺彔 鍏ㄩ��/鍏ㄤ笉閫� 鐖跺瓙鑱斿姩锛�</li> + <li>鍏佽鐢ㄦ埛鍒嗛厤鍒伴儴闂ㄧ埗鑺傜偣</li> + <li>鑿滃崟鏂板鏄惁缂撳瓨keep-alive</li> + <li>琛ㄦ牸鎿嶄綔鍒楅棿璺濊皟鏁�</li> + <li>闄愬埗绯荤粺鍐呯疆鍙傛暟涓嶅厑璁稿垹闄�</li> + <li>瀵屾枃鏈粍浠朵紭鍖栵紝鏀寔鑷畾涔夐珮搴�&鍥剧墖鍐茬獊闂</li> + <li>瀵屾枃鏈伐鍏锋爮鏍峰紡瀵归綈</li> + <li>瀵煎叆excel鏁村舰鍊兼牎楠屼紭鍖�</li> + <li>淇椤电鍏抽棴鎵�鏈夋椂鍥哄畾鏍囩璺敱涓嶅埛鏂伴棶棰�</li> + <li>琛ㄥ崟鏋勫缓甯冨眬鍨嬬粍浠舵柊澧炴寜閽�</li> + <li>宸︿晶鑿滃崟鏂囧瓧杩囬暱鏄剧ず鐪佺暐鍙�</li> + <li>淇鏍硅妭鐐逛负瀛愰儴闂ㄦ椂锛屾爲鐘剁粨鏋勬樉绀洪棶棰�</li> + <li>淇璋冪敤鐩爣瀛楃涓叉渶澶ч暱搴�</li> + <li>淇鑿滃崟鎻愮ず淇℃伅閿欒</li> + <li>淇瀹氭椂浠诲姟鎵ц涓�娆℃潈闄愭爣璇�</li> + <li>淇鏁版嵁搴撳瓧绗︿覆绫诲瀷nvarchar</li> + <li>浼樺寲閫掑綊瀛愯妭鐐�</li> + <li>浼樺寲鏁版嵁鏉冮檺鍒ゆ柇</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v3.1.0 - 2020-08-13"> + <ol> + <li>琛ㄦ牸宸ュ叿鏍忓彸渚ф坊鍔犲埛鏂�&鏄鹃殣鏌ヨ缁勪欢</li> + <li>鍚庣鏀寔CORS璺ㄥ煙璇锋眰</li> + <li>浠g爜鐢熸垚鏀寔閫夋嫨涓婄骇鑿滃崟</li> + <li>浠g爜鐢熸垚鏀寔鑷畾涔夎矾寰�</li> + <li>浠g爜鐢熸垚鏀寔澶嶉�夋</li> + <li>Excel瀵煎嚭瀵煎叆鏀寔dictType瀛楀吀绫诲瀷</li> + <li>Excel鏀寔鍒嗗壊瀛楃涓茬粍鍐呭</li> + <li>楠岃瘉鐮佺被鍨嬫敮鎸侊紙鏁扮粍璁$畻銆佸瓧绗﹂獙璇侊級</li> + <li>鍗囩骇vue-cli鐗堟湰鍒�4.4.4</li> + <li>淇敼 node-sass 涓� dart-sass</li> + <li>琛ㄥ崟绫诲瀷涓篒nteger/Long璁剧疆鏁村舰榛樿鍊�</li> + <li>浠g爜鐢熸垚鍣ㄩ粯璁apper璺緞涓庨粯璁apperScan璺緞涓嶄竴鑷�</li> + <li>浼樺寲闃查噸澶嶆彁浜ゆ嫤鎴櫒</li> + <li>浼樺寲涓婄骇鑿滃崟涓嶈兘閫夋嫨鑷繁</li> + <li>淇瑙掕壊鐨勬潈闄愬垎閰嶅悗锛屾湭瀹炴椂鐢熸晥闂</li> + <li>淇鍦ㄧ嚎鐢ㄦ埛鏃ュ織璁板綍绫诲瀷</li> + <li>淇瀵屾枃鏈┖鏍煎拰缂╄繘淇濆瓨鍚庝笉鐢熸晥闂</li> + <li>淇鍦ㄧ嚎鐢ㄦ埛鍒ゆ柇閫昏緫</li> + <li>鍞竴闄愬埗鏉′欢鍙繑鍥炲崟鏉℃暟鎹�</li> + <li>娣诲姞鑾峰彇褰撳墠鐨勭幆澧冮厤缃柟娉�</li> + <li>瓒呮椂鐧诲綍鍚庨〉闈㈣烦杞埌棣栭〉</li> + <li>鍏ㄥ眬寮傚父鐘舵�佹眽鍖栨嫤鎴鐞�</li> + <li>HTML杩囨护鍣ㄦ敼涓哄皢html杞箟</li> + <li>妫�鏌ュ瓧绗︽敮鎸佸皬鏁扮偣&闄嶇骇鏀规垚寮傚父鎻愰啋</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v3.0.0 - 2020-07-20"> + <ol> + <li>鍗曞簲鐢ㄨ皟鏁翠负澶氭ā鍧楅」鐩�</li> + <li>鍗囩骇element-ui鐗堟湰鍒�2.13.2</li> + <li>鍒犻櫎babel锛屾彁楂樼紪璇戦�熷害銆�</li> + <li>鏂板鑿滃崟榛樿涓荤被鐩�</li> + <li>缂栫爜鏂囦欢鍚嶄慨鏀逛负uuid鏂瑰紡</li> + <li>瀹氭椂浠诲姟cron琛ㄨ揪寮忛獙璇�</li> + <li>瑙掕壊鏉冮檺淇敼鏃跺凡鏈夋潈闄愭湭鑷姩鍕鹃�夊紓甯镐慨澶�</li> + <li>闃叉鍒囨崲鏉冮檺鐢ㄦ埛鍚庣櫥褰曞嚭鐜�404</li> + <li>Excel鏀寔sort瀵煎嚭鎺掑簭</li> + <li>鍒涘缓鐢ㄦ埛涓嶅厑璁搁�夋嫨瓒呯骇绠$悊鍛樿鑹�</li> + <li>淇浠g爜鐢熸垚瀵煎叆琛ㄧ粨鏋勫嚭鐜板紓甯搁〉闈笉鎻愰啋闂</li> + <li>淇浠g爜鐢熸垚鐐瑰嚮澶氭琛ㄤ慨鏀规暟鎹笉鍙樺寲鐨勯棶棰�</li> + <li>淇澶村儚涓婁紶鎴愬姛浜屾鎵撳紑鏃犳硶鏀瑰彉瑁佸壀妗嗗ぇ灏忓拰浣嶇疆闂</li> + <li>淇甯冨眬涓簊mall鑰卪ini鐢ㄦ埛琛ㄥ崟鏄剧ず閿欎綅闂</li> + <li>淇鐑儴缃插鑷寸殑寮烘崲寮傚父闂</li> + <li>淇敼鐢ㄦ埛绠$悊澶嶉�夋瀹藉害锛岄槻姝㈤儴鍒嗘祻瑙堝櫒鍑虹幇鐪佺暐鍙�</li> + <li>IpUtils宸ュ叿锛屾竻闄ss鐗规畩瀛楃锛岄槻姝ff娉ㄥ叆鏀诲嚮</li> + <li>鐢熸垚domain 濡傛灉鏄诞鐐瑰瀷 缁熶竴鐢˙igDecimal</li> + <li>瀹氭椂浠诲姟璋冩暣label-width锛岄槻姝㈤儴缃插嚭鐜伴敊浣�</li> + <li>璋冩暣琛ㄥご鍥哄畾鍒楅粯璁ゆ牱寮�</li> + <li>浠g爜鐢熸垚妯℃澘璋冩暣锛屽瓧娈典负String骞朵笖蹇呭~鍒欏姞绌轰覆鏉′欢</li> + <li>浠g爜鐢熸垚瀛楀吀Integer/Long浣跨敤parseInt</li> + <li> + 淇dict_sort涓嶅彲update涓�0鐨勯棶棰�&鏌ヨ杩斿洖澧炲姞dict_sort鍗囧簭鎺掑簭 + </li> + <li>淇宀椾綅瀵煎嚭鏉冮檺娉ㄨВ</li> + <li>绂佹鍔犲瘑瀵嗘枃杩斿洖鍓嶇</li> + <li>淇浠g爜鐢熸垚椤甸潰涓殑鏌ヨ鏉′欢鍒涘缓鏃堕棿鏈敓鏁堢殑闂</li> + <li>淇棣栭〉鎼滅储鑿滃崟澶栭摼鏃犳硶鐐瑰嚮璺宠浆闂</li> + <li>淇鑿滃崟绠$悊閫夋嫨鍥炬爣锛宐ackspace鍒犻櫎鏃朵笉杩囨护鏁版嵁</li> + <li>鐢ㄦ埛绠$悊閮ㄩ棬鍒嗘敮鑺傜偣涓嶅彲妫�鏌�&鏄剧ず璁℃暟</li> + <li>鏁版嵁鑼冨洿杩囨护灞炴�ц皟鏁�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v2.3.0 - 2020-06-01"> + <ol> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.70 淇楂樺嵄瀹夊叏婕忔礊</li> + <li>dev鍚姩榛樿鎵撳紑娴忚鍣�</li> + <li>vue-cli浣跨敤榛樿source-map</li> + <li>slidebar eslint鎶ラ敊浼樺寲</li> + <li>褰搕ags-view婊氬姩鍏抽棴鍙抽敭鑿滃崟</li> + <li>瀛楀吀绠$悊娣诲姞缂撳瓨璇诲彇</li> + <li>鍙傛暟绠$悊鏀寔缂撳瓨鎿嶄綔</li> + <li>鏀寔涓�绾ц彍鍗曪紙鍜屼富椤靛悓绾э級鍦╩ain鍖哄煙鏄剧ず</li> + <li>闄愬埗澶栭摼鍦板潃蹇呴』浠ttp(s)寮�澶�</li> + <li>tagview & sidebar 涓婚棰滆壊涓巈lement ui(鍏ㄥ眬)鍚屾</li> + <li>淇敼鏁版嵁婧愮被鍨嬩紭鍏堢骇锛屽厛鏍规嵁鏂规硶锛屽啀鏍规嵁绫�</li> + <li>鏀寔鏄惁闇�瑕佽缃畉oken灞炴�э紝鑷畾涔夎繑鍥炵爜娑堟伅銆�</li> + <li>swagger璇锋眰鍓嶇紑鍔犲叆閰嶇疆銆�</li> + <li>鐧诲綍鍦扮偣璁剧疆鍐呭杩囬暱鍒欓殣钘忔樉绀�</li> + <li>淇瀹氭椂浠诲姟鎵ц涓�娆℃寜閽悗涓嶆彁绀烘秷鎭棶棰�</li> + <li>淇敼涓婄骇閮ㄩ棬锛堥�夋嫨椤规帓闄ゆ湰韬拰涓嬬骇锛�</li> + <li>閫氱敤http鍙戦�佹柟娉曞鍔犲弬鏁� contentType 缂栫爜绫诲瀷</li> + <li>鏇存崲IP鍦板潃鏌ヨ鎺ュ彛</li> + <li>淇椤电鍙橀噺undefined</li> + <li>娣诲姞鏍¢獙閮ㄩ棬鍖呭惈鏈仠鐢ㄧ殑瀛愰儴闂�</li> + <li>淇敼瀹氭椂浠诲姟璇︽儏涓嬫鎵ц鏃堕棿鏃ユ湡鏄剧ず閿欒</li> + <li>瑙掕壊绠$悊鏌ヨ璁剧疆榛樿鎺掑簭瀛楁</li> + <li>swagger娣诲姞enable鍙傛暟鎺у埗鏄惁鍚敤</li> + <li>鍙json绫诲瀷璇锋眰鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest</li> + <li>淇敼浠g爜鐢熸垚瀛楀吀瀛楁int绫诲瀷娌℃湁鑷姩閫変腑闂</li> + <li>vuex鐢ㄦ埛鍚嶅彇鍊间慨姝�</li> + <li>琛ㄦ牸鏍戞ā鏉垮幓鎺夊浣欑殑)</li> + <li>浠g爜鐢熸垚搴忓彿淇</li> + <li>鍏ㄥ睆鎯呭喌涓嬩笉璋冩暣涓婂杈硅窛</li> + <li>浠g爜鐢熸垚Date瀛楁娣诲姞榛樿鏍煎紡</li> + <li>鐢ㄦ埛绠$悊瑙掕壊閫夋嫨鏉冮檺鎺у埗</li> + <li>淇璺敱鎳掑姞杞芥姤閿欓棶棰�</li> + <li>妯℃澘sql.vm娣诲姞鑿滃崟鐘舵��</li> + <li>璁剧疆鐢ㄦ埛鍚嶇О涓嶈兘淇敼</li> + <li>dialog娣诲姞append-to-body灞炴�э紝闃叉ie閬僵</li> + <li>鑿滃崟鍖哄垎鐘舵�佸拰鏄剧ず闅愯棌鍔熻兘</li> + <li>鍗囩骇fastjson鍒版渶鏂扮増1.2.68 淇瀹夊叏鍔犲浐</li> + <li>淇浠g爜鐢熸垚濡傛灉閫夋嫨瀛楀吀绫诲瀷缂哄け閫楀彿闂</li> + <li>鐧诲綍璇锋眰params鏇存崲涓篸ata锛岄槻姝㈡毚闇瞮rl</li> + <li>鏃ュ織杩斿洖鏃堕棿鏍煎紡澶勭悊</li> + <li>娣诲姞handle鎺у埗鍏佽鎷栧姩鐨勫厓绱�</li> + <li>甯冨眬璁剧疆鐐瑰嚮鎵╁ぇ鑼冨洿</li> + <li>浠g爜鐢熸垚鍒楀睘鎬ф帓搴忔煡璇�</li> + <li>浠g爜鐢熸垚鍒楁敮鎸佹嫋鍔ㄦ帓搴�</li> + <li>淇鏃堕棿鏍煎紡涓嶆敮鎸乮os闂</li> + <li>琛ㄥ崟鏋勫缓娣诲姞鐖剁骇class锛岄槻姝㈠啿绐�</li> + <li>瀹氭椂浠诲姟骞跺彂灞炴�т慨姝�</li> + <li>瑙掕壊绂佺敤&鑿滃崟闅愯棌涓嶆煡璇㈡潈闄�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v2.2.0 - 2020-03-18"> + <ol> + <li>绯荤粺鐩戞帶鏂板瀹氭椂浠诲姟鍔熻兘</li> + <li>娣诲姞涓�涓墦鍖匴eb宸ョ▼bat</li> + <li>淇椤电榧犳爣婊氳疆鎸変笅鐨勬椂鍊欙紝鍙互鍏抽棴涓嶅彲鍏抽棴鐨則ag</li> + <li>淇鐐瑰嚮閫�鍑虹櫥褰曟湁鏃朵細鏃犳彁绀洪棶棰�</li> + <li>淇闃查噸澶嶆彁浜ゆ敞瑙f棤鏁堥棶棰�</li> + <li>淇閫氱煡鍏憡鎵归噺鍒犻櫎寮傚父闂</li> + <li>娣诲姞鑿滃崟鏃惰矾鐢卞湴鍧�蹇呭~闄愬埗</li> + <li>浠g爜鐢熸垚瀛楁鎻忚堪鍙紪杈�</li> + <li>淇鐢ㄦ埛淇敼涓汉淇℃伅瀵艰嚧缂撳瓨涓嶈繃鏈熼棶棰�</li> + <li>涓汉淇℃伅鍒涘缓鏃堕棿鑾峰彇姝g‘灞炴�у��</li> + <li>鎿嶄綔鏃ュ織璇︾粏鏄剧ず姝g‘绫诲瀷</li> + <li>瀵煎叆琛ㄥ崟鍑昏鏁版嵁鏃堕�変腑瀵瑰簲鐨勫閫夋</li> + <li>鎵归噺鏇挎崲琛ㄥ墠缂�閫昏緫璋冩暣</li> + <li>鍥哄畾閲嶅畾鍚戣矾寰勮〃杈惧紡</li> + <li>鍗囩骇element-ui鐗堟湰鍒�2.13.0</li> + <li>鎿嶄綔鏃ュ織鎺掑簭璋冩暣</li> + <li>淇charts鍒囨崲渚ц竟鏍忔垨鑰呯缉鏀剧獥鍙f樉绀篵ug</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v2.1.0 - 2020-02-24"> + <ol> + <li>鏂板琛ㄥ崟鏋勫缓</li> + <li>浠g爜鐢熸垚鏀寔鏍戣〃缁撴瀯</li> + <li>鏂板鐢ㄦ埛瀵煎叆</li> + <li>淇鍔ㄦ�佸姞杞借矾鐢遍〉闈㈠埛鏂伴棶棰�</li> + <li>淇鍦板潃寮�鍏虫棤鏁堥棶棰�</li> + <li>姹夊寲閿欒鎻愮ず椤甸潰</li> + <li>浠g爜鐢熸垚宸茬煡闂淇敼</li> + <li>淇澶氭暟鎹簮涓嬮厤缃叧闂嚭鐜板紓甯稿鐞�</li> + <li>娣诲姞HTML杩囨护鍣紝鐢ㄤ簬鍘婚櫎XSS婕忔礊闅愭偅</li> + <li>淇涓婁紶澶村儚鎺у埗鍙板嚭鐜板紓甯�</li> + <li>淇敼鐢ㄦ埛绠$悊鍒嗛〉涓嶆纭殑闂</li> + <li>淇楠岃瘉鐮佽褰曟彁绀洪敊璇�</li> + <li>淇request.js缂哄皯Message寮曠敤</li> + <li>淇琛ㄦ牸鏃堕棿涓虹┖鍑虹幇鐨勫紓甯�</li> + <li>娣诲姞Jackson鏃ユ湡鍙嶅簭鍒楀寲鏃跺尯閰嶇疆</li> + <li>璋冩暣鏍规嵁鐢ㄦ埛鏉冮檺鍔犺浇鑿滃崟鏁版嵁鏍戝舰缁撴瀯</li> + <li>璋冩暣鎴愬姛鐧诲綍涓嶆仮澶嶆寜閽紝闃叉澶氭鐐瑰嚮</li> + <li>淇敼鐢ㄦ埛涓汉璧勬枡鍚屾缂撳瓨淇℃伅</li> + <li>淇椤甸潰鍚屾椂鍑虹幇el-upload鍜孍ditor涓嶆樉绀哄鐞�</li> + <li>淇鍦ㄨ鑹茬鐞嗛〉淇敼鑿滃崟鏉冮檺鍋跺皵鏈�変腑闂</li> + <li>閰嶇疆鏂囦欢鏂板redis瀵嗙爜灞炴��</li> + <li>璁剧疆mybatis鍏ㄥ眬鐨勯厤缃枃浠�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + + <el-collapse-item title="v2.0.0 - 2019-12-02"> + <ol> + <li>鏂板浠g爜鐢熸垚</li> + <li>鏂板@RepeatSubmit娉ㄨВ锛岄槻姝㈤噸澶嶆彁浜�</li> + <li>鏂板鑿滃崟涓荤洰褰曟坊鍔�/鍒犻櫎鎿嶄綔</li> + <li>鏃ュ織璁板綍杩囨护鐗规畩瀵硅薄锛岄槻姝㈣浆鎹㈠紓甯�</li> + <li>淇敼浠g爜鐢熸垚璺敱鑴氭湰閿欒</li> + <li>鐢ㄦ埛涓婁紶澶村儚瀹炴椂鍚屾缂撳瓨锛屾棤闇�閲嶆柊鐧诲綍</li> + <li>璋冩暣鍒囨崲椤电鍚庝笉閲嶆柊鍔犺浇鏁版嵁</li> + <li>娣诲姞jsencrypt瀹炵幇鍙傛暟鐨勫墠绔姞瀵�</li> + <li>绯荤粺閫�鍑哄垹闄ょ敤鎴风紦瀛樿褰�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v1.1.0 - 2019-11-11"> + <ol> + <li>鏂板鍦ㄧ嚎鐢ㄦ埛绠$悊</li> + <li>鏂板鎸夐挳缁勫姛鑳藉疄鐜帮紙鎵归噺鍒犻櫎銆佸鍑恒�佹竻绌猴級</li> + <li>鏂板鏌ヨ鏉′欢閲嶇疆鎸夐挳</li> + <li>鏂板Swagger鍏ㄥ眬Token閰嶇疆</li> + <li>鏂板鍚庣鍙傛暟鏍¢獙</li> + <li>淇瀛楀吀绠$悊椤甸潰鐨勬棩鏈熸煡璇㈠紓甯�</li> + <li>淇敼鏃堕棿鍑芥暟鍛藉悕闃叉鍐茬獊</li> + <li>鍘婚櫎鑿滃崟涓婄骇鏍¢獙锛岄粯璁や负椤剁骇</li> + <li>淇鐢ㄦ埛瀵嗙爜鏃犳硶淇敼闂</li> + <li>淇鑿滃崟绫诲瀷涓烘寜閽椂涓嶆樉绀烘潈闄愭爣璇�</li> + <li>鍏朵粬缁嗚妭浼樺寲</li> + </ol> + </el-collapse-item> + <el-collapse-item title="v1.0.0 - 2019-10-08"> + <ol> + <li>鑻ヤ緷鍓嶅悗绔垎绂荤郴缁熸寮忓彂甯�</li> + </ol> + </el-collapse-item> + </el-collapse> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script> +export default { + name: "Index", + data() { + return { + // 鐗堟湰鍙� + version: "3.8.6" + }; + }, + methods: { + goTarget(href) { + window.open(href, "_blank"); + } + } +}; +</script> + +<style scoped lang="scss"> +.home { + blockquote { + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; + } + hr { + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; + } + .col-item { + margin-bottom: 20px; + } + + ul { + padding: 0; + margin: 0; + } + + font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 13px; + color: #676a6c; + overflow-x: hidden; + + ul { + list-style-type: none; + } + + h4 { + margin-top: 0px; + } + + h2 { + margin-top: 10px; + font-size: 26px; + font-weight: 100; + } + + p { + margin-top: 10px; + + b { + font-weight: 700; + } + } + + .update-log { + ol { + display: block; + list-style-type: decimal; + margin-block-start: 1em; + margin-block-end: 1em; + margin-inline-start: 0; + margin-inline-end: 0; + padding-inline-start: 40px; + } + } +} +</style> + diff --git a/src/views/index_v1.vue b/src/views/index_v1.vue new file mode 100644 index 0000000..d2d2ec6 --- /dev/null +++ b/src/views/index_v1.vue @@ -0,0 +1,98 @@ +<template> + <div class="dashboard-editor-container"> + + <panel-group @handleSetLineChartData="handleSetLineChartData" /> + + <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> + <line-chart :chart-data="lineChartData" /> + </el-row> + + <el-row :gutter="32"> + <el-col :xs="24" :sm="24" :lg="8"> + <div class="chart-wrapper"> + <raddar-chart /> + </div> + </el-col> + <el-col :xs="24" :sm="24" :lg="8"> + <div class="chart-wrapper"> + <pie-chart /> + </div> + </el-col> + <el-col :xs="24" :sm="24" :lg="8"> + <div class="chart-wrapper"> + <bar-chart /> + </div> + </el-col> + </el-row> + + + </div> +</template> + +<script> +import PanelGroup from './dashboard/PanelGroup' +import LineChart from './dashboard/LineChart' +import RaddarChart from './dashboard/RaddarChart' +import PieChart from './dashboard/PieChart' +import BarChart from './dashboard/BarChart' + +const lineChartData = { + newVisitis: { + expectedData: [100, 120, 161, 134, 105, 160, 165], + actualData: [120, 82, 91, 154, 162, 140, 145] + }, + messages: { + expectedData: [200, 192, 120, 144, 160, 130, 140], + actualData: [180, 160, 151, 106, 145, 150, 130] + }, + purchases: { + expectedData: [80, 100, 121, 104, 105, 90, 100], + actualData: [120, 90, 100, 138, 142, 130, 130] + }, + shoppings: { + expectedData: [130, 140, 141, 142, 145, 150, 160], + actualData: [120, 82, 91, 154, 162, 140, 130] + } +} + +export default { + name: 'Index', + components: { + PanelGroup, + LineChart, + RaddarChart, + PieChart, + BarChart + }, + data() { + return { + lineChartData: lineChartData.newVisitis + } + }, + methods: { + handleSetLineChartData(type) { + this.lineChartData = lineChartData[type] + } + } +} +</script> + +<style lang="scss" scoped> +.dashboard-editor-container { + padding: 32px; + background-color: rgb(240, 242, 245); + position: relative; + + .chart-wrapper { + background: #fff; + padding: 16px 16px 0; + margin-bottom: 32px; + } +} + +@media (max-width:1024px) { + .chart-wrapper { + padding: 8px; + } +} +</style> diff --git a/src/views/login.vue b/src/views/login.vue new file mode 100644 index 0000000..e276d49 --- /dev/null +++ b/src/views/login.vue @@ -0,0 +1,221 @@ +<template> + <div class="login"> + <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form"> + <h3 class="title">鏁板瓧鍖栧悗鍙扮鐞嗙郴缁�</h3> + <el-form-item prop="username"> + <el-input + v-model="loginForm.username" + type="text" + auto-complete="off" + placeholder="璐﹀彿" + > + <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> + </el-input> + </el-form-item> + <el-form-item prop="password"> + <el-input + v-model="loginForm.password" + type="password" + auto-complete="off" + placeholder="瀵嗙爜" + @keyup.enter.native="handleLogin" + > + <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> + </el-input> + </el-form-item> + <el-form-item prop="code" v-if="captchaEnabled"> + <el-input + v-model="loginForm.code" + auto-complete="off" + placeholder="楠岃瘉鐮�" + style="width: 63%" + @keyup.enter.native="handleLogin" + > + <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> + </el-input> + <div class="login-code"> + <img :src="codeUrl" @click="getCode" class="login-code-img"/> + </div> + </el-form-item> + <el-checkbox v-model="loginForm.rememberMe" style="margin:0px 0px 25px 0px;">璁颁綇瀵嗙爜</el-checkbox> + <el-form-item style="width:100%;"> + <el-button + :loading="loading" + size="medium" + type="primary" + style="width:100%;" + @click.native.prevent="handleLogin" + > + <span v-if="!loading">鐧� 褰�</span> + <span v-else>鐧� 褰� 涓�...</span> + </el-button> + <div style="float: right;" v-if="register"> + <router-link class="link-type" :to="'/register'">绔嬪嵆娉ㄥ唽</router-link> + </div> + </el-form-item> + </el-form> + <!-- 搴曢儴 --> + <div class="el-login-footer"> + <span>Copyright 漏 2018-2023 ruoyi.vip All Rights Reserved.</span> + </div> + </div> +</template> + +<script> +import { getCodeImg } from "@/api/login"; +import Cookies from "js-cookie"; +import { encrypt, decrypt } from '@/utils/jsencrypt' + +export default { + name: "Login", + data() { + return { + // codeUrl: "", + loginForm: { + username: "admin", + password: "admin123", + rememberMe: false + // , + // code: "", + // uuid: "" + }, + loginRules: { + username: [ + { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勮处鍙�" } + ], + password: [ + { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勫瘑鐮�" } + ] + // , + // code: [{ required: true, trigger: "change", message: "璇疯緭鍏ラ獙璇佺爜" }] + }, + loading: false, + // 楠岃瘉鐮佸紑鍏� + captchaEnabled: false, + // 娉ㄥ唽寮�鍏� + register: false, + redirect: undefined + }; + }, + watch: { + $route: { + handler: function(route) { + this.redirect = route.query && route.query.redirect; + }, + immediate: true + } + }, + created() { + // this.getCode(); + this.getCookie(); + }, + methods: { + // getCode() { + // getCodeImg().then(res => { + // this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; + // if (this.captchaEnabled) { + // this.codeUrl = "data:image/gif;base64," + res.img; + // this.loginForm.uuid = res.uuid; + // } + // }); + // }, + getCookie() { + const username = Cookies.get("username"); + const password = Cookies.get("password"); + const rememberMe = Cookies.get('rememberMe') + this.loginForm = { + username: username === undefined ? this.loginForm.username : username, + password: password === undefined ? this.loginForm.password : decrypt(password), + rememberMe: rememberMe === undefined ? false : Boolean(rememberMe) + }; + }, + handleLogin() { + this.$refs.loginForm.validate(valid => { + if (valid) { + this.loading = true; + if (this.loginForm.rememberMe) { + Cookies.set("username", this.loginForm.username, { expires: 30 }); + Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 }); + Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 }); + } else { + Cookies.remove("username"); + Cookies.remove("password"); + Cookies.remove('rememberMe'); + } + this.$store.dispatch("Login", this.loginForm).then(() => { + this.$router.push({ path: this.redirect || "/" }).catch(()=>{}); + }).catch(() => { + this.loading = false; + if (this.captchaEnabled) { + this.getCode(); + } + }); + } + }); + } + } +}; +</script> + +<style rel="stylesheet/scss" lang="scss"> +.login { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + background-image: url("../assets/images/login-background.jpg"); + background-size: cover; +} +.title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; +} + +.login-form { + border-radius: 6px; + background: #ffffff; + width: 400px; + padding: 25px 25px 5px 25px; + .el-input { + height: 38px; + input { + height: 38px; + } + } + .input-icon { + height: 39px; + width: 14px; + margin-left: 2px; + } +} +.login-tip { + font-size: 13px; + text-align: center; + color: #bfbfbf; +} +.login-code { + width: 33%; + height: 38px; + float: right; + img { + cursor: pointer; + vertical-align: middle; + } +} +.el-login-footer { + height: 40px; + line-height: 40px; + position: fixed; + bottom: 0; + width: 100%; + text-align: center; + color: #fff; + font-family: Arial; + font-size: 12px; + letter-spacing: 1px; +} +.login-code-img { + height: 38px; +} +</style> diff --git a/src/views/manage/assess/index.vue b/src/views/manage/assess/index.vue new file mode 100644 index 0000000..69837e4 --- /dev/null +++ b/src/views/manage/assess/index.vue @@ -0,0 +1,323 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="璇勪及椤圭洰" prop="item"> + <el-input + v-model="queryParams.item" + placeholder="璇疯緭鍏ュ悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:harbor:add']" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="dsTaskList"> + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="鏂规绫诲瀷" align="center" prop="plan" /> + <el-table-column label="绫诲瀷" align="center" prop="type" /> + <el-table-column label="璇勪及椤圭洰" align="center" prop="item" /> + <el-table-column label="璁$畻鏂规硶" align="center" prop="itemDetail" /> + <el-table-column label="鍗曚綅" align="center" prop="unit" /> + <el-table-column label="瑕佺礌鎸囨爣" align="center" prop="code" /> + <el-table-column label="褰掍竴鍖�" align="center" prop="normal" /> + <el-table-column label="瑕佺礌鏉冮噸" align="center" prop="weight" /> + <el-table-column label="鍒嗙被鎸囨爣" align="center" prop="classifyIndex" /> + <el-table-column label="鍒嗙被鏉冮噸" align="center" prop="classifyWeight" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:harbor:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:harbor:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀规腐鍙d俊鎭璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="750px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鏂规绫诲瀷" prop="plan"> + <el-input v-model="form.plan" placeholder="璇疯緭鍏ユ柟妗堢被鍨�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="绫诲瀷" prop="type"> + <el-select v-model="form.type" placeholder="璇烽�夋嫨"> + <el-option + v-for="column in deptOptions" + :key="column.value" + :label="column.label" + :value="column.value" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="璇勪及椤圭洰" prop="item"> + <el-input v-model="form.item" placeholder="璇疯緭鍏ヨ瘎浼伴」鐩�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="璁$畻鏂规硶" prop="itemDetail"> + <el-input v-model="form.itemDetail" placeholder="璇疯緭鍏�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍗曚綅" prop="unit"> + <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="瑕佺礌鎸囨爣" prop="code"> + <el-input v-model="form.code" placeholder="璇疯緭鍏ヨ绱犳寚鏍�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="褰掍竴鍖�" prop="normal"> + <el-input v-model="form.normal" placeholder="璇疯緭鍏ュ綊涓�鍖�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="瑕佺礌鏉冮噸" prop="weight"> + <el-input v-model="form.weight" placeholder="璇疯緭鍏ヨ绱犳潈閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍒嗙被鎸囨爣" prop="classifyIndex"> + <el-input v-model="form.classifyIndex" placeholder="璇疯緭鍏ュ垎绫绘寚鏍�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍒嗙被鏉冮噸" prop="classifyWeight"> + <el-input v-model="form.classifyWeight" placeholder="璇疯緭鍏ュ垎绫绘潈閲�" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + addAssessItem, + delAssessItem, + updateAssessItem, + getAssessList, + getAssessItem, +} from "@/api/manage/assess"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "Harbor", + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + selectShipType: "", + // 閮ㄩ棬鏍戦�夐」 + deptOptions: [ + { + label: "鍩哄湴", + value: "JD", + }, + { + label: "鏀槦", + value: "ZD", + }, + ], + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 淇濋殰闇�姹傝〃鏍兼暟鎹� + dsTaskList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + plan: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + type: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + item: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + itemDetail: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + unit: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + code: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + normal: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + weight: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + classifyIndex: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + classifyWeight: [{ required: true, message: "璇ュ瓧娈典笉鑳戒负绌�", trigger: "blur" }], + }, + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 鏌ヨtable鍒楄〃 */ + getList() { + this.loading = true; + getAssessList(this.queryParams).then((response) => { + this.dsTaskList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞寰呰ˉ缁欒埌鑹�"; + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎"' + row.item + '"鐨勬暟鎹」锛�') + .then(function () { + return delAssessItem(row.pkid); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getAssessItem(row.pkid).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼淇℃伅"; + }); + }, + + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + type: "", + plan: "", + item: "", + itemDetail: "", + unit: "", + code: "", + normal: "", + weight: null, + classifyIndex: "", + classifyWeight: null, + }; + this.resetForm("form"); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + console.log(this.form); + + if (this.form.pkid != null) { + updateAssessItem(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addAssessItem(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + }, +}; +</script> diff --git a/src/views/manage/assure/index.vue b/src/views/manage/assure/index.vue new file mode 100644 index 0000000..0f485d4 --- /dev/null +++ b/src/views/manage/assure/index.vue @@ -0,0 +1,540 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="鑸板瀷" prop="shipType"> + <el-input + v-model="queryParams.shipType" + placeholder="璇疯緭鍏ヨ埌鍨�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:harbor:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-upload2" + size="mini" + @click="handleImport" + >瀵煎叆</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="dsTaskList" + @selection-change="handleSelectionChange" + > + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="鑸板瀷" align="center" prop="shipType" /> + <el-table-column label="鑸峰彿" align="center" prop="shipNo" /> + <el-table-column label="鍚ㄤ綅(鍚�)" align="center" prop="tonnage" /> + <el-table-column label="鍚冩按(绫�)" align="center" prop="draft" /> + <el-table-column label="鑸伴暱(绫�)" align="center" prop="shipLen" /> + <el-table-column label="瀹氬憳(浜�)" align="center" prop="staff" /> + <el-table-column label="鎴樻湳缂栫粍" align="center" prop="grpName" /> + <el-table-column label="浣嶇疆鍖洪棿" align="center" prop="posArea" /> + <el-table-column label="浼樺厛绾�" align="center" prop="level" /> + <el-table-column label="鑸敤鏌存补(鍚�)" align="center" prop="oilA" /> + <el-table-column label="閫氱敤鏌存补(鍚�)" align="center" prop="oilB" /> + <el-table-column label="鑸┖鐓ゆ补(鍚�)" align="center" prop="oilG" /> + <el-table-column label="瀵煎脊(鏋�)" align="center" prop="ammoD" /> + <el-table-column label="鐐脊(鏋�)" align="center" prop="ammoP" /> + <el-table-column label="楸兼按闆�(鏋�)" align="center" prop="ammoS" /> + <el-table-column label="鍏朵粬寮硅嵂(鏋�)" align="center" prop="ammoO" /> + <el-table-column label="娣℃按(鍚�)" align="center" prop="water" /> + <el-table-column label="绾按(鍚�)" align="center" prop="waterP" /> + <el-table-column label="涓诲壇椋�(杞�)" align="center" prop="food" /> + <el-table-column label="妗惰姘�(杞�)" align="center" prop="foodW" /> + <el-table-column label="鍏朵粬鐗╄祫(杞�)" align="center" prop="foodO" /> + <el-table-column label="璁″垝鎶垫腐鏃堕棿" align="center" prop="pstime" /> + <el-table-column label="璁″垝绂绘腐鏃堕棿" align="center" prop="petime" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:harbor:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:harbor:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀规腐鍙d俊鎭璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="750px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鑸峰彿" prop="shipNo"> + <el-input v-model="form.shipNo" placeholder="璇疯緭鍏ヨ埛鍙�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鑸板瀷" prop="shipType"> + <el-select v-model="form.shipType" placeholder="璇烽�夋嫨" @change="selectedChange"> + <el-option + v-for="column in deptOptions" + :key="column.id" + :label="column.shipDesign" + :value="column.shipDesign" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="鎴樻湳缂栫粍" prop="grpName"> + <el-input v-model="form.grpName" placeholder="璇疯緭鍏ユ垬鏈紪缁�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="浣嶇疆鍖洪棿" prop="posArea"> + <el-input v-model="form.posArea" placeholder="璇疯緭鍏ヤ綅缃尯闂�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="浼樺厛绾�" prop="level"> + <el-input v-model="form.level" placeholder="璇疯緭鍏ヤ紭鍏堢骇" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="鑸扮敤鏌存补" prop="oilA"> + <el-input v-model="form.oilA" placeholder="璇疯緭鍏ヨ埌鐢ㄦ煷娌归噺" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="閫氱敤鏌存补" prop="oilB"> + <el-input v-model="form.oilB" placeholder="璇疯緭鍏ラ�氱敤鏌存补閲�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="鑸┖鐓ゆ补" prop="oilG"> + <el-input v-model="form.oilG" placeholder="璇疯緭鍏ヨ埅绌虹叅娌归噺" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="6"> + <el-form-item label="瀵煎脊" prop="ammoD"> + <el-input v-model="form.ammoD" placeholder="璇疯緭鍏ュ寮规暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="鐐脊" prop="ammoP"> + <el-input v-model="form.ammoP" placeholder="璇疯緭鍏ョ偖寮规暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="楸兼按闆�" prop="ammoS"> + <el-input v-model="form.ammoS" placeholder="璇疯緭鍏ラ奔姘撮浄鏁伴噺" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="鍏朵粬寮硅嵂" prop="ammoO"> + <el-input v-model="form.ammoO" placeholder="璇疯緭鍏ュ叾浠栧脊鑽暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="娣℃按鏁伴噺" prop="water"> + <el-input v-model="form.water" placeholder="璇疯緭鍏ユ贰姘存暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="绾按鏁伴噺" prop="waterP"> + <el-input v-model="form.waterP" placeholder="璇疯緭鍏ョ函姘存暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="涓诲壇椋熼噺" prop="food"> + <el-input v-model="form.food" placeholder="璇疯緭鍏ヤ富鍓閲�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="妗惰姘存暟閲�" prop="foodW"> + <el-input v-model="form.foodW" placeholder="璇疯緭鍏ユ《瑁呮按鏁伴噺" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="鍏朵粬鐗╄祫鏁伴噺" prop="foodO"> + <el-input v-model="form.foodO" placeholder="璇疯緭鍏ュ叾浠栫墿璧勬暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="璁″垝鎶垫腐鏃堕棿" prop="pstime"> + <el-date-picker + v-model="form.pstime" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="datetime" + placeholder="璁″垝鎶垫腐鏃堕棿" + ></el-date-picker> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="璁″垝绂绘腐鏃堕棿" prop="petime"> + <el-date-picker + v-model="form.petime" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="datetime" + placeholder="璁″垝绂绘腐鏃堕棿" + ></el-date-picker> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + + <!-- 鏂囦欢瀵煎叆瀵硅瘽妗� --> + <el-dialog + :title="upload.title" + :visible.sync="upload.open" + width="400px" + append-to-body + > + <el-upload + ref="upload" + :limit="1" + :headers="upload.headers" + :action="upload.url" + :data="uploadData" + :disabled="upload.isUploading" + :on-progress="handleFileUploadProgress" + :on-success="handleFileSuccess" + :auto-upload="false" + :before-upload="handleBeforeUpload" + drag + > + <i class="el-icon-upload"></i> + <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div> + <div class="el-upload__tip text-center" slot="tip"> + <!-- <div class="el-upload__tip" slot="tip"> + <el-checkbox v-model="upload.updateSupport" /> 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + </div> --> + <!-- <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span> --> + <el-link + type="primary" + :underline="false" + style="font-size: 12px; vertical-align: baseline" + @click="importTemplate" + >涓嬭浇妯℃澘</el-link + > + </div> + </el-upload> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button> + <el-button @click="upload.open = false">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + dsTaskList, + getDsTask, + delDsTask, + addDsTask, + updateDsTask, +} from "@/api/manage/dsTask"; +import { listAlldpShipTypeList } from "@/api/manage/shipType"; +import Treeselect from "@riophae/vue-treeselect"; +import { getToken } from "@/utils/auth"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "Harbor", + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + selectShipType: "", + // 閮ㄩ棬鏍戦�夐」 + deptOptions: undefined, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 淇濋殰闇�姹傝〃鏍兼暟鎹� + dsTaskList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + shipType: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + shipNo: [{ required: true, message: "鑸峰彿涓嶈兘涓虹┖", trigger: "blur" }], + shipType: [{ required: true, message: "鑸板瀷涓嶈兘涓虹┖", trigger: "blur" }], + }, + // 鐢ㄦ埛瀵煎叆鍙傛暟 + upload: { + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛� + open: false, + // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛� + title: "", + // 鏄惁绂佺敤涓婁紶 + isUploading: false, + // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + updateSupport: 0, + // 璁剧疆涓婁紶鐨勮姹傚ご閮� + headers: { Authorization: "Bearer " + getToken() }, + // 涓婁紶鐨勫湴鍧� + // url: process.env.VUE_APP_BASE_API + "/system/user/importData", + url: process.env.VUE_APP_BASE_API + "dp/sysFile/uploadFile", + }, + }; + }, + created() { + this.getList(); + this.getShipTypeList(); + }, + methods: { + + /** 涓嬭浇妯℃澘鎿嶄綔 */ + importTemplate() { + this.download( + "system/user/importTemplate", + {}, + `淇濋殰闇�姹傛ā鏉�.xls` + ); + // window.open("./template.xls"); + }, + + // 鏂囦欢涓婁紶鎴愬姛澶勭悊 + handleFileSuccess(response, file, fileList) { + // if (response.code === 200) { + // this.$modal.closeLoading(); + // this.upload.open = false; + // this.upload.isUploading = false; + // this.$refs.upload.clearFiles(); + // this.$modal.msgSuccess("涓婁紶鎴愬姛锛�"); + // // this.$alert( + // // "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + + // // response.msg + + // // "</div>", + // // "瀵煎叆缁撴灉", + // // { dangerouslyUseHTMLString: true } + // // ); + // this.getList(); + // } else { + // this.number--; + // this.$modal.closeLoading(); + // this.$modal.msgError("涓婁紶澶辫触锛岃閲嶆柊涓婁紶锛�"); + // } + }, + // 鎻愪氦涓婁紶鏂囦欢 + submitFileForm() { + this.upload.open = false; + // this.$refs.upload.submit(); + }, + + // 鏂囦欢涓婁紶涓鐞� + handleFileUploadProgress(event, file, fileList) { + this.upload.isUploading = true; + }, + /** 瀵煎叆鎸夐挳鎿嶄綔 */ + handleImport() { + this.upload.title = "闇�姹傚鍏�"; + this.upload.open = true; + }, + /** 鏌ヨ淇濋殰闇�姹傚垪琛� */ + getList() { + this.loading = true; + dsTaskList(this.queryParams).then((response) => { + this.dsTaskList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + /** 鏌ヨ鑸拌墖绫诲瀷涓嬫媺鏁版嵁 */ + getShipTypeList() { + listAlldpShipTypeList().then((response) => { + console.log(response.data); + this.deptOptions = response.data; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + pkid: null, + shipNo: null, + shipType: null, + tonnage: null, + draft: null, + shipLen: null, + staff: null, + grpName: null, + posArea: null, + level: null, + oilA: null, + oilB: null, + oilG: null, + ammoD: null, + ammoP: null, + ammoS: null, + ammoO: null, + water: null, + waterP: null, + food: null, + foodW: null, + foodO: null, + delFlag: null, + createBy: null, + createTime: null, + updateBy: null, + updateTime: null, + remark: null, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + selectedChange(selection) { + let selectedShipType = this.deptOptions.find(item => item.shipDesign == this.form.shipType); + this.form.tonnage = selectedShipType.tonnage; + this.form.draft = selectedShipType.draft; + this.form.shipLen = selectedShipType.length; + this.form.staff = selectedShipType.crew; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞寰呰ˉ缁欒埌鑹�"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getDsTask(row.pkid).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼淇℃伅"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.pkid != null) { + updateDsTask(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addDsTask(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎"' + row.shipNo + '"鐨勬暟鎹」锛�') + .then(function () { + return delDsTask(row.pkid); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + }, +}; +</script> diff --git a/src/views/manage/berth/index.vue b/src/views/manage/berth/index.vue new file mode 100644 index 0000000..f33645e --- /dev/null +++ b/src/views/manage/berth/index.vue @@ -0,0 +1,322 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="鐮佸ご" prop="harborId"> + <el-select v-model="queryParams.harborId" placeholder="璇烽�夋嫨鐮佸ご"> + <el-option key="0" label="鎵�鏈�" :value="0" /> + <el-option + v-for="item in whOptions" + :key="item.pkId" + :label="item.dockName" + :value="item.pkId" + ></el-option> + </el-select> + </el-form-item> + <!-- <el-form-item label="鐮佸ごid" prop="whId"> + <el-input + v-model="queryParams.whId" + placeholder="璇疯緭鍏ョ爜澶磇d" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> --> + <!-- <el-form-item label="娉婁綅鍚嶇О" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="璇疯緭鍏ユ硦浣嶅悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> --> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:berth:add']" + >鏂板</el-button + > + </el-col> + + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="berthList" + @selection-change="handleSelectionChange" + > + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="娓彛鍚嶇О" align="center" prop="harborName" /> + <el-table-column label="娉婁綅鍚嶇О" align="center" prop="name" /> + <el-table-column label="娉婁綅闀垮害" align="center" prop="berthLen" /> + <el-table-column label="鏈�灏忔按娣�" align="center" prop="depth" /> + <el-table-column label="鍋滄硦鑸拌墖鏁伴噺" align="center" prop="shipsNum" /> + <el-table-column prop="status" label="鐘舵��" width="60"> + <template slot-scope="scope"> + <span>{{ scope.row.status === 1 ? "鍚敤" : "鍋滅敤" }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:berth:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:berth:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀圭爜澶�-娉婁綅瀵硅瘽妗� --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鐮佸ご" prop="harborId"> + <el-select v-model="form.harborId" placeholder="璇烽�夋嫨鐮佸ご"> + <el-option + v-for="item in whOptions" + :key="item.pkId" + :label="item.dockName" + :value="item.pkId" + ></el-option> + </el-select> + </el-form-item> + <el-form-item label="娉婁綅鍚嶇О" prop="name"> + <el-input v-model="form.name" placeholder="璇疯緭鍏ユ硦浣嶅悕绉�" /> + </el-form-item> + <el-form-item label="娉婁綅闀垮害" prop="berthLen"> + <el-input v-model="form.berthLen" type="number" placeholder="璇疯緭鍏ユ硦浣嶅悕绉�" /> + </el-form-item> + <el-form-item label="鏈�灏忔按娣�" prop="depth"> + <el-input v-model="form.depth" type="number" placeholder="璇疯緭鍏ユ渶灏忔按娣�" /> + </el-form-item> + <el-form-item label="鍋滄硦鑸拌墖鏁伴噺" prop="shipsNum"> + <el-input v-model="form.shipsNum" type="number" placeholder="璇疯緭鍏ユ渶灏忔按娣�" /> + </el-form-item> + <el-form-item label="鍙敤鐘舵��" prop="status"> + <el-select v-model="form.status" placeholder="璇烽�夋嫨鐘舵��"> + <el-option key="99" label="姝e父" :value="1"></el-option> + <el-option key="100" label="鍋滅敤" :value="0"></el-option> + </el-select> + </el-form-item> + <el-form-item label="鎺掑簭" prop="orderNum"> + <el-input v-model="form.orderNum" type="number" placeholder="璇疯緭鍏ュ簭鍙�" /> + </el-form-item> + </el-form> + + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listBerth, getBerth, delBerth, addBerth, updateBerth } from "@/api/manage/berth"; +import { listAll } from "@/api/manage/stock"; +import { equList } from "@/api/manage/equipment"; + +export default { + name: "Berth", + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐮佸ご-娉婁綅琛ㄦ牸鏁版嵁 + berthList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + whId: null, + beName: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + //鐮佸ご閫夐」 + whOptions: [], + // 琛ㄥ崟鏍¢獙 + rules: { + whId: [{ required: true, message: "鐮佸ごid涓嶈兘涓虹┖", trigger: "blur" }], + beName: [{ required: true, message: "娉婁綅鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + }, + }; + }, + created() { + this.getList(); + listAll().then((response) => { + console.log(response); + this.whOptions = response.data; + }); + }, + methods: { + /** 鏌ヨ鐮佸ご-娉婁綅鍒楄〃 */ + getList() { + this.loading = true; + listBerth(this.queryParams).then((response) => { + this.berthList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + beId: null, + whId: null, + beName: null, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.beId); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + listAll().then((response) => { + console.log(response); + this.whOptions = response.data; + }); + this.open = true; + this.title = "娣诲姞鐮佸ご-娉婁綅"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + console.log(row); + listAll().then((response) => { + console.log(response); + this.whOptions = response.data; + }); + // const beId = row.beId || this.ids; + getBerth(row.pkid).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鐮佸ご-娉婁綅"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.pkid != null) { + updateBerth(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addBerth(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + // const beIds = row.beId || this.ids; + equList(row.pkid).then((response) => { + if (response.data.length > 0) { + this.$message.error(row.name + "涓嬫湁璁惧锛岃鍏堝垹闄ゅ搴旇澶�"); + } else { + this.$modal + .confirm('鏄惁纭鍒犻櫎"' + row.name + '"?') + .then(function () { + return delBerth(row.pkid); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + } + }); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/berth/export", + { + ...this.queryParams, + }, + `berth_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/manage/daily/index.vue b/src/views/manage/daily/index.vue new file mode 100644 index 0000000..3887df6 --- /dev/null +++ b/src/views/manage/daily/index.vue @@ -0,0 +1,392 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px" + @submit.native.prevent> + <el-form-item label="鑸板瀷" prop="shipType"> + <el-input v-model="queryParams.shipType" placeholder="璇疯緭鍏ヨ埌鍨�" clearable @keyup.enter.native="handleQuery" /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" + v-hasPermi="['system:harbor:add']">鏂板</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="dailyTaskList"> + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="鑸板瀷" align="center" prop="shipType" /> + <el-table-column label="鑸峰彿" align="center" prop="shipNo" /> + <el-table-column label="鍚ㄤ綅(鍚�)" align="center" prop="tonnage" /> + <el-table-column label="鍚冩按(绫�)" align="center" prop="draft" /> + <el-table-column label="鑸伴暱(绫�)" align="center" prop="shipLen" /> + <el-table-column label="瀹氬憳(浜�)" align="center" prop="staff" /> + <el-table-column label="鎴樻湳缂栫粍" align="center" prop="grpName" /> + <!-- <el-table-column label="浣嶇疆鍖洪棿" align="center" prop="posArea" /> --> + <!-- <el-table-column label="浼樺厛绾�" align="center" prop="level" /> --> + <el-table-column label="鑸敤鏌存补(鍚�)" align="center" prop="oilA" /> + <el-table-column label="閫氱敤鏌存补(鍚�)" align="center" prop="oilB" /> + <el-table-column label="鑸┖鐓ゆ补(鍚�)" align="center" prop="oilG" /> + <el-table-column label="瀵煎脊(鏋�)" align="center" prop="ammoD" /> + <el-table-column label="鐐脊(鏋�)" align="center" prop="ammoP" /> + <el-table-column label="楸兼按闆�(鏋�)" align="center" prop="ammoS" /> + <el-table-column label="鍏朵粬寮硅嵂(鏋�)" align="center" prop="ammoO" /> + <el-table-column label="娣℃按(鍚�)" align="center" prop="water" /> + <el-table-column label="绾按(鍚�)" align="center" prop="waterP" /> + <el-table-column label="涓诲壇椋�(杞�)" align="center" prop="food" /> + <el-table-column label="妗惰姘�(杞�)" align="center" prop="foodW" /> + <el-table-column label="鍏朵粬鐗╄祫(杞�)" align="center" prop="foodO" /> + <el-table-column label="璁″垝鎶垫腐鏃堕棿" align="center" prop="peTime" /> + <el-table-column label="璁″垝绂绘腐鏃堕棿" align="center" prop="psTime" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" + v-hasPermi="['system:harbor:remove']">鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" + @pagination="getList" /> + + <!-- 娣诲姞鎴栦慨鏀规腐鍙d俊鎭璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="750px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鑸峰彿" prop="shipNo"> + <el-input v-model="form.shipNo" placeholder="璇疯緭鍏ヨ埛鍙�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鑸板瀷" prop="shipType"> + <el-select v-model="form.shipType" placeholder="璇烽�夋嫨" @change="selectedChange"> + <el-option v-for="column in deptOptions" :key="column.id" :label="column.shipDesign" + :value="column.shipDesign"></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鐮佸ご" prop="harborId"> + <el-select v-model="form.harborInfo" value-key="whId" @change="selectedHarbor" placeholder="璇烽�夋嫨瑕佸垎閰嶇殑鐮佸ご"> + <el-option v-for="column in harborOptions" :key="column.id" :label="column.name" + :value="column"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="娉婁綅" prop="berthinfo"> + <el-select :disabled="berthAvailable" value-key="pkid" v-model="form.berthInfo" placeholder="璇烽�夋嫨瑕佸垎閰嶇殑娉婁綅"> + <el-option v-for="column in berthOptions" :key="column.pkid" :label="column.name" + :value="column"></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鎴樻湳缂栫粍" prop="grpName"> + <el-input v-model="form.grpName" placeholder="璇疯緭鍏ユ垬鏈紪缁�" /> + </el-form-item> + </el-col> + <!-- <el-col :span="8"> + <el-form-item label="浣嶇疆鍖洪棿" prop="posArea"> + <el-input v-model="form.posArea" placeholder="璇疯緭鍏ヤ綅缃尯闂�" /> + </el-form-item> + </el-col> --> + <el-col :span="12"> + <el-form-item label="浼樺厛绾�" prop="level"> + <el-input v-model="form.level" placeholder="璇疯緭鍏ヤ紭鍏堢骇" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="鑸扮敤鏌存补" prop="oilA"> + <el-input v-model="form.oilA" placeholder="璇疯緭鍏ヨ埌鐢ㄦ煷娌归噺" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="閫氱敤鏌存补" prop="oilB"> + <el-input v-model="form.oilB" placeholder="璇疯緭鍏ラ�氱敤鏌存补閲�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="鑸┖鐓ゆ补" prop="oilG"> + <el-input v-model="form.oilG" placeholder="璇疯緭鍏ヨ埅绌虹叅娌归噺" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="6"> + <el-form-item label="瀵煎脊" prop="ammoD"> + <el-input v-model="form.ammoD" placeholder="璇疯緭鍏ュ寮规暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="鐐脊" prop="ammoP"> + <el-input v-model="form.ammoP" placeholder="璇疯緭鍏ョ偖寮规暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="楸兼按闆�" prop="ammoS"> + <el-input v-model="form.ammoS" placeholder="璇疯緭鍏ラ奔姘撮浄鏁伴噺" /> + </el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="鍏朵粬寮硅嵂" prop="ammoO"> + <el-input v-model="form.ammoO" placeholder="璇疯緭鍏ュ叾浠栧脊鑽暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="娣℃按鏁伴噺" prop="water"> + <el-input v-model="form.water" placeholder="璇疯緭鍏ユ贰姘存暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="绾按鏁伴噺" prop="waterP"> + <el-input v-model="form.waterP" placeholder="璇疯緭鍏ョ函姘存暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="8"> + <el-form-item label="涓诲壇椋熼噺" prop="food"> + <el-input v-model="form.food" placeholder="璇疯緭鍏ヤ富鍓閲�" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="妗惰姘存暟閲�" prop="foodW"> + <el-input v-model="form.foodW" placeholder="璇疯緭鍏ユ《瑁呮按鏁伴噺" /> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="鍏朵粬鐗╄祫鏁伴噺" prop="foodO"> + <el-input v-model="form.foodO" placeholder="璇疯緭鍏ュ叾浠栫墿璧勬暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="璁″垝鎶垫腐鏃堕棿" prop="psTime"> + <el-date-picker v-model="form.psTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" + type="datetime" placeholder="璁″垝鎶垫腐鏃堕棿"></el-date-picker> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="璁″垝绂绘腐鏃堕棿" prop="peTime"> + <el-date-picker v-model="form.peTime" style="width: 240px" value-format="yyyy-MM-dd HH:mm:ss" + type="datetime" placeholder="璁″垝绂绘腐鏃堕棿"></el-date-picker> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { getDailyTask, delDailyTask, addDailyTask } from "@/api/manage/dsTask"; +import axios from "axios"; +import { listAlldpShipTypeList } from "@/api/manage/shipType"; +import { list } from "@/api/manage/wharf"; +import { beList } from "@/api/manage/berth"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "Harbor", + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + selectShipType: "", + berthPOI: [], + // 閮ㄩ棬鏍戦�夐」 + deptOptions: undefined, + harborOptions: undefined, + berthOptions: undefined, + berthAvailable: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 淇濋殰闇�姹傝〃鏍兼暟鎹� + dailyTaskList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + shipNo: [{ required: true, message: "鑸峰彿涓嶈兘涓虹┖", trigger: "blur" }], + shipType: [{ required: true, message: "鑸板瀷涓嶈兘涓虹┖", trigger: "blur" }], + }, + }; + }, + created() { + this.getList(); + this.getShipTypeList(); + }, + methods: { + /** 鏌ヨ淇濋殰闇�姹傚垪琛� */ + getList() { + this.loading = true; + getDailyTask(this.queryParams).then((response) => { + this.dailyTaskList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + /** 鏌ヨ涓嬫媺鏁版嵁 */ + getShipTypeList() { + listAlldpShipTypeList().then((response) => { + this.deptOptions = response.data; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + taskId: 999, + shipNo: null, + shipType: null, + harborInfo: null, + harborName: null, + harborId: null, + berthInfo: null, + berthName: null, + berthId: null, + tonnage: null, + draft: null, + shipLen: null, + staff: null, + grpName: null, + posArea: null, + level: "1", + oilA: null, + oilB: null, + oilG: null, + ammoD: null, + ammoP: null, + ammoS: null, + ammoO: null, + water: null, + waterP: null, + food: null, + foodW: null, + foodO: null, + remark: null, + psTime: "", + peTime: "", + posArea: "XMG", + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + selectedChange(selection) { + let selectedShipType = this.deptOptions.find( + (item) => item.shipDesign == this.form.shipType + ); + this.form.tonnage = selectedShipType.tonnage; + this.form.draft = selectedShipType.draft; + this.form.shipLen = selectedShipType.length; + this.form.staff = selectedShipType.crew; + }, + selectedHarbor(value) { + this.berthAvailable = false; + this.form.harborId = value.whId + this.form.harborName = value.name + + beList(value.whId).then((response) => { + this.berthOptions = response.data.filter((item) => item.name !== "鍥尯"); + }); + axios.get("/berthPOI.json").then((res) => { + this.berthPOI = res.data; + }); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞寰呰ˉ缁欒埌鑹�"; + list().then((response) => { + this.harborOptions = response.data; + }); + }, + + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + this.form.berthId = this.form.berthInfo.pkid; + this.form.berthName = this.form.berthInfo.name; + delete this.form.harborInfo; + delete this.form.berthInfo; + let { lon, lat, alt, heading } = this.berthPOI.filter( + (item) => item.berthId == this.form.berthId + )[0]; + addDailyTask({ lon, lat, alt, heading }, this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎"' + row.shipNo + '"鐨勬暟鎹」锛�') + .then(function () { + return delDailyTask(row.pkid); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => { }); + }, + }, +}; +</script> diff --git a/src/views/manage/data/chartView.vue b/src/views/manage/data/chartView.vue new file mode 100644 index 0000000..01c4c52 --- /dev/null +++ b/src/views/manage/data/chartView.vue @@ -0,0 +1,578 @@ +<template> + <div class="app-container"> + <div class="oilContainer"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i>娌硅〃鏁版嵁</span> + </div> + <div> + <el-row> + <el-col :span="6" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-pie-chart"></i> 鏁版嵁澶勭悊缁熻</span> + </div> + <div class="container"> + <div ref="oilPie" style="height: 300px" /> + </div> + </el-card> + </el-col> + + <el-col :span="8" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i> 鎿嶄綔缁熻</span> + </div> + <div class="container"> + <div ref="oilLine" style="height: 300px" /> + </div> + </el-card> + </el-col> + <el-col :span="10" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-tickets"></i> 鎺ュ彛璋冪敤</span> + </div> + <div class="container"> + <dv-scroll-board :config="oilConfig" style="height: 300px" /> + </div> + </el-card> + </el-col> + </el-row> + </div> + </el-card> + </div> + <div class="waterContainer"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i>姘磋〃鏁版嵁</span> + </div> + <div> + <el-row> + <el-col :span="6" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-pie-chart"></i> 鏁版嵁澶勭悊缁熻</span> + </div> + <div class="container"> + <div ref="waterPie" style="height: 300px" /> + </div> + </el-card> + </el-col> + + <el-col :span="8" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i> 鎿嶄綔缁熻</span> + </div> + <div class="container"> + <div ref="waterLine" style="height: 300px" /> + </div> + </el-card> + </el-col> + <el-col :span="10" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-tickets"></i> 鎺ュ彛璋冪敤</span> + </div> + <div class="container"> + <dv-scroll-board :config="WaterConfig" style="height: 300px" /> + </div> + </el-card> + </el-col> + </el-row> + </div> + </el-card> + </div> + <div class="eleContainer"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i>鐢佃〃鏁版嵁</span> + </div> + <div> + <el-row> + <el-col :span="6" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-pie-chart"></i> 鏁版嵁澶勭悊缁熻</span> + </div> + <div class="container"> + <div ref="elePie" style="height: 300px" /> + </div> + </el-card> + </el-col> + + <el-col :span="8" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-data-line"></i> 鎿嶄綔缁熻</span> + </div> + <div class="container"> + <div ref="eleLine" style="height: 300px" /> + </div> + </el-card> + </el-col> + <el-col :span="10" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-tickets"></i> 鎺ュ彛璋冪敤</span> + </div> + <div class="container"> + <dv-scroll-board :config="eleConfig" style="height: 300px" /> + </div> + </el-card> + </el-col> + </el-row> + </div> + </el-card> + </div> + </div> +</template> + +<script> +import { getCount, getLineData, getOperList } from "@/api/manage/clean"; +import * as echarts from "echarts"; +import dayjs from "dayjs"; +export default { + name: "Cache", + data() { + return { + waterPie: null, + waterLine: null, + WaterConfig: {}, + elePie: null, + eleLine: null, + eleConfig: {}, + oilPie: null, + oilLine: null, + oilConfig: {}, + }; + }, + created() { + this.getWaterList(); + this.getEleList(); + this.getOilList(); + }, + methods: { + /** 鏌ヤ俊鎭� */ + getWaterList() { + let startTime = dayjs().subtract(7, "day").format("YYYY-MM-DD"); + let endTime = dayjs().format("YYYY-MM-DD"); + getCount({ + title: "姘磋〃鏁版嵁", + }).then((response) => { + if (response.code == 200) { + let raw = response.data.rawCount; + let processed = response.data.processedData; + let last = raw - processed; + this.waterPie = echarts.init(this.$refs.waterPie, "macarons"); + this.waterPie.setOption({ + tooltip: { + trigger: "item", + }, + grid: { + left: "5%", + right: "5%", + top: "5%", + bottom: "5%", + containLabel: true, + }, + legend: {}, + series: [ + { + name: "鏁版嵁澶勭悊缁熻", + type: "pie", + radius: [5, 90], + center: ["50%", "48%"], + itemStyle: { + borderRadius: 10, + borderColor: "#fff", + borderWidth: 2, + }, + //data: response.data.commandStats, + data: [ + { value: processed, name: "宸插鐞�" }, + { value: last, name: "鏈鐞�" }, + ], + animationEasing: "cubicInOut", + animationDuration: 1000, + }, + ], + }); + } else { + this.$message.error("鑾峰彇姘磋〃鏁版嵁鎶ラ敊"); + } + }); + getLineData({ + title: "姘磋〃鏁版嵁", + startTime, + endTime, + }).then((res) => { + if (res.code == 200) { + //dateTime: "2025-04-20", insertCount: 0, updateCount: 0, deleteCount: 0 + let dateArr = []; + let insertArr = []; + let updateArr = []; + let deleteArr = []; + res.data.forEach((item) => { + dateArr.push(item.dateTime); + insertArr.push(item.insertCount); + updateArr.push(item.updateCount); + deleteArr.push(item.deleteCount); + }); + this.waterLine = echarts.init(this.$refs.waterLine, "macarons"); + this.waterLine.setOption({ + tooltip: { + trigger: "axis", + }, + legend: { + data: ["鏂板", "缂栬緫", "鍒犻櫎"], + }, + xAxis: { + type: "category", + boundaryGap: false, + data: dateArr, + }, + yAxis: { + type: "value", + }, + series: [ + { + name: "鏂板", + type: "line", + data: insertArr, + }, + { + name: "缂栬緫", + type: "line", + data: updateArr, + }, + { + name: "鍒犻櫎", + type: "line", + data: deleteArr, + }, + ], + }); + } else { + this.$message.error("鑾峰彇姘磋〃鏁版嵁鎶ラ敊"); + } + }); + getOperList({ + pageNum: 1, + pageSize: 20, + title: "姘磋〃鏁版嵁", + }).then((res) => { + if (res.code == 200) { + let configData = []; + res.data.rows.forEach((item, index) => { + let json = JSON.parse(item.jsonResult); + configData.push([ + index + 1, + item.title, + json.data, + item.operName, + item.operTime, + ]); + }); + this.WaterConfig = { + header: ["缂栧彿", "鍚嶇О", "鏁伴噺", "鐢ㄦ埛鍚�", "鎿嶄綔鏃堕棿"], + rowNum: 8, + columnWidth: [60, 120, 60], + align: ["center", "center", "center", "center", "center"], + headerBGC: "#ffffff", + oddRowBGC: "#ffffff", + evenRowBGC: "#f6f8fa", + data: configData, + }; + } else { + this.$message.error("鑾峰彇姘磋〃鏁版嵁鎶ラ敊"); + } + }); + }, + getEleList() { + let startTime = dayjs().subtract(7, "day").format("YYYY-MM-DD"); + let endTime = dayjs().format("YYYY-MM-DD"); + getCount({ + title: "鐢佃〃鏁版嵁", + }).then((response) => { + if (response.code == 200) { + let raw = response.data.rawCount; + let processed = response.data.processedData; + let last = raw - processed; + this.elePie = echarts.init(this.$refs.elePie, "macarons"); + this.elePie.setOption({ + tooltip: { + trigger: "item", + }, + grid: { + left: "5%", + right: "5%", + top: "5%", + bottom: "5%", + containLabel: true, + }, + legend: {}, + series: [ + { + name: "鏁版嵁澶勭悊缁熻", + type: "pie", + radius: [5, 90], + center: ["50%", "48%"], + itemStyle: { + borderRadius: 10, + borderColor: "#fff", + borderWidth: 2, + }, + //data: response.data.commandStats, + data: [ + { value: processed, name: "宸插鐞�" }, + { value: last, name: "鏈鐞�" }, + ], + animationEasing: "cubicInOut", + animationDuration: 1000, + }, + ], + }); + } else { + this.$message.error("鑾峰彇鐢佃〃鏁版嵁鎶ラ敊"); + } + }); + getLineData({ + title: "鐢佃〃鏁版嵁", + startTime, + endTime, + }).then((res) => { + if (res.code == 200) { + //dateTime: "2025-04-20", insertCount: 0, updateCount: 0, deleteCount: 0 + let dateArr = []; + let insertArr = []; + let updateArr = []; + let deleteArr = []; + res.data.forEach((item) => { + dateArr.push(item.dateTime); + insertArr.push(item.insertCount); + updateArr.push(item.updateCount); + deleteArr.push(item.deleteCount); + }); + this.eleLine = echarts.init(this.$refs.eleLine, "macarons"); + this.eleLine.setOption({ + tooltip: { + trigger: "axis", + }, + legend: { + data: ["鏂板", "缂栬緫", "鍒犻櫎"], + }, + xAxis: { + type: "category", + boundaryGap: false, + data: dateArr, + }, + yAxis: { + type: "value", + }, + series: [ + { + name: "鏂板", + type: "line", + data: insertArr, + }, + { + name: "缂栬緫", + type: "line", + data: updateArr, + }, + { + name: "鍒犻櫎", + type: "line", + data: deleteArr, + }, + ], + }); + } else { + this.$message.error("鑾峰彇鐢佃〃鏁版嵁鎶ラ敊"); + } + }); + getOperList({ + pageNum: 1, + pageSize: 20, + title: "鐢佃〃鏁版嵁", + }).then((res) => { + if (res.code == 200) { + let configData = []; + res.data.rows.forEach((item, index) => { + let json = JSON.parse(item.jsonResult); + configData.push([ + index + 1, + item.title, + json.data, + item.operName, + item.operTime, + ]); + }); + this.eleConfig = { + header: ["缂栧彿", "鍚嶇О", "鏁伴噺", "鐢ㄦ埛鍚�", "鎿嶄綔鏃堕棿"], + rowNum: 8, + columnWidth: [60, 120, 60], + align: ["center", "center", "center", "center", "center"], + headerBGC: "#ffffff", + oddRowBGC: "#ffffff", + evenRowBGC: "#f6f8fa", + data: configData, + }; + } else { + this.$message.error("鑾峰彇鐢佃〃鏁版嵁鎶ラ敊"); + } + }); + }, + getOilList() { + let startTime = dayjs().subtract(7, "day").format("YYYY-MM-DD"); + let endTime = dayjs().format("YYYY-MM-DD"); + getCount({ + title: "娌硅〃鏁版嵁", + }).then((response) => { + if (response.code == 200) { + let raw = response.data.rawCount; + let processed = response.data.processedData; + let last = raw - processed; + this.oilPie = echarts.init(this.$refs.oilPie, "macarons"); + this.oilPie.setOption({ + tooltip: { + trigger: "item", + }, + grid: { + left: "5%", + right: "5%", + top: "5%", + bottom: "5%", + containLabel: true, + }, + legend: {}, + series: [ + { + name: "鏁版嵁澶勭悊缁熻", + type: "pie", + radius: [5, 90], + center: ["50%", "48%"], + itemStyle: { + borderRadius: 10, + borderColor: "#fff", + borderWidth: 2, + }, + //data: response.data.commandStats, + data: [ + { value: processed, name: "宸插鐞�" }, + { value: last, name: "鏈鐞�" }, + ], + animationEasing: "cubicInOut", + animationDuration: 1000, + }, + ], + }); + } else { + this.$message.error("鑾峰彇娌硅〃鏁版嵁鎶ラ敊"); + } + }); + getLineData({ + title: "娌硅〃鏁版嵁", + startTime, + endTime, + }).then((res) => { + if (res.code == 200) { + //dateTime: "2025-04-20", insertCount: 0, updateCount: 0, deleteCount: 0 + let dateArr = []; + let insertArr = []; + let updateArr = []; + let deleteArr = []; + res.data.forEach((item) => { + dateArr.push(item.dateTime); + insertArr.push(item.insertCount); + updateArr.push(item.updateCount); + deleteArr.push(item.deleteCount); + }); + this.oilLine = echarts.init(this.$refs.oilLine, "macarons"); + this.oilLine.setOption({ + tooltip: { + trigger: "axis", + }, + legend: { + data: ["鏂板", "缂栬緫", "鍒犻櫎"], + }, + xAxis: { + type: "category", + boundaryGap: false, + data: dateArr, + }, + yAxis: { + type: "value", + }, + series: [ + { + name: "鏂板", + type: "line", + data: insertArr, + }, + { + name: "缂栬緫", + type: "line", + data: updateArr, + }, + { + name: "鍒犻櫎", + type: "line", + data: deleteArr, + }, + ], + }); + } else { + this.$message.error("鑾峰彇娌硅〃鏁版嵁鎶ラ敊"); + } + }); + getOperList({ + pageNum: 1, + pageSize: 20, + title: "娌硅〃鏁版嵁", + }).then((res) => { + if (res.code == 200) { + let configData = []; + res.data.rows.forEach((item, index) => { + let json = JSON.parse(item.jsonResult); + configData.push([ + index + 1, + item.title, + json.data, + item.operName, + item.operTime, + ]); + }); + this.oilConfig = { + header: ["缂栧彿", "鍚嶇О", "鏁伴噺", "鐢ㄦ埛鍚�", "鎿嶄綔鏃堕棿"], + rowNum: 8, + columnWidth: [60, 120, 60], + align: ["center", "center", "center", "center", "center"], + headerBGC: "#ffffff", + oddRowBGC: "#ffffff", + evenRowBGC: "#f6f8fa", + data: configData, + }; + } else { + this.$message.error("鑾峰彇娌硅〃鏁版嵁鎶ラ敊"); + } + }); + }, + }, +}; +</script> + +<style scoped lang="scss"> +.waterContainer { + margin-top: 15px; +} + +.eleContainer { + margin-top: 15px; +} +.dv-scroll-board { + color: black !important; +} +</style> diff --git a/src/views/manage/data/metaData.vue b/src/views/manage/data/metaData.vue new file mode 100644 index 0000000..f70fd7e --- /dev/null +++ b/src/views/manage/data/metaData.vue @@ -0,0 +1,493 @@ +<template> + <div class="app-container"> + <el-row :gutter="20"> + <!--鎰熺煡璁惧--> + <el-col :span="4" :xs="24"> + <div class="head-container"> + <el-tree + :data="equOptions" + ref="tree" + node-key="id" + highlight-current + @node-click="handleNodeClick" + /> + </div> + </el-col> + <!--璁惧鎺ㄩ�佹暟鎹�--> + <el-col :span="20" :xs="24"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + > + <el-form-item label="閲囬泦鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="datetimerange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button + type="primary" + icon="el-icon-search" + size="mini" + @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery" + >閲嶇疆</el-button + > + <el-button icon="el-icon-plus" size="mini" @click="addToResult" + >澶勭悊涓嬪彂</el-button + > + </el-form-item> + </el-form> + + <el-table + v-loading="loading" + :data="equDataList" + table-layout="auto" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55"></el-table-column> + + <el-table-column type="index" width="50" label="搴忓彿" /> + <el-table-column + v-for="(col, index) in columns" + :key="index" + :label="col.param" + :prop="col.paramCode" + min-width="150" + align="center" + /> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-col> + </el-row> + </div> +</template> + +<script> +import { + listUser, + getUser, + delUser, + addUser, + updateUser, + resetUserPwd, + changeUserStatus, + deptTreeSelect, +} from "@/api/system/user"; +import { + equTree, + dataList, + dataPageList, + addEquRes, + getEquTypeByid, +} from "@/api/manage/equipment"; +import { getToken } from "@/utils/auth"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "User", + dicts: ["sys_normal_disable", "sys_user_sex"], + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + selectedData: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐢ㄦ埛琛ㄦ牸鏁版嵁 + equDataList: null, + // 寮瑰嚭灞傛爣棰� + title: "", + // 璁惧鏍戦�夐」 + equOptions: undefined, + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 閮ㄩ棬鍚嶇О + deptName: undefined, + // 榛樿瀵嗙爜 + initPassword: undefined, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 榛樿閫変腑鐨勮妭鐐� + defaultCheckedKeys: 15, + defaultExpandedKeys: [], + // 宀椾綅閫夐」 + postOptions: [], + // 瑙掕壊閫夐」 + roleOptions: [], + // 琛ㄥ崟鍙傛暟 + form: {}, + defaultProps: { + children: "children", + label: "label", + }, + // 鐢ㄦ埛瀵煎叆鍙傛暟 + upload: { + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛� + open: false, + // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛� + title: "", + // 鏄惁绂佺敤涓婁紶 + isUploading: false, + // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + updateSupport: 0, + // 璁剧疆涓婁紶鐨勮姹傚ご閮� + headers: { Authorization: "Bearer " + getToken() }, + // 涓婁紶鐨勫湴鍧� + url: process.env.VUE_APP_BASE_API + "/system/user/importData", + }, + // 鏌ヨ鍙傛暟 + queryParams: { + startTime: null, + endTime: null, + pageSize: 20, + pageNum: 0, + id: 0, + }, + // 鍒椾俊鎭� + columns: [ + { key: 0, label: `鐢ㄦ埛缂栧彿`, visible: true }, + { key: 1, label: `鐢ㄦ埛鍚嶇О`, visible: true }, + { key: 2, label: `鐢ㄦ埛鏄电О`, visible: true }, + { key: 3, label: `閮ㄩ棬`, visible: true }, + { key: 4, label: `鎵嬫満鍙风爜`, visible: true }, + { key: 5, label: `鐘舵�乣, visible: true }, + { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }, + ], + // 琛ㄥ崟鏍¢獙 + rules: { + userName: [ + { required: true, message: "鐢ㄦ埛鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }, + { + min: 2, + max: 20, + message: "鐢ㄦ埛鍚嶇О闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿", + trigger: "blur", + }, + ], + nickName: [{ required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" }], + password: [ + { required: true, message: "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }, + { + min: 5, + max: 20, + message: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿", + trigger: "blur", + }, + ], + email: [ + { + type: "email", + message: "璇疯緭鍏ユ纭殑閭鍦板潃", + trigger: ["blur", "change"], + }, + ], + phonenumber: [ + { + pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, + message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", + trigger: "blur", + }, + ], + }, + }; + }, + watch: { + // 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 + deptName(val) { + this.$refs.tree.filter(val); + }, + equOptions(val) { + if (val.length > 0) { + this.$nextTick(() => { + this.$refs.tree.setCurrentKey(val[0].children[0].id); + this.handleNodeClick(val[0].children[0]); + }); + } + }, + }, + created() { + this.getEquTree(); + this.getConfigKey("sys.user.initPassword").then((response) => { + this.initPassword = response.msg; + }); + }, + methods: { + /** 鏌ヨ鐢ㄦ埛鍒楄〃 */ + getList() { + this.queryParams.startTime = this.dateRange[0]; + this.queryParams.endTime = this.dateRange[1]; + this.loading = true; + dataPageList(this.queryParams).then((response) => { + /** this.userList = response.rows; */ + this.total = response.data.dataList.total; + this.equDataList = response.data.dataList.rows; + this.columns = response.data.tableList.reverse(); + + this.loading = false; + }); + }, + /** 鏌ヨ璁惧涓嬫媺鏍戠粨鏋� */ + getEquTree() { + equTree().then((response) => { + this.equOptions = response.data; + console.log(this.equOptions); + var datas = response.data; + datas.forEach((val, key) => { + if (val.children) { + this.defaultExpandedKeys.push(val.id); + } + }); + this.defaultCheckedKeys = response.data[0].children[0].id; + }); + }, + // 鑺傜偣鍗曞嚮浜嬩欢 + handleNodeClick(data) { + if (data.disabled) { + return; + } + this.queryParams.id = data.id; + this.handleQuery(); + }, + // 鐢ㄦ埛鐘舵�佷慨鏀� + handleStatusChange(row) { + let text = row.status === "0" ? "鍚敤" : "鍋滅敤"; + this.$modal + .confirm('纭瑕�"' + text + '""' + row.userName + '"鐢ㄦ埛鍚楋紵') + .then(function () { + return changeUserStatus(row.userId, row.status); + }) + .then(() => { + this.$modal.msgSuccess(text + "鎴愬姛"); + }) + .catch(function () { + row.status = row.status === "0" ? "1" : "0"; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + userId: undefined, + deptId: undefined, + userName: undefined, + nickName: undefined, + password: undefined, + phonenumber: undefined, + email: undefined, + sex: undefined, + status: "0", + remark: undefined, + postIds: [], + roleIds: [], + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.deptId = undefined; + this.$refs.tree.setCurrentKey(null); + this.handleQuery(); + }, + + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + // console.log(selection); + this.selectedData = selection; + // this.ids = selection.map((item) => item.userId); + // this.single = selection.length != 1; + // this.multiple = !selection.length; + }, + addToResult() { + getEquTypeByid(this.queryParams.id).then((response) => { + addEquRes(response.data, this.selectedData).then((response) => { + this.$modal.msgSuccess( + `涓嬪彂鎴愬姛锛屾湰娆℃彁浜�${this.selectedData.length}鏉℃暟鎹紝鎴愬姛鎻掑叆${response.data}鏉℃暟鎹甡 + ); + // this.open = false; + // this.getList(); + }); + }); + }, + // 鏇村鎿嶄綔瑙﹀彂 + handleCommand(command, row) { + switch (command) { + case "handleResetPwd": + this.handleResetPwd(row); + break; + case "handleAuthRole": + this.handleAuthRole(row); + break; + default: + break; + } + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + getUser().then((response) => { + this.postOptions = response.posts; + this.roleOptions = response.roles; + this.open = true; + this.title = "娣诲姞鐢ㄦ埛"; + this.form.password = this.initPassword; + }); + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const userId = row.userId || this.ids; + getUser(userId).then((response) => { + this.form = response.data; + this.postOptions = response.posts; + this.roleOptions = response.roles; + this.$set(this.form, "postIds", response.postIds); + this.$set(this.form, "roleIds", response.roleIds); + this.open = true; + this.title = "淇敼鐢ㄦ埛"; + this.form.password = ""; + }); + }, + /** 閲嶇疆瀵嗙爜鎸夐挳鎿嶄綔 */ + handleResetPwd(row) { + this.$prompt('璇疯緭鍏�"' + row.userName + '"鐨勬柊瀵嗙爜', "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + closeOnClickModal: false, + inputPattern: /^.{5,20}$/, + inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿", + }) + .then(({ value }) => { + resetUserPwd(row.userId, value).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value); + }); + }) + .catch(() => {}); + }, + /** 鍒嗛厤瑙掕壊鎿嶄綔 */ + handleAuthRole: function (row) { + const userId = row.userId; + this.$router.push("/system/user-auth/role/" + userId); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.userId != undefined) { + updateUser(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addUser(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const userIds = row.userId || this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎鐢ㄦ埛缂栧彿涓�"' + userIds + '"鐨勬暟鎹」锛�') + .then(function () { + return delUser(userIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/user/export", + { + ...this.queryParams, + }, + `user_${new Date().getTime()}.xlsx` + ); + }, + /** 瀵煎叆鎸夐挳鎿嶄綔 */ + handleImport() { + this.upload.title = "鐢ㄦ埛瀵煎叆"; + this.upload.open = true; + }, + /** 涓嬭浇妯℃澘鎿嶄綔 */ + importTemplate() { + this.download( + "system/user/importTemplate", + {}, + `user_template_${new Date().getTime()}.xlsx` + ); + }, + // 鏂囦欢涓婁紶涓鐞� + handleFileUploadProgress(event, file, fileList) { + this.upload.isUploading = true; + }, + // 鏂囦欢涓婁紶鎴愬姛澶勭悊 + handleFileSuccess(response, file, fileList) { + this.upload.open = false; + this.upload.isUploading = false; + this.$refs.upload.clearFiles(); + this.$alert( + "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + + response.msg + + "</div>", + "瀵煎叆缁撴灉", + { dangerouslyUseHTMLString: true } + ); + this.getList(); + }, + // 鎻愪氦涓婁紶鏂囦欢 + submitFileForm() { + this.$refs.upload.submit(); + }, + }, +}; +</script> diff --git a/src/views/manage/data/resultData.vue b/src/views/manage/data/resultData.vue new file mode 100644 index 0000000..f9ae9e0 --- /dev/null +++ b/src/views/manage/data/resultData.vue @@ -0,0 +1,397 @@ +<template> + <div class="app-container"> + <el-row :gutter="20"> + <!--鎰熺煡璁惧--> + <el-col :span="4" :xs="24"> + <div class="head-container"> + <el-tree + :data="equOptions" + ref="tree" + node-key="id" + highlight-current + @node-click="handleNodeClick" + /> + </div> + </el-col> + <!--璁惧鎺ㄩ�佹暟鎹�--> + <el-col :span="20" :xs="24"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + > + <el-form-item label="閲囬泦鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="datetimerange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button + type="primary" + icon="el-icon-search" + size="mini" + @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery" + >閲嶇疆</el-button + > + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + >鍒犻櫎</el-button + > + </el-col> + </el-form-item> + </el-form> + + <el-table + @selection-change="handleSelectionChange" + v-loading="loading" + :data="equDataList" + table-layout="auto" + fit + > + <el-table-column type="selection" width="55"></el-table-column> + <el-table-column type="index" width="50" label="搴忓彿" /> + <el-table-column + v-for="(col, index) in columns" + :key="index" + :label="col.param" + :prop="col.paramCode" + min-width="150" + align="center" + /> + <el-table-column + label="鎿嶄綔" + align="center" + class-name="small-padding fixed-width" + min-width="100" + > + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:supplement:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:supplement:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-col> + </el-row> + <!-- 娣诲姞鎴栦慨鏀硅埌鑸瑰璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" label-width="150px"> + <div v-for="(col, index) in columns"> + <el-form-item + v-if="col.paramCode !== 'createTime' && col.paramCode !== 'updateTime'" + :label="col.param" + :prop="col.paramCode" + > + <el-input v-model="form[col.paramCode]" placeholder="璇疯緭鍏�" /> + </el-form-item> + </div> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listUser, + getUser, + delUser, + addUser, + updateUser, + resetUserPwd, + changeUserStatus, + deptTreeSelect, +} from "@/api/system/user"; +import { + equTree, + dataList, + dataPageList, + updateResData, + delResData, + getEquTypeByid, +} from "@/api/manage/equRes"; +import { getToken } from "@/utils/auth"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "User", + dicts: ["sys_normal_disable", "sys_user_sex"], + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐢ㄦ埛琛ㄦ牸鏁版嵁 + equDataList: null, + // 寮瑰嚭灞傛爣棰� + title: "", + // 璁惧鏍戦�夐」 + equOptions: undefined, + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 閮ㄩ棬鍚嶇О + deptName: undefined, + // 榛樿瀵嗙爜 + initPassword: undefined, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 榛樿閫変腑鐨勮妭鐐� + defaultCheckedKeys: 15, + defaultExpandedKeys: [], + // 宀椾綅閫夐」 + postOptions: [], + // 瑙掕壊閫夐」 + roleOptions: [], + // 琛ㄥ崟鍙傛暟 + form: {}, + defaultProps: { + children: "children", + label: "label", + }, + // 鐢ㄦ埛瀵煎叆鍙傛暟 + upload: { + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛� + open: false, + // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛� + title: "", + // 鏄惁绂佺敤涓婁紶 + isUploading: false, + // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + updateSupport: 0, + // 璁剧疆涓婁紶鐨勮姹傚ご閮� + headers: { Authorization: "Bearer " + getToken() }, + // 涓婁紶鐨勫湴鍧� + url: process.env.VUE_APP_BASE_API + "/system/user/importData", + }, + // 鏌ヨ鍙傛暟 + queryParams: { + startTime: null, + endTime: null, + pageSize: 20, + pageNum: 0, + id: 0, + }, + // 鍒椾俊鎭� + columns: [ + { key: 0, label: `鐢ㄦ埛缂栧彿`, visible: true }, + { key: 1, label: `鐢ㄦ埛鍚嶇О`, visible: true }, + { key: 2, label: `鐢ㄦ埛鏄电О`, visible: true }, + { key: 3, label: `閮ㄩ棬`, visible: true }, + { key: 4, label: `鎵嬫満鍙风爜`, visible: true }, + { key: 5, label: `鐘舵�乣, visible: true }, + { key: 6, label: `鍒涘缓鏃堕棿`, visible: true }, + ], + // 琛ㄥ崟鏍¢獙 + }; + }, + watch: { + // 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 + deptName(val) { + this.$refs.tree.filter(val); + }, + equOptions(val) { + if (val.length > 0) { + this.$nextTick(() => { + this.$refs.tree.setCurrentKey(val[0].children[0].id); + this.handleNodeClick(val[0].children[0]); + }); + } + }, + }, + created() { + this.getEquTree(); + this.getConfigKey("sys.user.initPassword").then((response) => { + this.initPassword = response.msg; + }); + }, + methods: { + /** 鏌ヨ鍒楄〃 */ + getList() { + if (!this.dateRange) { + this.resetQuery(); + } + + this.queryParams.startTime = this.dateRange[0]; + this.queryParams.endTime = this.dateRange[1]; + this.loading = true; + dataPageList(this.queryParams).then((response) => { + /** this.userList = response.rows; */ + this.total = response.data.dataList.total; + this.equDataList = response.data.dataList.rows; + response.data.tableList.push({ + id: null, + deviceName: null, + deviceAddress: 0, + ip: null, + port: null, + functionCode: 0, + registerAdress: null, + registerCount: null, + crc: null, + dataType: null, + param: "鏇存柊鏃堕棿", + paramCode: "updateTime", + unit: null, + }); + this.columns = response.data.tableList.reverse(); + + this.loading = false; + }); + }, + /** 鏌ヨ璁惧涓嬫媺鏍戠粨鏋� */ + getEquTree() { + equTree().then((response) => { + this.equOptions = response.data; + // console.log(this.equOptions); + var datas = response.data; + datas.forEach((val, key) => { + if (val.children) { + this.defaultExpandedKeys.push(val.id); + } + }); + this.defaultCheckedKeys = response.data[0].children[0].id; + }); + }, + // 鑺傜偣鍗曞嚮浜嬩欢 + handleNodeClick(data) { + if (data.disabled) { + return; + } + this.queryParams.id = data.id; + this.handleQuery(); + }, + + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + userId: undefined, + deptId: undefined, + userName: undefined, + nickName: undefined, + password: undefined, + phonenumber: undefined, + email: undefined, + sex: undefined, + status: "0", + remark: undefined, + postIds: [], + roleIds: [], + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.deptId = undefined; + this.$refs.tree.setCurrentKey(null); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.id); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + const { updateTime, ...formData } = row; + this.form = formData; + this.open = true; + this.title = "淇敼鏁版嵁"; + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + getEquTypeByid(this.queryParams.id).then((response) => { + updateResData(response.data, this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const equid = this.queryParams.id; + const userIds = row.id || this.ids; + this.$modal + .confirm("鏄惁纭鍒犻櫎鏁版嵁椤癸紵") + .then(function () { + return getEquTypeByid(equid); + }) + .then((res) => { + let idsArr = Array.isArray(userIds) ? userIds : [userIds]; + delResData(res.data, idsArr).then((response) => { + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + this.getList(); + }); + }) + .catch(() => {}); + }, + }, +}; +</script> diff --git a/src/views/manage/equType/index.vue b/src/views/manage/equType/index.vue new file mode 100644 index 0000000..0b0eddf --- /dev/null +++ b/src/views/manage/equType/index.vue @@ -0,0 +1,349 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="璁惧绫诲瀷鍚嶇О" prop="typeName"> + <el-input + v-model="queryParams.typeName" + placeholder="璇疯緭鍏ヨ澶囩被鍨嬪悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:equipment:add']" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="equipmentList" + @selection-change="handleSelectionChange" + > + <!-- <el-table-column type="selection" width="55" align="center" /> --> + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="绫诲瀷鍚嶇О" align="center" prop="typeName" /> + <el-table-column label="璁惧璇︽儏" align="center" prop="description" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:equipment:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:equipment:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀硅澶囩被鍨嬪璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="绫诲瀷鍚嶇О" prop="typeName"> + <el-input v-model="form.typeName" placeholder="璇疯緭鍏ヨ澶囩被鍨嬪悕绉�" /> + </el-form-item> + <el-form-item label="璁惧璇︽儏" prop="description"> + <el-input v-model="form.description" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" /> + </el-form-item> + <el-form-item label="璁惧鍥剧墖" prop="filePath"> + <el-upload + :file-list="fileList" + :action="uploadFileUrl" + list-type="picture-card" + :on-preview="handlePictureCardPreview" + :on-remove="handleRemove" + :on-success="handleAvatarSuccess" + accept=".jpg,.jpeg,.png,.rar,.zip" + > + <i class="el-icon-plus"></i> + </el-upload> + <el-dialog :visible.sync="dialogVisible"> + <img width="100%" :src="dialogImageUrl" alt="" /> + </el-dialog> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listEquipment, + getEquipment, + delEquipment, + addEquipment, + updateEquipment, +} from "@/api/manage/equType"; + +// let url = process.env.VUE_URL+'common/upload' +const baseUrl = process.env.VUE_APP_BASE_API; + +console.log("uploadUrl", baseUrl); +export default { + name: "Equipment", + dicts: ["dp_equipment_type"], + data() { + return { + // 閬僵灞� + loading: true, + fileList: [], + dialogImageUrl: "", + dialogVisible: false, + imageUrl: "", + // 閫変腑鏁扮粍 + ids: [], + url: process.env.VUE_URL + "common/upload", + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 娉婁綅--璁惧琛ㄦ牸鏁版嵁 + equipmentList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + beId: null, + equName: null, + equType: null, + DESCRIPTION: null, + filePath: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + //鐮佸ご閫夐」 + whOptions: [], + //娉婁綅閫夐」 + beOptions: [], + // 琛ㄥ崟鏍¢獙 + rules: { + beId: [{ required: true, message: "娉婁綅涓嶈兘涓虹┖", trigger: "blur" }], + whId: [{ required: true, message: "鐮佸ご涓嶈兘涓虹┖", trigger: "blur" }], + equName: [{ required: true, message: "璁惧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + equType: [{ required: true, message: "璁惧绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }], + }, + uploadFileUrl: baseUrl + "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ娉婁綅--璁惧鍒楄〃 */ + getList() { + this.loading = true; + listEquipment(this.queryParams).then((response) => { + this.equipmentList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + this.imageUrl = ""; + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + id: null, + beId: null, + equName: null, + equType: null, + description: null, + filePath: null, + }; + this.resetForm("form"); + this.fileList = []; + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.ID); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.imageUrl = ""; + this.open = true; + this.title = "娣诲姞鎰熺煡璁惧绫诲瀷"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getEquipment(row.id).then((response) => { + this.form = response.data; + var fileListStr = response.data.filePath; + if (fileListStr) { + if (fileListStr.endsWith(",")) { + this.imageUrl = fileListStr; + fileListStr = fileListStr.slice(0, -1); // 鍒犻櫎鏈�鍚庝竴涓瓧绗︼紙閫楀彿锛� + } else { + this.imageUrl = fileListStr + ","; + } + const arr = fileListStr.split(","); // 灏嗘枃浠惰矾寰勫瓧绗︿覆鎷嗗垎鎴愭暟缁� + const baseFileUrl = baseUrl.slice(0, -1); + this.fileList = arr.map((item, index) => ({ + name: item.split("/").pop(), // 鎻愬彇鏂囦欢鍚� + url: baseFileUrl + item, // 鎷兼帴瀹屾暣鐨勬枃浠� URL + status: "success", // 涓婁紶鐘舵�佽缃负鎴愬姛 + uid: `uid-${index}`, // 浣跨敤鍞竴鐨� uid + })); + console.log(this.fileList); // 妫�鏌ユ枃浠跺垪琛� + } else { + this.imageUrl = ""; + } + console.log(this.form); // 妫�鏌ヨ〃鍗曟暟鎹� + this.open = true; + this.title = "淇敼娉婁綅--璁惧"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.id != null) { + updateEquipment(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addEquipment(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎娉婁綅--璁惧缂栧彿涓�"' + row.id + '"鐨勬暟鎹」锛�') + .then(function () { + return delEquipment(row.id); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/equipment/export", + { + ...this.queryParams, + }, + `equipment_${new Date().getTime()}.xlsx` + ); + }, + + handleRemove(file, fileList) { + // var fileUrl = this.imageUrl.replace(file.response.fileName + ",", ""); + // this.form.filePath = fileUrl; + // console.log(this.form.filePath); + + // console.log(baseUrl.slice(0, -1)) + const remainingUrls = fileList.map((item) => + item.url.replace(baseUrl.slice(0, -1), "") + ); + this.form.filePath = remainingUrls.join(","); + this.imageUrl = remainingUrls.join(","); + console.log(this.form.filePath); + }, + handlePictureCardPreview(file) { + console.log(file + "777"); + this.dialogImageUrl = file.url; + this.dialogVisible = true; + }, + handleAvatarSuccess(res, file) { + this.imageUrl += res.fileName + ","; + this.form.filePath = this.imageUrl; + console.log(this.form.filePath); + }, + beforeupload(file, fileList) { + let types = ["image/jpeg", "image/jpg", "image/png"]; + + const isImage = types.includes(file.type); + + const isLt20M = file.size / 1024 / 1024 < 9999999999; + if (!isLt20M) { + this.$message.error("涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 20MB!"); + return false; + } + return true; + }, + }, +}; +</script> diff --git a/src/views/manage/equipment/index.vue b/src/views/manage/equipment/index.vue new file mode 100644 index 0000000..1d1fcc8 --- /dev/null +++ b/src/views/manage/equipment/index.vue @@ -0,0 +1,452 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="璁惧鍚嶇О" prop="equName"> + <el-input + v-model="queryParams.equName" + placeholder="璇疯緭鍏ヨ澶囧悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:equipment:add']" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="equipmentList" + @selection-change="handleSelectionChange" + > + <!-- <el-table-column type="selection" width="55" align="center" /> --> + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="鐮佸ご鍚嶇О" align="center" prop="whName" /> + <el-table-column label="娉婁綅鍚嶇О" align="center" prop="beName" /> + <el-table-column label="璁惧鍚嶇О" align="center" prop="equName" /> + <el-table-column label="璁惧绫诲瀷" align="center" prop="typeName" /> + <!-- <el-table-column label="璁惧璇︽儏" align="center" prop="description" /> --> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:equipment:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:equipment:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀规硦浣�--璁惧瀵硅瘽妗� --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="娓彛" prop="whId"> + <el-select v-model="form.whId" placeholder="璇烽�夋嫨娓彛" @change="getBerth"> + <el-option + v-for="item in whOptions" + :key="item.whId" + :label="item.name" + :value="item.whId" + ></el-option> + </el-select> + </el-form-item> + <el-form-item label="娉婁綅" prop="beId"> + <el-select v-model="form.beId" placeholder="璇烽�夋嫨娉婁綅"> + <el-option + v-for="item in beOptions" + :key="item.pkid" + :label="item.name" + :value="item.pkid" + ></el-option> + </el-select> + </el-form-item> + <el-form-item label="璁惧绫诲瀷" prop="equTypeId"> + <el-select v-model="form.equipmentTypeId" placeholder="鑿滃崟鐘舵��" clearable> + <el-option + v-for="(t,index) in equTypeOptions" + :key="index" + :label="t.typeName" + :value="t.id" + /> + </el-select> + </el-form-item> + <el-form-item label="璁惧鍚嶇О" prop="equName"> + <el-input v-model="form.equName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" /> + </el-form-item> + <el-form-item label="鏇存柊鏃堕棿" prop="intervalTime"> + <el-input v-model="form.intervalTime" placeholder="璇疯緭鍏ユ洿鏂版椂闂�" /> + </el-form-item> + <el-form-item label="鏌ヨ鏃堕棿娈�" prop="PERIOD_TIME"> + <el-input v-model="form.periodTime" placeholder="璇疯緭鍏ユ煡璇㈡椂闂存" /> + </el-form-item> + <el-form-item label="閫氫俊鍗忚" prop="PROTOCOL"> + <el-input v-model="form.protocol" placeholder="璇疯緭鍏ラ�氫俊鍗忚" /> + </el-form-item> + <el-form-item label="缁忓害" prop="x"> + <el-input v-model="form.x" placeholder="璇疯緭鍏ヨ澶囩粡搴�" /> + </el-form-item> + <el-form-item label="绾害" prop="y"> + <el-input v-model="form.y" placeholder="璇疯緭鍏ョ含搴�" /> + </el-form-item> + <el-form-item label="楂樺害" prop="z"> + <el-input v-model="form.z" placeholder="璇疯緭鍏ラ珮搴�" /> + </el-form-item> + <el-form-item label="IP" prop="ip"> + <el-input v-model="form.ip" placeholder="璇疯緭鍏P" /> + </el-form-item> + <el-form-item label="绔彛" prop="port"> + <el-input-number v-model="form.port" placeholder="璇疯緭鍏ョ鍙�" /> + </el-form-item> + <el-form-item label="鍦板潃鐮�" prop="deviceAddress"> + <el-input-number v-model="form.deviceAddress" placeholder="璇疯緭鍏ュ湴鍧�鐮�" /> + </el-form-item> + <el-form-item label="妯″瀷瀛楁" prop="fieldName"> + <el-input v-model="form.fieldName" placeholder="璇疯緭鍏ユā鍨嬪瓧娈�" /> + </el-form-item> + <!-- <el-form-item label="璁惧璇︽儏" prop="description"> + <el-input + v-model="form.description" + type="textarea" + placeholder="璇疯緭鍏ュ唴瀹�" + /> + </el-form-item> --> + <!-- <el-form-item label="璁惧鍥剧墖" prop="filePath"> + <el-upload + :file-list="fileList" + :action="uploadFileUrl" + list-type="picture-card" + :on-preview="handlePictureCardPreview" + :on-remove="handleRemove" + :on-success="handleAvatarSuccess" + accept=".jpg,.jpeg,.png,.rar,.zip" + > + <i class="el-icon-plus"></i> + </el-upload> + <el-dialog :visible.sync="dialogVisible"> + <img width="100%" :src="dialogImageUrl" alt="" /> + </el-dialog> + </el-form-item> --> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listEquipment, + getEquipment, + delEquipment, + addEquipment, + updateEquipment, +} from "@/api/manage/equipment"; +import { list } from "@/api/manage/wharf"; +import { beList } from "@/api/manage/berth"; +import { listAll } from "@/api/manage/stock"; + +import { getAllEquype } from "@/api/manage/equType"; + +// let url = process.env.VUE_URL+'common/upload' +const baseUrl = process.env.VUE_APP_BASE_API; + +console.log("uploadUrl", baseUrl); +export default { + name: "Equipment", + dicts: ["dp_equipment_type"], + data() { + return { + // 閬僵灞� + loading: true, + fileList: [], + dialogImageUrl: "", + dialogVisible: false, + //璁惧绫诲瀷涓嬫媺閫� + equTypeOptions: [], + imageUrl: "", + // 閫変腑鏁扮粍 + ids: [], + url: process.env.VUE_URL + "common/upload", + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 娉婁綅--璁惧琛ㄦ牸鏁版嵁 + equipmentList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 20, + beId: null, + equName: null, + equType: null, + DESCRIPTION: null, + filePath: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + //鐮佸ご閫夐」 + whOptions: [], + //娉婁綅閫夐」 + beOptions: [], + // 琛ㄥ崟鏍¢獙 + rules: { + beId: [{ required: true, message: "娉婁綅涓嶈兘涓虹┖", trigger: "blur" }], + whId: [{ required: true, message: "鐮佸ご涓嶈兘涓虹┖", trigger: "blur" }], + equName: [{ required: true, message: "璁惧鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + equType: [{ required: true, message: "璁惧绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }], + }, + uploadFileUrl: baseUrl + "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ娉婁綅--璁惧鍒楄〃 */ + getList() { + this.loading = true; + listEquipment(this.queryParams).then((response) => { + this.equipmentList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + this.imageUrl = ""; + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + id: null, + beId: null, + equName: null, + equType: null, + description: null, + filePath: null, + }; + this.resetForm("form"); + this.fileList = []; + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.ID); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.imageUrl = ""; + list().then((response) => { + this.whOptions = response.data; + }); + //鑾峰彇璁惧绫诲瀷涓嬫媺椤� + getAllEquype().then((response) => { + this.equTypeOptions = response.data; + }); + this.open = true; + this.title = "娣诲姞娉婁綅--璁惧"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getEquipment(row.id).then((response) => { + this.form = response.data; + // console.log(this.form) + var fileListStr = response.data.filePath; + if (fileListStr) { + if (fileListStr.endsWith(",")) { + this.imageUrl = fileListStr; + fileListStr = fileListStr.slice(0, -1); // 鍒犻櫎鏈�鍚庝竴涓瓧绗︼紙閫楀彿锛� + } else { + this.imageUrl = fileListStr + ","; + } + const arr = fileListStr.split(","); // 灏嗘枃浠惰矾寰勫瓧绗︿覆鎷嗗垎鎴愭暟缁� + const baseFileUrl = baseUrl.slice(0, -1); + this.fileList = arr.map((item, index) => ({ + name: item.split("/").pop(), // 鎻愬彇鏂囦欢鍚� + url: baseFileUrl + item, // 鎷兼帴瀹屾暣鐨勬枃浠� URL + status: "success", // 涓婁紶鐘舵�佽缃负鎴愬姛 + uid: `uid-${index}`, // 浣跨敤鍞竴鐨� uid + })); + console.log(this.fileList); // 妫�鏌ユ枃浠跺垪琛� + } else { + this.imageUrl = ""; + } + // console.log(this.form); // 妫�鏌ヨ〃鍗曟暟鎹� + this.open = true; + this.title = "淇敼娉婁綅--璁惧"; + }); + list().then((response) => { + this.whOptions = response.data; + }); + beList(row.whId).then((response) => { + this.beOptions = response.data; + }); + //鑾峰彇璁惧绫诲瀷涓嬫媺椤� + getAllEquype().then((response) => { + this.equTypeOptions = response.data; + }); + + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.id != null) { + updateEquipment(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addEquipment(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎娉婁綅--璁惧缂栧彿涓�"' + row.id + '"鐨勬暟鎹」锛�') + .then(function () { + return delEquipment(row.id); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/equipment/export", + { + ...this.queryParams, + }, + `equipment_${new Date().getTime()}.xlsx` + ); + }, + + //閫変腑鐮佸ご瑙﹀彂浜嬩欢 + getBerth(whId) { + this.form.beId = null; + + beList(whId).then((response) => { + console.log(response); + this.beOptions = response.data; + }); + }, + handleRemove(file, fileList) { + // var fileUrl = this.imageUrl.replace(file.response.fileName + ",", ""); + // this.form.filePath = fileUrl; + // console.log(this.form.filePath); + + // console.log(baseUrl.slice(0, -1)) + const remainingUrls = fileList.map((item) => + item.url.replace(baseUrl.slice(0, -1), "") + ); + this.form.filePath = remainingUrls.join(","); + this.imageUrl = remainingUrls.join(","); + console.log(this.form.filePath); + }, + handlePictureCardPreview(file) { + console.log(file + "777"); + this.dialogImageUrl = file.url; + this.dialogVisible = true; + }, + handleAvatarSuccess(res, file) { + this.imageUrl += res.fileName + ","; + this.form.filePath = this.imageUrl; + console.log(this.form.filePath); + }, + beforeupload(file, fileList) { + let types = ["image/jpeg", "image/jpg", "image/png"]; + + const isImage = types.includes(file.type); + + const isLt20M = file.size / 1024 / 1024 < 9999999999; + if (!isLt20M) { + this.$message.error("涓婁紶澶村儚鍥剧墖澶у皬涓嶈兘瓒呰繃 20MB!"); + return false; + } + return true; + }, + }, +}; +</script> diff --git a/src/views/manage/shipDevice/index.vue b/src/views/manage/shipDevice/index.vue new file mode 100644 index 0000000..40c4985 --- /dev/null +++ b/src/views/manage/shipDevice/index.vue @@ -0,0 +1,325 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="璁惧缂栧彿" prop="deviceId"> + <el-input + v-model="queryParams.deviceId" + placeholder="璇疯緭鍏ヨ澶囩紪鍙�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="璁惧鍚嶇О" prop="deviceName"> + <el-input + v-model="queryParams.deviceName" + placeholder="璇疯緭鍏ヨ澶囧悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:device:add']" + >鏂板</el-button> + </el-col> + </el-row> + + <el-table v-loading="loading" :data="deviceList" @selection-change="handleSelectionChange"> + <el-table-column label="璁惧缂栧彿" align="center" prop="deviceId" /> + <el-table-column label="璁惧鍚嶇О" align="center" prop="deviceName" /> + <el-table-column label="璁惧鑸拌埞绫诲瀷" align="center" prop="shipTypeName" /> + <!-- <el-table-column label="璁惧姒傝堪" align="center" prop="deviceOverview" /> --> + <!-- <el-table-column label="璁惧妯″瀷鏂囦欢" align="center" prop="deviceModel" /> --> + <!-- <el-table-column label="璁惧鍙傛暟" align="center" prop="deviceParameters" /> --> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:device:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:device:remove']" + >鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀硅埌鑹囪澶囧璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="璁惧绫诲瀷" prop="deviceId"> + <el-input v-model="form.deviceId" placeholder="璇疯緭鍏ヨ澶囩紪鍙�" /> + </el-form-item> + <el-form-item label="璁惧鍚嶇О" prop="deviceName"> + <el-input v-model="form.deviceName" placeholder="璇疯緭鍏ヨ澶囧悕绉�" /> + </el-form-item> + <el-form-item label="鑸拌埞绫诲瀷" prop="shipTypeId"> + <el-select v-model="form.shipTypeId" placeholder="璇烽�夋嫨鎵�灞炶埌鑸圭被鍨�"> + <el-option + v-for="item in shipTypeOptions" + :key="item.id" + :label="item.typeName+'-'+item.shipDesign" + :value="item.id" + ></el-option> + </el-select> + </el-form-item> + <!-- <el-form-item label="璁惧姒傝堪" prop="deviceOverview"> + <el-input v-model="form.deviceOverview" type="textarea" placeholder="璇疯緭鍏ヨ澶囨杩�" /> + </el-form-item> + <el-form-item label="璁惧鍙傛暟" prop="deviceParameters"> + <el-input v-model="form.deviceParameters" type="textarea" placeholder="璇疯緭鍏ヨ澶囧弬鏁�" /> + </el-form-item> --> + <el-form-item label="target" prop="target"> + <el-input v-model="form.target" placeholder="璇疯緭鍏ヨ澶噒arget" /> + </el-form-item> + <el-form-item label="position" prop="position"> + <el-input v-model="form.position" placeholder="璇疯緭鍏ヨ澶噋osition" /> + </el-form-item> + <el-form-item label="妯″瀷瀛楁" prop="fieldName"> + <el-input v-model="form.fieldName" placeholder="璇疯緭鍏ヨ澶囨ā鍨嬪瓧娈�" /> + </el-form-item> + <!-- <el-form-item label="妯″瀷鏂囦欢" prop="deviceModel"> + <el-upload + class="upload-demo" + :action="uploadFileUrl" + :on-remove="handleRemove" + :on-success="handleAvatarSuccess" + :file-list="fileList" + > + <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button> + </el-upload> + </el-form-item> --> + + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listDevice, getDevice, delDevice, addDevice, updateDevice } from "@/api/manage/device"; +import { listAlldpShipTypeList} from "@/api/manage/shipType"; + +const baseUrl = process.env.VUE_APP_BASE_API + +export default { + name: "Device", + data() { + return { + // 閬僵灞� + loading: true, + fileList: [], + imageUrl: "", + // 閫変腑鏁扮粍 + ids: [], + shipTypeOptions:[], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鑸拌墖璁惧琛ㄦ牸鏁版嵁 + deviceList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + deviceId: null, + deviceName: null, + deviceShipId: null, + deviceOverview: null, + deviceModel: null, + deviceParameters: null, + updateTime: null, + updateUser: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + deviceId: [ + { required: true, message: "璁惧缂栧彿涓嶈兘涓虹┖", trigger: "blur" } + ], + }, + uploadFileUrl: baseUrl+ "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鑸拌墖璁惧鍒楄〃 */ + getList() { + this.loading = true; + listDevice(this.queryParams).then(response => { + this.deviceList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + deviceId: null, + deviceName: null, + deviceShipId: null, + deviceOverview: null, + deviceModel: null, + deviceParameters: null, + updateTime: null, + updateUser: null, + ID: null + }; + this.resetForm("form"); + this.fileList = []; + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.ID) + this.single = selection.length!==1 + this.multiple = !selection.length + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.imageUrl = ""; + listAlldpShipTypeList().then(response=>{ + this.shipTypeOptions = response.data; + }) + this.open = true; + this.title = "娣诲姞鑸拌墖璁惧"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + listAlldpShipTypeList().then(response=>{ + this.shipTypeOptions = response.data; + }) + const id = row.id + getDevice(id).then(response => { + this.form = response.data; + this.open = true; + this.title = "淇敼鑸拌墖璁惧"; + var fileListStr = response.data.deviceModel; + this.imageUrl = fileListStr == null ? "" : fileListStr; + if (fileListStr) { + if (fileListStr.endsWith(",")) { + this.imageUrl = fileListStr; + fileListStr = fileListStr.slice(0, -1); // 鍒犻櫎鏈�鍚庝竴涓瓧绗︼紙閫楀彿锛� + }else{ + this.imageUrl = fileListStr + ','; + } + const arr = fileListStr.split(","); // 灏嗘枃浠惰矾寰勫瓧绗︿覆鎷嗗垎鎴愭暟缁� + this.fileList = arr.map((item, index) => ({ + name: item.split("/").pop(), // 鎻愬彇鏂囦欢鍚� + url: baseUrl.slice(0, -1) + item, // 鎷兼帴瀹屾暣鐨勬枃浠� URL + status: "success", // 涓婁紶鐘舵�佽缃负鎴愬姛 + uid: `uid-${index}`, // 浣跨敤鍞竴鐨� uid + })); + }else{ + this.imageUrl = ''; + } + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.id != null) { + updateDevice(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addDevice(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const id = row.id; + this.$modal.confirm('鏄惁纭鍒犻櫎鑸拌墖璁惧缂栧彿涓�"' + row.deviceId+ '"鐨勬暟鎹」锛�').then(function() { + return delDevice(id); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + handleRemove(file, fileList) { + // var fileUrl = this.imageUrl.replace(file.response.fileName + ",", ""); + // this.form.deviceModel = fileUrl; + // console.log(this.form.deviceModel); + // console.log(baseUrl.slice(0, -1)) + const remainingUrls = fileList.map((item) => + item.url.replace(baseUrl.slice(0, -1), "") + ); + this.form.deviceModel = remainingUrls.join(","); + this.imageUrl = remainingUrls.join(","); + // console.log(this.form.deviceModel); + }, + handleAvatarSuccess(res, file) { + this.imageUrl += res.fileName + ","; + this.form.deviceModel = this.imageUrl; + console.log(this.form.deviceModel); + } + } +}; +</script> diff --git a/src/views/manage/shipType/index.vue b/src/views/manage/shipType/index.vue new file mode 100644 index 0000000..8624961 --- /dev/null +++ b/src/views/manage/shipType/index.vue @@ -0,0 +1,362 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="鑸拌墖绫诲瀷" prop="typeName"> + <el-input + v-model="queryParams.typeName" + placeholder="璇疯緭鍏ヨ埌鑹囩被鍨�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:device:add']" + >鏂板</el-button + > + </el-col> + </el-row> + + <el-table + v-loading="loading" + :data="deviceList" + @selection-change="handleSelectionChange" + > + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="鑸拌墖绫诲瀷鍚嶇О" align="center" prop="typeName" /> + <el-table-column label="鑸拌墖鍨嬪彿鍚嶇О" align="center" prop="shipDesign" /> + <el-table-column label="鍚ㄤ綅(鍚�)" align="center" prop="tonnage" /> + <el-table-column label="鍚冩按(绫�)" align="center" prop="draft" /> + <el-table-column label="鑸伴暱(绫�)" align="center" prop="length" /> + <el-table-column label="瀹氬憳(浜�)" align="center" prop="crew" /> + <!-- <el-table-column label="target" min-width="500" align="center" prop="target" /> + <el-table-column label="position" min-width="500" align="center" prop="position" /> --> + <el-table-column + label="璁惧姒傝堪" + min-width="1000" + align="center" + prop="shipOverview" + /> + <el-table-column + label="璁惧鍙傛暟" + min-width="1000" + align="center" + prop="shipParameters" + /> + <el-table-column label="鎿嶄綔" min-width="100" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:device:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:device:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀硅埌鑹囪澶囧璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鑸拌墖绫诲瀷鍚嶇О" prop="typeName"> + <el-input v-model="form.typeName" placeholder="璇疯緭鍏ヨ埌鑹囩被鍨嬪悕绉�" /> + </el-form-item> + <el-form-item label="鑸拌墖鍨嬪彿鍚嶇О" prop="shipDesign"> + <el-input v-model="form.shipDesign" placeholder="璇疯緭鍏ヨ埌鑹囧瀷鍙峰悕绉�" /> + </el-form-item> + <el-form-item label="鍚ㄤ綅(鍚�)" prop="tonnage"> + <el-input v-model="form.tonnage" type="textarea" placeholder="璇疯緭鍏ヨ澶囨杩�" /> + </el-form-item> + <el-form-item label="鍚冩按(绫�)" prop="draft"> + <el-input v-model="form.draft" type="textarea" placeholder="璇疯緭鍏ヨ澶囨杩�" /> + </el-form-item> + <el-form-item label="鑸伴暱(绫�)" prop="length"> + <el-input v-model="form.length" type="textarea" placeholder="璇疯緭鍏ヨ澶囨杩�" /> + </el-form-item> + <el-form-item label="瀹氬憳(浜�)" prop="crew"> + <el-input v-model="form.crew" type="textarea" placeholder="璇疯緭鍏ヨ澶囨杩�" /> + </el-form-item> + <el-form-item label="position" prop="position"> + <el-input v-model="form.position" placeholder="璇疯緭鍏osition" /> + </el-form-item> + <el-form-item label="target " prop="target "> + <el-input v-model="form.target" placeholder="璇疯緭鍏arget" /> + </el-form-item> + <el-form-item label="璁惧姒傝堪" prop="shipOverview"> + <el-input + v-model="form.shipOverview" + type="textarea" + placeholder="璇疯緭鍏ヨ澶囨杩�" + /> + </el-form-item> + <el-form-item label="璁惧鍙傛暟" prop="shipParameters"> + <el-input + v-model="form.shipParameters" + type="textarea" + placeholder="璇疯緭鍏ヨ澶囧弬鏁�" + /> + </el-form-item> + <el-form-item label="妯″瀷鏂囦欢" prop="shipModel"> + <el-upload + class="upload-demo" + :action="uploadFileUrl" + :on-remove="handleRemove" + :on-success="handleAvatarSuccess" + :file-list="fileList" + > + <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button> + <!-- <div slot="tip" class="el-upload__tip"> + 鍙兘涓婁紶jpg/png鏂囦欢锛屼笖涓嶈秴杩�500kb + </div> --> + </el-upload> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listSipType, + getdpShipType, + deldpShipType, + adddpShipType, + updatedpShipType, +} from "@/api/manage/shipType"; + +const baseUrl = process.env.VUE_APP_BASE_API; + +export default { + name: "Device", + data() { + return { + // 閬僵灞� + loading: true, + fileList: [], + imageUrl: "", + // 閫変腑鏁扮粍 + ids: [], + shipOptions: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鑸拌墖璁惧琛ㄦ牸鏁版嵁 + deviceList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + deviceId: null, + deviceName: null, + deviceShipId: null, + deviceOverview: null, + shipModel: null, + deviceParameters: null, + updateTime: null, + updateUser: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + deviceId: [{ required: true, message: "璁惧缂栧彿涓嶈兘涓虹┖", trigger: "blur" }], + }, + uploadFileUrl: baseUrl + "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鑸拌墖璁惧鍒楄〃 */ + getList() { + this.loading = true; + listSipType(this.queryParams).then((response) => { + this.deviceList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + deviceId: null, + deviceName: null, + deviceShipId: null, + deviceOverview: null, + shipModel: null, + deviceParameters: null, + updateTime: null, + updateUser: null, + ID: null, + }; + this.resetForm("form"); + this.fileList = []; + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.ID); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.imageUrl = ""; + // shipList().then(response=>{ + // this.shipOptions = response.data; + // }) + this.open = true; + this.title = "娣诲姞鑸拌墖璁惧绫诲瀷"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const id = row.id; + getdpShipType(id).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鑸拌墖璁惧绫诲瀷"; + var fileListStr = response.data.shipModel; + this.imageUrl = fileListStr == null ? "" : fileListStr; + if (fileListStr) { + if (fileListStr.endsWith(",")) { + this.imageUrl = fileListStr; + fileListStr = fileListStr.slice(0, -1); // 鍒犻櫎鏈�鍚庝竴涓瓧绗︼紙閫楀彿锛� + } else { + this.imageUrl = fileListStr + ","; + } + const arr = fileListStr.split(","); // 灏嗘枃浠惰矾寰勫瓧绗︿覆鎷嗗垎鎴愭暟缁� + this.fileList = arr.map((item, index) => ({ + name: item.split("/").pop(), // 鎻愬彇鏂囦欢鍚� + url: baseUrl.slice(0, -1) + item, // 鎷兼帴瀹屾暣鐨勬枃浠� URL + status: "success", // 涓婁紶鐘舵�佽缃负鎴愬姛 + uid: `uid-${index}`, // 浣跨敤鍞竴鐨� uid + })); + } else { + this.imageUrl = ""; + } + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.id != null) { + updatedpShipType(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + adddpShipType(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const id = row.id; + this.$modal + .confirm('鏄惁纭鍒犻櫎鑸拌墖璁惧鍨嬪彿涓�"' + row.shipDesign + '"鐨勬暟鎹」锛�') + .then(function () { + return deldpShipType(id); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + handleRemove(file, fileList) { + // var fileUrl = this.imageUrl.replace(file.response.fileName + ",", ""); + // this.form.shipModel = fileUrl; + // console.log(this.form.shipModel); + // console.log(baseUrl.slice(0, -1)) + const remainingUrls = fileList.map((item) => + item.url.replace(baseUrl.slice(0, -1), "") + ); + this.form.shipModel = remainingUrls.join(","); + this.imageUrl = remainingUrls.join(","); + // console.log(this.form.shipModel); + }, + handleAvatarSuccess(res, file) { + this.imageUrl += res.fileName + ","; + this.form.shipModel = this.imageUrl; + console.log(this.form.shipModel); + }, + }, +}; +</script> diff --git a/src/views/manage/ships/index.vue b/src/views/manage/ships/index.vue new file mode 100644 index 0000000..89d7d0c --- /dev/null +++ b/src/views/manage/ships/index.vue @@ -0,0 +1,432 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="鑸拌埞鍚嶇О" prop="shipName"> + <el-input + v-model="queryParams.shipName" + placeholder="璇疯緭鍏ヨ埌鑸瑰悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:ships:add']" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="shipsList" + @selection-change="handleSelectionChange" + > + <!-- <el-table-column type="selection" width="55" align="center" /> --> + <el-table-column label="鑸拌埞缂栧彿" align="center" prop="shipId" /> + <el-table-column label="鑸拌埞鍚嶇О" align="center" prop="shipName" /> + <el-table-column label="鑸拌埞绫诲瀷" align="center" prop="shipType" /> + <el-table-column label="鑸拌埞鍨嬪彿" align="center" prop="shipDesign" /> + <!-- <el-table-column + label="鑸拌埞绫诲瀷(鑸硅埌绫诲瀷(1椹遍�愯埌;2鎶ゅ崼鑸�;3鐧婚檰鑸�;4鎵浄鑸�;5鎷栬埞;6娌硅埞;))" + align="center" + prop="shipType" + /> --> + <el-table-column label="鎵�灞炵爜澶�" align="center" prop="whName" /> + <el-table-column label="鎵�灞炴硦浣�" align="center" prop="beName" /> + <!-- <el-table-column label="target" align="center" prop="target" /> + <el-table-column label="position" align="center" prop="position" /> --> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:ships:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:ships:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀硅埌鑸瑰璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鑸拌埞鍚嶇О" prop="shipName"> + <el-input v-model="form.shipName" placeholder="璇疯緭鍏ヨ埌鑸瑰悕绉�" /> + </el-form-item> + <!-- <el-row> + <el-col :span="12"> --> + <el-form-item label="鑸拌埞绫诲瀷" prop="shipTypeId"> + <el-select + v-model="form.shipTypeId" + placeholder="鑸拌埞绫诲瀷" + clearable + @change="getShipDesign" + > + <el-option + v-for="s in shipTypeOptions" + :key="s.id" + :label="s.typeName + '-' + s.shipDesign" + :value="s.id" + /> + </el-select> + </el-form-item> + <!-- <el-form-item label="鑸拌埞鍨嬪彿" prop="shipDesign"> + <el-input v-model="form.shipDesign" disabled="true" placeholder="璇疯緭鍏ヨ埌鑸规杩�" /> + </el-form-item> --> + <!-- </el-col> + <el-col :span="12"> --> + <el-form-item label="鑸拌埞缂栧彿" prop="shipId"> + <el-input v-model="form.shipId" placeholder="璇疯緭鍏ヨ埌鑸规杩�" /> + </el-form-item> + <!-- </el-col> + </el-row> --> + + <!-- <el-form-item label="鑸拌埞姒傝堪" prop="shipOverview"> + <el-input + v-model="form.shipOverview" + type="textarea" + placeholder="璇疯緭鍏ヨ埌鑸规杩�" + /> + </el-form-item> + <el-form-item label="鑸拌埞鍙傛暟" prop="shipParameters"> + <el-input + v-model="form.shipParameters" + type="textarea" + placeholder="璇疯緭鍏ヨ埌鑸瑰弬鏁�" + /> + </el-form-item> --> + <!-- <el-form-item label="position" prop="position"> + <el-input v-model="form.position" placeholder="璇疯緭鍏osition" /> + </el-form-item> + <el-form-item label="target " prop="target "> + <el-input v-model="form.target" placeholder="璇疯緭鍏arget" /> + </el-form-item> --> + <el-row> + <el-col :span="12"> + <el-form-item label="鐮佸ご" prop="whId"> + <el-select v-model="form.whId" placeholder="璇烽�夋嫨鐮佸ご" @change="getBerth"> + <el-option + v-for="item in whOptions" + :key="item.pkId" + :label="item.harborName" + :value="item.pkId" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="娉婁綅" prop="beId"> + <el-select v-model="form.beId" placeholder="璇烽�夋嫨娉婁綅"> + <el-option + v-for="item in beOptions" + :key="item.pkid" + :label="item.name" + :value="item.pkid" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + + <!-- <el-form-item label="妯″瀷鏂囦欢" prop="shipModel"> + <el-upload + class="upload-demo" + :action="uploadFileUrl" + :on-remove="handleRemove" + :on-success="handleAvatarSuccess" + :file-list="fileList" + > + <el-button size="small" type="primary">鐐瑰嚮涓婁紶</el-button> + </el-upload> + </el-form-item> --> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listShips, getShips, delShips, addShips, updateShips } from "@/api/manage/ships"; +import { listAll } from "@/api/manage/stock"; +import { beList } from "@/api/manage/berth"; +import { listAlldpShipTypeList, getdpShipType } from "@/api/manage/shipType"; +import { getDeviceList } from "@/api/manage/device"; +const baseUrl = process.env.VUE_APP_BASE_API; +export default { + name: "Ships", + dicts: ["dp_ship_type"], + data() { + return { + // 閬僵灞� + loading: true, + fileList: [], + imageUrl: "", + // 閫変腑鏁扮粍 + ids: [], + whOptions: [], + //娉婁綅閫夐」 + beOptions: [], + //鑸拌埞绫诲瀷閫夐」 + shipTypeOptions: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鑸拌埞琛ㄦ牸鏁版嵁 + shipsList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + shipId: null, + shipName: null, + shipType: null, + shipModel: null, + shipOverview: null, + shipParameters: null, + updateTime: null, + updateUser: null, + whId: null, + beId: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + shipId: [{ required: true, message: "鑸拌埞缂栧彿涓嶈兘涓虹┖", trigger: "blur" }], + shipType: [{ required: true, message: "鑸拌埞绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }], + shipName: [{ required: true, message: "鑸拌埞鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + }, + uploadFileUrl: baseUrl + "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鑸拌埞鍒楄〃 */ + getList() { + this.loading = true; + listShips(this.queryParams).then((response) => { + this.shipsList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + shipId: null, + shipName: null, + shipType: null, + shipModel: null, + shipOverview: null, + shipParameters: null, + updateTime: null, + updateUser: null, + ID: null, + whId: null, + beId: null, + }; + this.resetForm("form"); + this.fileList = []; + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.ID); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + getShipDesign(id) { + getdpShipType(id).then((response) => { + this.form.shipDesign = response.data.shipDesign; + console.log(response.data); + }); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.imageUrl = ""; + listAll().then((response) => { + this.whOptions = response.data; + }); + //鑾峰彇鑸拌埞绫诲瀷 + listAlldpShipTypeList().then((response) => { + this.shipTypeOptions = response.data; + }); + this.open = true; + this.title = "娣诲姞鑸拌埞"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + listAll().then((response) => { + this.whOptions = response.data; + }); + beList(row.whId).then((response) => { + this.beOptions = response.data; + }); + //鑾峰彇鑸拌埞绫诲瀷 + listAlldpShipTypeList().then((response) => { + this.shipTypeOptions = response.data; + }); + const ID = row.id; + getShips(ID).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鑸拌埞"; + var fileListStr = response.data.shipModel; + if (fileListStr) { + console.log(fileListStr); + if (fileListStr.endsWith(",")) { + this.imageUrl = fileListStr; + fileListStr = fileListStr.slice(0, -1); // 鍒犻櫎鏈�鍚庝竴涓瓧绗︼紙閫楀彿锛� + } else { + this.imageUrl = fileListStr + ","; + } + const arr = fileListStr.split(","); // 灏嗘枃浠惰矾寰勫瓧绗︿覆鎷嗗垎鎴愭暟缁� + console.log("arr", arr); + this.fileList = arr.map((item, index) => ({ + name: item.split("/").pop(), // 鎻愬彇鏂囦欢鍚� + url: baseUrl.slice(0, -1) + item, // 鎷兼帴瀹屾暣鐨勬枃浠� URL + status: "success", // 涓婁紶鐘舵�佽缃负鎴愬姛 + uid: `uid-${index}`, // 浣跨敤鍞竴鐨� uid + })); + console.log("鑾峰彇瀹炰綋绫昏浆鎹㈠悗", this.fileList); // 妫�鏌ユ枃浠跺垪琛� + } else { + this.imageUrl = ""; + } + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.id != null) { + updateShips(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addShips(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const IDs = row.id; + //鏌ヨ鏄惁鏈夊瓙璁惧 + getDeviceList(row.shipId).then((response) => { + if (response.data.length > 0) { + this.$message.error(row.shipName + "涓嬫湁璁惧,璇峰厛鍒犻櫎鐩稿叧璁惧鍚庡啀鍒犻櫎!"); + } else { + this.$modal + .confirm('鏄惁纭鍒犻櫎鑸拌埞鍚嶄负"' + row.shipName + '"鐨勬暟鎹」锛�') + .then(function () { + return delShips(IDs); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + } + }); + }, + //閫変腑鐮佸ご瑙﹀彂浜嬩欢 + getBerth(whId) { + this.form.beId = null; + beList(whId).then((response) => { + this.beOptions = response.data; + }); + }, + handleRemove(file, fileList) { + const remainingUrls = fileList.map((item) => + item.url.replace(baseUrl.slice(0, -1), "") + ); + this.form.shipModel = remainingUrls.join(","); + this.imageUrl = remainingUrls.join(","); + console.log("鍒犻櫎瀹屾垚", this.form.shipModel); + }, + handleAvatarSuccess(res, file) { + this.imageUrl += res.fileName + ","; + this.form.shipModel = this.imageUrl; + console.log("涓婁紶瀹屾垚", this.form.shipModel); + }, + }, +}; +</script> diff --git a/src/views/manage/stock/index.vue b/src/views/manage/stock/index.vue new file mode 100644 index 0000000..ee33927 --- /dev/null +++ b/src/views/manage/stock/index.vue @@ -0,0 +1,423 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="娓彛鍚嶇О" prop="name"> + <el-input + v-model="queryParams.dockName" + placeholder="璇疯緭鍏ョ爜澶村悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:harbor:add']" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="harborList" + @selection-change="handleSelectionChange" + > + <el-table-column label="搴忓彿" align="center" type="index" /> + <el-table-column label="娓彛鍚嶇О" align="center" prop="name" /> + <el-table-column label="鏀槦鍚嶇О" align="center" prop="bumenName" /> + <el-table-column label="娉婁綅鏁伴噺" align="center" prop="berthNo" /> + <el-table-column label="鏌存补瀛橀噺" align="center" prop="oilB" /> + <el-table-column label="鐓ゆ补瀛橀噺" align="center" prop="oilG" /> + <el-table-column label="瀵煎脊鏁伴噺" align="center" prop="ammoD" /> + <el-table-column label="鐐脊鏁伴噺" align="center" prop="ammoP" /> + <el-table-column label="姘撮浄鏁伴噺" align="center" prop="ammoS" /> + <el-table-column label="鐮佸ご鍚嶇О" align="center" prop="dockName" /> + <el-table-column label="娣℃按鏁伴噺" align="center" prop="water" /> + <el-table-column label="鐗╄祫鏁伴噺" align="center" prop="material" /> + <el-table-column label="鍏朵粬寮硅嵂" align="center" prop="ammoO" /> + <el-table-column label="澶囨敞" align="center" prop="remark" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:harbor:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:harbor:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀规腐鍙d俊鎭璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鐮佸ご鍚嶇О" prop="dockName"> + <el-input v-model="form.dockName" placeholder="璇疯緭鍏ョ爜澶村悕绉�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="娓彛鍚嶇О" prop="name"> + <el-input v-model="form.name" placeholder="璇疯緭鍏ユ腐鍙e悕绉�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鎵�灞為儴闂�" prop="deptId"> + <treeselect + v-model="form.deptId" + :options="deptOptions" + :show-count="true" + placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" + /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="娉婁綅鏁伴噺" prop="berthNo"> + <el-input v-model="form.berthNo" placeholder="璇疯緭鍏ユ硦浣嶆暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鏌存补瀛橀噺" prop="oilB"> + <el-input v-model="form.oilB" placeholder="璇疯緭鍏ヨ埌鐢ㄦ煷娌瑰瓨閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐓ゆ补瀛橀噺" prop="oilG"> + <el-input v-model="form.oilG" placeholder="璇疯緭鍏ヨ埌鐢ㄧ叅娌瑰瓨閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="瀵煎脊鏁伴噺" prop="ammoD"> + <el-input v-model="form.ammoD" placeholder="璇疯緭鍏ュ寮规暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐐脊鏁伴噺" prop="ammoP"> + <el-input v-model="form.ammoP" placeholder="璇疯緭鍏ョ偖寮规暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="姘撮浄鏁伴噺" prop="ammoS"> + <el-input v-model="form.ammoS" placeholder="璇疯緭鍏ユ按闆锋暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍏朵粬寮硅嵂鏁伴噺" prop="ammoO"> + <el-input v-model="form.ammoO" placeholder="璇疯緭鍏ュ叾浠栧脊鑽暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="娣℃按鏁伴噺" prop="water"> + <el-input v-model="form.water" placeholder="璇疯緭鍏ユ贰姘存暟閲�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐗╄祫鏁伴噺" prop="material"> + <el-input v-model="form.material" placeholder="璇疯緭鍏ョ墿璧勬暟閲�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="height" prop="height"> + <el-input v-model="form.height" placeholder="璇疯緭鍏eight" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="heading" prop="heading"> + <el-input v-model="form.heading" placeholder="璇疯緭鍏eading" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="pitch" prop="pitch"> + <el-input v-model="form.pitch" placeholder="璇疯緭鍏itch" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="roll" prop="roll"> + <el-input v-model="form.roll" placeholder="璇疯緭鍏oll" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="绾害" prop="latitude"> + <el-input v-model="form.latitude" placeholder="璇疯緭鍏ョ含搴�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="缁忓害" prop="longitude"> + <el-input v-model="form.longitude" placeholder="璇疯緭鍏ョ粡搴�" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鏈烘杞﹁締" prop="vehicleCount"> + <el-input v-model="form.vehicleCount" type="number" placeholder="璇疯緭鍏ョ含搴�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="閬撹矾鏉′欢" prop="roadConditions"> + <el-input v-model="form.roadConditions" placeholder="璇疯緭鍏ョ粡搴�" /> + </el-form-item> + </el-col> + </el-row> + <el-form-item label="澶囨敞" prop="remark"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" /> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listHarbor, + getHarbor, + delHarbor, + addHarbor, + updateHarbor, +} from "@/api/manage/stock"; +import { deptTreeSelect } from "@/api/system/user"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "Harbor", + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 閮ㄩ棬鏍戦�夐」 + deptOptions: undefined, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 娓彛淇℃伅琛ㄦ牸鏁版嵁 + harborList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + name: null, + deptId: null, + deptName: null, + berthNo: null, + oilB: null, + oilG: null, + ammoD: null, + ammoP: null, + ammoS: null, + dockName: null, + water: null, + material: null, + ammoO: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + name: [{ required: true, message: "娓彛鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + deptName: [{ required: true, message: "鏀槦鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + }, + }; + }, + created() { + this.getList(); + this.getDeptTree(); + }, + methods: { + /** 鏌ヨ娓彛淇℃伅鍒楄〃 */ + getList() { + this.loading = true; + listHarbor(this.queryParams).then((response) => { + this.harborList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + /** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ + getDeptTree() { + deptTreeSelect().then((response) => { + this.deptOptions = response.data; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + pkId: null, + name: null, + deptId: null, + deptName: null, + berthNo: null, + oilB: null, + oilG: null, + ammoD: null, + ammoP: null, + ammoS: null, + delFlag: null, + createBy: null, + createTime: null, + updateBy: null, + updateTime: null, + dockName: null, + water: null, + material: null, + ammoO: null, + remark: null, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.pkId); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞娓彛淇℃伅"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getHarbor(row.pkId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼娓彛淇℃伅"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.pkId != null) { + updateHarbor(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addHarbor(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎鐮佸ご鍚嶇О"' + row.dockName + '"鐨勬暟鎹」锛�') + .then(function () { + return delHarbor(row.pkId); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/harbor/export", + { + ...this.queryParams, + }, + `harbor_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/manage/supplement/index.vue b/src/views/manage/supplement/index.vue new file mode 100644 index 0000000..69116c7 --- /dev/null +++ b/src/views/manage/supplement/index.vue @@ -0,0 +1,268 @@ +<template> + <div class="app-container"> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" + >鏂板</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="supplementList" + @selection-change="handleSelectionChange" + > + <el-table-column type="index" label="搴忓彿" width="55" align="center" /> + <el-table-column label="鑸拌埞绫诲瀷" align="center" prop="shipDesign" /> + <el-table-column label="鍗曚綅" align="center" prop="unit" /> + <el-table-column label="绉嶇被" align="center" prop="category" /> + <el-table-column label="琛ョ粰鏃堕棿" align="center" prop="supplyTime" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:supplement:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:supplement:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鑸拌埞绫诲瀷" prop="shipTypeId"> + <el-select + v-model="form.shipDesign" + placeholder="鑸拌埞绫诲瀷" + clearable + @change="getShipDesign" + > + <el-option + v-for="s in shipTypeOptions" + :key="s.id" + :label="s.typeName + '-' + s.shipDesign" + :value="s.id" + /> + </el-select> + </el-form-item> + <el-form-item label="鍗曚綅" prop="unit"> + <el-input v-model="form.unit" placeholder="璇疯緭鍏ュ崟浣�" /> + </el-form-item> + <el-form-item label="绉嶇被" prop="category"> + <el-input v-model="form.category" placeholder="璇疯緭鍏ョ绫�" /> + </el-form-item> + <el-form-item label="琛ョ粰鏃堕棿(鏃�)" prop="supplyTime"> + <el-input v-model="form.supplyTime" placeholder="璇疯緭鍏ヨˉ缁欐椂闂�" /> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listsupplement, + getsupplement, + delsupplement, + addsupplement, + updatesupplement, +} from "@/api/manage/supplement"; +import { listAlldpShipTypeList, getdpShipType } from "@/api/manage/shipType"; +const baseUrl = process.env.VUE_APP_BASE_API; +export default { + name: "supplement", + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + //鑸拌埞绫诲瀷閫夐」 + shipTypeOptions: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鍗曚綅琛ョ粰琛ㄦ牸鏁版嵁 + supplementList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + shipId: null, + shipName: null, + shipType: null, + shipModel: null, + shipOverview: null, + shipParameters: null, + updateTime: null, + updateUser: null, + whId: null, + beId: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + shipId: [{ required: true, message: "鑸拌埞缂栧彿涓嶈兘涓虹┖", trigger: "blur" }], + shipType: [{ required: true, message: "鑸拌埞绫诲瀷涓嶈兘涓虹┖", trigger: "blur" }], + shipName: [{ required: true, message: "鑸拌埞鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + }, + uploadFileUrl: baseUrl + "common/upload", + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鍒楄〃 */ + getList() { + this.loading = true; + listsupplement(this.queryParams).then((response) => { + this.supplementList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + shipId: null, + shipName: null, + shipType: null, + shipModel: null, + shipOverview: null, + shipParameters: null, + updateTime: null, + updateUser: null, + ID: null, + whId: null, + beId: null, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.ID); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + getShipDesign(id) { + getdpShipType(id).then((response) => { + this.form.shipDesign = response.data.shipDesign; + console.log(response.data); + }); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + //鑾峰彇鑸拌埞绫诲瀷 + listAlldpShipTypeList().then((response) => { + this.shipTypeOptions = response.data; + }); + this.open = true; + this.title = "娣诲姞"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + //鑾峰彇鑸拌埞绫诲瀷 + listAlldpShipTypeList().then((response) => { + this.shipTypeOptions = response.data; + }); + const ID = row.id; + getsupplement(ID).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.id != null) { + updatesupplement(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addsupplement(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const IDs = row.id; + //鏌ヨ鏄惁鏈夊瓙璁惧 + + this.$modal + .confirm('鏄惁纭鍒犻櫎"' + row.shipDesign + '"鐨勬暟鎹」锛�') + .then(function () { + return delsupplement(IDs); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + + }, +}; +</script> diff --git a/src/views/manage/wharf/index.vue b/src/views/manage/wharf/index.vue new file mode 100644 index 0000000..9352d77 --- /dev/null +++ b/src/views/manage/wharf/index.vue @@ -0,0 +1,309 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="鐮佸ご鍚嶇О" prop="NAME"> + <el-input + v-model="queryParams.name" + placeholder="璇疯緭鍏ョ爜澶村悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:wharf:add']" + >鏂板</el-button + > + </el-col> + <!-- <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:wharf:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:wharf:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:wharf:export']" + >瀵煎嚭</el-button> + </el-col> --> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="wharfList" + @selection-change="handleSelectionChange" + > + <!-- <el-table-column type="selection" width="55" align="center" /> --> + <el-table-column label="id" align="center" prop="whId" /> + <el-table-column label="鐮佸ご鍚嶇О" align="center" prop="name" /> + <el-table-column label="height" align="center" prop="height" /> + <el-table-column label="heading" align="center" prop="heading" /> + <el-table-column label="pitch" align="center" prop="pitch" /> + <el-table-column label="roll" align="center" prop="roll" /> + <el-table-column label="绾害" align="center" prop="latitude" /> + <el-table-column label="缁忓害" align="center" prop="longitude" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:wharf:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:wharf:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀圭爜澶村璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鐮佸ご鍚嶇О" prop="name"> + <el-input v-model="form.name" placeholder="璇疯緭鍏ョ爜澶村悕绉�" /> + </el-form-item> + <el-form-item label="height" prop="height"> + <el-input v-model="form.height" placeholder="璇疯緭鍏eight" /> + </el-form-item> + <el-form-item label="heading" prop="heading"> + <el-input v-model="form.heading" placeholder="璇疯緭鍏eading" /> + </el-form-item> + <el-form-item label="pitch" prop="pitch"> + <el-input v-model="form.pitch" placeholder="璇疯緭鍏itch" /> + </el-form-item> + <el-form-item label="roll" prop="roll"> + <el-input v-model="form.roll" placeholder="璇疯緭鍏oll" /> + </el-form-item> + <el-form-item label="绾害" prop="latitude"> + <el-input v-model="form.latitude" placeholder="璇疯緭鍏ョ含搴�" /> + </el-form-item> + <el-form-item label="缁忓害" prop="longitude"> + <el-input v-model="form.longitude" placeholder="璇疯緭鍏ョ粡搴�" /> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listWharf, getWharf, delWharf, addWharf, updateWharf } from "@/api/manage/wharf"; +import { beList } from "@/api/manage/berth"; +export default { + name: "Wharf", + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐮佸ご琛ㄦ牸鏁版嵁 + wharfList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + NAME: null, + HEIGHT: null, + HEADING: null, + PITCH: null, + LATITUDE: null, + LONGITUDE: null, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: {}, + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鐮佸ご鍒楄〃 */ + getList() { + this.loading = true; + listWharf(this.queryParams).then((response) => { + this.wharfList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + whId: null, + NAME: null, + HEIGHT: null, + HEADING: null, + PITCH: null, + LATITUDE: null, + LONGITUDE: null, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.whId); + this.single = selection.length !== 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞鐮佸ご"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const whId = row.whId || this.ids; + getWharf(whId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鐮佸ご"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.whId != null) { + updateWharf(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addWharf(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const whIds = row.whId; + beList(whIds).then((response) => { + if (response.data.length > 0) { + this.$message.error(row.name + "涓嬫湁娉婁綅锛岃鍏堝垹闄ゅ搴旀硦浣�"); + } else { + this.$modal + .confirm('鏄惁纭鍒犻櫎鐮佸ご缂栧彿涓�"' + whIds + '"鐨勬暟鎹」锛�') + .then(function () { + return delWharf(whIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + } + }); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/wharf/export", + { + ...this.queryParams, + }, + `wharf_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/monitor/cache/index.vue b/src/views/monitor/cache/index.vue new file mode 100644 index 0000000..e81da2e --- /dev/null +++ b/src/views/monitor/cache/index.vue @@ -0,0 +1,144 @@ +<template> + <div class="app-container"> + <el-row> + <el-col :span="24" class="card-box"> + <el-card> + <div slot="header"><span><i class="el-icon-monitor"></i> 鍩烘湰淇℃伅</span></div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%"> + <tbody> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">Redis鐗堟湰</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_version }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">杩愯妯″紡</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.redis_mode == "standalone" ? "鍗曟満" : "闆嗙兢" }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">绔彛</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.tcp_port }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">瀹㈡埛绔暟</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.connected_clients }}</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕棿(澶�)</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.uptime_in_days }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鍐呭瓨</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.used_memory_human }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">浣跨敤CPU</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ parseFloat(cache.info.used_cpu_user_children).toFixed(2) }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">鍐呭瓨閰嶇疆</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.maxmemory_human }}</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">AOF鏄惁寮�鍚�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.aof_enabled == "0" ? "鍚�" : "鏄�" }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">RDB鏄惁鎴愬姛</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.rdb_last_bgsave_status }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">Key鏁伴噺</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.dbSize">{{ cache.dbSize }} </div></td> + <td class="el-table__cell is-leaf"><div class="cell">缃戠粶鍏ュ彛/鍑哄彛</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="cache.info">{{ cache.info.instantaneous_input_kbps }}kps/{{cache.info.instantaneous_output_kbps}}kps</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + + <el-col :span="12" class="card-box"> + <el-card> + <div slot="header"><span><i class="el-icon-pie-chart"></i> 鍛戒护缁熻</span></div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <div ref="commandstats" style="height: 420px" /> + </div> + </el-card> + </el-col> + + <el-col :span="12" class="card-box"> + <el-card> + <div slot="header"><span><i class="el-icon-odometer"></i> 鍐呭瓨淇℃伅</span></div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <div ref="usedmemory" style="height: 420px" /> + </div> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script> +import { getCache } from "@/api/monitor/cache"; +import * as echarts from "echarts"; + +export default { + name: "Cache", + data() { + return { + // 缁熻鍛戒护淇℃伅 + commandstats: null, + // 浣跨敤鍐呭瓨 + usedmemory: null, + // cache淇℃伅 + cache: [] + } + }, + created() { + this.getList(); + this.openLoading(); + }, + methods: { + /** 鏌ョ紦瀛樿淇℃伅 */ + getList() { + getCache().then((response) => { + this.cache = response.data; + this.$modal.closeLoading(); + + this.commandstats = echarts.init(this.$refs.commandstats, "macarons"); + this.commandstats.setOption({ + tooltip: { + trigger: "item", + formatter: "{a} <br/>{b} : {c} ({d}%)", + }, + series: [ + { + name: "鍛戒护", + type: "pie", + roseType: "radius", + radius: [15, 95], + center: ["50%", "38%"], + data: response.data.commandStats, + animationEasing: "cubicInOut", + animationDuration: 1000, + } + ] + }); + this.usedmemory = echarts.init(this.$refs.usedmemory, "macarons"); + this.usedmemory.setOption({ + tooltip: { + formatter: "{b} <br/>{a} : " + this.cache.info.used_memory_human, + }, + series: [ + { + name: "宄板��", + type: "gauge", + min: 0, + max: 1000, + detail: { + formatter: this.cache.info.used_memory_human, + }, + data: [ + { + value: parseFloat(this.cache.info.used_memory_human), + name: "鍐呭瓨娑堣��", + } + ] + } + ] + }); + }); + }, + // 鎵撳紑鍔犺浇灞� + openLoading() { + this.$modal.loading("姝e湪鍔犺浇缂撳瓨鐩戞帶鏁版嵁锛岃绋嶅�欙紒"); + } + } +}; +</script> diff --git a/src/views/monitor/cache/list.vue b/src/views/monitor/cache/list.vue new file mode 100644 index 0000000..29a7c74 --- /dev/null +++ b/src/views/monitor/cache/list.vue @@ -0,0 +1,241 @@ +<template> + <div class="app-container"> + <el-row :gutter="10"> + <el-col :span="8"> + <el-card style="height: calc(100vh - 125px)"> + <div slot="header"> + <span><i class="el-icon-collection"></i> 缂撳瓨鍒楄〃</span> + <el-button + style="float: right; padding: 3px 0" + type="text" + icon="el-icon-refresh-right" + @click="refreshCacheNames()" + ></el-button> + </div> + <el-table + v-loading="loading" + :data="cacheNames" + :height="tableHeight" + highlight-current-row + @row-click="getCacheKeys" + style="width: 100%" + > + <el-table-column + label="搴忓彿" + width="60" + type="index" + ></el-table-column> + + <el-table-column + label="缂撳瓨鍚嶇О" + align="center" + prop="cacheName" + :show-overflow-tooltip="true" + :formatter="nameFormatter" + ></el-table-column> + + <el-table-column + label="澶囨敞" + align="center" + prop="remark" + :show-overflow-tooltip="true" + /> + <el-table-column + label="鎿嶄綔" + width="60" + align="center" + class-name="small-padding fixed-width" + > + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleClearCacheName(scope.row)" + ></el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </el-col> + + <el-col :span="8"> + <el-card style="height: calc(100vh - 125px)"> + <div slot="header"> + <span><i class="el-icon-key"></i> 閿悕鍒楄〃</span> + <el-button + style="float: right; padding: 3px 0" + type="text" + icon="el-icon-refresh-right" + @click="refreshCacheKeys()" + ></el-button> + </div> + <el-table + v-loading="subLoading" + :data="cacheKeys" + :height="tableHeight" + highlight-current-row + @row-click="handleCacheValue" + style="width: 100%" + > + <el-table-column + label="搴忓彿" + width="60" + type="index" + ></el-table-column> + <el-table-column + label="缂撳瓨閿悕" + align="center" + :show-overflow-tooltip="true" + :formatter="keyFormatter" + > + </el-table-column> + <el-table-column + label="鎿嶄綔" + width="60" + align="center" + class-name="small-padding fixed-width" + > + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleClearCacheKey(scope.row)" + ></el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </el-col> + + <el-col :span="8"> + <el-card :bordered="false" style="height: calc(100vh - 125px)"> + <div slot="header"> + <span><i class="el-icon-document"></i> 缂撳瓨鍐呭</span> + <el-button + style="float: right; padding: 3px 0" + type="text" + icon="el-icon-refresh-right" + @click="handleClearCacheAll()" + >娓呯悊鍏ㄩ儴</el-button + > + </div> + <el-form :model="cacheForm"> + <el-row :gutter="32"> + <el-col :offset="1" :span="22"> + <el-form-item label="缂撳瓨鍚嶇О:" prop="cacheName"> + <el-input v-model="cacheForm.cacheName" :readOnly="true" /> + </el-form-item> + </el-col> + <el-col :offset="1" :span="22"> + <el-form-item label="缂撳瓨閿悕:" prop="cacheKey"> + <el-input v-model="cacheForm.cacheKey" :readOnly="true" /> + </el-form-item> + </el-col> + <el-col :offset="1" :span="22"> + <el-form-item label="缂撳瓨鍐呭:" prop="cacheValue"> + <el-input + v-model="cacheForm.cacheValue" + type="textarea" + :rows="8" + :readOnly="true" + /> + </el-form-item> + </el-col> + </el-row> + </el-form> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script> +import { listCacheName, listCacheKey, getCacheValue, clearCacheName, clearCacheKey, clearCacheAll } from "@/api/monitor/cache"; + +export default { + name: "CacheList", + data() { + return { + cacheNames: [], + cacheKeys: [], + cacheForm: {}, + loading: true, + subLoading: false, + nowCacheName: "", + tableHeight: window.innerHeight - 200 + }; + }, + created() { + this.getCacheNames(); + }, + methods: { + /** 鏌ヨ缂撳瓨鍚嶇О鍒楄〃 */ + getCacheNames() { + this.loading = true; + listCacheName().then(response => { + this.cacheNames = response.data; + this.loading = false; + }); + }, + /** 鍒锋柊缂撳瓨鍚嶇О鍒楄〃 */ + refreshCacheNames() { + this.getCacheNames(); + this.$modal.msgSuccess("鍒锋柊缂撳瓨鍒楄〃鎴愬姛"); + }, + /** 娓呯悊鎸囧畾鍚嶇О缂撳瓨 */ + handleClearCacheName(row) { + clearCacheName(row.cacheName).then(response => { + this.$modal.msgSuccess("娓呯悊缂撳瓨鍚嶇О[" + row.cacheName + "]鎴愬姛"); + this.getCacheKeys(); + }); + }, + /** 鏌ヨ缂撳瓨閿悕鍒楄〃 */ + getCacheKeys(row) { + const cacheName = row !== undefined ? row.cacheName : this.nowCacheName; + if (cacheName === "") { + return; + } + this.subLoading = true; + listCacheKey(cacheName).then(response => { + this.cacheKeys = response.data; + this.subLoading = false; + this.nowCacheName = cacheName; + }); + }, + /** 鍒锋柊缂撳瓨閿悕鍒楄〃 */ + refreshCacheKeys() { + this.getCacheKeys(); + this.$modal.msgSuccess("鍒锋柊閿悕鍒楄〃鎴愬姛"); + }, + /** 娓呯悊鎸囧畾閿悕缂撳瓨 */ + handleClearCacheKey(cacheKey) { + clearCacheKey(cacheKey).then(response => { + this.$modal.msgSuccess("娓呯悊缂撳瓨閿悕[" + cacheKey + "]鎴愬姛"); + this.getCacheKeys(); + }); + }, + /** 鍒楄〃鍓嶇紑鍘婚櫎 */ + nameFormatter(row) { + return row.cacheName.replace(":", ""); + }, + /** 閿悕鍓嶇紑鍘婚櫎 */ + keyFormatter(cacheKey) { + return cacheKey.replace(this.nowCacheName, ""); + }, + /** 鏌ヨ缂撳瓨鍐呭璇︾粏 */ + handleCacheValue(cacheKey) { + getCacheValue(this.nowCacheName, cacheKey).then(response => { + this.cacheForm = response.data; + }); + }, + /** 娓呯悊鍏ㄩ儴缂撳瓨 */ + handleClearCacheAll() { + clearCacheAll().then(response => { + this.$modal.msgSuccess("娓呯悊鍏ㄩ儴缂撳瓨鎴愬姛"); + }); + } + }, +}; +</script> diff --git a/src/views/monitor/druid/index.vue b/src/views/monitor/druid/index.vue new file mode 100644 index 0000000..c6ad585 --- /dev/null +++ b/src/views/monitor/druid/index.vue @@ -0,0 +1,15 @@ +<template> + <i-frame :src="url" /> +</template> +<script> +import iFrame from "@/components/iFrame/index"; +export default { + name: "Druid", + components: { iFrame }, + data() { + return { + url: process.env.VUE_APP_BASE_API + "/druid/login.html" + }; + }, +}; +</script> diff --git a/src/views/monitor/job/index.vue b/src/views/monitor/job/index.vue new file mode 100644 index 0000000..9b1b9ae --- /dev/null +++ b/src/views/monitor/job/index.vue @@ -0,0 +1,602 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="浠诲姟鍚嶇О" prop="jobName"> + <el-input + v-model="queryParams.jobName" + placeholder="璇疯緭鍏ヤ换鍔″悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="浠诲姟缁勫悕" prop="jobGroup"> + <el-select v-model="queryParams.jobGroup" placeholder="璇烽�夋嫨浠诲姟缁勫悕" clearable> + <el-option + v-for="dict in dict.type.sys_job_group" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="浠诲姟鐘舵��" prop="status"> + <el-select v-model="queryParams.status" placeholder="璇烽�夋嫨浠诲姟鐘舵��" clearable> + <el-option + v-for="dict in dict.type.sys_job_status" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['monitor:job:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['monitor:job:edit']" + >淇敼</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['monitor:job:remove']" + >鍒犻櫎</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['monitor:job:export']" + >瀵煎嚭</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-s-operation" + size="mini" + @click="handleJobLog" + v-hasPermi="['monitor:job:query']" + >鏃ュ織</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="jobList" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="浠诲姟缂栧彿" width="100" align="center" prop="jobId" /> + <el-table-column + label="浠诲姟鍚嶇О" + align="center" + prop="jobName" + :show-overflow-tooltip="true" + /> + <el-table-column label="浠诲姟缁勫悕" align="center" prop="jobGroup"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup" /> + </template> + </el-table-column> + <el-table-column + label="璋冪敤鐩爣瀛楃涓�" + align="center" + prop="invokeTarget" + :show-overflow-tooltip="true" + /> + <el-table-column + label="cron鎵ц琛ㄨ揪寮�" + align="center" + prop="cronExpression" + :show-overflow-tooltip="true" + /> + <el-table-column label="鐘舵��" align="center"> + <template slot-scope="scope"> + <el-switch + v-model="scope.row.status" + active-value="0" + inactive-value="1" + @change="handleStatusChange(scope.row)" + ></el-switch> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['monitor:job:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['monitor:job:remove']" + >鍒犻櫎</el-button + > + <el-dropdown + size="mini" + @command="(command) => handleCommand(command, scope.row)" + v-hasPermi="['monitor:job:changeStatus', 'monitor:job:query']" + > + <el-button size="mini" type="text" icon="el-icon-d-arrow-right" + >鏇村</el-button + > + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item + command="handleRun" + icon="el-icon-caret-right" + v-hasPermi="['monitor:job:changeStatus']" + >鎵ц涓�娆�</el-dropdown-item + > + <el-dropdown-item + command="handleView" + icon="el-icon-view" + v-hasPermi="['monitor:job:query']" + >浠诲姟璇︾粏</el-dropdown-item + > + <el-dropdown-item + command="handleJobLog" + icon="el-icon-s-operation" + v-hasPermi="['monitor:job:query']" + >璋冨害鏃ュ織</el-dropdown-item + > + </el-dropdown-menu> + </el-dropdown> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰畾鏃朵换鍔″璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="120px"> + <el-row> + <el-col :span="12"> + <el-form-item label="浠诲姟鍚嶇О" prop="jobName"> + <el-input v-model="form.jobName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浠诲姟鍒嗙粍" prop="jobGroup"> + <el-select v-model="form.jobGroup" placeholder="璇烽�夋嫨浠诲姟鍒嗙粍"> + <el-option + v-for="dict in dict.type.sys_job_group" + :key="dict.value" + :label="dict.label" + :value="dict.value" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item prop="invokeTarget"> + <span slot="label"> + 璋冪敤鏂规硶 + <el-tooltip placement="top"> + <div slot="content"> + Bean璋冪敤绀轰緥锛歳yTask.ryParams('ry') + <br />Class绫昏皟鐢ㄧず渚嬶細com.ruoyi.quartz.task.RyTask.ryParams('ry') + <br />鍙傛暟璇存槑锛氭敮鎸佸瓧绗︿覆锛屽竷灏旂被鍨嬶紝闀挎暣鍨嬶紝娴偣鍨嬶紝鏁村瀷 + </div> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="form.invokeTarget" placeholder="璇疯緭鍏ヨ皟鐢ㄧ洰鏍囧瓧绗︿覆" /> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="cron琛ㄨ揪寮�" prop="cronExpression"> + <el-input v-model="form.cronExpression" placeholder="璇疯緭鍏ron鎵ц琛ㄨ揪寮�"> + <template slot="append"> + <el-button type="primary" @click="handleShowCron"> + 鐢熸垚琛ㄨ揪寮� + <i class="el-icon-time el-icon--right"></i> + </el-button> + </template> + </el-input> + </el-form-item> + </el-col> + <el-col :span="24" v-if="form.jobId !== undefined"> + <el-form-item label="鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_job_status" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鎵ц绛栫暐" prop="misfirePolicy"> + <el-radio-group v-model="form.misfirePolicy" size="small"> + <el-radio-button label="1">绔嬪嵆鎵ц</el-radio-button> + <el-radio-button label="2">鎵ц涓�娆�</el-radio-button> + <el-radio-button label="3">鏀惧純鎵ц</el-radio-button> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鏄惁骞跺彂" prop="concurrent"> + <el-radio-group v-model="form.concurrent" size="small"> + <el-radio-button label="0">鍏佽</el-radio-button> + <el-radio-button label="1">绂佹</el-radio-button> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + + <el-dialog + title="Cron琛ㄨ揪寮忕敓鎴愬櫒" + :visible.sync="openCron" + append-to-body + destroy-on-close + class="scrollbar" + > + <crontab + @hide="openCron = false" + @fill="crontabFill" + :expression="expression" + ></crontab> + </el-dialog> + + <!-- 浠诲姟鏃ュ織璇︾粏 --> + <el-dialog title="浠诲姟璇︾粏" :visible.sync="openView" width="700px" append-to-body> + <el-form ref="form" :model="form" label-width="120px" size="mini"> + <el-row> + <el-col :span="12"> + <el-form-item label="浠诲姟缂栧彿锛�">{{ form.jobId }}</el-form-item> + <el-form-item label="浠诲姟鍚嶇О锛�">{{ form.jobName }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浠诲姟鍒嗙粍锛�">{{ jobGroupFormat(form) }}</el-form-item> + <el-form-item label="鍒涘缓鏃堕棿锛�">{{ form.createTime }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="cron琛ㄨ揪寮忥細">{{ form.cronExpression }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="涓嬫鎵ц鏃堕棿锛�">{{ + parseTime(form.nextValidTime) + }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="璋冪敤鐩爣鏂规硶锛�">{{ form.invokeTarget }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浠诲姟鐘舵�侊細"> + <div v-if="form.status == 0">姝e父</div> + <div v-else-if="form.status == 1">鏆傚仠</div> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鏄惁骞跺彂锛�"> + <div v-if="form.concurrent == 0">鍏佽</div> + <div v-else-if="form.concurrent == 1">绂佹</div> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鎵ц绛栫暐锛�"> + <div v-if="form.misfirePolicy == 0">榛樿绛栫暐</div> + <div v-else-if="form.misfirePolicy == 1">绔嬪嵆鎵ц</div> + <div v-else-if="form.misfirePolicy == 2">鎵ц涓�娆�</div> + <div v-else-if="form.misfirePolicy == 3">鏀惧純鎵ц</div> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button @click="openView = false">鍏� 闂�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listJob, + getJob, + delJob, + addJob, + updateJob, + runJob, + changeJobStatus, +} from "@/api/monitor/job"; +import Crontab from "@/components/Crontab"; + +export default { + components: { Crontab }, + name: "Job", + dicts: ["sys_job_group", "sys_job_status"], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 瀹氭椂浠诲姟琛ㄦ牸鏁版嵁 + jobList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏄惁鏄剧ず璇︾粏寮瑰嚭灞� + openView: false, + // 鏄惁鏄剧ずCron琛ㄨ揪寮忓脊鍑哄眰 + openCron: false, + // 浼犲叆鐨勮〃杈惧紡 + expression: "", + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + jobName: undefined, + jobGroup: undefined, + status: undefined, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + jobName: [{ required: true, message: "浠诲姟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + invokeTarget: [ + { required: true, message: "璋冪敤鐩爣瀛楃涓蹭笉鑳戒负绌�", trigger: "blur" }, + ], + cronExpression: [ + { required: true, message: "cron鎵ц琛ㄨ揪寮忎笉鑳戒负绌�", trigger: "blur" }, + ], + }, + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瀹氭椂浠诲姟鍒楄〃 */ + getList() { + this.loading = true; + listJob(this.queryParams).then((response) => { + this.jobList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 浠诲姟缁勫悕瀛楀吀缈昏瘧 + jobGroupFormat(row, column) { + return this.selectDictLabel(this.dict.type.sys_job_group, row.jobGroup); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + jobId: undefined, + jobName: undefined, + jobGroup: undefined, + invokeTarget: undefined, + cronExpression: undefined, + misfirePolicy: 1, + concurrent: 1, + status: "0", + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.jobId); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + // 鏇村鎿嶄綔瑙﹀彂 + handleCommand(command, row) { + switch (command) { + case "handleRun": + this.handleRun(row); + break; + case "handleView": + this.handleView(row); + break; + case "handleJobLog": + this.handleJobLog(row); + break; + default: + break; + } + }, + // 浠诲姟鐘舵�佷慨鏀� + handleStatusChange(row) { + let text = row.status === "0" ? "鍚敤" : "鍋滅敤"; + this.$modal + .confirm('纭瑕�"' + text + '""' + row.jobName + '"浠诲姟鍚楋紵') + .then(function () { + return changeJobStatus(row.jobId, row.status); + }) + .then(() => { + this.$modal.msgSuccess(text + "鎴愬姛"); + }) + .catch(function () { + row.status = row.status === "0" ? "1" : "0"; + }); + }, + /* 绔嬪嵆鎵ц涓�娆� */ + handleRun(row) { + this.$modal + .confirm('纭瑕佺珛鍗虫墽琛屼竴娆�"' + row.jobName + '"浠诲姟鍚楋紵') + .then(function () { + return runJob(row.jobId, row.jobGroup); + }) + .then(() => { + this.$modal.msgSuccess("鎵ц鎴愬姛"); + }) + .catch(() => {}); + }, + /** 浠诲姟璇︾粏淇℃伅 */ + handleView(row) { + getJob(row.jobId).then((response) => { + this.form = response.data; + this.openView = true; + }); + }, + /** cron琛ㄨ揪寮忔寜閽搷浣� */ + handleShowCron() { + this.expression = this.form.cronExpression; + this.openCron = true; + }, + /** 纭畾鍚庡洖浼犲�� */ + crontabFill(value) { + this.form.cronExpression = value; + }, + /** 浠诲姟鏃ュ織鍒楄〃鏌ヨ */ + handleJobLog(row) { + const jobId = row.jobId || 0; + this.$router.push("/monitor/job-log/index/" + jobId); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞浠诲姟"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const jobId = row.jobId || this.ids; + getJob(jobId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼浠诲姟"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.jobId != undefined) { + updateJob(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addJob(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const jobIds = row.jobId || this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎瀹氭椂浠诲姟缂栧彿涓�"' + jobIds + '"鐨勬暟鎹」锛�') + .then(function () { + return delJob(jobIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "monitor/job/export", + { + ...this.queryParams, + }, + `job_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/monitor/job/log.vue b/src/views/monitor/job/log.vue new file mode 100644 index 0000000..4855582 --- /dev/null +++ b/src/views/monitor/job/log.vue @@ -0,0 +1,347 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="浠诲姟鍚嶇О" prop="jobName"> + <el-input + v-model="queryParams.jobName" + placeholder="璇疯緭鍏ヤ换鍔″悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="浠诲姟缁勫悕" prop="jobGroup"> + <el-select + v-model="queryParams.jobGroup" + placeholder="璇烽�夋嫨浠诲姟缁勫悕" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_job_group" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鎵ц鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="璇烽�夋嫨鎵ц鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_common_status" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鎵ц鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['monitor:job:remove']" + >鍒犻櫎</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + @click="handleClean" + v-hasPermi="['monitor:job:remove']" + >娓呯┖</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['monitor:job:export']" + >瀵煎嚭</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-close" + size="mini" + @click="handleClose" + >鍏抽棴</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="jobLogList" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="鏃ュ織缂栧彿" width="80" align="center" prop="jobLogId" /> + <el-table-column + label="浠诲姟鍚嶇О" + align="center" + prop="jobName" + :show-overflow-tooltip="true" + /> + <el-table-column + label="浠诲姟缁勫悕" + align="center" + prop="jobGroup" + :show-overflow-tooltip="true" + > + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_job_group" :value="scope.row.jobGroup" /> + </template> + </el-table-column> + <el-table-column + label="璋冪敤鐩爣瀛楃涓�" + align="center" + prop="invokeTarget" + :show-overflow-tooltip="true" + /> + <el-table-column + label="鏃ュ織淇℃伅" + align="center" + prop="jobMessage" + :show-overflow-tooltip="true" + /> + <el-table-column label="鎵ц鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="鎵ц鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-view" + @click="handleView(scope.row)" + v-hasPermi="['monitor:job:query']" + >璇︾粏</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 璋冨害鏃ュ織璇︾粏 --> + <el-dialog title="璋冨害鏃ュ織璇︾粏" :visible.sync="open" width="700px" append-to-body> + <el-form ref="form" :model="form" label-width="100px" size="mini"> + <el-row> + <el-col :span="12"> + <el-form-item label="鏃ュ織搴忓彿锛�">{{ form.jobLogId }}</el-form-item> + <el-form-item label="浠诲姟鍚嶇О锛�">{{ form.jobName }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浠诲姟鍒嗙粍锛�">{{ form.jobGroup }}</el-form-item> + <el-form-item label="鎵ц鏃堕棿锛�">{{ form.createTime }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="璋冪敤鏂规硶锛�">{{ form.invokeTarget }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鏃ュ織淇℃伅锛�">{{ form.jobMessage }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鎵ц鐘舵�侊細"> + <div v-if="form.status == 0">姝e父</div> + <div v-else-if="form.status == 1">澶辫触</div> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="寮傚父淇℃伅锛�" v-if="form.status == 1">{{ + form.exceptionInfo + }}</el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button @click="open = false">鍏� 闂�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { getJob } from "@/api/monitor/job"; +import { listJobLog, delJobLog, cleanJobLog } from "@/api/monitor/jobLog"; + +export default { + name: "JobLog", + dicts: ["sys_common_status", "sys_job_group"], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 璋冨害鏃ュ織琛ㄦ牸鏁版嵁 + jobLogList: [], + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 琛ㄥ崟鍙傛暟 + form: {}, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + jobName: undefined, + jobGroup: undefined, + status: undefined, + }, + }; + }, + created() { + const jobId = this.$route.params && this.$route.params.jobId; + if (jobId !== undefined && jobId != 0) { + getJob(jobId).then((response) => { + this.queryParams.jobName = response.data.jobName; + this.queryParams.jobGroup = response.data.jobGroup; + this.getList(); + }); + } else { + this.getList(); + } + }, + methods: { + /** 鏌ヨ璋冨害鏃ュ織鍒楄〃 */ + getList() { + this.loading = true; + listJobLog(this.addDateRange(this.queryParams, this.dateRange)).then((response) => { + this.jobLogList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 杩斿洖鎸夐挳 + handleClose() { + const obj = { path: "/monitor/job" }; + this.$tab.closeOpenPage(obj); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.jobLogId); + this.multiple = !selection.length; + }, + /** 璇︾粏鎸夐挳鎿嶄綔 */ + handleView(row) { + this.open = true; + this.form = row; + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const jobLogIds = this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎璋冨害鏃ュ織缂栧彿涓�"' + jobLogIds + '"鐨勬暟鎹」锛�') + .then(function () { + return delJobLog(jobLogIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + /** 娓呯┖鎸夐挳鎿嶄綔 */ + handleClean() { + this.$modal + .confirm("鏄惁纭娓呯┖鎵�鏈夎皟搴︽棩蹇楁暟鎹」锛�") + .then(function () { + return cleanJobLog(); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("娓呯┖鎴愬姛"); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "/monitor/jobLog/export", + { + ...this.queryParams, + }, + `log_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/monitor/logininfor/index.vue b/src/views/monitor/logininfor/index.vue new file mode 100644 index 0000000..d6af834 --- /dev/null +++ b/src/views/monitor/logininfor/index.vue @@ -0,0 +1,246 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="鐧诲綍鍦板潃" prop="ipaddr"> + <el-input + v-model="queryParams.ipaddr" + placeholder="璇疯緭鍏ョ櫥褰曞湴鍧�" + clearable + style="width: 240px;" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input + v-model="queryParams.userName" + placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" + clearable + style="width: 240px;" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="鐧诲綍鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_common_status" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鐧诲綍鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + :default-time="['00:00:00', '23:59:59']" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['monitor:logininfor:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + @click="handleClean" + v-hasPermi="['monitor:logininfor:remove']" + >娓呯┖</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-unlock" + size="mini" + :disabled="single" + @click="handleUnlock" + v-hasPermi="['monitor:logininfor:unlock']" + >瑙i攣</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['monitor:logininfor:export']" + >瀵煎嚭</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="璁块棶缂栧彿" align="center" prop="infoId" /> + <el-table-column label="鐢ㄦ埛鍚嶇О" align="center" prop="userName" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" /> + <el-table-column label="鐧诲綍鍦板潃" align="center" prop="ipaddr" width="130" :show-overflow-tooltip="true" /> + <el-table-column label="鐧诲綍鍦扮偣" align="center" prop="loginLocation" :show-overflow-tooltip="true" /> + <el-table-column label="娴忚鍣�" align="center" prop="browser" :show-overflow-tooltip="true" /> + <el-table-column label="鎿嶄綔绯荤粺" align="center" prop="os" /> + <el-table-column label="鐧诲綍鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔淇℃伅" align="center" prop="msg" :show-overflow-tooltip="true" /> + <el-table-column label="鐧诲綍鏃ユ湡" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.loginTime) }}</span> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </div> +</template> + +<script> +import { list, delLogininfor, cleanLogininfor, unlockLogininfor } from "@/api/monitor/logininfor"; + +export default { + name: "Logininfor", + dicts: ['sys_common_status'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 閫夋嫨鐢ㄦ埛鍚� + selectName: "", + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 琛ㄦ牸鏁版嵁 + list: [], + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 榛樿鎺掑簭 + defaultSort: {prop: 'loginTime', order: 'descending'}, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + ipaddr: undefined, + userName: undefined, + status: undefined + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 */ + getList() { + this.loading = true; + list(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.list = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.pageNum = 1; + this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order) + }, + /** 澶氶�夋閫変腑鏁版嵁 */ + handleSelectionChange(selection) { + this.ids = selection.map(item => item.infoId) + this.single = selection.length!=1 + this.multiple = !selection.length + this.selectName = selection.map(item => item.userName); + }, + /** 鎺掑簭瑙﹀彂浜嬩欢 */ + handleSortChange(column, prop, order) { + this.queryParams.orderByColumn = column.prop; + this.queryParams.isAsc = column.order; + this.getList(); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const infoIds = row.infoId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎璁块棶缂栧彿涓�"' + infoIds + '"鐨勬暟鎹」锛�').then(function() { + return delLogininfor(infoIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 娓呯┖鎸夐挳鎿嶄綔 */ + handleClean() { + this.$modal.confirm('鏄惁纭娓呯┖鎵�鏈夌櫥褰曟棩蹇楁暟鎹」锛�').then(function() { + return cleanLogininfor(); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("娓呯┖鎴愬姛"); + }).catch(() => {}); + }, + /** 瑙i攣鎸夐挳鎿嶄綔 */ + handleUnlock() { + const username = this.selectName; + this.$modal.confirm('鏄惁纭瑙i攣鐢ㄦ埛"' + username + '"鏁版嵁椤�?').then(function() { + return unlockLogininfor(username); + }).then(() => { + this.$modal.msgSuccess("鐢ㄦ埛" + username + "瑙i攣鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('monitor/logininfor/export', { + ...this.queryParams + }, `logininfor_${new Date().getTime()}.xlsx`) + } + } +}; +</script> + diff --git a/src/views/monitor/online/index.vue b/src/views/monitor/online/index.vue new file mode 100644 index 0000000..6222025 --- /dev/null +++ b/src/views/monitor/online/index.vue @@ -0,0 +1,132 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" label-width="68px"> + <el-form-item label="鐧诲綍鍦板潃" prop="ipaddr"> + <el-input + v-model="queryParams.ipaddr" + placeholder="璇疯緭鍏ョ櫥褰曞湴鍧�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input + v-model="queryParams.userName" + placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + + </el-form> + <el-table + v-loading="loading" + :data="list.slice((pageNum-1)*pageSize,pageNum*pageSize)" + style="width: 100%;" + > + <el-table-column label="搴忓彿" type="index" align="center"> + <template slot-scope="scope"> + <span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span> + </template> + </el-table-column> + <el-table-column label="浼氳瘽缂栧彿" align="center" prop="tokenId" :show-overflow-tooltip="true" /> + <el-table-column label="鐧诲綍鍚嶇О" align="center" prop="userName" :show-overflow-tooltip="true" /> + <el-table-column label="閮ㄩ棬鍚嶇О" align="center" prop="deptName" /> + <el-table-column label="涓绘満" align="center" prop="ipaddr" :show-overflow-tooltip="true" /> + <el-table-column label="鐧诲綍鍦扮偣" align="center" prop="loginLocation" :show-overflow-tooltip="true" /> + <el-table-column label="娴忚鍣�" align="center" prop="browser" /> + <el-table-column label="鎿嶄綔绯荤粺" align="center" prop="os" /> + <el-table-column label="鐧诲綍鏃堕棿" align="center" prop="loginTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.loginTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleForceLogout(scope.row)" + v-hasPermi="['monitor:online:forceLogout']" + >寮洪��</el-button> + </template> + </el-table-column> + </el-table> + + <pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" /> + </div> +</template> + +<script> +import { list, forceLogout } from "@/api/monitor/online"; +import axios from 'axios' +export default { + name: "Online", + data() { + return { + // 閬僵灞� + loading: true, + // 鎬绘潯鏁� + total: 0, + // 琛ㄦ牸鏁版嵁 + list: [], + pageNum: 1, + pageSize: 10, + // 鏌ヨ鍙傛暟 + queryParams: { + ipaddr: undefined, + userName: undefined + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鐧诲綍鏃ュ織鍒楄〃 */ + getList() { + console.log(1) + console.log(document.cookie) + this.loading = true; + list(this.queryParams).then(response => { + this.list = response.rows; + this.total = response.total; + this.loading = false; + }); + + // axios.get('http://127.0.0.1:8081/monitor/online/test', + // { withCredentials: true, + // headers: { 'Content-Type': 'application/json', + // 'ck': document.cookie } }) + // .then(response => { console.log(response.data); }) + // .catch(error => { console.error('Error:', error); }); + }, + + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 寮洪��鎸夐挳鎿嶄綔 */ + handleForceLogout(row) { + this.$modal.confirm('鏄惁纭寮洪��鍚嶇О涓�"' + row.userName + '"鐨勭敤鎴凤紵').then(function() { + return forceLogout(row.tokenId); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("寮洪��鎴愬姛"); + }).catch(() => {}); + } + } +}; +</script> + diff --git a/src/views/monitor/operlog/index.vue b/src/views/monitor/operlog/index.vue new file mode 100644 index 0000000..988f983 --- /dev/null +++ b/src/views/monitor/operlog/index.vue @@ -0,0 +1,323 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="鎿嶄綔鍦板潃" prop="operIp"> + <el-input + v-model="queryParams.operIp" + placeholder="璇疯緭鍏ユ搷浣滃湴鍧�" + clearable + style="width: 240px;" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="绯荤粺妯″潡" prop="title"> + <el-input + v-model="queryParams.title" + placeholder="璇疯緭鍏ョ郴缁熸ā鍧�" + clearable + style="width: 240px;" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鎿嶄綔浜哄憳" prop="operName"> + <el-input + v-model="queryParams.operName" + placeholder="璇疯緭鍏ユ搷浣滀汉鍛�" + clearable + style="width: 240px;" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="绫诲瀷" prop="businessType"> + <el-select + v-model="queryParams.businessType" + placeholder="鎿嶄綔绫诲瀷" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_oper_type" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="鎿嶄綔鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_common_status" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鎿嶄綔鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd HH:mm:ss" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + :default-time="['00:00:00', '23:59:59']" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['monitor:operlog:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + @click="handleClean" + v-hasPermi="['monitor:operlog:remove']" + >娓呯┖</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['monitor:operlog:export']" + >瀵煎嚭</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table ref="tables" v-loading="loading" :data="list" @selection-change="handleSelectionChange" :default-sort="defaultSort" @sort-change="handleSortChange"> + <el-table-column type="selection" width="50" align="center" /> + <el-table-column label="鏃ュ織缂栧彿" align="center" prop="operId" /> + <el-table-column label="绯荤粺妯″潡" align="center" prop="title" :show-overflow-tooltip="true" /> + <el-table-column label="鎿嶄綔绫诲瀷" align="center" prop="businessType"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_oper_type" :value="scope.row.businessType"/> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔浜哄憳" align="center" prop="operName" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']" /> + <el-table-column label="鎿嶄綔鍦板潃" align="center" prop="operIp" width="130" :show-overflow-tooltip="true" /> + <el-table-column label="鎿嶄綔鍦扮偣" align="center" prop="operLocation" :show-overflow-tooltip="true" /> + <el-table-column label="鎿嶄綔鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.operTime) }}</span> + </template> + </el-table-column> + <el-table-column label="娑堣�楁椂闂�" align="center" prop="costTime" width="110" :show-overflow-tooltip="true" sortable="custom" :sort-orders="['descending', 'ascending']"> + <template slot-scope="scope"> + <span>{{ scope.row.costTime }}姣</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-view" + @click="handleView(scope.row,scope.index)" + v-hasPermi="['monitor:operlog:query']" + >璇︾粏</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 鎿嶄綔鏃ュ織璇︾粏 --> + <el-dialog title="鎿嶄綔鏃ュ織璇︾粏" :visible.sync="open" width="700px" append-to-body> + <el-form ref="form" :model="form" label-width="100px" size="mini"> + <el-row> + <el-col :span="12"> + <el-form-item label="鎿嶄綔妯″潡锛�">{{ form.title }} / {{ typeFormat(form) }}</el-form-item> + <el-form-item + label="鐧诲綍淇℃伅锛�" + >{{ form.operName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="璇锋眰鍦板潃锛�">{{ form.operUrl }}</el-form-item> + <el-form-item label="璇锋眰鏂瑰紡锛�">{{ form.requestMethod }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鎿嶄綔鏂规硶锛�">{{ form.method }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="璇锋眰鍙傛暟锛�">{{ form.operParam }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="杩斿洖鍙傛暟锛�">{{ form.jsonResult }}</el-form-item> + </el-col> + <el-col :span="6"> + <el-form-item label="鎿嶄綔鐘舵�侊細"> + <div v-if="form.status === 0">姝e父</div> + <div v-else-if="form.status === 1">澶辫触</div> + </el-form-item> + </el-col> + <el-col :span="8"> + <el-form-item label="娑堣�楁椂闂达細">{{ form.costTime }}姣</el-form-item> + </el-col> + <el-col :span="10"> + <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime) }}</el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="寮傚父淇℃伅锛�" v-if="form.status === 1">{{ form.errorMsg }}</el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button @click="open = false">鍏� 闂�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { list, delOperlog, cleanOperlog } from "@/api/monitor/operlog"; + +export default { + name: "Operlog", + dicts: ['sys_oper_type', 'sys_common_status'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 琛ㄦ牸鏁版嵁 + list: [], + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 榛樿鎺掑簭 + defaultSort: {prop: 'operTime', order: 'descending'}, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + operIp: undefined, + title: undefined, + operName: undefined, + businessType: undefined, + status: undefined + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鐧诲綍鏃ュ織 */ + getList() { + this.loading = true; + list(this.addDateRange(this.queryParams, this.dateRange)).then( response => { + this.list = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + // 鎿嶄綔鏃ュ織绫诲瀷瀛楀吀缈昏瘧 + typeFormat(row, column) { + return this.selectDictLabel(this.dict.type.sys_oper_type, row.businessType); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.pageNum = 1; + this.$refs.tables.sort(this.defaultSort.prop, this.defaultSort.order) + }, + /** 澶氶�夋閫変腑鏁版嵁 */ + handleSelectionChange(selection) { + this.ids = selection.map(item => item.operId) + this.multiple = !selection.length + }, + /** 鎺掑簭瑙﹀彂浜嬩欢 */ + handleSortChange(column, prop, order) { + this.queryParams.orderByColumn = column.prop; + this.queryParams.isAsc = column.order; + this.getList(); + }, + /** 璇︾粏鎸夐挳鎿嶄綔 */ + handleView(row) { + this.open = true; + this.form = row; + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const operIds = row.operId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎鏃ュ織缂栧彿涓�"' + operIds + '"鐨勬暟鎹」锛�').then(function() { + return delOperlog(operIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 娓呯┖鎸夐挳鎿嶄綔 */ + handleClean() { + this.$modal.confirm('鏄惁纭娓呯┖鎵�鏈夋搷浣滄棩蹇楁暟鎹」锛�').then(function() { + return cleanOperlog(); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("娓呯┖鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('monitor/operlog/export', { + ...this.queryParams + }, `operlog_${new Date().getTime()}.xlsx`) + } + } +}; +</script> + diff --git a/src/views/monitor/server/index.vue b/src/views/monitor/server/index.vue new file mode 100644 index 0000000..15ffc9a --- /dev/null +++ b/src/views/monitor/server/index.vue @@ -0,0 +1,207 @@ +<template> + <div class="app-container"> + <el-row> + <el-col :span="12" class="card-box"> + <el-card> + <div slot="header"><span><i class="el-icon-cpu"></i> CPU</span></div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%;"> + <thead> + <tr> + <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鍊�</div></th> + </tr> + </thead> + <tbody> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鏍稿績鏁�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.cpuNum }}</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鐢ㄦ埛浣跨敤鐜�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.used }}%</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">绯荤粺浣跨敤鐜�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.sys }}%</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">褰撳墠绌洪棽鐜�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.cpu">{{ server.cpu.free }}%</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + + <el-col :span="12" class="card-box"> + <el-card> + <div slot="header"><span><i class="el-icon-tickets"></i> 鍐呭瓨</span></div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%;"> + <thead> + <tr> + <th class="el-table__cell is-leaf"><div class="cell">灞炴��</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鍐呭瓨</div></th> + <th class="el-table__cell is-leaf"><div class="cell">JVM</div></th> + </tr> + </thead> + <tbody> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鎬诲唴瀛�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.total }}G</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.total }}M</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">宸茬敤鍐呭瓨</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.used}}G</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.used}}M</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鍓╀綑鍐呭瓨</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem">{{ server.mem.free }}G</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.free }}M</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">浣跨敤鐜�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.mem" :class="{'text-danger': server.mem.usage > 80}">{{ server.mem.usage }}%</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm" :class="{'text-danger': server.jvm.usage > 80}">{{ server.jvm.usage }}%</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + + <el-col :span="24" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-monitor"></i> 鏈嶅姟鍣ㄤ俊鎭�</span> + </div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%;"> + <tbody> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣ㄥ悕绉�</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerName }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">鎿嶄綔绯荤粺</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osName }}</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鏈嶅姟鍣↖P</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.computerIp }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">绯荤粺鏋舵瀯</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.osArch }}</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + + <el-col :span="24" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-coffee-cup"></i> Java铏氭嫙鏈轰俊鎭�</span> + </div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%;table-layout:fixed;"> + <tbody> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">Java鍚嶇О</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.name }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">Java鐗堟湰</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.version }}</div></td> + </tr> + <tr> + <td class="el-table__cell is-leaf"><div class="cell">鍚姩鏃堕棿</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.startTime }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">杩愯鏃堕暱</div></td> + <td class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.runTime }}</div></td> + </tr> + <tr> + <td colspan="1" class="el-table__cell is-leaf"><div class="cell">瀹夎璺緞</div></td> + <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.home }}</div></td> + </tr> + <tr> + <td colspan="1" class="el-table__cell is-leaf"><div class="cell">椤圭洰璺緞</div></td> + <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.sys">{{ server.sys.userDir }}</div></td> + </tr> + <tr> + <td colspan="1" class="el-table__cell is-leaf"><div class="cell">杩愯鍙傛暟</div></td> + <td colspan="3" class="el-table__cell is-leaf"><div class="cell" v-if="server.jvm">{{ server.jvm.inputArgs }}</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + + <el-col :span="24" class="card-box"> + <el-card> + <div slot="header"> + <span><i class="el-icon-receiving"></i> 纾佺洏鐘舵��</span> + </div> + <div class="el-table el-table--enable-row-hover el-table--medium"> + <table cellspacing="0" style="width: 100%;"> + <thead> + <tr> + <th class="el-table__cell el-table__cell is-leaf"><div class="cell">鐩樼璺緞</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鏂囦欢绯荤粺</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鐩樼绫诲瀷</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鎬诲ぇ灏�</div></th> + <th class="el-table__cell is-leaf"><div class="cell">鍙敤澶у皬</div></th> + <th class="el-table__cell is-leaf"><div class="cell">宸茬敤澶у皬</div></th> + <th class="el-table__cell is-leaf"><div class="cell">宸茬敤鐧惧垎姣�</div></th> + </tr> + </thead> + <tbody v-if="server.sysFiles"> + <tr v-for="(sysFile, index) in server.sysFiles" :key="index"> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.dirName }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.sysTypeName }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.typeName }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.total }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.free }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell">{{ sysFile.used }}</div></td> + <td class="el-table__cell is-leaf"><div class="cell" :class="{'text-danger': sysFile.usage > 80}">{{ sysFile.usage }}%</div></td> + </tr> + </tbody> + </table> + </div> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script> +import { getServer } from "@/api/monitor/server"; + +export default { + name: "Server", + data() { + return { + // 鏈嶅姟鍣ㄤ俊鎭� + server: [] + }; + }, + created() { + this.getList(); + this.openLoading(); + }, + methods: { + /** 鏌ヨ鏈嶅姟鍣ㄤ俊鎭� */ + getList() { + getServer().then(response => { + this.server = response.data; + this.$modal.closeLoading(); + }); + }, + // 鎵撳紑鍔犺浇灞� + openLoading() { + this.$modal.loading("姝e湪鍔犺浇鏈嶅姟鐩戞帶鏁版嵁锛岃绋嶅�欙紒"); + } + } +}; +</script> diff --git a/src/views/redirect.vue b/src/views/redirect.vue new file mode 100644 index 0000000..db4c1d6 --- /dev/null +++ b/src/views/redirect.vue @@ -0,0 +1,12 @@ +<script> +export default { + created() { + const { params, query } = this.$route + const { path } = params + this.$router.replace({ path: '/' + path, query }) + }, + render: function(h) { + return h() // avoid warning message + } +} +</script> diff --git a/src/views/register.vue b/src/views/register.vue new file mode 100644 index 0000000..396d582 --- /dev/null +++ b/src/views/register.vue @@ -0,0 +1,209 @@ +<template> + <div class="register"> + <el-form ref="registerForm" :model="registerForm" :rules="registerRules" class="register-form"> + <h3 class="title">鑻ヤ緷鍚庡彴绠$悊绯荤粺</h3> + <el-form-item prop="username"> + <el-input v-model="registerForm.username" type="text" auto-complete="off" placeholder="璐﹀彿"> + <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" /> + </el-input> + </el-form-item> + <el-form-item prop="password"> + <el-input + v-model="registerForm.password" + type="password" + auto-complete="off" + placeholder="瀵嗙爜" + @keyup.enter.native="handleRegister" + > + <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> + </el-input> + </el-form-item> + <el-form-item prop="confirmPassword"> + <el-input + v-model="registerForm.confirmPassword" + type="password" + auto-complete="off" + placeholder="纭瀵嗙爜" + @keyup.enter.native="handleRegister" + > + <svg-icon slot="prefix" icon-class="password" class="el-input__icon input-icon" /> + </el-input> + </el-form-item> + <el-form-item prop="code" v-if="captchaEnabled"> + <el-input + v-model="registerForm.code" + auto-complete="off" + placeholder="楠岃瘉鐮�" + style="width: 63%" + @keyup.enter.native="handleRegister" + > + <svg-icon slot="prefix" icon-class="validCode" class="el-input__icon input-icon" /> + </el-input> + <div class="register-code"> + <img :src="codeUrl" @click="getCode" class="register-code-img"/> + </div> + </el-form-item> + <el-form-item style="width:100%;"> + <el-button + :loading="loading" + size="medium" + type="primary" + style="width:100%;" + @click.native.prevent="handleRegister" + > + <span v-if="!loading">娉� 鍐�</span> + <span v-else>娉� 鍐� 涓�...</span> + </el-button> + <div style="float: right;"> + <router-link class="link-type" :to="'/login'">浣跨敤宸叉湁璐︽埛鐧诲綍</router-link> + </div> + </el-form-item> + </el-form> + <!-- 搴曢儴 --> + <div class="el-register-footer"> + <span>Copyright 漏 2018-2023 ruoyi.vip All Rights Reserved.</span> + </div> + </div> +</template> + +<script> +import { getCodeImg, register } from "@/api/login"; + +export default { + name: "Register", + data() { + const equalToPassword = (rule, value, callback) => { + if (this.registerForm.password !== value) { + callback(new Error("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�")); + } else { + callback(); + } + }; + return { + codeUrl: "", + registerForm: { + username: "", + password: "", + confirmPassword: "", + code: "", + uuid: "" + }, + registerRules: { + username: [ + { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勮处鍙�" }, + { min: 2, max: 20, message: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' } + ], + password: [ + { required: true, trigger: "blur", message: "璇疯緭鍏ユ偍鐨勫瘑鐮�" }, + { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' } + ], + confirmPassword: [ + { required: true, trigger: "blur", message: "璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�" }, + { required: true, validator: equalToPassword, trigger: "blur" } + ], + code: [{ required: true, trigger: "change", message: "璇疯緭鍏ラ獙璇佺爜" }] + }, + loading: false, + captchaEnabled: true + }; + }, + created() { + this.getCode(); + }, + methods: { + getCode() { + getCodeImg().then(res => { + this.captchaEnabled = res.captchaEnabled === undefined ? true : res.captchaEnabled; + if (this.captchaEnabled) { + this.codeUrl = "data:image/gif;base64," + res.img; + this.registerForm.uuid = res.uuid; + } + }); + }, + handleRegister() { + this.$refs.registerForm.validate(valid => { + if (valid) { + this.loading = true; + register(this.registerForm).then(res => { + const username = this.registerForm.username; + this.$alert("<font color='red'>鎭枩浣狅紝鎮ㄧ殑璐﹀彿 " + username + " 娉ㄥ唽鎴愬姛锛�</font>", '绯荤粺鎻愮ず', { + dangerouslyUseHTMLString: true, + type: 'success' + }).then(() => { + this.$router.push("/login"); + }).catch(() => {}); + }).catch(() => { + this.loading = false; + if (this.captchaEnabled) { + this.getCode(); + } + }) + } + }); + } + } +}; +</script> + +<style rel="stylesheet/scss" lang="scss"> +.register { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + background-image: url("../assets/images/login-background.jpg"); + background-size: cover; +} +.title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; +} + +.register-form { + border-radius: 6px; + background: #ffffff; + width: 400px; + padding: 25px 25px 5px 25px; + .el-input { + height: 38px; + input { + height: 38px; + } + } + .input-icon { + height: 39px; + width: 14px; + margin-left: 2px; + } +} +.register-tip { + font-size: 13px; + text-align: center; + color: #bfbfbf; +} +.register-code { + width: 33%; + height: 38px; + float: right; + img { + cursor: pointer; + vertical-align: middle; + } +} +.el-register-footer { + height: 40px; + line-height: 40px; + position: fixed; + bottom: 0; + width: 100%; + text-align: center; + color: #fff; + font-family: Arial; + font-size: 12px; + letter-spacing: 1px; +} +.register-code-img { + height: 38px; +} +</style> diff --git a/src/views/system/config/index.vue b/src/views/system/config/index.vue new file mode 100644 index 0000000..3ab81fc --- /dev/null +++ b/src/views/system/config/index.vue @@ -0,0 +1,343 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="鍙傛暟鍚嶇О" prop="configName"> + <el-input + v-model="queryParams.configName" + placeholder="璇疯緭鍏ュ弬鏁板悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鍙傛暟閿悕" prop="configKey"> + <el-input + v-model="queryParams.configKey" + placeholder="璇疯緭鍏ュ弬鏁伴敭鍚�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="绯荤粺鍐呯疆" prop="configType"> + <el-select v-model="queryParams.configType" placeholder="绯荤粺鍐呯疆" clearable> + <el-option + v-for="dict in dict.type.sys_yes_no" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鍒涘缓鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:config:add']" + >鏂板</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:config:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:config:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:config:export']" + >瀵煎嚭</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-refresh" + size="mini" + @click="handleRefreshCache" + v-hasPermi="['system:config:remove']" + >鍒锋柊缂撳瓨</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="configList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="鍙傛暟涓婚敭" align="center" prop="configId" /> + <el-table-column label="鍙傛暟鍚嶇О" align="center" prop="configName" :show-overflow-tooltip="true" /> + <el-table-column label="鍙傛暟閿悕" align="center" prop="configKey" :show-overflow-tooltip="true" /> + <el-table-column label="鍙傛暟閿��" align="center" prop="configValue" :show-overflow-tooltip="true" /> + <el-table-column label="绯荤粺鍐呯疆" align="center" prop="configType"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_yes_no" :value="scope.row.configType"/> + </template> + </el-table-column> + <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:config:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:config:remove']" + >鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="鍙傛暟鍚嶇О" prop="configName"> + <el-input v-model="form.configName" placeholder="璇疯緭鍏ュ弬鏁板悕绉�" /> + </el-form-item> + <el-form-item label="鍙傛暟閿悕" prop="configKey"> + <el-input v-model="form.configKey" placeholder="璇疯緭鍏ュ弬鏁伴敭鍚�" /> + </el-form-item> + <el-form-item label="鍙傛暟閿��" prop="configValue"> + <el-input v-model="form.configValue" placeholder="璇疯緭鍏ュ弬鏁伴敭鍊�" /> + </el-form-item> + <el-form-item label="绯荤粺鍐呯疆" prop="configType"> + <el-radio-group v-model="form.configType"> + <el-radio + v-for="dict in dict.type.sys_yes_no" + :key="dict.value" + :label="dict.value" + >{{dict.label}}</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="澶囨敞" prop="remark"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" /> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listConfig, getConfig, delConfig, addConfig, updateConfig, refreshCache } from "@/api/system/config"; + +export default { + name: "Config", + dicts: ['sys_yes_no'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鍙傛暟琛ㄦ牸鏁版嵁 + configList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + configName: undefined, + configKey: undefined, + configType: undefined + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + configName: [ + { required: true, message: "鍙傛暟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" } + ], + configKey: [ + { required: true, message: "鍙傛暟閿悕涓嶈兘涓虹┖", trigger: "blur" } + ], + configValue: [ + { required: true, message: "鍙傛暟閿�间笉鑳戒负绌�", trigger: "blur" } + ] + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鍙傛暟鍒楄〃 */ + getList() { + this.loading = true; + listConfig(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.configList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + configId: undefined, + configName: undefined, + configKey: undefined, + configValue: undefined, + configType: "Y", + remark: undefined + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞鍙傛暟"; + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.configId) + this.single = selection.length!=1 + this.multiple = !selection.length + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const configId = row.configId || this.ids + getConfig(configId).then(response => { + this.form = response.data; + this.open = true; + this.title = "淇敼鍙傛暟"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.configId != undefined) { + updateConfig(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addConfig(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const configIds = row.configId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎鍙傛暟缂栧彿涓�"' + configIds + '"鐨勬暟鎹」锛�').then(function() { + return delConfig(configIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('system/config/export', { + ...this.queryParams + }, `config_${new Date().getTime()}.xlsx`) + }, + /** 鍒锋柊缂撳瓨鎸夐挳鎿嶄綔 */ + handleRefreshCache() { + refreshCache().then(() => { + this.$modal.msgSuccess("鍒锋柊鎴愬姛"); + }); + } + } +}; +</script> diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue new file mode 100644 index 0000000..4490d6a --- /dev/null +++ b/src/views/system/dept/index.vue @@ -0,0 +1,377 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + @submit.native.prevent + > + <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName"> + <el-input + v-model="queryParams.deptName" + placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select v-model="queryParams.status" placeholder="閮ㄩ棬鐘舵��" clearable> + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:dept:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-sort" + size="mini" + @click="toggleExpandAll" + >灞曞紑/鎶樺彔</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-if="refreshTable" + v-loading="loading" + :data="deptList" + row-key="deptId" + :default-expand-all="isExpandAll" + :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" + > + <el-table-column prop="deptName" label="閮ㄩ棬鍚嶇О" width="260"></el-table-column> + <el-table-column prop="orderNum" label="鎺掑簭" width="200"></el-table-column> + <el-table-column prop="status" label="鐘舵��" width="100"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:dept:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-plus" + @click="handleAdd(scope.row)" + v-hasPermi="['system:dept:add']" + >鏂板</el-button + > + <el-button + v-if="scope.row.parentId != 0" + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:dept:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <!-- 娣诲姞鎴栦慨鏀归儴闂ㄥ璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-row> + <el-col :span="24" v-if="form.parentId !== 0"> + <el-form-item label="涓婄骇閮ㄩ棬" prop="parentId"> + <treeselect + v-model="form.parentId" + :options="deptOptions" + :normalizer="normalizer" + placeholder="閫夋嫨涓婄骇閮ㄩ棬" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="閮ㄩ棬鍚嶇О" prop="deptName"> + <el-input v-model="form.deptName" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鏄剧ず鎺掑簭" prop="orderNum"> + <el-input-number + v-model="form.orderNum" + controls-position="right" + :min="0" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="璐熻矗浜�" prop="leader"> + <el-input v-model="form.leader" placeholder="璇疯緭鍏ヨ礋璐d汉" maxlength="20" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鑱旂郴鐢佃瘽" prop="phone"> + <el-input + v-model="form.phone" + placeholder="璇疯緭鍏ヨ仈绯荤數璇�" + maxlength="11" + /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="閭" prop="email"> + <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="閮ㄩ棬鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listDept, + getDept, + delDept, + addDept, + updateDept, + listDeptExcludeChild, +} from "@/api/system/dept"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "Dept", + dicts: ["sys_normal_disable"], + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 琛ㄦ牸鏍戞暟鎹� + deptList: [], + // 閮ㄩ棬鏍戦�夐」 + deptOptions: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄥ睍寮� + isExpandAll: true, + // 閲嶆柊娓叉煋琛ㄦ牸鐘舵�� + refreshTable: true, + // 鏌ヨ鍙傛暟 + queryParams: { + deptName: undefined, + status: undefined, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + parentId: [{ required: true, message: "涓婄骇閮ㄩ棬涓嶈兘涓虹┖", trigger: "blur" }], + deptName: [{ required: true, message: "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + orderNum: [{ required: true, message: "鏄剧ず鎺掑簭涓嶈兘涓虹┖", trigger: "blur" }], + email: [ + { + type: "email", + message: "璇疯緭鍏ユ纭殑閭鍦板潃", + trigger: ["blur", "change"], + }, + ], + phone: [ + { + pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, + message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", + trigger: "blur", + }, + ], + }, + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ閮ㄩ棬鍒楄〃 */ + getList() { + this.loading = true; + listDept(this.queryParams).then((response) => { + this.deptList = this.handleTree(response.data, "deptId"); + this.loading = false; + }); + }, + /** 杞崲閮ㄩ棬鏁版嵁缁撴瀯 */ + normalizer(node) { + if (node.children && !node.children.length) { + delete node.children; + } + return { + id: node.deptId, + label: node.deptName, + children: node.children, + }; + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + deptId: undefined, + parentId: undefined, + deptName: undefined, + orderNum: undefined, + leader: undefined, + phone: undefined, + email: undefined, + status: "0", + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd(row) { + this.reset(); + if (row != undefined) { + this.form.parentId = row.deptId; + } + this.open = true; + this.title = "娣诲姞閮ㄩ棬"; + listDept().then((response) => { + this.deptOptions = this.handleTree(response.data, "deptId"); + }); + }, + /** 灞曞紑/鎶樺彔鎿嶄綔 */ + toggleExpandAll() { + this.refreshTable = false; + this.isExpandAll = !this.isExpandAll; + this.$nextTick(() => { + this.refreshTable = true; + }); + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + getDept(row.deptId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼閮ㄩ棬"; + listDeptExcludeChild(row.deptId).then((response) => { + this.deptOptions = this.handleTree(response.data, "deptId"); + if (this.deptOptions.length == 0) { + const noResultsOptions = { + deptId: this.form.parentId, + deptName: this.form.parentName, + children: [], + }; + this.deptOptions.push(noResultsOptions); + } + }); + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.deptId != undefined) { + updateDept(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addDept(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎鍚嶇О涓�"' + row.deptName + '"鐨勬暟鎹」锛�') + .then(function () { + return delDept(row.deptId); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + }, +}; +</script> diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue new file mode 100644 index 0000000..e365818 --- /dev/null +++ b/src/views/system/dict/data.vue @@ -0,0 +1,446 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + @submit.native.prevent + > + <el-form-item label="瀛楀吀鍚嶇О" prop="dictType"> + <el-select v-model="queryParams.dictType"> + <el-option + v-for="item in typeOptions" + :key="item.dictId" + :label="item.dictName" + :value="item.dictType" + /> + </el-select> + </el-form-item> + <el-form-item label="瀛楀吀鏍囩" prop="dictLabel"> + <el-input + v-model="queryParams.dictLabel" + placeholder="璇疯緭鍏ュ瓧鍏告爣绛�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select v-model="queryParams.status" placeholder="鏁版嵁鐘舵��" clearable> + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:dict:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:dict:edit']" + >淇敼</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:dict:remove']" + >鍒犻櫎</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:dict:export']" + >瀵煎嚭</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-close" + size="mini" + @click="handleClose" + >鍏抽棴</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="dataList" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="瀛楀吀缂栫爜" align="center" prop="dictCode" /> + <el-table-column label="瀛楀吀鏍囩" align="center" prop="dictLabel"> + <template slot-scope="scope"> + <span + v-if=" + (scope.row.listClass == '' || scope.row.listClass == 'default') && + (scope.row.cssClass == '' || scope.row.cssClass == null) + " + >{{ scope.row.dictLabel }}</span + > + <el-tag + v-else + :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" + :class="scope.row.cssClass" + >{{ scope.row.dictLabel }}</el-tag + > + </template> + </el-table-column> + <el-table-column label="瀛楀吀閿��" align="center" prop="dictValue" /> + <el-table-column label="瀛楀吀鎺掑簭" align="center" prop="dictSort" /> + <el-table-column label="鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column + label="澶囨敞" + align="center" + prop="remark" + :show-overflow-tooltip="true" + /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:dict:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:dict:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="瀛楀吀绫诲瀷"> + <el-input v-model="form.dictType" :disabled="true" /> + </el-form-item> + <el-form-item label="鏁版嵁鏍囩" prop="dictLabel"> + <el-input v-model="form.dictLabel" placeholder="璇疯緭鍏ユ暟鎹爣绛�" /> + </el-form-item> + <el-form-item label="鏁版嵁閿��" prop="dictValue"> + <el-input v-model="form.dictValue" placeholder="璇疯緭鍏ユ暟鎹敭鍊�" /> + </el-form-item> + <el-form-item label="鏍峰紡灞炴��" prop="cssClass"> + <el-input v-model="form.cssClass" placeholder="璇疯緭鍏ユ牱寮忓睘鎬�" /> + </el-form-item> + <el-form-item label="鏄剧ず鎺掑簭" prop="dictSort"> + <el-input-number v-model="form.dictSort" controls-position="right" :min="0" /> + </el-form-item> + <el-form-item label="鍥炴樉鏍峰紡" prop="listClass"> + <el-select v-model="form.listClass"> + <el-option + v-for="item in listClassOptions" + :key="item.value" + :label="item.label + '(' + item.value + ')'" + :value="item.value" + ></el-option> + </el-select> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + <el-form-item label="澶囨敞" prop="remark"> + <el-input + v-model="form.remark" + type="textarea" + placeholder="璇疯緭鍏ュ唴瀹�" + ></el-input> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data"; +import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type"; + +export default { + name: "Data", + dicts: ["sys_normal_disable"], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 瀛楀吀琛ㄦ牸鏁版嵁 + dataList: [], + // 榛樿瀛楀吀绫诲瀷 + defaultDictType: "", + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏁版嵁鏍囩鍥炴樉鏍峰紡 + listClassOptions: [ + { + value: "default", + label: "榛樿", + }, + { + value: "primary", + label: "涓昏", + }, + { + value: "success", + label: "鎴愬姛", + }, + { + value: "info", + label: "淇℃伅", + }, + { + value: "warning", + label: "璀﹀憡", + }, + { + value: "danger", + label: "鍗遍櫓", + }, + ], + // 绫诲瀷鏁版嵁瀛楀吀 + typeOptions: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + dictName: undefined, + dictType: undefined, + status: undefined, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + dictLabel: [{ required: true, message: "鏁版嵁鏍囩涓嶈兘涓虹┖", trigger: "blur" }], + dictValue: [{ required: true, message: "鏁版嵁閿�间笉鑳戒负绌�", trigger: "blur" }], + dictSort: [{ required: true, message: "鏁版嵁椤哄簭涓嶈兘涓虹┖", trigger: "blur" }], + }, + }; + }, + created() { + const dictId = this.$route.params && this.$route.params.dictId; + this.getType(dictId); + this.getTypeList(); + }, + methods: { + /** 鏌ヨ瀛楀吀绫诲瀷璇︾粏 */ + getType(dictId) { + getType(dictId).then((response) => { + this.queryParams.dictType = response.data.dictType; + this.defaultDictType = response.data.dictType; + this.getList(); + }); + }, + /** 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 */ + getTypeList() { + getDictOptionselect().then((response) => { + this.typeOptions = response.data; + }); + }, + /** 鏌ヨ瀛楀吀鏁版嵁鍒楄〃 */ + getList() { + this.loading = true; + listData(this.queryParams).then((response) => { + this.dataList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + dictCode: undefined, + dictLabel: undefined, + dictValue: undefined, + cssClass: undefined, + listClass: "default", + dictSort: 0, + status: "0", + remark: undefined, + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 杩斿洖鎸夐挳鎿嶄綔 */ + handleClose() { + const obj = { path: "/system/dict" }; + this.$tab.closeOpenPage(obj); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.queryParams.dictType = this.defaultDictType; + this.handleQuery(); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞瀛楀吀鏁版嵁"; + this.form.dictType = this.queryParams.dictType; + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.dictCode); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const dictCode = row.dictCode || this.ids; + getData(dictCode).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼瀛楀吀鏁版嵁"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.dictCode != undefined) { + updateData(this.form).then((response) => { + this.$store.dispatch("dict/removeDict", this.queryParams.dictType); + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addData(this.form).then((response) => { + this.$store.dispatch("dict/removeDict", this.queryParams.dictType); + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const dictCodes = row.dictCode || this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎瀛楀吀缂栫爜涓�"' + dictCodes + '"鐨勬暟鎹」锛�') + .then(function () { + return delData(dictCodes); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + this.$store.dispatch("dict/removeDict", this.queryParams.dictType); + }) + .catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download( + "system/dict/data/export", + { + ...this.queryParams, + }, + `data_${new Date().getTime()}.xlsx` + ); + }, + }, +}; +</script> diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue new file mode 100644 index 0000000..6ca5457 --- /dev/null +++ b/src/views/system/dict/index.vue @@ -0,0 +1,347 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="瀛楀吀鍚嶇О" prop="dictName"> + <el-input + v-model="queryParams.dictName" + placeholder="璇疯緭鍏ュ瓧鍏稿悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="瀛楀吀绫诲瀷" prop="dictType"> + <el-input + v-model="queryParams.dictType" + placeholder="璇疯緭鍏ュ瓧鍏哥被鍨�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="瀛楀吀鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鍒涘缓鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:dict:add']" + >鏂板</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:dict:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:dict:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:dict:export']" + >瀵煎嚭</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-refresh" + size="mini" + @click="handleRefreshCache" + v-hasPermi="['system:dict:remove']" + >鍒锋柊缂撳瓨</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="瀛楀吀缂栧彿" align="center" prop="dictId" /> + <el-table-column label="瀛楀吀鍚嶇О" align="center" prop="dictName" :show-overflow-tooltip="true" /> + <el-table-column label="瀛楀吀绫诲瀷" align="center" :show-overflow-tooltip="true"> + <template slot-scope="scope"> + <router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type"> + <span>{{ scope.row.dictType }}</span> + </router-link> + </template> + </el-table-column> + <el-table-column label="鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:dict:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:dict:remove']" + >鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰弬鏁伴厤缃璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="瀛楀吀鍚嶇О" prop="dictName"> + <el-input v-model="form.dictName" placeholder="璇疯緭鍏ュ瓧鍏稿悕绉�" /> + </el-form-item> + <el-form-item label="瀛楀吀绫诲瀷" prop="dictType"> + <el-input v-model="form.dictType" placeholder="璇疯緭鍏ュ瓧鍏哥被鍨�" /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{dict.label}}</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="澶囨敞" prop="remark"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type"; + +export default { + name: "Dict", + dicts: ['sys_normal_disable'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 瀛楀吀琛ㄦ牸鏁版嵁 + typeList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + dictName: undefined, + dictType: undefined, + status: undefined + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + dictName: [ + { required: true, message: "瀛楀吀鍚嶇О涓嶈兘涓虹┖", trigger: "blur" } + ], + dictType: [ + { required: true, message: "瀛楀吀绫诲瀷涓嶈兘涓虹┖", trigger: "blur" } + ] + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瀛楀吀绫诲瀷鍒楄〃 */ + getList() { + this.loading = true; + listType(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.typeList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + dictId: undefined, + dictName: undefined, + dictType: undefined, + status: "0", + remark: undefined + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞瀛楀吀绫诲瀷"; + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.dictId) + this.single = selection.length!=1 + this.multiple = !selection.length + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const dictId = row.dictId || this.ids + getType(dictId).then(response => { + this.form = response.data; + this.open = true; + this.title = "淇敼瀛楀吀绫诲瀷"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.dictId != undefined) { + updateType(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addType(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const dictIds = row.dictId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎瀛楀吀缂栧彿涓�"' + dictIds + '"鐨勬暟鎹」锛�').then(function() { + return delType(dictIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('system/dict/type/export', { + ...this.queryParams + }, `type_${new Date().getTime()}.xlsx`) + }, + /** 鍒锋柊缂撳瓨鎸夐挳鎿嶄綔 */ + handleRefreshCache() { + refreshCache().then(() => { + this.$modal.msgSuccess("鍒锋柊鎴愬姛"); + this.$store.dispatch('dict/cleanDict'); + }); + } + } +}; +</script> \ No newline at end of file diff --git a/src/views/system/gkInformation/index.vue b/src/views/system/gkInformation/index.vue new file mode 100644 index 0000000..a3e814d --- /dev/null +++ b/src/views/system/gkInformation/index.vue @@ -0,0 +1,642 @@ +<template> + <div class="app-container"> + <el-row :gutter="24"> + <!--閮ㄩ棬鏁版嵁--> + <!-- <el-col :span="4" :xs="24"> + <div class="head-container"> + <el-input + v-model="deptName" + placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" + clearable + size="small" + prefix-icon="el-icon-search" + style="margin-bottom: 20px" + /> + </div> + <div class="head-container"> + <el-tree + :data="deptOptions" + :props="defaultProps" + :expand-on-click-node="false" + :filter-node-method="filterNode" + ref="tree" + node-key="id" + default-expand-all + highlight-current + @node-click="handleNodeClick" + /> + </div> + </el-col> --> + <!--娓彛鏁版嵁--> + <el-col :span="24" :xs="24"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + > + <el-form-item label="鏂囦欢鍚嶇О" prop="name"> + <el-input + v-model="queryParams.name" + placeholder="璇疯緭鍏ユ枃浠跺悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鏂囦欢绫诲瀷" prop="type"> + <el-input + v-model="queryParams.type" + placeholder="璇疯緭鍏ユ枃浠剁被鍨�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + <!-- <el-select + v-model="queryParams.type" + placeholder="鏂囦欢绫诲瀷" + clearable + style="width: 240px" + > + <el-option + v-for="item in TypeList" + :key="item.value" + :label="item.label" + :value="item.value" + /> + </el-select> --> + </el-form-item> + <el-form-item> + <el-button + type="primary" + icon="el-icon-search" + size="mini" + @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery" + >閲嶇疆</el-button + > + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-upload2" + size="mini" + @click="handleImport" + >瀵煎叆</el-button + > + </el-col> + <!-- <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + >瀵煎嚭</el-button + > + </el-col> --> + <right-toolbar + :showSearch.sync="showSearch" + @queryTable="getList" + :columns="columns" + ></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="userList.slice((queryParams.pageNum - 1) * queryParams.pageSize, queryParams.pageNum * queryParams.pageSize)" + > + + <el-table-column + label="鏂囦欢缂栧彿" + align="center" + key="id" + prop="id" + v-if="columns[0].visible" + /> + <el-table-column + label="鏂囦欢鍚嶇О" + align="center" + key="name" + prop="name" + v-if="columns[1].visible" + :show-overflow-tooltip="true" + /> + <el-table-column + label="鏂囦欢璇存槑" + align="center" + key="remark" + prop="remark" + v-if="columns[2].visible" + :show-overflow-tooltip="true" + /> + <el-table-column + label="鏂囦欢绫诲瀷" + align="center" + key="type" + prop="type" + v-if="columns[3].visible" + :show-overflow-tooltip="true" + /> + <el-table-column + label="鏂囦欢澶у皬" + align="center" + key="size" + prop="size" + v-if="columns[4].visible" + width="120" + /> + <el-table-column + label="涓婁紶鏃堕棿" + align="center" + prop="createTime" + v-if="columns[5].visible" + width="160" + > + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column + label="鎿嶄綔" + align="center" + width="160" + class-name="small-padding fixed-width" + > + <template slot-scope="scope" v-if="scope.row.id !== 1"> + <!-- <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + >淇敼</el-button + > --> + <el-button + size="mini" + type="text" + icon="el-icon-download" + @click="downloadFile(scope.row)" + >涓嬭浇</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-col> + </el-row> + <!-- 鏂囦欢瀵煎叆瀵硅瘽妗� --> + <el-dialog + :title="upload.title" + :visible.sync="upload.open" + width="400px" + append-to-body + > + <el-upload + ref="upload" + :limit="1" + :headers="upload.headers" + :action="upload.url" + :data="uploadData" + :disabled="upload.isUploading" + :on-progress="handleFileUploadProgress" + :on-success="handleFileSuccess" + :auto-upload="false" + :before-upload="handleBeforeUpload" + drag + > + <i class="el-icon-upload"></i> + <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div> + <div class="el-upload__tip text-center" slot="tip"> + <!-- <div class="el-upload__tip" slot="tip"> + <el-checkbox v-model="upload.updateSupport" /> 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + </div> --> + <!-- <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span> --> + <!-- <el-link + type="primary" + :underline="false" + style="font-size: 12px; vertical-align: baseline" + @click="importTemplate" + >涓嬭浇妯℃澘</el-link + > --> + </div> + </el-upload> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button> + <el-button @click="upload.open = false">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listFile, + deleteBatch, + SearchlistFile, +} from "@/api/system/gkInformation/gkInfo"; +//鏂囦欢绠$悊銆� + +import { getToken } from "@/utils/auth"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; +import { number } from "echarts"; + +export default { + name: "User", + dicts: ["sys_normal_disable", "sys_user_sex"], + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + rowid:[], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐢ㄦ埛琛ㄦ牸鏁版嵁 + userList: null, + // 寮瑰嚭灞傛爣棰� + title: "", + // 閮ㄩ棬鏍戦�夐」 + deptOptions: undefined, + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 閮ㄩ棬鍚嶇О + deptName: undefined, + // 榛樿瀵嗙爜 + initPassword: undefined, + // 鏃ユ湡鑼冨洿 + // dateRange: [], + // 宀椾綅閫夐」 + postOptions: [], + // 瑙掕壊閫夐」 + roleOptions: [], + // 琛ㄥ崟鍙傛暟 + form: {}, + defaultProps: { + children: "children", + label: "label", + }, + // 鐢ㄦ埛瀵煎叆鍙傛暟 + upload: { + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛� + open: false, + // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛� + title: "", + // 鏄惁绂佺敤涓婁紶 + isUploading: false, + // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + updateSupport: 0, + // 璁剧疆涓婁紶鐨勮姹傚ご閮� + headers: { Authorization: "Bearer " + getToken() }, + // 涓婁紶鐨勫湴鍧� + // url: process.env.VUE_APP_BASE_API + "/system/user/importData", + url: process.env.VUE_APP_BASE_API + "dp/sysFile/uploadFile", + }, + //鏂囦欢绫诲瀷 + fileType: [ + "bmp", + "gif", + "jpg", + "jpeg", + "png", + "doc", + "docx", + "xls", + "xlsx", + "ppt", + "pptx", + "html", + "htm", + "txt", + "rar", + "zip", + "gz", + "bz2", + "swf", + "flv", + "mp4", + "avi", + "rmvb", + "swf", + "flv", + "mp3", + "wav", + "wma", + "wmv", + "mid", + "avi", + "mpg", + "asf", + "rm", + "rmvb", + "pdf", + "glb", + "gltf" + ], + number: 0, + uploadData: { + type: "", + name: "", + remark: "", + }, + //澶у皬闄愬埗锛圡B锛� + fileSize: 1024, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + name: null, + // phonenumber: undefined, + type: null, + // deptId: undefined, + offset: 0, + }, + TypeList: [ + { value: "瑙嗛", label: "瑙嗛" }, + { value: "闊抽", label: "闊抽" }, + { value: "鍥剧墖", label: "鍥剧墖" }, + { value: "鏂囨。", label: "鏂囨。" }, + ], + // 鍒椾俊鎭� + columns: [ + { key: 0, label: `鏂囦欢缂栧彿`, visible: true }, + { key: 1, label: `鏂囦欢鍚嶇О`, visible: true }, + { key: 2, label: `鏂囦欢璇存槑`, visible: true }, + { key: 3, label: `鏂囦欢绫诲瀷`, visible: true }, + { key: 4, label: `鏂囦欢澶у皬`, visible: true }, + { key: 5, label: `涓婁紶鏃堕棿`, visible: true }, + ], + // 琛ㄥ崟鏍¢獙 + rules: { + name: [ + { required: true, message: "鏂囦欢鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }, + { + min: 2, + max: 20, + message: "鏂囦欢鍚嶇О闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿", + trigger: "blur", + }, + ], + remark: [{ required: true, message: "鏂囦欢璇存槑涓嶈兘涓虹┖", trigger: "blur" }], + }, + // + TreeList: [ + { + id: 101, + label: "娓彛璧勬枡", + disabled: false, + }, + { + id: 4000, + label: "鎶ヨ〃鍒嗘瀽", + disabled: false, + children: [ + { + id: 4002, + label: "姘存繁", + disabled: false, + }, + { + id: 4003, + label: "娌硅〃", + disabled: false, + }, + { + id: 4004, + label: "姘磋〃", + disabled: false, + }, + { + id: 4005, + label: "鐢佃〃", + disabled: false, + }, + ], + }, + ], + }; + }, + watch: { + // 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 + deptName(val) { + this.$refs.tree.filter(val); + }, + }, + created() { + this.getList(); + this.getDeptTree(); + }, + methods: { + /** 鏌ヨ鐢ㄦ埛鍒楄〃 */ + getList() { + this.loading = true; + listFile(this.addDateRange(this.queryParams)).then((response) => { + this.userList = response.data; + this.total = response.data.length; + this.loading = false; + }); + }, + //鎼滅储鏌ヨ + getSearchList() { + this.loading = true; + SearchlistFile(this.queryParams).then((response) => { + this.userList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + /** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ + getDeptTree() { + this.deptOptions = this.TreeList; + }, + // 绛涢�夎妭鐐� + filterNode(value, data) { + if (!value) return true; + return data.label.indexOf(value) !== -1; + }, + // 鑺傜偣鍗曞嚮浜嬩欢 + handleNodeClick(data) { + this.queryParams.deptId = data.id; + this.handleQuery(); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + id: undefined, + deptId: undefined, + name: undefined, + remark: undefined, + size: undefined, + type: "0", + postIds: [], + roleIds: [], + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + // this.getList(); + this.getSearchList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + // this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.id = undefined; + this.$refs.tree.setCurrentKey(null); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + debugger + this.ids = selection.map((item) => item.id); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.rowid.push(row.id) + const fileIds = this.rowid || this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎鏂囦欢缂栧彿涓�"' + fileIds + '"鐨勬暟鎹」锛�') + .then(function () { + return deleteBatch(fileIds); + }) + .then(() => { + this.getList(); + this.rowid = []; + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + // /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + // handleExport() { + // this.download( + // "system/user/export", + // { + // ...this.queryParams, + // }, + // `user_${new Date().getTime()}.xlsx` + // ); + // }, + //涓嬭浇 + downloadFile(row) { + this.downloadFiles( + "dp/sysFile/download", + { + id: row.id, + }, + `${row.filePath.substring(row.filePath.lastIndexOf("/") + 1)}` + ); + }, + /** 瀵煎叆鎸夐挳鎿嶄綔 */ + handleImport() { + this.upload.title = "鏂囦欢瀵煎叆"; + this.upload.open = true; + }, + /** 涓嬭浇妯℃澘鎿嶄綔 */ + // importTemplate() { + // this.download( + // "system/user/importTemplate", + // {}, + // `user_template_${new Date().getTime()}.xlsx` + // ); + // }, + // 鏂囦欢涓婁紶涓鐞� + handleFileUploadProgress(event, file, fileList) { + this.upload.isUploading = true; + }, + // 鏂囦欢涓婁紶鎴愬姛澶勭悊 + handleFileSuccess(response, file, fileList) { + if (response.code === 200) { + this.$modal.closeLoading(); + this.upload.open = false; + this.upload.isUploading = false; + this.$refs.upload.clearFiles(); + this.$modal.msgSuccess("涓婁紶鎴愬姛锛�"); + // this.$alert( + // "<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + + // response.msg + + // "</div>", + // "瀵煎叆缁撴灉", + // { dangerouslyUseHTMLString: true } + // ); + this.getList(); + } else { + this.number--; + this.$modal.closeLoading(); + this.$modal.msgError("涓婁紶澶辫触锛岃閲嶆柊涓婁紶锛�"); + } + }, + // 鎻愪氦涓婁紶鏂囦欢 + submitFileForm() { + this.$refs.upload.submit(); + }, + //鏍¢獙鏂囦欢绫诲瀷 + handleBeforeUpload(file) { + //鏍¢獙鏂囦欢绫诲瀷 + if (this.fileType) { + const fileName = file.name.split("."); + const fileExt = fileName[fileName.length - 1]; + this.uploadData.name = fileName[0]; + this.uploadData.type = fileExt; + const isTypeOk = this.fileType.indexOf(fileExt) >= 0; + if (!isTypeOk) { + this.$modal.msgError( + `鏂囦欢鏍煎紡涓嶆纭紝璇蜂笂浼�${this.fileType.join("/")}鏍煎紡鏂囦欢锛乣 + ); + return false; + } + } + //鏍¢獙鏂囦欢澶у皬 + if (this.fileSize) { + const isLt = file.size / 1024 / 1024 < this.fileSize; + if (!isLt) { + this.$modal.msgError(`涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃${this.fileSize}MB锛乣); + return false; + } + } + this.$modal.loading(`姝e湪涓婁紶鏂囦欢锛岃绋嶅�欍�傘�傘�傘�傘�俙); + this.number++; + return true; + }, + }, +}; +</script> diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue new file mode 100644 index 0000000..3d2503d --- /dev/null +++ b/src/views/system/menu/index.vue @@ -0,0 +1,524 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + @submit.native.prevent + > + <el-form-item label="鑿滃崟鍚嶇О" prop="menuName"> + <el-input + v-model="queryParams.menuName" + placeholder="璇疯緭鍏ヨ彍鍗曞悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select v-model="queryParams.status" placeholder="鑿滃崟鐘舵��" clearable> + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:menu:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-sort" + size="mini" + @click="toggleExpandAll" + >灞曞紑/鎶樺彔</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-if="refreshTable" + v-loading="loading" + :data="menuList" + row-key="menuId" + :default-expand-all="isExpandAll" + :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" + > + <el-table-column + prop="menuName" + label="鑿滃崟鍚嶇О" + :show-overflow-tooltip="true" + width="160" + ></el-table-column> + <el-table-column prop="icon" label="鍥炬爣" align="center" width="100"> + <template slot-scope="scope"> + <svg-icon :icon-class="scope.row.icon" /> + </template> + </el-table-column> + <el-table-column prop="orderNum" label="鎺掑簭" width="60"></el-table-column> + <el-table-column + prop="perms" + label="鏉冮檺鏍囪瘑" + :show-overflow-tooltip="true" + ></el-table-column> + <el-table-column + prop="component" + label="缁勪欢璺緞" + :show-overflow-tooltip="true" + ></el-table-column> + <el-table-column prop="status" label="鐘舵��" width="80"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:menu:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-plus" + @click="handleAdd(scope.row)" + v-hasPermi="['system:menu:add']" + >鏂板</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:menu:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <!-- 娣诲姞鎴栦慨鏀硅彍鍗曞璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="680px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> + <el-row> + <el-col :span="24"> + <el-form-item label="涓婄骇鑿滃崟" prop="parentId"> + <treeselect + v-model="form.parentId" + :options="menuOptions" + :normalizer="normalizer" + :show-count="true" + placeholder="閫夋嫨涓婄骇鑿滃崟" + /> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鑿滃崟绫诲瀷" prop="menuType"> + <el-radio-group v-model="form.menuType"> + <el-radio label="M">鐩綍</el-radio> + <el-radio label="C">鑿滃崟</el-radio> + <el-radio label="F">鎸夐挳</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="24" v-if="form.menuType != 'F'"> + <el-form-item label="鑿滃崟鍥炬爣" prop="icon"> + <el-popover + placement="bottom-start" + width="460" + trigger="click" + @show="$refs['iconSelect'].reset()" + > + <IconSelect + ref="iconSelect" + @selected="selected" + :active-icon="form.icon" + /> + <el-input + slot="reference" + v-model="form.icon" + placeholder="鐐瑰嚮閫夋嫨鍥炬爣" + readonly + > + <svg-icon + v-if="form.icon" + slot="prefix" + :icon-class="form.icon" + style="width: 25px" + /> + <i v-else slot="prefix" class="el-icon-search el-input__icon" /> + </el-input> + </el-popover> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鑿滃崟鍚嶇О" prop="menuName"> + <el-input v-model="form.menuName" placeholder="璇疯緭鍏ヨ彍鍗曞悕绉�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鏄剧ず鎺掑簭" prop="orderNum"> + <el-input-number + v-model="form.orderNum" + controls-position="right" + :min="0" + /> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType != 'F'"> + <el-form-item prop="isFrame"> + <span slot="label"> + <el-tooltip + content="閫夋嫨鏄閾惧垯璺敱鍦板潃闇�瑕佷互`http(s)://`寮�澶�" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 鏄惁澶栭摼 + </span> + <el-radio-group v-model="form.isFrame"> + <el-radio label="0">鏄�</el-radio> + <el-radio label="1">鍚�</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType != 'F'"> + <el-form-item prop="path"> + <span slot="label"> + <el-tooltip + content="璁块棶鐨勮矾鐢卞湴鍧�锛屽锛歚user`锛屽澶栫綉鍦板潃闇�鍐呴摼璁块棶鍒欎互`http(s)://`寮�澶�" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 璺敱鍦板潃 + </span> + <el-input v-model="form.path" placeholder="璇疯緭鍏ヨ矾鐢卞湴鍧�" /> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType == 'C'"> + <el-form-item prop="component"> + <span slot="label"> + <el-tooltip + content="璁块棶鐨勭粍浠惰矾寰勶紝濡傦細`system/user/index`锛岄粯璁ゅ湪`views`鐩綍涓�" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 缁勪欢璺緞 + </span> + <el-input v-model="form.component" placeholder="璇疯緭鍏ョ粍浠惰矾寰�" /> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType != 'M'"> + <el-form-item prop="perms"> + <el-input + v-model="form.perms" + placeholder="璇疯緭鍏ユ潈闄愭爣璇�" + maxlength="100" + /> + <span slot="label"> + <el-tooltip + content="鎺у埗鍣ㄤ腑瀹氫箟鐨勬潈闄愬瓧绗︼紝濡傦細@PreAuthorize(`@ss.hasPermi('system:user:list')`)" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 鏉冮檺瀛楃 + </span> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType == 'C'"> + <el-form-item prop="query"> + <el-input + v-model="form.query" + placeholder="璇疯緭鍏ヨ矾鐢卞弬鏁�" + maxlength="255" + /> + <span slot="label"> + <el-tooltip + content='璁块棶璺敱鐨勯粯璁や紶閫掑弬鏁帮紝濡傦細`{"id": 1, "name": "ry"}`' + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 璺敱鍙傛暟 + </span> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType == 'C'"> + <el-form-item prop="isCache"> + <span slot="label"> + <el-tooltip + content="閫夋嫨鏄垯浼氳`keep-alive`缂撳瓨锛岄渶瑕佸尮閰嶇粍浠剁殑`name`鍜屽湴鍧�淇濇寔涓�鑷�" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 鏄惁缂撳瓨 + </span> + <el-radio-group v-model="form.isCache"> + <el-radio label="0">缂撳瓨</el-radio> + <el-radio label="1">涓嶇紦瀛�</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12" v-if="form.menuType != 'F'"> + <el-form-item prop="visible"> + <span slot="label"> + <el-tooltip + content="閫夋嫨闅愯棌鍒欒矾鐢卞皢涓嶄細鍑虹幇鍦ㄤ晶杈规爮锛屼絾浠嶇劧鍙互璁块棶" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 鏄剧ず鐘舵�� + </span> + <el-radio-group v-model="form.visible"> + <el-radio + v-for="dict in dict.type.sys_show_hide" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item prop="status"> + <span slot="label"> + <el-tooltip + content="閫夋嫨鍋滅敤鍒欒矾鐢卞皢涓嶄細鍑虹幇鍦ㄤ晶杈规爮锛屼篃涓嶈兘琚闂�" + placement="top" + > + <i class="el-icon-question"></i> + </el-tooltip> + 鑿滃崟鐘舵�� + </span> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/menu"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; +import IconSelect from "@/components/IconSelect"; + +export default { + name: "Menu", + dicts: ["sys_show_hide", "sys_normal_disable"], + components: { Treeselect, IconSelect }, + data() { + return { + // 閬僵灞� + loading: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鑿滃崟琛ㄦ牸鏍戞暟鎹� + menuList: [], + // 鑿滃崟鏍戦�夐」 + menuOptions: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄦ姌鍙� + isExpandAll: false, + // 閲嶆柊娓叉煋琛ㄦ牸鐘舵�� + refreshTable: true, + // 鏌ヨ鍙傛暟 + queryParams: { + menuName: undefined, + visible: undefined, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + menuName: [{ required: true, message: "鑿滃崟鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }], + orderNum: [{ required: true, message: "鑿滃崟椤哄簭涓嶈兘涓虹┖", trigger: "blur" }], + path: [{ required: true, message: "璺敱鍦板潃涓嶈兘涓虹┖", trigger: "blur" }], + }, + }; + }, + created() { + this.getList(); + }, + methods: { + // 閫夋嫨鍥炬爣 + selected(name) { + this.form.icon = name; + }, + /** 鏌ヨ鑿滃崟鍒楄〃 */ + getList() { + this.loading = true; + listMenu(this.queryParams).then((response) => { + this.menuList = this.handleTree(response.data, "menuId"); + this.loading = false; + }); + }, + /** 杞崲鑿滃崟鏁版嵁缁撴瀯 */ + normalizer(node) { + if (node.children && !node.children.length) { + delete node.children; + } + return { + id: node.menuId, + label: node.menuName, + children: node.children, + }; + }, + /** 鏌ヨ鑿滃崟涓嬫媺鏍戠粨鏋� */ + getTreeselect() { + listMenu().then((response) => { + this.menuOptions = []; + const menu = { menuId: 0, menuName: "涓荤被鐩�", children: [] }; + menu.children = this.handleTree(response.data, "menuId"); + this.menuOptions.push(menu); + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + menuId: undefined, + parentId: 0, + menuName: undefined, + icon: undefined, + menuType: "M", + orderNum: undefined, + isFrame: "1", + isCache: "0", + visible: "0", + status: "0", + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd(row) { + this.reset(); + this.getTreeselect(); + if (row != null && row.menuId) { + this.form.parentId = row.menuId; + } else { + this.form.parentId = 0; + } + this.open = true; + this.title = "娣诲姞鑿滃崟"; + }, + /** 灞曞紑/鎶樺彔鎿嶄綔 */ + toggleExpandAll() { + this.refreshTable = false; + this.isExpandAll = !this.isExpandAll; + this.$nextTick(() => { + this.refreshTable = true; + }); + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + this.getTreeselect(); + getMenu(row.menuId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鑿滃崟"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.menuId != undefined) { + updateMenu(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addMenu(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + this.$modal + .confirm('鏄惁纭鍒犻櫎鍚嶇О涓�"' + row.menuName + '"鐨勬暟鎹」锛�') + .then(function () { + return delMenu(row.menuId); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + }, +}; +</script> diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue new file mode 100644 index 0000000..fe2c03a --- /dev/null +++ b/src/views/system/notice/index.vue @@ -0,0 +1,337 @@ +<template> + <div class="app-container"> + <el-form + :model="queryParams" + ref="queryForm" + size="small" + :inline="true" + v-show="showSearch" + label-width="68px" + > + <el-form-item label="鍏憡鏍囬" prop="noticeTitle"> + <el-input + v-model="queryParams.noticeTitle" + placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鎿嶄綔浜哄憳" prop="createBy"> + <el-input + v-model="queryParams.createBy" + placeholder="璇疯緭鍏ユ搷浣滀汉鍛�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="绫诲瀷" prop="noticeType"> + <el-select v-model="queryParams.noticeType" placeholder="鍏憡绫诲瀷" clearable> + <el-option + v-for="dict in dict.type.sys_notice_type" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery" + >鎼滅储</el-button + > + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:notice:add']" + >鏂板</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:notice:edit']" + >淇敼</el-button + > + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:notice:remove']" + >鍒犻櫎</el-button + > + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table + v-loading="loading" + :data="noticeList" + @selection-change="handleSelectionChange" + > + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="搴忓彿" align="center" prop="noticeId" width="100" /> + <el-table-column + label="鍏憡鏍囬" + align="center" + prop="noticeTitle" + :show-overflow-tooltip="true" + /> + <el-table-column label="鍏憡绫诲瀷" align="center" prop="noticeType" width="100"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_notice_type" :value="scope.row.noticeType" /> + </template> + </el-table-column> + <el-table-column label="鐘舵��" align="center" prop="status" width="100"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_notice_status" :value="scope.row.status" /> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鑰�" align="center" prop="createBy" width="100" /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="100"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime, "{y}-{m}-{d}") }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:notice:edit']" + >淇敼</el-button + > + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:notice:remove']" + >鍒犻櫎</el-button + > + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total > 0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰叕鍛婂璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="780px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鍏憡鏍囬" prop="noticeTitle"> + <el-input v-model="form.noticeTitle" placeholder="璇疯緭鍏ュ叕鍛婃爣棰�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鍏憡绫诲瀷" prop="noticeType"> + <el-select v-model="form.noticeType" placeholder="璇烽�夋嫨鍏憡绫诲瀷"> + <el-option + v-for="dict in dict.type.sys_notice_type" + :key="dict.value" + :label="dict.label" + :value="dict.value" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_notice_status" + :key="dict.value" + :label="dict.value" + >{{ dict.label }}</el-radio + > + </el-radio-group> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="鍐呭"> + <editor v-model="form.noticeContent" :min-height="192" /> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { + listNotice, + getNotice, + delNotice, + addNotice, + updateNotice, +} from "@/api/system/notice"; + +export default { + name: "Notice", + dicts: ["sys_notice_status", "sys_notice_type"], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鍏憡琛ㄦ牸鏁版嵁 + noticeList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + noticeTitle: undefined, + createBy: undefined, + status: undefined, + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + noticeTitle: [{ required: true, message: "鍏憡鏍囬涓嶈兘涓虹┖", trigger: "blur" }], + noticeType: [{ required: true, message: "鍏憡绫诲瀷涓嶈兘涓虹┖", trigger: "change" }], + }, + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ鍏憡鍒楄〃 */ + getList() { + this.loading = true; + listNotice(this.queryParams).then((response) => { + this.noticeList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + noticeId: undefined, + noticeTitle: undefined, + noticeType: undefined, + noticeContent: undefined, + status: "0", + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map((item) => item.noticeId); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞鍏憡"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const noticeId = row.noticeId || this.ids; + getNotice(noticeId).then((response) => { + this.form = response.data; + this.open = true; + this.title = "淇敼鍏憡"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function () { + this.$refs["form"].validate((valid) => { + if (valid) { + if (this.form.noticeId != undefined) { + updateNotice(this.form).then((response) => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addNotice(this.form).then((response) => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const noticeIds = row.noticeId || this.ids; + this.$modal + .confirm('鏄惁纭鍒犻櫎鍏憡缂栧彿涓�"' + noticeIds + '"鐨勬暟鎹」锛�') + .then(function () { + return delNotice(noticeIds); + }) + .then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }) + .catch(() => {}); + }, + }, +}; +</script> diff --git a/src/views/system/peizhi/aliyunEmailForm.vue b/src/views/system/peizhi/aliyunEmailForm.vue new file mode 100644 index 0000000..eff9018 --- /dev/null +++ b/src/views/system/peizhi/aliyunEmailForm.vue @@ -0,0 +1,67 @@ +<template> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + layout="vertical" + > + <el-form-item label="闃块噷浜戝瘑閽D锛�" name="SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID"> + <el-input v-model:value="formData.SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID" placeholder="璇疯緭鍏ラ樋閲屼簯瀵嗛挜ID" /> + </el-form-item> + <el-form-item label="闃块噷浜戝瘑閽ECRET锛�" name="SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET"> + <el-input v-model:value="formData.SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET" placeholder="璇疯緭鍏ラ樋閲屼簯瀵嗛挜SECRET" /> + </el-form-item> + <el-form-item label="闃块噷浜戝尯鍩烮D锛�" name="SNOWY_EMAIL_ALIYUN_REGION_ID"> + <el-input v-model:value="formData.SNOWY_EMAIL_ALIYUN_REGION_ID" placeholder="璇疯緭鍏ラ樋閲屼簯鍖哄煙ID" /> + </el-form-item> + <el-form-item> + <el-button type="primary" :loading="submitLoading" @click="onSubmit()">淇濆瓨</el-button> + <el-button style="margin-left: 10px" @click="() => formRef.resetFields()">閲嶇疆</el-button> + </el-form-item> + </el-form> +</template> +<style> + .el-tabs{ + height: 400px!important; + } +</style> +<script> + export default { + name: "Role", + data() { + return { + loadSpinning: "true", + formData:{ + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID:'闃块噷浜戝瘑閽D锛�', + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET:'闃块噷浜戝瘑閽ECRET锛�', + SNOWY_EMAIL_ALIYUN_REGION_ID:'闃块噷浜戝尯鍩烮D' + }, + formRules: { + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID: [ + { required: true, message: '璇疯緭鍏ラ樋閲屼簯瀵嗛挜ID', trigger: 'blur' } + ] + }, + submitLoading:false + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瑙掕壊鍒楄〃 */ + getList() { + this.loading = true; + // listRole(this.addDateRange(this.queryParams, this.dateRange)).then( + // (response) => { + // this.roleList = response.rows; + // this.total = response.total; + // this.loading = false; + // } + // ); + }, + onSubmit(){ + + } + }, +}; +</script> diff --git a/src/views/system/peizhi/index.vue b/src/views/system/peizhi/index.vue new file mode 100644 index 0000000..292777a --- /dev/null +++ b/src/views/system/peizhi/index.vue @@ -0,0 +1,65 @@ +<template> + <div class="app-container"> + <el-tabs v-model="activeName" @tab-click="handleClick"> + <el-tab-pane label="閭閰嶇疆" name="first"> + <el-tabs tab-position="left" style="height: 200px"> + <el-tab-pane label="鏈湴閭"> + <LocalEmailForm/> + </el-tab-pane> + <el-tab-pane label="闃块噷閭欢"> + <AliyunEmailForm/> + </el-tab-pane> + <el-tab-pane label="鑵捐閭欢"> + <TencentEmailForm/> + </el-tab-pane> + </el-tabs> + </el-tab-pane> + <el-tab-pane label="鐭俊閰嶇疆" name="second">鐭俊閰嶇疆</el-tab-pane> + <el-tab-pane label="鏂囦欢閰嶇疆" name="third">鏂囦欢閰嶇疆</el-tab-pane> + </el-tabs> + </div> +</template> +<style lang="scss" scoped></style> +<script> +import LocalEmailForm from './localEmailForm.vue' +import AliyunEmailForm from './aliyunEmailForm.vue' +import TencentEmailForm from './tencentEmailForm.vue' +export default { + name: "Role", + dicts: ["sys_normal_disable"], + components:{LocalEmailForm,AliyunEmailForm,TencentEmailForm}, + data() { + return { + activeName: "first", + emailForm:{ + number:'鏈湴閭欢鍙戦�侀偖绠卞彿', + key:'鏈湴閭欢瀵嗛挜' + }, + rules: { + number: [ + { required: true, message: '璇疯緭鏈湴閭欢鍙戦�侀偖绠卞彿', trigger: 'blur' } + ] + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瑙掕壊鍒楄〃 */ + getList() { + this.loading = true; + // listRole(this.addDateRange(this.queryParams, this.dateRange)).then( + // (response) => { + // this.roleList = response.rows; + // this.total = response.total; + // this.loading = false; + // } + // ); + }, + handleClick(tab, event) { + console.log(tab, event); + }, + }, +}; +</script> diff --git a/src/views/system/peizhi/localEmailForm.vue b/src/views/system/peizhi/localEmailForm.vue new file mode 100644 index 0000000..894c416 --- /dev/null +++ b/src/views/system/peizhi/localEmailForm.vue @@ -0,0 +1,92 @@ +<template> + <!-- <el-spin :spinning="loadSpinning"> --> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + layout="vertical" + > + <el-form-item label="鍙戦�侀偖绠卞彿锛�" name="SNOWY_EMAIL_LOCAL_FROM"> + <el-input v-model:value="formData.SNOWY_EMAIL_LOCAL_FROM" placeholder="璇疯緭鍏ュ彂閫侀偖绠卞彿" /> + </el-form-item> + <el-form-item label="閭瀵嗛挜锛�" name="SNOWY_EMAIL_LOCAL_PASSWORD"> + <el-input v-model:value="formData.SNOWY_EMAIL_LOCAL_PASSWORD" placeholder="璇疯緭鍏ラ偖绠卞瘑閽�" /> + </el-form-item> + <el-form-item> + <el-button type="primary" :loading="submitLoading" @click="saveConfig">淇濆瓨</el-button> + <el-button style="margin-left: 10px" @click="resetFields">閲嶇疆</el-button> + </el-form-item> + </el-form> + <!-- </el-spin> --> +</template> +<style> + .el-tabs{ + height: 400px!important; + } +</style> +<script> +import {edit,configList} from "@/api/peizhi/index"; +export default { + name: "Role", + data() { + return { + loadSpinning: "true", + formData:{ + SNOWY_EMAIL_LOCAL_FROM:'鏈湴閭欢鍙戦�侀偖绠卞彿', + SNOWY_EMAIL_LOCAL_PASSWORD:'鏈湴閭欢瀵嗛挜', + }, + formRules: { + SNOWY_EMAIL_LOCAL_FROM: [ + { required: true, message: '璇疯緭鏈湴閭欢鍙戦�侀偖绠卞彿', trigger: 'blur' } + ] + }, + submitLoading:false + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瑙掕壊鍒楄〃 */ + getList() { + const param = { + category: 'EMAIL_LOCAL' + } + configList(param).then((res) =>{ + if (res.code==200) { + res.data.forEach((item) => { + this.formData[item.configKey] = item.configValue + }) + } else { + message.warning('琛ㄥ崟椤逛笉瀛樺湪锛岃鍒濆鍖栨暟鎹簱') + } + // listRole(this.addDateRange(this.queryParams, this.dateRange)).then( + // (response) => { + // this.roleList = response.rows; + // this.total = response.total; + // this.loading = false; + }) + // ); + }, + saveConfig() { + this.submitLoading = true; + this.$refs["formRef"].validate(valid => { + if (valid) { + console.log(this.formData) + edit(this.formData).then(response => { + this.$modal.msgSuccess("淇濆瓨鎴愬姛"); + this.submitLoading = false; + // this.open = false; + // this.getList(); + }); + }else{ + alert(1) + } + }); + }, + resetFields(){ + alert("閲嶇疆"); + } + }, +}; +</script> diff --git a/src/views/system/peizhi/tencentEmailForm.vue b/src/views/system/peizhi/tencentEmailForm.vue new file mode 100644 index 0000000..a693528 --- /dev/null +++ b/src/views/system/peizhi/tencentEmailForm.vue @@ -0,0 +1,67 @@ +<template> + <el-form + ref="formRef" + :model="formData" + :rules="formRules" + layout="vertical" + > + <el-form-item label="鑵捐浜戝瘑閽D锛�" name="SNOWY_EMAIL_TENCENT_SECRET_ID"> + <el-input v-model:value="formData.SNOWY_EMAIL_TENCENT_SECRET_ID" placeholder="璇疯緭鍏ヨ吘璁簯瀵嗛挜ID" /> + </el-form-item> + <el-form-item label="鑵捐浜戝瘑閽ECRET锛�" name="SNOWY_EMAIL_TENCENT_SECRET_KEY"> + <el-input v-model:value="formData.SNOWY_EMAIL_TENCENT_SECRET_KEY" placeholder="璇疯緭鍏ヨ吘璁簯瀵嗛挜SECRET" /> + </el-form-item> + <el-form-item label="鑵捐浜戝尯鍩烮D锛�" name="SNOWY_EMAIL_TENCENT_REGION_ID"> + <el-input v-model:value="formData.SNOWY_EMAIL_TENCENT_REGION_ID" placeholder="璇疯緭鍏ヨ吘璁簯鍖哄煙ID" /> + </el-form-item> + <el-form-item> + <el-button type="primary" :loading="submitLoading" @click="onSubmit()">淇濆瓨</el-button> + <el-button style="margin-left: 10px" @click="() => formRef.resetFields()">閲嶇疆</el-button> + </el-form-item> + </el-form> +</template> +<style> + .el-tabs{ + height: 400px!important; + } +</style> +<script > + export default { + name: "Role", + data() { + return { + loadSpinning: "true", + formData:{ + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID:'鑵捐浜戝瘑閽D锛�', + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_SECRET:'鑵捐浜戝瘑閽ECRET锛�', + SNOWY_EMAIL_ALIYUN_REGION_ID:'鑵捐浜戝尯鍩烮D' + }, + formRules: { + SNOWY_EMAIL_ALIYUN_ACCESS_KEY_ID: [ + { required: true, message: '璇疯緭鍏ヨ吘璁簯瀵嗛挜ID', trigger: 'blur' } + ] + }, + submitLoading:false + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瑙掕壊鍒楄〃 */ + getList() { + this.loading = true; + // listRole(this.addDateRange(this.queryParams, this.dateRange)).then( + // (response) => { + // this.roleList = response.rows; + // this.total = response.total; + // this.loading = false; + // } + // ); + }, + handleClick(tab, event) { + console.log(tab, event); + }, + }, +}; +</script> diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue new file mode 100644 index 0000000..444bf63 --- /dev/null +++ b/src/views/system/post/index.vue @@ -0,0 +1,309 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="宀椾綅缂栫爜" prop="postCode"> + <el-input + v-model="queryParams.postCode" + placeholder="璇疯緭鍏ュ矖浣嶇紪鐮�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="宀椾綅鍚嶇О" prop="postName"> + <el-input + v-model="queryParams.postName" + placeholder="璇疯緭鍏ュ矖浣嶅悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select v-model="queryParams.status" placeholder="宀椾綅鐘舵��" clearable> + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:post:add']" + >鏂板</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:post:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:post:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:post:export']" + >瀵煎嚭</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="宀椾綅缂栧彿" align="center" prop="postId" /> + <el-table-column label="宀椾綅缂栫爜" align="center" prop="postCode" /> + <el-table-column label="宀椾綅鍚嶇О" align="center" prop="postName" /> + <el-table-column label="宀椾綅鎺掑簭" align="center" prop="postSort" /> + <el-table-column label="鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:post:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:post:remove']" + >鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀瑰矖浣嶅璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="宀椾綅鍚嶇О" prop="postName"> + <el-input v-model="form.postName" placeholder="璇疯緭鍏ュ矖浣嶅悕绉�" /> + </el-form-item> + <el-form-item label="宀椾綅缂栫爜" prop="postCode"> + <el-input v-model="form.postCode" placeholder="璇疯緭鍏ョ紪鐮佸悕绉�" /> + </el-form-item> + <el-form-item label="宀椾綅椤哄簭" prop="postSort"> + <el-input-number v-model="form.postSort" controls-position="right" :min="0" /> + </el-form-item> + <el-form-item label="宀椾綅鐘舵��" prop="status"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{dict.label}}</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="澶囨敞" prop="remark"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" /> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listPost, getPost, delPost, addPost, updatePost } from "@/api/system/post"; + +export default { + name: "Post", + dicts: ['sys_normal_disable'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 宀椾綅琛ㄦ牸鏁版嵁 + postList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + postCode: undefined, + postName: undefined, + status: undefined + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + // 琛ㄥ崟鏍¢獙 + rules: { + postName: [ + { required: true, message: "宀椾綅鍚嶇О涓嶈兘涓虹┖", trigger: "blur" } + ], + postCode: [ + { required: true, message: "宀椾綅缂栫爜涓嶈兘涓虹┖", trigger: "blur" } + ], + postSort: [ + { required: true, message: "宀椾綅椤哄簭涓嶈兘涓虹┖", trigger: "blur" } + ] + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ宀椾綅鍒楄〃 */ + getList() { + this.loading = true; + listPost(this.queryParams).then(response => { + this.postList = response.rows; + this.total = response.total; + this.loading = false; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + postId: undefined, + postCode: undefined, + postName: undefined, + postSort: 0, + status: "0", + remark: undefined + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.postId) + this.single = selection.length!=1 + this.multiple = !selection.length + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.open = true; + this.title = "娣诲姞宀椾綅"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const postId = row.postId || this.ids + getPost(postId).then(response => { + this.form = response.data; + this.open = true; + this.title = "淇敼宀椾綅"; + }); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.postId != undefined) { + updatePost(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addPost(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const postIds = row.postId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎宀椾綅缂栧彿涓�"' + postIds + '"鐨勬暟鎹」锛�').then(function() { + return delPost(postIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('system/post/export', { + ...this.queryParams + }, `post_${new Date().getTime()}.xlsx`) + } + } +}; +</script> diff --git a/src/views/system/role/authUser.vue b/src/views/system/role/authUser.vue new file mode 100644 index 0000000..147aa33 --- /dev/null +++ b/src/views/system/role/authUser.vue @@ -0,0 +1,199 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> + <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input + v-model="queryParams.userName" + placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> + <el-input + v-model="queryParams.phonenumber" + placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="openSelectUser" + v-hasPermi="['system:role:add']" + >娣诲姞鐢ㄦ埛</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-circle-close" + size="mini" + :disabled="multiple" + @click="cancelAuthUserAll" + v-hasPermi="['system:role:remove']" + >鎵归噺鍙栨秷鎺堟潈</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-close" + size="mini" + @click="handleClose" + >鍏抽棴</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="鐢ㄦ埛鍚嶇О" prop="userName" :show-overflow-tooltip="true" /> + <el-table-column label="鐢ㄦ埛鏄电О" prop="nickName" :show-overflow-tooltip="true" /> + <el-table-column label="閭" prop="email" :show-overflow-tooltip="true" /> + <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" /> + <el-table-column label="鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + size="mini" + type="text" + icon="el-icon-circle-close" + @click="cancelAuthUser(scope.row)" + v-hasPermi="['system:role:remove']" + >鍙栨秷鎺堟潈</el-button> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + <select-user ref="select" :roleId="queryParams.roleId" @ok="handleQuery" /> + </div> +</template> + +<script> +import { allocatedUserList, authUserCancel, authUserCancelAll } from "@/api/system/role"; +import selectUser from "./selectUser"; + +export default { + name: "AuthUser", + dicts: ['sys_normal_disable'], + components: { selectUser }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鐢ㄦ埛缁� + userIds: [], + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐢ㄦ埛琛ㄦ牸鏁版嵁 + userList: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + roleId: undefined, + userName: undefined, + phonenumber: undefined + } + }; + }, + created() { + const roleId = this.$route.params && this.$route.params.roleId; + if (roleId) { + this.queryParams.roleId = roleId; + this.getList(); + } + }, + methods: { + /** 鏌ヨ鎺堟潈鐢ㄦ埛鍒楄〃 */ + getList() { + this.loading = true; + allocatedUserList(this.queryParams).then(response => { + this.userList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + // 杩斿洖鎸夐挳 + handleClose() { + const obj = { path: "/system/role" }; + this.$tab.closeOpenPage(obj); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.userIds = selection.map(item => item.userId) + this.multiple = !selection.length + }, + /** 鎵撳紑鎺堟潈鐢ㄦ埛琛ㄥ脊绐� */ + openSelectUser() { + this.$refs.select.show(); + }, + /** 鍙栨秷鎺堟潈鎸夐挳鎿嶄綔 */ + cancelAuthUser(row) { + const roleId = this.queryParams.roleId; + this.$modal.confirm('纭瑕佸彇娑堣鐢ㄦ埛"' + row.userName + '"瑙掕壊鍚楋紵').then(function() { + return authUserCancel({ userId: row.userId, roleId: roleId }); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍙栨秷鎺堟潈鎴愬姛"); + }).catch(() => {}); + }, + /** 鎵归噺鍙栨秷鎺堟潈鎸夐挳鎿嶄綔 */ + cancelAuthUserAll(row) { + const roleId = this.queryParams.roleId; + const userIds = this.userIds.join(","); + this.$modal.confirm('鏄惁鍙栨秷閫変腑鐢ㄦ埛鎺堟潈鏁版嵁椤癸紵').then(function() { + return authUserCancelAll({ roleId: roleId, userIds: userIds }); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍙栨秷鎺堟潈鎴愬姛"); + }).catch(() => {}); + } + } +}; +</script> \ No newline at end of file diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue new file mode 100644 index 0000000..fb3b5ef --- /dev/null +++ b/src/views/system/role/index.vue @@ -0,0 +1,605 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch"> + <el-form-item label="瑙掕壊鍚嶇О" prop="roleName"> + <el-input + v-model="queryParams.roleName" + placeholder="璇疯緭鍏ヨ鑹插悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鏉冮檺瀛楃" prop="roleKey"> + <el-input + v-model="queryParams.roleKey" + placeholder="璇疯緭鍏ユ潈闄愬瓧绗�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="瑙掕壊鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鍒涘缓鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:role:add']" + >鏂板</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:role:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:role:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:role:export']" + >瀵煎嚭</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column label="瑙掕壊缂栧彿" prop="roleId" width="120" /> + <el-table-column label="瑙掕壊鍚嶇О" prop="roleName" :show-overflow-tooltip="true" width="150" /> + <el-table-column label="鏉冮檺瀛楃" prop="roleKey" :show-overflow-tooltip="true" width="150" /> + <el-table-column label="鏄剧ず椤哄簭" prop="roleSort" width="100" /> + <el-table-column label="鐘舵��" align="center" width="100"> + <template slot-scope="scope"> + <el-switch + v-model="scope.row.status" + active-value="0" + inactive-value="1" + @change="handleStatusChange(scope.row)" + ></el-switch> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope" v-if="scope.row.roleId !== 1"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:role:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:role:remove']" + >鍒犻櫎</el-button> + <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:role:edit']"> + <el-button size="mini" type="text" icon="el-icon-d-arrow-right">鏇村</el-button> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item command="handleDataScope" icon="el-icon-circle-check" + v-hasPermi="['system:role:edit']">鏁版嵁鏉冮檺</el-dropdown-item> + <el-dropdown-item command="handleAuthUser" icon="el-icon-user" + v-hasPermi="['system:role:edit']">鍒嗛厤鐢ㄦ埛</el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + + <!-- 娣诲姞鎴栦慨鏀硅鑹查厤缃璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="100px"> + <el-form-item label="瑙掕壊鍚嶇О" prop="roleName"> + <el-input v-model="form.roleName" placeholder="璇疯緭鍏ヨ鑹插悕绉�" /> + </el-form-item> + <el-form-item prop="roleKey"> + <span slot="label"> + <el-tooltip content="鎺у埗鍣ㄤ腑瀹氫箟鐨勬潈闄愬瓧绗︼紝濡傦細@PreAuthorize(`@ss.hasRole('admin')`)" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + 鏉冮檺瀛楃 + </span> + <el-input v-model="form.roleKey" placeholder="璇疯緭鍏ユ潈闄愬瓧绗�" /> + </el-form-item> + <el-form-item label="瑙掕壊椤哄簭" prop="roleSort"> + <el-input-number v-model="form.roleSort" controls-position="right" :min="0" /> + </el-form-item> + <el-form-item label="鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{dict.label}}</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item label="鑿滃崟鏉冮檺"> + <el-checkbox v-model="menuExpand" @change="handleCheckedTreeExpand($event, 'menu')">灞曞紑/鎶樺彔</el-checkbox> + <el-checkbox v-model="menuNodeAll" @change="handleCheckedTreeNodeAll($event, 'menu')">鍏ㄩ��/鍏ㄤ笉閫�</el-checkbox> + <el-checkbox v-model="form.menuCheckStrictly" @change="handleCheckedTreeConnect($event, 'menu')">鐖跺瓙鑱斿姩</el-checkbox> + <el-tree + class="tree-border" + :data="menuOptions" + show-checkbox + ref="menu" + node-key="id" + :check-strictly="!form.menuCheckStrictly" + empty-text="鍔犺浇涓紝璇风◢鍊�" + :props="defaultProps" + ></el-tree> + </el-form-item> + <el-form-item label="澶囨敞"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + + <!-- 鍒嗛厤瑙掕壊鏁版嵁鏉冮檺瀵硅瘽妗� --> + <el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body> + <el-form :model="form" label-width="80px"> + <el-form-item label="瑙掕壊鍚嶇О"> + <el-input v-model="form.roleName" :disabled="true" /> + </el-form-item> + <el-form-item label="鏉冮檺瀛楃"> + <el-input v-model="form.roleKey" :disabled="true" /> + </el-form-item> + <el-form-item label="鏉冮檺鑼冨洿"> + <el-select v-model="form.dataScope" @change="dataScopeSelectChange"> + <el-option + v-for="item in dataScopeOptions" + :key="item.value" + :label="item.label" + :value="item.value" + ></el-option> + </el-select> + </el-form-item> + <el-form-item label="鏁版嵁鏉冮檺" v-show="form.dataScope == 2"> + <el-checkbox v-model="deptExpand" @change="handleCheckedTreeExpand($event, 'dept')">灞曞紑/鎶樺彔</el-checkbox> + <el-checkbox v-model="deptNodeAll" @change="handleCheckedTreeNodeAll($event, 'dept')">鍏ㄩ��/鍏ㄤ笉閫�</el-checkbox> + <el-checkbox v-model="form.deptCheckStrictly" @change="handleCheckedTreeConnect($event, 'dept')">鐖跺瓙鑱斿姩</el-checkbox> + <el-tree + class="tree-border" + :data="deptOptions" + show-checkbox + default-expand-all + ref="dept" + node-key="id" + :check-strictly="!form.deptCheckStrictly" + empty-text="鍔犺浇涓紝璇风◢鍊�" + :props="defaultProps" + ></el-tree> + </el-form-item> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitDataScope">纭� 瀹�</el-button> + <el-button @click="cancelDataScope">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listRole, getRole, delRole, addRole, updateRole, dataScope, changeRoleStatus, deptTreeSelect } from "@/api/system/role"; +import { treeselect as menuTreeselect, roleMenuTreeselect } from "@/api/system/menu"; + +export default { + name: "Role", + dicts: ['sys_normal_disable'], + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 瑙掕壊琛ㄦ牸鏁版嵁 + roleList: [], + // 寮瑰嚭灞傛爣棰� + title: "", + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鏁版嵁鏉冮檺锛� + openDataScope: false, + menuExpand: false, + menuNodeAll: false, + deptExpand: true, + deptNodeAll: false, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 鏁版嵁鑼冨洿閫夐」 + dataScopeOptions: [ + { + value: "1", + label: "鍏ㄩ儴鏁版嵁鏉冮檺" + }, + { + value: "2", + label: "鑷畾鏁版嵁鏉冮檺" + }, + { + value: "3", + label: "鏈儴闂ㄦ暟鎹潈闄�" + }, + { + value: "4", + label: "鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺" + }, + { + value: "5", + label: "浠呮湰浜烘暟鎹潈闄�" + } + ], + // 鑿滃崟鍒楄〃 + menuOptions: [], + // 閮ㄩ棬鍒楄〃 + deptOptions: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + roleName: undefined, + roleKey: undefined, + status: undefined + }, + // 琛ㄥ崟鍙傛暟 + form: {}, + defaultProps: { + children: "children", + label: "label" + }, + // 琛ㄥ崟鏍¢獙 + rules: { + roleName: [ + { required: true, message: "瑙掕壊鍚嶇О涓嶈兘涓虹┖", trigger: "blur" } + ], + roleKey: [ + { required: true, message: "鏉冮檺瀛楃涓嶈兘涓虹┖", trigger: "blur" } + ], + roleSort: [ + { required: true, message: "瑙掕壊椤哄簭涓嶈兘涓虹┖", trigger: "blur" } + ] + } + }; + }, + created() { + this.getList(); + }, + methods: { + /** 鏌ヨ瑙掕壊鍒楄〃 */ + getList() { + this.loading = true; + listRole(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.roleList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + /** 鏌ヨ鑿滃崟鏍戠粨鏋� */ + getMenuTreeselect() { + menuTreeselect().then(response => { + this.menuOptions = response.data; + }); + }, + // 鎵�鏈夎彍鍗曡妭鐐规暟鎹� + getMenuAllCheckedKeys() { + // 鐩墠琚�変腑鐨勮彍鍗曡妭鐐� + let checkedKeys = this.$refs.menu.getCheckedKeys(); + // 鍗婇�変腑鐨勮彍鍗曡妭鐐� + let halfCheckedKeys = this.$refs.menu.getHalfCheckedKeys(); + checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys); + return checkedKeys; + }, + // 鎵�鏈夐儴闂ㄨ妭鐐规暟鎹� + getDeptAllCheckedKeys() { + // 鐩墠琚�変腑鐨勯儴闂ㄨ妭鐐� + let checkedKeys = this.$refs.dept.getCheckedKeys(); + // 鍗婇�変腑鐨勯儴闂ㄨ妭鐐� + let halfCheckedKeys = this.$refs.dept.getHalfCheckedKeys(); + checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys); + return checkedKeys; + }, + /** 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戠粨鏋� */ + getRoleMenuTreeselect(roleId) { + return roleMenuTreeselect(roleId).then(response => { + this.menuOptions = response.menus; + return response; + }); + }, + /** 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戠粨鏋� */ + getDeptTree(roleId) { + return deptTreeSelect(roleId).then(response => { + this.deptOptions = response.depts; + return response; + }); + }, + // 瑙掕壊鐘舵�佷慨鏀� + handleStatusChange(row) { + let text = row.status === "0" ? "鍚敤" : "鍋滅敤"; + this.$modal.confirm('纭瑕�"' + text + '""' + row.roleName + '"瑙掕壊鍚楋紵').then(function() { + return changeRoleStatus(row.roleId, row.status); + }).then(() => { + this.$modal.msgSuccess(text + "鎴愬姛"); + }).catch(function() { + row.status = row.status === "0" ? "1" : "0"; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 鍙栨秷鎸夐挳锛堟暟鎹潈闄愶級 + cancelDataScope() { + this.openDataScope = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + if (this.$refs.menu != undefined) { + this.$refs.menu.setCheckedKeys([]); + } + this.menuExpand = false, + this.menuNodeAll = false, + this.deptExpand = true, + this.deptNodeAll = false, + this.form = { + roleId: undefined, + roleName: undefined, + roleKey: undefined, + roleSort: 0, + status: "0", + menuIds: [], + deptIds: [], + menuCheckStrictly: true, + deptCheckStrictly: true, + remark: undefined + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.roleId) + this.single = selection.length!=1 + this.multiple = !selection.length + }, + // 鏇村鎿嶄綔瑙﹀彂 + handleCommand(command, row) { + switch (command) { + case "handleDataScope": + this.handleDataScope(row); + break; + case "handleAuthUser": + this.handleAuthUser(row); + break; + default: + break; + } + }, + // 鏍戞潈闄愶紙灞曞紑/鎶樺彔锛� + handleCheckedTreeExpand(value, type) { + if (type == 'menu') { + let treeList = this.menuOptions; + for (let i = 0; i < treeList.length; i++) { + this.$refs.menu.store.nodesMap[treeList[i].id].expanded = value; + } + } else if (type == 'dept') { + let treeList = this.deptOptions; + for (let i = 0; i < treeList.length; i++) { + this.$refs.dept.store.nodesMap[treeList[i].id].expanded = value; + } + } + }, + // 鏍戞潈闄愶紙鍏ㄩ��/鍏ㄤ笉閫夛級 + handleCheckedTreeNodeAll(value, type) { + if (type == 'menu') { + this.$refs.menu.setCheckedNodes(value ? this.menuOptions: []); + } else if (type == 'dept') { + this.$refs.dept.setCheckedNodes(value ? this.deptOptions: []); + } + }, + // 鏍戞潈闄愶紙鐖跺瓙鑱斿姩锛� + handleCheckedTreeConnect(value, type) { + if (type == 'menu') { + this.form.menuCheckStrictly = value ? true: false; + } else if (type == 'dept') { + this.form.deptCheckStrictly = value ? true: false; + } + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + this.getMenuTreeselect(); + this.open = true; + this.title = "娣诲姞瑙掕壊"; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const roleId = row.roleId || this.ids + const roleMenu = this.getRoleMenuTreeselect(roleId); + getRole(roleId).then(response => { + this.form = response.data; + this.open = true; + this.$nextTick(() => { + roleMenu.then(res => { + let checkedKeys = res.checkedKeys + checkedKeys.forEach((v) => { + this.$nextTick(()=>{ + this.$refs.menu.setChecked(v, true ,false); + }) + }) + }); + }); + this.title = "淇敼瑙掕壊"; + }); + }, + /** 閫夋嫨瑙掕壊鏉冮檺鑼冨洿瑙﹀彂 */ + dataScopeSelectChange(value) { + if(value !== '2') { + this.$refs.dept.setCheckedKeys([]); + } + }, + /** 鍒嗛厤鏁版嵁鏉冮檺鎿嶄綔 */ + handleDataScope(row) { + this.reset(); + const deptTreeSelect = this.getDeptTree(row.roleId); + getRole(row.roleId).then(response => { + this.form = response.data; + this.openDataScope = true; + this.$nextTick(() => { + deptTreeSelect.then(res => { + this.$refs.dept.setCheckedKeys(res.checkedKeys); + }); + }); + this.title = "鍒嗛厤鏁版嵁鏉冮檺"; + }); + }, + /** 鍒嗛厤鐢ㄦ埛鎿嶄綔 */ + handleAuthUser: function(row) { + const roleId = row.roleId; + this.$router.push("/system/role-auth/user/" + roleId); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.roleId != undefined) { + this.form.menuIds = this.getMenuAllCheckedKeys(); + updateRole(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + this.form.menuIds = this.getMenuAllCheckedKeys(); + addRole(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鎻愪氦鎸夐挳锛堟暟鎹潈闄愶級 */ + submitDataScope: function() { + if (this.form.roleId != undefined) { + this.form.deptIds = this.getDeptAllCheckedKeys(); + dataScope(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.openDataScope = false; + this.getList(); + }); + } + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const roleIds = row.roleId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎瑙掕壊缂栧彿涓�"' + roleIds + '"鐨勬暟鎹」锛�').then(function() { + return delRole(roleIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('system/role/export', { + ...this.queryParams + }, `role_${new Date().getTime()}.xlsx`) + } + } +}; +</script> \ No newline at end of file diff --git a/src/views/system/role/selectUser.vue b/src/views/system/role/selectUser.vue new file mode 100644 index 0000000..b2b072f --- /dev/null +++ b/src/views/system/role/selectUser.vue @@ -0,0 +1,138 @@ +<template> + <!-- 鎺堟潈鐢ㄦ埛 --> + <el-dialog title="閫夋嫨鐢ㄦ埛" :visible.sync="visible" width="800px" top="5vh" append-to-body> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> + <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input + v-model="queryParams.userName" + placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> + <el-input + v-model="queryParams.phonenumber" + placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + <el-row> + <el-table @row-click="clickRow" ref="table" :data="userList" @selection-change="handleSelectionChange" height="260px"> + <el-table-column type="selection" width="55"></el-table-column> + <el-table-column label="鐢ㄦ埛鍚嶇О" prop="userName" :show-overflow-tooltip="true" /> + <el-table-column label="鐢ㄦ埛鏄电О" prop="nickName" :show-overflow-tooltip="true" /> + <el-table-column label="閭" prop="email" :show-overflow-tooltip="true" /> + <el-table-column label="鎵嬫満" prop="phonenumber" :show-overflow-tooltip="true" /> + <el-table-column label="鐘舵��" align="center" prop="status"> + <template slot-scope="scope"> + <dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + </el-table> + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-row> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="handleSelectUser">纭� 瀹�</el-button> + <el-button @click="visible = false">鍙� 娑�</el-button> + </div> + </el-dialog> +</template> + +<script> +import { unallocatedUserList, authUserSelectAll } from "@/api/system/role"; +export default { + dicts: ['sys_normal_disable'], + props: { + // 瑙掕壊缂栧彿 + roleId: { + type: [Number, String] + } + }, + data() { + return { + // 閬僵灞� + visible: false, + // 閫変腑鏁扮粍鍊� + userIds: [], + // 鎬绘潯鏁� + total: 0, + // 鏈巿鏉冪敤鎴锋暟鎹� + userList: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + roleId: undefined, + userName: undefined, + phonenumber: undefined + } + }; + }, + methods: { + // 鏄剧ず寮规 + show() { + this.queryParams.roleId = this.roleId; + this.getList(); + this.visible = true; + }, + clickRow(row) { + this.$refs.table.toggleRowSelection(row); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.userIds = selection.map(item => item.userId); + }, + // 鏌ヨ琛ㄦ暟鎹� + getList() { + unallocatedUserList(this.queryParams).then(res => { + this.userList = res.rows; + this.total = res.total; + }); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 閫夋嫨鎺堟潈鐢ㄦ埛鎿嶄綔 */ + handleSelectUser() { + const roleId = this.queryParams.roleId; + const userIds = this.userIds.join(","); + if (userIds == "") { + this.$modal.msgError("璇烽�夋嫨瑕佸垎閰嶇殑鐢ㄦ埛"); + return; + } + authUserSelectAll({ roleId: roleId, userIds: userIds }).then(res => { + this.$modal.msgSuccess(res.msg); + if (res.code === 200) { + this.visible = false; + this.$emit("ok"); + } + }); + } + } +}; +</script> diff --git a/src/views/system/user/authRole.vue b/src/views/system/user/authRole.vue new file mode 100644 index 0000000..ab5e72f --- /dev/null +++ b/src/views/system/user/authRole.vue @@ -0,0 +1,117 @@ +<template> + <div class="app-container"> + <h4 class="form-header h4">鍩烘湰淇℃伅</h4> + <el-form ref="form" :model="form" label-width="80px"> + <el-row> + <el-col :span="8" :offset="2"> + <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName"> + <el-input v-model="form.nickName" disabled /> + </el-form-item> + </el-col> + <el-col :span="8" :offset="2"> + <el-form-item label="鐧诲綍璐﹀彿" prop="userName"> + <el-input v-model="form.userName" disabled /> + </el-form-item> + </el-col> + </el-row> + </el-form> + + <h4 class="form-header h4">瑙掕壊淇℃伅</h4> + <el-table v-loading="loading" :row-key="getRowKey" @row-click="clickRow" ref="table" @selection-change="handleSelectionChange" :data="roles.slice((pageNum-1)*pageSize,pageNum*pageSize)"> + <el-table-column label="搴忓彿" type="index" align="center"> + <template slot-scope="scope"> + <span>{{(pageNum - 1) * pageSize + scope.$index + 1}}</span> + </template> + </el-table-column> + <el-table-column type="selection" :reserve-selection="true" width="55"></el-table-column> + <el-table-column label="瑙掕壊缂栧彿" align="center" prop="roleId" /> + <el-table-column label="瑙掕壊鍚嶇О" align="center" prop="roleName" /> + <el-table-column label="鏉冮檺瀛楃" align="center" prop="roleKey" /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + </el-table> + + <pagination v-show="total>0" :total="total" :page.sync="pageNum" :limit.sync="pageSize" /> + + <el-form label-width="100px"> + <el-form-item style="text-align: center;margin-left:-120px;margin-top:30px;"> + <el-button type="primary" @click="submitForm()">鎻愪氦</el-button> + <el-button @click="close()">杩斿洖</el-button> + </el-form-item> + </el-form> + </div> +</template> + +<script> +import { getAuthRole, updateAuthRole } from "@/api/system/user"; + +export default { + name: "AuthRole", + data() { + return { + // 閬僵灞� + loading: true, + // 鍒嗛〉淇℃伅 + total: 0, + pageNum: 1, + pageSize: 10, + // 閫変腑瑙掕壊缂栧彿 + roleIds:[], + // 瑙掕壊淇℃伅 + roles: [], + // 鐢ㄦ埛淇℃伅 + form: {} + }; + }, + created() { + const userId = this.$route.params && this.$route.params.userId; + if (userId) { + this.loading = true; + getAuthRole(userId).then((response) => { + this.form = response.user; + this.roles = response.roles; + this.total = this.roles.length; + this.$nextTick(() => { + this.roles.forEach((row) => { + if (row.flag) { + this.$refs.table.toggleRowSelection(row); + } + }); + }); + this.loading = false; + }); + } + }, + methods: { + /** 鍗曞嚮閫変腑琛屾暟鎹� */ + clickRow(row) { + this.$refs.table.toggleRowSelection(row); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.roleIds = selection.map((item) => item.roleId); + }, + // 淇濆瓨閫変腑鐨勬暟鎹紪鍙� + getRowKey(row) { + return row.roleId; + }, + /** 鎻愪氦鎸夐挳 */ + submitForm() { + const userId = this.form.userId; + const roleIds = this.roleIds.join(","); + updateAuthRole({ userId: userId, roleIds: roleIds }).then((response) => { + this.$modal.msgSuccess("鎺堟潈鎴愬姛"); + this.close(); + }); + }, + /** 鍏抽棴鎸夐挳 */ + close() { + const obj = { path: "/system/user" }; + this.$tab.closeOpenPage(obj); + }, + }, +}; +</script> \ No newline at end of file diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue new file mode 100644 index 0000000..ae87fe4 --- /dev/null +++ b/src/views/system/user/index.vue @@ -0,0 +1,670 @@ +<template> + <div class="app-container"> + <el-row :gutter="20"> + <!--閮ㄩ棬鏁版嵁--> + <el-col :span="4" :xs="24"> + <div class="head-container"> + <el-input + v-model="deptName" + placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" + clearable + size="small" + prefix-icon="el-icon-search" + style="margin-bottom: 20px" + /> + </div> + <div class="head-container"> + <el-tree + :data="deptOptions" + :props="defaultProps" + :expand-on-click-node="false" + :filter-node-method="filterNode" + ref="tree" + node-key="id" + default-expand-all + highlight-current + @node-click="handleNodeClick" + /> + </div> + </el-col> + <!--鐢ㄦ埛鏁版嵁--> + <el-col :span="20" :xs="24"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input + v-model="queryParams.userName" + placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> + <el-input + v-model="queryParams.phonenumber" + placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" + clearable + style="width: 240px" + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鐘舵��" prop="status"> + <el-select + v-model="queryParams.status" + placeholder="鐢ㄦ埛鐘舵��" + clearable + style="width: 240px" + > + <el-option + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.label" + :value="dict.value" + /> + </el-select> + </el-form-item> + <el-form-item label="鍒涘缓鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-plus" + size="mini" + @click="handleAdd" + v-hasPermi="['system:user:add']" + >鏂板</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleUpdate" + v-hasPermi="['system:user:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['system:user:remove']" + >鍒犻櫎</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-upload2" + size="mini" + @click="handleImport" + v-hasPermi="['system:user:import']" + >瀵煎叆</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="warning" + plain + icon="el-icon-download" + size="mini" + @click="handleExport" + v-hasPermi="['system:user:export']" + >瀵煎嚭</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="50" align="center" /> + <el-table-column label="鐢ㄦ埛缂栧彿" align="center" key="userId" prop="userId" v-if="columns[0].visible" /> + <el-table-column label="鐢ㄦ埛鍚嶇О" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" /> + <el-table-column label="鐢ㄦ埛鏄电О" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" /> + <el-table-column label="閮ㄩ棬" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" /> + <el-table-column label="鎵嬫満鍙风爜" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" /> + <el-table-column label="鐘舵��" align="center" key="status" v-if="columns[5].visible"> + <template slot-scope="scope"> + <el-switch + v-model="scope.row.status" + active-value="0" + inactive-value="1" + @change="handleStatusChange(scope.row)" + ></el-switch> + </template> + </el-table-column> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" v-if="columns[6].visible" width="160"> + <template slot-scope="scope"> + <span>{{ parseTime(scope.row.createTime) }}</span> + </template> + </el-table-column> + <el-table-column + label="鎿嶄綔" + align="center" + width="160" + class-name="small-padding fixed-width" + > + <template slot-scope="scope" v-if="scope.row.userId !== 1"> + <el-button + size="mini" + type="text" + icon="el-icon-edit" + @click="handleUpdate(scope.row)" + v-hasPermi="['system:user:edit']" + >淇敼</el-button> + <el-button + size="mini" + type="text" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['system:user:remove']" + >鍒犻櫎</el-button> + <el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['system:user:resetPwd', 'system:user:edit']"> + <el-button size="mini" type="text" icon="el-icon-d-arrow-right">鏇村</el-button> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item command="handleResetPwd" icon="el-icon-key" + v-hasPermi="['system:user:resetPwd']">閲嶇疆瀵嗙爜</el-dropdown-item> + <el-dropdown-item command="handleAuthRole" icon="el-icon-circle-check" + v-hasPermi="['system:user:edit']">鍒嗛厤瑙掕壊</el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </template> + </el-table-column> + </el-table> + + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-col> + </el-row> + + <!-- 娣诲姞鎴栦慨鏀圭敤鎴烽厤缃璇濇 --> + <el-dialog :title="title" :visible.sync="open" width="600px" append-to-body> + <el-form ref="form" :model="form" :rules="rules" label-width="80px"> + <el-row> + <el-col :span="12"> + <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName"> + <el-input v-model="form.nickName" placeholder="璇疯緭鍏ョ敤鎴锋樀绉�" maxlength="30" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId"> + <treeselect v-model="form.deptId" :options="deptOptions" :show-count="true" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> + <el-input v-model="form.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" maxlength="11" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="閭" prop="email"> + <el-input v-model="form.email" placeholder="璇疯緭鍏ラ偖绠�" maxlength="50" /> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item v-if="form.userId == undefined" label="鐢ㄦ埛鍚嶇О" prop="userName"> + <el-input v-model="form.userName" placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" maxlength="30" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item v-if="form.userId == undefined" label="鐢ㄦ埛瀵嗙爜" prop="password"> + <el-input v-model="form.password" placeholder="璇疯緭鍏ョ敤鎴峰瘑鐮�" type="password" maxlength="20" show-password/> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="鐢ㄦ埛鎬у埆"> + <el-select v-model="form.sex" placeholder="璇烽�夋嫨鎬у埆"> + <el-option + v-for="dict in dict.type.sys_user_sex" + :key="dict.value" + :label="dict.label" + :value="dict.value" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鐘舵��"> + <el-radio-group v-model="form.status"> + <el-radio + v-for="dict in dict.type.sys_normal_disable" + :key="dict.value" + :label="dict.value" + >{{dict.label}}</el-radio> + </el-radio-group> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="12"> + <el-form-item label="宀椾綅"> + <el-select v-model="form.postIds" multiple placeholder="璇烽�夋嫨宀椾綅"> + <el-option + v-for="item in postOptions" + :key="item.postId" + :label="item.postName" + :value="item.postId" + :disabled="item.status == 1" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="瑙掕壊"> + <el-select v-model="form.roleIds" multiple placeholder="璇烽�夋嫨瑙掕壊"> + <el-option + v-for="item in roleOptions" + :key="item.roleId" + :label="item.roleName" + :value="item.roleId" + :disabled="item.status == 1" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row> + <el-col :span="24"> + <el-form-item label="澶囨敞"> + <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> + <el-button @click="cancel">鍙� 娑�</el-button> + </div> + </el-dialog> + + <!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� --> + <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body> + <el-upload + ref="upload" + :limit="1" + accept=".xlsx, .xls" + :headers="upload.headers" + :action="upload.url + '?updateSupport=' + upload.updateSupport" + :disabled="upload.isUploading" + :on-progress="handleFileUploadProgress" + :on-success="handleFileSuccess" + :auto-upload="false" + drag + > + <i class="el-icon-upload"></i> + <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div> + <div class="el-upload__tip text-center" slot="tip"> + <div class="el-upload__tip" slot="tip"> + <el-checkbox v-model="upload.updateSupport" /> 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + </div> + <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span> + <el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate">涓嬭浇妯℃澘</el-link> + </div> + </el-upload> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button> + <el-button @click="upload.open = false">鍙� 娑�</el-button> + </div> + </el-dialog> + </div> +</template> + +<script> +import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUserStatus, deptTreeSelect } from "@/api/system/user"; +import { getToken } from "@/utils/auth"; +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + name: "User", + dicts: ['sys_normal_disable', 'sys_user_sex'], + components: { Treeselect }, + data() { + return { + // 閬僵灞� + loading: true, + // 閫変腑鏁扮粍 + ids: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 鐢ㄦ埛琛ㄦ牸鏁版嵁 + userList: null, + // 寮瑰嚭灞傛爣棰� + title: "", + // 閮ㄩ棬鏍戦�夐」 + deptOptions: undefined, + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 閮ㄩ棬鍚嶇О + deptName: undefined, + // 榛樿瀵嗙爜 + initPassword: undefined, + // 鏃ユ湡鑼冨洿 + dateRange: [], + // 宀椾綅閫夐」 + postOptions: [], + // 瑙掕壊閫夐」 + roleOptions: [], + // 琛ㄥ崟鍙傛暟 + form: {}, + defaultProps: { + children: "children", + label: "label" + }, + // 鐢ㄦ埛瀵煎叆鍙傛暟 + upload: { + // 鏄惁鏄剧ず寮瑰嚭灞傦紙鐢ㄦ埛瀵煎叆锛� + open: false, + // 寮瑰嚭灞傛爣棰橈紙鐢ㄦ埛瀵煎叆锛� + title: "", + // 鏄惁绂佺敤涓婁紶 + isUploading: false, + // 鏄惁鏇存柊宸茬粡瀛樺湪鐨勭敤鎴锋暟鎹� + updateSupport: 0, + // 璁剧疆涓婁紶鐨勮姹傚ご閮� + headers: { Authorization: "Bearer " + getToken() }, + // 涓婁紶鐨勫湴鍧� + url: process.env.VUE_APP_BASE_API + "/system/user/importData" + }, + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + userName: undefined, + phonenumber: undefined, + status: undefined, + deptId: undefined + }, + // 鍒椾俊鎭� + columns: [ + { key: 0, label: `鐢ㄦ埛缂栧彿`, visible: true }, + { key: 1, label: `鐢ㄦ埛鍚嶇О`, visible: true }, + { key: 2, label: `鐢ㄦ埛鏄电О`, visible: true }, + { key: 3, label: `閮ㄩ棬`, visible: true }, + { key: 4, label: `鎵嬫満鍙风爜`, visible: true }, + { key: 5, label: `鐘舵�乣, visible: true }, + { key: 6, label: `鍒涘缓鏃堕棿`, visible: true } + ], + // 琛ㄥ崟鏍¢獙 + rules: { + userName: [ + { required: true, message: "鐢ㄦ埛鍚嶇О涓嶈兘涓虹┖", trigger: "blur" }, + { min: 2, max: 20, message: '鐢ㄦ埛鍚嶇О闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' } + ], + nickName: [ + { required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" } + ], + password: [ + { required: true, message: "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }, + { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' } + ], + email: [ + { + type: "email", + message: "璇疯緭鍏ユ纭殑閭鍦板潃", + trigger: ["blur", "change"] + } + ], + phonenumber: [ + { + pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, + message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", + trigger: "blur" + } + ] + } + }; + }, + watch: { + // 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 + deptName(val) { + this.$refs.tree.filter(val); + } + }, + created() { + this.getList(); + this.getDeptTree(); + this.getConfigKey("sys.user.initPassword").then(response => { + this.initPassword = response.msg; + }); + }, + methods: { + /** 鏌ヨ鐢ㄦ埛鍒楄〃 */ + getList() { + this.loading = true; + listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.userList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + /** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ + getDeptTree() { + deptTreeSelect().then(response => { + this.deptOptions = response.data; + }); + }, + // 绛涢�夎妭鐐� + filterNode(value, data) { + if (!value) return true; + return data.label.indexOf(value) !== -1; + }, + // 鑺傜偣鍗曞嚮浜嬩欢 + handleNodeClick(data) { + this.queryParams.deptId = data.id; + this.handleQuery(); + }, + // 鐢ㄦ埛鐘舵�佷慨鏀� + handleStatusChange(row) { + let text = row.status === "0" ? "鍚敤" : "鍋滅敤"; + this.$modal.confirm('纭瑕�"' + text + '""' + row.userName + '"鐢ㄦ埛鍚楋紵').then(function() { + return changeUserStatus(row.userId, row.status); + }).then(() => { + this.$modal.msgSuccess(text + "鎴愬姛"); + }).catch(function() { + row.status = row.status === "0" ? "1" : "0"; + }); + }, + // 鍙栨秷鎸夐挳 + cancel() { + this.open = false; + this.reset(); + }, + // 琛ㄥ崟閲嶇疆 + reset() { + this.form = { + userId: undefined, + deptId: undefined, + userName: undefined, + nickName: undefined, + password: undefined, + phonenumber: undefined, + email: undefined, + sex: undefined, + status: "0", + remark: undefined, + postIds: [], + roleIds: [] + }; + this.resetForm("form"); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.queryParams.deptId = undefined; + this.$refs.tree.setCurrentKey(null); + this.handleQuery(); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.userId); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + // 鏇村鎿嶄綔瑙﹀彂 + handleCommand(command, row) { + switch (command) { + case "handleResetPwd": + this.handleResetPwd(row); + break; + case "handleAuthRole": + this.handleAuthRole(row); + break; + default: + break; + } + }, + /** 鏂板鎸夐挳鎿嶄綔 */ + handleAdd() { + this.reset(); + getUser().then(response => { + this.postOptions = response.posts; + this.roleOptions = response.roles; + this.open = true; + this.title = "娣诲姞鐢ㄦ埛"; + this.form.password = this.initPassword; + }); + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleUpdate(row) { + this.reset(); + const userId = row.userId || this.ids; + getUser(userId).then(response => { + this.form = response.data; + this.postOptions = response.posts; + this.roleOptions = response.roles; + this.$set(this.form, "postIds", response.postIds); + this.$set(this.form, "roleIds", response.roleIds); + this.open = true; + this.title = "淇敼鐢ㄦ埛"; + this.form.password = ""; + }); + }, + /** 閲嶇疆瀵嗙爜鎸夐挳鎿嶄綔 */ + handleResetPwd(row) { + this.$prompt('璇疯緭鍏�"' + row.userName + '"鐨勬柊瀵嗙爜', "鎻愮ず", { + confirmButtonText: "纭畾", + cancelButtonText: "鍙栨秷", + closeOnClickModal: false, + inputPattern: /^.{5,20}$/, + inputErrorMessage: "鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿" + }).then(({ value }) => { + resetUserPwd(row.userId, value).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛锛屾柊瀵嗙爜鏄細" + value); + }); + }).catch(() => {}); + }, + /** 鍒嗛厤瑙掕壊鎿嶄綔 */ + handleAuthRole: function(row) { + const userId = row.userId; + this.$router.push("/system/user-auth/role/" + userId); + }, + /** 鎻愪氦鎸夐挳 */ + submitForm: function() { + this.$refs["form"].validate(valid => { + if (valid) { + if (this.form.userId != undefined) { + updateUser(this.form).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.open = false; + this.getList(); + }); + } else { + addUser(this.form).then(response => { + this.$modal.msgSuccess("鏂板鎴愬姛"); + this.open = false; + this.getList(); + }); + } + } + }); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const userIds = row.userId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎鐢ㄦ埛缂栧彿涓�"' + userIds + '"鐨勬暟鎹」锛�').then(function() { + return delUser(userIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + }, + /** 瀵煎嚭鎸夐挳鎿嶄綔 */ + handleExport() { + this.download('system/user/export', { + ...this.queryParams + }, `user_${new Date().getTime()}.xlsx`) + }, + /** 瀵煎叆鎸夐挳鎿嶄綔 */ + handleImport() { + this.upload.title = "鐢ㄦ埛瀵煎叆"; + this.upload.open = true; + }, + /** 涓嬭浇妯℃澘鎿嶄綔 */ + importTemplate() { + this.download('system/user/importTemplate', { + }, `user_template_${new Date().getTime()}.xlsx`) + }, + // 鏂囦欢涓婁紶涓鐞� + handleFileUploadProgress(event, file, fileList) { + this.upload.isUploading = true; + }, + // 鏂囦欢涓婁紶鎴愬姛澶勭悊 + handleFileSuccess(response, file, fileList) { + this.upload.open = false; + this.upload.isUploading = false; + this.$refs.upload.clearFiles(); + this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "瀵煎叆缁撴灉", { dangerouslyUseHTMLString: true }); + this.getList(); + }, + // 鎻愪氦涓婁紶鏂囦欢 + submitFileForm() { + this.$refs.upload.submit(); + } + } +}; +</script> \ No newline at end of file diff --git a/src/views/system/user/profile/index.vue b/src/views/system/user/profile/index.vue new file mode 100644 index 0000000..529c564 --- /dev/null +++ b/src/views/system/user/profile/index.vue @@ -0,0 +1,91 @@ +<template> + <div class="app-container"> + <el-row :gutter="20"> + <el-col :span="6" :xs="24"> + <el-card class="box-card"> + <div slot="header" class="clearfix"> + <span>涓汉淇℃伅</span> + </div> + <div> + <div class="text-center"> + <userAvatar /> + </div> + <ul class="list-group list-group-striped"> + <li class="list-group-item"> + <svg-icon icon-class="user" />鐢ㄦ埛鍚嶇О + <div class="pull-right">{{ user.userName }}</div> + </li> + <li class="list-group-item"> + <svg-icon icon-class="phone" />鎵嬫満鍙风爜 + <div class="pull-right">{{ user.phonenumber }}</div> + </li> + <li class="list-group-item"> + <svg-icon icon-class="email" />鐢ㄦ埛閭 + <div class="pull-right">{{ user.email }}</div> + </li> + <li class="list-group-item"> + <svg-icon icon-class="tree" />鎵�灞為儴闂� + <div class="pull-right" v-if="user.dept">{{ user.dept.deptName }} / {{ postGroup }}</div> + </li> + <li class="list-group-item"> + <svg-icon icon-class="peoples" />鎵�灞炶鑹� + <div class="pull-right">{{ roleGroup }}</div> + </li> + <li class="list-group-item"> + <svg-icon icon-class="date" />鍒涘缓鏃ユ湡 + <div class="pull-right">{{ user.createTime }}</div> + </li> + </ul> + </div> + </el-card> + </el-col> + <el-col :span="18" :xs="24"> + <el-card> + <div slot="header" class="clearfix"> + <span>鍩烘湰璧勬枡</span> + </div> + <el-tabs v-model="activeTab"> + <el-tab-pane label="鍩烘湰璧勬枡" name="userinfo"> + <userInfo :user="user" /> + </el-tab-pane> + <el-tab-pane label="淇敼瀵嗙爜" name="resetPwd"> + <resetPwd /> + </el-tab-pane> + </el-tabs> + </el-card> + </el-col> + </el-row> + </div> +</template> + +<script> +import userAvatar from "./userAvatar"; +import userInfo from "./userInfo"; +import resetPwd from "./resetPwd"; +import { getUserProfile } from "@/api/system/user"; + +export default { + name: "Profile", + components: { userAvatar, userInfo, resetPwd }, + data() { + return { + user: {}, + roleGroup: {}, + postGroup: {}, + activeTab: "userinfo" + }; + }, + created() { + this.getUser(); + }, + methods: { + getUser() { + getUserProfile().then(response => { + this.user = response.data; + this.roleGroup = response.roleGroup; + this.postGroup = response.postGroup; + }); + } + } +}; +</script> diff --git a/src/views/system/user/profile/resetPwd.vue b/src/views/system/user/profile/resetPwd.vue new file mode 100644 index 0000000..64e8f8c --- /dev/null +++ b/src/views/system/user/profile/resetPwd.vue @@ -0,0 +1,68 @@ +<template> + <el-form ref="form" :model="user" :rules="rules" label-width="80px"> + <el-form-item label="鏃у瘑鐮�" prop="oldPassword"> + <el-input v-model="user.oldPassword" placeholder="璇疯緭鍏ユ棫瀵嗙爜" type="password" show-password/> + </el-form-item> + <el-form-item label="鏂板瘑鐮�" prop="newPassword"> + <el-input v-model="user.newPassword" placeholder="璇疯緭鍏ユ柊瀵嗙爜" type="password" show-password/> + </el-form-item> + <el-form-item label="纭瀵嗙爜" prop="confirmPassword"> + <el-input v-model="user.confirmPassword" placeholder="璇风‘璁ゆ柊瀵嗙爜" type="password" show-password/> + </el-form-item> + <el-form-item> + <el-button type="primary" size="mini" @click="submit">淇濆瓨</el-button> + <el-button type="danger" size="mini" @click="close">鍏抽棴</el-button> + </el-form-item> + </el-form> +</template> + +<script> +import { updateUserPwd } from "@/api/system/user"; + +export default { + data() { + const equalToPassword = (rule, value, callback) => { + if (this.user.newPassword !== value) { + callback(new Error("涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�")); + } else { + callback(); + } + }; + return { + user: { + oldPassword: undefined, + newPassword: undefined, + confirmPassword: undefined + }, + // 琛ㄥ崟鏍¢獙 + rules: { + oldPassword: [ + { required: true, message: "鏃у瘑鐮佷笉鑳戒负绌�", trigger: "blur" } + ], + newPassword: [ + { required: true, message: "鏂板瘑鐮佷笉鑳戒负绌�", trigger: "blur" }, + { min: 6, max: 20, message: "闀垮害鍦� 6 鍒� 20 涓瓧绗�", trigger: "blur" } + ], + confirmPassword: [ + { required: true, message: "纭瀵嗙爜涓嶈兘涓虹┖", trigger: "blur" }, + { required: true, validator: equalToPassword, trigger: "blur" } + ] + } + }; + }, + methods: { + submit() { + this.$refs["form"].validate(valid => { + if (valid) { + updateUserPwd(this.user.oldPassword, this.user.newPassword).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + }); + } + }); + }, + close() { + this.$tab.closePage(); + } + } +}; +</script> diff --git a/src/views/system/user/profile/userAvatar.vue b/src/views/system/user/profile/userAvatar.vue new file mode 100644 index 0000000..96aa01f --- /dev/null +++ b/src/views/system/user/profile/userAvatar.vue @@ -0,0 +1,182 @@ +<template> + <div> + <div class="user-info-head" @click="editCropper()"><img v-bind:src="options.img" title="鐐瑰嚮涓婁紶澶村儚" class="img-circle img-lg" /></div> + <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body @opened="modalOpened" @close="closeDialog"> + <el-row> + <el-col :xs="24" :md="12" :style="{height: '350px'}"> + <vue-cropper + ref="cropper" + :img="options.img" + :info="true" + :autoCrop="options.autoCrop" + :autoCropWidth="options.autoCropWidth" + :autoCropHeight="options.autoCropHeight" + :fixedBox="options.fixedBox" + :outputType="options.outputType" + @realTime="realTime" + v-if="visible" + /> + </el-col> + <el-col :xs="24" :md="12" :style="{height: '350px'}"> + <div class="avatar-upload-preview"> + <img :src="previews.url" :style="previews.img" /> + </div> + </el-col> + </el-row> + <br /> + <el-row> + <el-col :lg="2" :sm="3" :xs="3"> + <el-upload action="#" :http-request="requestUpload" :show-file-list="false" :before-upload="beforeUpload"> + <el-button size="small"> + 閫夋嫨 + <i class="el-icon-upload el-icon--right"></i> + </el-button> + </el-upload> + </el-col> + <el-col :lg="{span: 1, offset: 2}" :sm="2" :xs="2"> + <el-button icon="el-icon-plus" size="small" @click="changeScale(1)"></el-button> + </el-col> + <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"> + <el-button icon="el-icon-minus" size="small" @click="changeScale(-1)"></el-button> + </el-col> + <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"> + <el-button icon="el-icon-refresh-left" size="small" @click="rotateLeft()"></el-button> + </el-col> + <el-col :lg="{span: 1, offset: 1}" :sm="2" :xs="2"> + <el-button icon="el-icon-refresh-right" size="small" @click="rotateRight()"></el-button> + </el-col> + <el-col :lg="{span: 2, offset: 6}" :sm="2" :xs="2"> + <el-button type="primary" size="small" @click="uploadImg()">鎻� 浜�</el-button> + </el-col> + </el-row> + </el-dialog> + </div> +</template> + +<script> +import store from "@/store"; +import { VueCropper } from "vue-cropper"; +import { uploadAvatar } from "@/api/system/user"; +import { debounce } from '@/utils' + +export default { + components: { VueCropper }, + data() { + return { + // 鏄惁鏄剧ず寮瑰嚭灞� + open: false, + // 鏄惁鏄剧ずcropper + visible: false, + // 寮瑰嚭灞傛爣棰� + title: "淇敼澶村儚", + options: { + img: store.getters.avatar, //瑁佸壀鍥剧墖鐨勫湴鍧� + autoCrop: true, // 鏄惁榛樿鐢熸垚鎴浘妗� + autoCropWidth: 200, // 榛樿鐢熸垚鎴浘妗嗗搴� + autoCropHeight: 200, // 榛樿鐢熸垚鎴浘妗嗛珮搴� + fixedBox: true, // 鍥哄畾鎴浘妗嗗ぇ灏� 涓嶅厑璁告敼鍙� + outputType:"png" // 榛樿鐢熸垚鎴浘涓篜NG鏍煎紡 + }, + previews: {}, + resizeHandler: null + }; + }, + methods: { + // 缂栬緫澶村儚 + editCropper() { + this.open = true; + }, + // 鎵撳紑寮瑰嚭灞傜粨鏉熸椂鐨勫洖璋� + modalOpened() { + this.visible = true; + if (!this.resizeHandler) { + this.resizeHandler = debounce(() => { + this.refresh() + }, 100) + } + window.addEventListener("resize", this.resizeHandler) + }, + // 鍒锋柊缁勪欢 + refresh() { + this.$refs.cropper.refresh(); + }, + // 瑕嗙洊榛樿鐨勪笂浼犺涓� + requestUpload() { + }, + // 鍚戝乏鏃嬭浆 + rotateLeft() { + this.$refs.cropper.rotateLeft(); + }, + // 鍚戝彸鏃嬭浆 + rotateRight() { + this.$refs.cropper.rotateRight(); + }, + // 鍥剧墖缂╂斁 + changeScale(num) { + num = num || 1; + this.$refs.cropper.changeScale(num); + }, + // 涓婁紶棰勫鐞� + beforeUpload(file) { + if (file.type.indexOf("image/") == -1) { + this.$modal.msgError("鏂囦欢鏍煎紡閿欒锛岃涓婁紶鍥剧墖绫诲瀷,濡傦細JPG锛孭NG鍚庣紑鐨勬枃浠躲��"); + } else { + const reader = new FileReader(); + reader.readAsDataURL(file); + reader.onload = () => { + this.options.img = reader.result; + }; + } + }, + // 涓婁紶鍥剧墖 + uploadImg() { + this.$refs.cropper.getCropBlob(data => { + let formData = new FormData(); + formData.append("avatarfile", data); + uploadAvatar(formData).then(response => { + this.open = false; + this.options.img = process.env.VUE_APP_BASE_API + response.imgUrl; + store.commit('SET_AVATAR', this.options.img); + this.$modal.msgSuccess("淇敼鎴愬姛"); + this.visible = false; + }); + }); + }, + // 瀹炴椂棰勮 + realTime(data) { + this.previews = data; + }, + // 鍏抽棴绐楀彛 + closeDialog() { + this.options.img = store.getters.avatar + this.visible = false; + window.removeEventListener("resize", this.resizeHandler) + } + } +}; +</script> +<style scoped lang="scss"> +.user-info-head { + position: relative; + display: inline-block; + height: 120px; +} + +.user-info-head:hover:after { + content: '+'; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + color: #eee; + background: rgba(0, 0, 0, 0.5); + font-size: 24px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + cursor: pointer; + line-height: 110px; + border-radius: 50%; +} +</style> diff --git a/src/views/system/user/profile/userInfo.vue b/src/views/system/user/profile/userInfo.vue new file mode 100644 index 0000000..c09a20b --- /dev/null +++ b/src/views/system/user/profile/userInfo.vue @@ -0,0 +1,75 @@ +<template> + <el-form ref="form" :model="user" :rules="rules" label-width="80px"> + <el-form-item label="鐢ㄦ埛鏄电О" prop="nickName"> + <el-input v-model="user.nickName" maxlength="30" /> + </el-form-item> + <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> + <el-input v-model="user.phonenumber" maxlength="11" /> + </el-form-item> + <el-form-item label="閭" prop="email"> + <el-input v-model="user.email" maxlength="50" /> + </el-form-item> + <el-form-item label="鎬у埆"> + <el-radio-group v-model="user.sex"> + <el-radio label="0">鐢�</el-radio> + <el-radio label="1">濂�</el-radio> + </el-radio-group> + </el-form-item> + <el-form-item> + <el-button type="primary" size="mini" @click="submit">淇濆瓨</el-button> + <el-button type="danger" size="mini" @click="close">鍏抽棴</el-button> + </el-form-item> + </el-form> +</template> + +<script> +import { updateUserProfile } from "@/api/system/user"; + +export default { + props: { + user: { + type: Object + } + }, + data() { + return { + // 琛ㄥ崟鏍¢獙 + rules: { + nickName: [ + { required: true, message: "鐢ㄦ埛鏄电О涓嶈兘涓虹┖", trigger: "blur" } + ], + email: [ + { required: true, message: "閭鍦板潃涓嶈兘涓虹┖", trigger: "blur" }, + { + type: "email", + message: "璇疯緭鍏ユ纭殑閭鍦板潃", + trigger: ["blur", "change"] + } + ], + phonenumber: [ + { required: true, message: "鎵嬫満鍙风爜涓嶈兘涓虹┖", trigger: "blur" }, + { + pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, + message: "璇疯緭鍏ユ纭殑鎵嬫満鍙风爜", + trigger: "blur" + } + ] + } + }; + }, + methods: { + submit() { + this.$refs["form"].validate(valid => { + if (valid) { + updateUserProfile(this.user).then(response => { + this.$modal.msgSuccess("淇敼鎴愬姛"); + }); + } + }); + }, + close() { + this.$tab.closePage(); + } + } +}; +</script> diff --git a/src/views/tool/build/CodeTypeDialog.vue b/src/views/tool/build/CodeTypeDialog.vue new file mode 100644 index 0000000..b5c2e2e --- /dev/null +++ b/src/views/tool/build/CodeTypeDialog.vue @@ -0,0 +1,106 @@ +<template> + <div> + <el-dialog + v-bind="$attrs" + width="500px" + :close-on-click-modal="false" + :modal-append-to-body="false" + v-on="$listeners" + @open="onOpen" + @close="onClose" + > + <el-row :gutter="15"> + <el-form + ref="elForm" + :model="formData" + :rules="rules" + size="medium" + label-width="100px" + > + <el-col :span="24"> + <el-form-item label="鐢熸垚绫诲瀷" prop="type"> + <el-radio-group v-model="formData.type"> + <el-radio-button + v-for="(item, index) in typeOptions" + :key="index" + :label="item.value" + :disabled="item.disabled" + > + {{ item.label }} + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item v-if="showFileName" label="鏂囦欢鍚�" prop="fileName"> + <el-input v-model="formData.fileName" placeholder="璇疯緭鍏ユ枃浠跺悕" clearable /> + </el-form-item> + </el-col> + </el-form> + </el-row> + + <div slot="footer"> + <el-button @click="close"> + 鍙栨秷 + </el-button> + <el-button type="primary" @click="handleConfirm"> + 纭畾 + </el-button> + </div> + </el-dialog> + </div> +</template> +<script> +export default { + inheritAttrs: false, + props: ['showFileName'], + data() { + return { + formData: { + fileName: undefined, + type: 'file' + }, + rules: { + fileName: [{ + required: true, + message: '璇疯緭鍏ユ枃浠跺悕', + trigger: 'blur' + }], + type: [{ + required: true, + message: '鐢熸垚绫诲瀷涓嶈兘涓虹┖', + trigger: 'change' + }] + }, + typeOptions: [{ + label: '椤甸潰', + value: 'file' + }, { + label: '寮圭獥', + value: 'dialog' + }] + } + }, + computed: { + }, + watch: {}, + mounted() {}, + methods: { + onOpen() { + if (this.showFileName) { + this.formData.fileName = `${+new Date()}.vue` + } + }, + onClose() { + }, + close(e) { + this.$emit('update:visible', false) + }, + handleConfirm() { + this.$refs.elForm.validate(valid => { + if (!valid) return + this.$emit('confirm', { ...this.formData }) + this.close() + }) + } + } +} +</script> diff --git a/src/views/tool/build/DraggableItem.vue b/src/views/tool/build/DraggableItem.vue new file mode 100644 index 0000000..e881778 --- /dev/null +++ b/src/views/tool/build/DraggableItem.vue @@ -0,0 +1,100 @@ +<script> +import draggable from 'vuedraggable' +import render from '@/utils/generator/render' + +const components = { + itemBtns(h, element, index, parent) { + const { copyItem, deleteItem } = this.$listeners + return [ + <span class="drawing-item-copy" title="澶嶅埗" onClick={event => { + copyItem(element, parent); event.stopPropagation() + }}> + <i class="el-icon-copy-document" /> + </span>, + <span class="drawing-item-delete" title="鍒犻櫎" onClick={event => { + deleteItem(index, parent); event.stopPropagation() + }}> + <i class="el-icon-delete" /> + </span> + ] + } +} +const layouts = { + colFormItem(h, element, index, parent) { + const { activeItem } = this.$listeners + let className = this.activeId === element.formId ? 'drawing-item active-from-item' : 'drawing-item' + if (this.formConf.unFocusedComponentBorder) className += ' unfocus-bordered' + return ( + <el-col span={element.span} class={className} + nativeOnClick={event => { activeItem(element); event.stopPropagation() }}> + <el-form-item label-width={element.labelWidth ? `${element.labelWidth}px` : null} + label={element.label} required={element.required}> + <render key={element.renderKey} conf={element} onInput={ event => { + this.$set(element, 'defaultValue', event) + }} /> + </el-form-item> + {components.itemBtns.apply(this, arguments)} + </el-col> + ) + }, + rowFormItem(h, element, index, parent) { + const { activeItem } = this.$listeners + const className = this.activeId === element.formId ? 'drawing-row-item active-from-item' : 'drawing-row-item' + let child = renderChildren.apply(this, arguments) + if (element.type === 'flex') { + child = <el-row type={element.type} justify={element.justify} align={element.align}> + {child} + </el-row> + } + return ( + <el-col span={element.span}> + <el-row gutter={element.gutter} class={className} + nativeOnClick={event => { activeItem(element); event.stopPropagation() }}> + <span class="component-name">{element.componentName}</span> + <draggable list={element.children} animation={340} group="componentsGroup" class="drag-wrapper"> + {child} + </draggable> + {components.itemBtns.apply(this, arguments)} + </el-row> + </el-col> + ) + } +} + +function renderChildren(h, element, index, parent) { + if (!Array.isArray(element.children)) return null + return element.children.map((el, i) => { + const layout = layouts[el.layout] + if (layout) { + return layout.call(this, h, el, i, element.children) + } + return layoutIsNotFound() + }) +} + +function layoutIsNotFound() { + throw new Error(`娌℃湁涓�${this.element.layout}鍖归厤鐨刲ayout`) +} + +export default { + components: { + render, + draggable + }, + props: [ + 'element', + 'index', + 'drawingList', + 'activeId', + 'formConf' + ], + render(h) { + const layout = layouts[this.element.layout] + + if (layout) { + return layout.call(this, h, this.element, this.index, this.drawingList) + } + return layoutIsNotFound() + } +} +</script> diff --git a/src/views/tool/build/IconsDialog.vue b/src/views/tool/build/IconsDialog.vue new file mode 100644 index 0000000..958be50 --- /dev/null +++ b/src/views/tool/build/IconsDialog.vue @@ -0,0 +1,123 @@ +<template> + <div class="icon-dialog"> + <el-dialog + v-bind="$attrs" + width="980px" + :modal-append-to-body="false" + v-on="$listeners" + @open="onOpen" + @close="onClose" + > + <div slot="title"> + 閫夋嫨鍥炬爣 + <el-input + v-model="key" + size="mini" + :style="{width: '260px'}" + placeholder="璇疯緭鍏ュ浘鏍囧悕绉�" + prefix-icon="el-icon-search" + clearable + /> + </div> + <ul class="icon-ul"> + <li + v-for="icon in iconList" + :key="icon" + :class="active===icon?'active-item':''" + @click="onSelect(icon)" + > + <i :class="icon" /> + <div>{{ icon }}</div> + </li> + </ul> + </el-dialog> + </div> +</template> +<script> +import iconList from '@/utils/generator/icon.json' + +const originList = iconList.map(name => `el-icon-${name}`) + +export default { + inheritAttrs: false, + props: ['current'], + data() { + return { + iconList: originList, + active: null, + key: '' + } + }, + watch: { + key(val) { + if (val) { + this.iconList = originList.filter(name => name.indexOf(val) > -1) + } else { + this.iconList = originList + } + } + }, + methods: { + onOpen() { + this.active = this.current + this.key = '' + }, + onClose() {}, + onSelect(icon) { + this.active = icon + this.$emit('select', icon) + this.$emit('update:visible', false) + } + } +} +</script> +<style lang="scss" scoped> +.icon-ul { + margin: 0; + padding: 0; + font-size: 0; + li { + list-style-type: none; + text-align: center; + font-size: 14px; + display: inline-block; + width: 16.66%; + box-sizing: border-box; + height: 108px; + padding: 15px 6px 6px 6px; + cursor: pointer; + overflow: hidden; + &:hover { + background: #f2f2f2; + } + &.active-item{ + background: #e1f3fb; + color: #7a6df0 + } + > i { + font-size: 30px; + line-height: 50px; + } + } +} +.icon-dialog { + ::v-deep .el-dialog { + border-radius: 8px; + margin-bottom: 0; + margin-top: 4vh !important; + display: flex; + flex-direction: column; + max-height: 92vh; + overflow: hidden; + box-sizing: border-box; + .el-dialog__header { + padding-top: 14px; + } + .el-dialog__body { + margin: 0 20px 20px 20px; + padding: 0; + overflow: auto; + } + } +} +</style> diff --git a/src/views/tool/build/RightPanel.vue b/src/views/tool/build/RightPanel.vue new file mode 100644 index 0000000..c2760eb --- /dev/null +++ b/src/views/tool/build/RightPanel.vue @@ -0,0 +1,946 @@ +<template> + <div class="right-board"> + <el-tabs v-model="currentTab" class="center-tabs"> + <el-tab-pane label="缁勪欢灞炴��" name="field" /> + <el-tab-pane label="琛ㄥ崟灞炴��" name="form" /> + </el-tabs> + <div class="field-box"> + <a class="document-link" target="_blank" :href="documentLink" title="鏌ョ湅缁勪欢鏂囨。"> + <i class="el-icon-link" /> + </a> + <el-scrollbar class="right-scrollbar"> + <!-- 缁勪欢灞炴�� --> + <el-form v-show="currentTab==='field' && showField" size="small" label-width="90px"> + <el-form-item v-if="activeData.changeTag" label="缁勪欢绫诲瀷"> + <el-select + v-model="activeData.tagIcon" + placeholder="璇烽�夋嫨缁勪欢绫诲瀷" + :style="{width: '100%'}" + @change="tagChange" + > + <el-option-group v-for="group in tagList" :key="group.label" :label="group.label"> + <el-option + v-for="item in group.options" + :key="item.label" + :label="item.label" + :value="item.tagIcon" + > + <svg-icon class="node-icon" :icon-class="item.tagIcon" /> + <span> {{ item.label }}</span> + </el-option> + </el-option-group> + </el-select> + </el-form-item> + <el-form-item v-if="activeData.vModel!==undefined" label="瀛楁鍚�"> + <el-input v-model="activeData.vModel" placeholder="璇疯緭鍏ュ瓧娈靛悕锛坴-model锛�" /> + </el-form-item> + <el-form-item v-if="activeData.componentName!==undefined" label="缁勪欢鍚�"> + {{ activeData.componentName }} + </el-form-item> + <el-form-item v-if="activeData.label!==undefined" label="鏍囬"> + <el-input v-model="activeData.label" placeholder="璇疯緭鍏ユ爣棰�" /> + </el-form-item> + <el-form-item v-if="activeData.placeholder!==undefined" label="鍗犱綅鎻愮ず"> + <el-input v-model="activeData.placeholder" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" /> + </el-form-item> + <el-form-item v-if="activeData['start-placeholder']!==undefined" label="寮�濮嬪崰浣�"> + <el-input v-model="activeData['start-placeholder']" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" /> + </el-form-item> + <el-form-item v-if="activeData['end-placeholder']!==undefined" label="缁撴潫鍗犱綅"> + <el-input v-model="activeData['end-placeholder']" placeholder="璇疯緭鍏ュ崰浣嶆彁绀�" /> + </el-form-item> + <el-form-item v-if="activeData.span!==undefined" label="琛ㄥ崟鏍呮牸"> + <el-slider v-model="activeData.span" :max="24" :min="1" :marks="{12:''}" @change="spanChange" /> + </el-form-item> + <el-form-item v-if="activeData.layout==='rowFormItem'" label="鏍呮牸闂撮殧"> + <el-input-number v-model="activeData.gutter" :min="0" placeholder="鏍呮牸闂撮殧" /> + </el-form-item> + <el-form-item v-if="activeData.layout==='rowFormItem'" label="甯冨眬妯″紡"> + <el-radio-group v-model="activeData.type"> + <el-radio-button label="default" /> + <el-radio-button label="flex" /> + </el-radio-group> + </el-form-item> + <el-form-item v-if="activeData.justify!==undefined&&activeData.type==='flex'" label="姘村钩鎺掑垪"> + <el-select v-model="activeData.justify" placeholder="璇烽�夋嫨姘村钩鎺掑垪" :style="{width: '100%'}"> + <el-option + v-for="(item, index) in justifyOptions" + :key="index" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item v-if="activeData.align!==undefined&&activeData.type==='flex'" label="鍨傜洿鎺掑垪"> + <el-radio-group v-model="activeData.align"> + <el-radio-button label="top" /> + <el-radio-button label="middle" /> + <el-radio-button label="bottom" /> + </el-radio-group> + </el-form-item> + <el-form-item v-if="activeData.labelWidth!==undefined" label="鏍囩瀹藉害"> + <el-input v-model.number="activeData.labelWidth" type="number" placeholder="璇疯緭鍏ユ爣绛惧搴�" /> + </el-form-item> + <el-form-item v-if="activeData.style&&activeData.style.width!==undefined" label="缁勪欢瀹藉害"> + <el-input v-model="activeData.style.width" placeholder="璇疯緭鍏ョ粍浠跺搴�" clearable /> + </el-form-item> + <el-form-item v-if="activeData.vModel!==undefined" label="榛樿鍊�"> + <el-input + :value="setDefaultValue(activeData.defaultValue)" + placeholder="璇疯緭鍏ラ粯璁ゅ��" + @input="onDefaultValueInput" + /> + </el-form-item> + <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="鑷冲皯搴旈��"> + <el-input-number + :value="activeData.min" + :min="0" + placeholder="鑷冲皯搴旈��" + @input="$set(activeData, 'min', $event?$event:undefined)" + /> + </el-form-item> + <el-form-item v-if="activeData.tag==='el-checkbox-group'" label="鏈�澶氬彲閫�"> + <el-input-number + :value="activeData.max" + :min="0" + placeholder="鏈�澶氬彲閫�" + @input="$set(activeData, 'max', $event?$event:undefined)" + /> + </el-form-item> + <el-form-item v-if="activeData.prepend!==undefined" label="鍓嶇紑"> + <el-input v-model="activeData.prepend" placeholder="璇疯緭鍏ュ墠缂�" /> + </el-form-item> + <el-form-item v-if="activeData.append!==undefined" label="鍚庣紑"> + <el-input v-model="activeData.append" placeholder="璇疯緭鍏ュ悗缂�" /> + </el-form-item> + <el-form-item v-if="activeData['prefix-icon']!==undefined" label="鍓嶅浘鏍�"> + <el-input v-model="activeData['prefix-icon']" placeholder="璇疯緭鍏ュ墠鍥炬爣鍚嶇О"> + <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('prefix-icon')"> + 閫夋嫨 + </el-button> + </el-input> + </el-form-item> + <el-form-item v-if="activeData['suffix-icon'] !== undefined" label="鍚庡浘鏍�"> + <el-input v-model="activeData['suffix-icon']" placeholder="璇疯緭鍏ュ悗鍥炬爣鍚嶇О"> + <el-button slot="append" icon="el-icon-thumb" @click="openIconsDialog('suffix-icon')"> + 閫夋嫨 + </el-button> + </el-input> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-cascader'" label="閫夐」鍒嗛殧绗�"> + <el-input v-model="activeData.separator" placeholder="璇疯緭鍏ラ�夐」鍒嗛殧绗�" /> + </el-form-item> + <el-form-item v-if="activeData.autosize !== undefined" label="鏈�灏忚鏁�"> + <el-input-number v-model="activeData.autosize.minRows" :min="1" placeholder="鏈�灏忚鏁�" /> + </el-form-item> + <el-form-item v-if="activeData.autosize !== undefined" label="鏈�澶ц鏁�"> + <el-input-number v-model="activeData.autosize.maxRows" :min="1" placeholder="鏈�澶ц鏁�" /> + </el-form-item> + <el-form-item v-if="activeData.min !== undefined" label="鏈�灏忓��"> + <el-input-number v-model="activeData.min" placeholder="鏈�灏忓��" /> + </el-form-item> + <el-form-item v-if="activeData.max !== undefined" label="鏈�澶у��"> + <el-input-number v-model="activeData.max" placeholder="鏈�澶у��" /> + </el-form-item> + <el-form-item v-if="activeData.step !== undefined" label="姝ラ暱"> + <el-input-number v-model="activeData.step" placeholder="姝ユ暟" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-input-number'" label="绮惧害"> + <el-input-number v-model="activeData.precision" :min="0" placeholder="绮惧害" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-input-number'" label="鎸夐挳浣嶇疆"> + <el-radio-group v-model="activeData['controls-position']"> + <el-radio-button label=""> + 榛樿 + </el-radio-button> + <el-radio-button label="right"> + 鍙充晶 + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item v-if="activeData.maxlength !== undefined" label="鏈�澶氳緭鍏�"> + <el-input v-model="activeData.maxlength" placeholder="璇疯緭鍏ュ瓧绗﹂暱搴�"> + <template slot="append"> + 涓瓧绗� + </template> + </el-input> + </el-form-item> + <el-form-item v-if="activeData['active-text'] !== undefined" label="寮�鍚彁绀�"> + <el-input v-model="activeData['active-text']" placeholder="璇疯緭鍏ュ紑鍚彁绀�" /> + </el-form-item> + <el-form-item v-if="activeData['inactive-text'] !== undefined" label="鍏抽棴鎻愮ず"> + <el-input v-model="activeData['inactive-text']" placeholder="璇疯緭鍏ュ叧闂彁绀�" /> + </el-form-item> + <el-form-item v-if="activeData['active-value'] !== undefined" label="寮�鍚��"> + <el-input + :value="setDefaultValue(activeData['active-value'])" + placeholder="璇疯緭鍏ュ紑鍚��" + @input="onSwitchValueInput($event, 'active-value')" + /> + </el-form-item> + <el-form-item v-if="activeData['inactive-value'] !== undefined" label="鍏抽棴鍊�"> + <el-input + :value="setDefaultValue(activeData['inactive-value'])" + placeholder="璇疯緭鍏ュ叧闂��" + @input="onSwitchValueInput($event, 'inactive-value')" + /> + </el-form-item> + <el-form-item + v-if="activeData.type !== undefined && 'el-date-picker' === activeData.tag" + label="鏃堕棿绫诲瀷" + > + <el-select + v-model="activeData.type" + placeholder="璇烽�夋嫨鏃堕棿绫诲瀷" + :style="{ width: '100%' }" + @change="dateTypeChange" + > + <el-option + v-for="(item, index) in dateOptions" + :key="index" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item v-if="activeData.name !== undefined" label="鏂囦欢瀛楁鍚�"> + <el-input v-model="activeData.name" placeholder="璇疯緭鍏ヤ笂浼犳枃浠跺瓧娈靛悕" /> + </el-form-item> + <el-form-item v-if="activeData.accept !== undefined" label="鏂囦欢绫诲瀷"> + <el-select + v-model="activeData.accept" + placeholder="璇烽�夋嫨鏂囦欢绫诲瀷" + :style="{ width: '100%' }" + clearable + > + <el-option label="鍥剧墖" value="image/*" /> + <el-option label="瑙嗛" value="video/*" /> + <el-option label="闊抽" value="audio/*" /> + <el-option label="excel" value=".xls,.xlsx" /> + <el-option label="word" value=".doc,.docx" /> + <el-option label="pdf" value=".pdf" /> + <el-option label="txt" value=".txt" /> + </el-select> + </el-form-item> + <el-form-item v-if="activeData.fileSize !== undefined" label="鏂囦欢澶у皬"> + <el-input v-model.number="activeData.fileSize" placeholder="璇疯緭鍏ユ枃浠跺ぇ灏�"> + <el-select slot="append" v-model="activeData.sizeUnit" :style="{ width: '66px' }"> + <el-option label="KB" value="KB" /> + <el-option label="MB" value="MB" /> + <el-option label="GB" value="GB" /> + </el-select> + </el-input> + </el-form-item> + <el-form-item v-if="activeData.action !== undefined" label="涓婁紶鍦板潃"> + <el-input v-model="activeData.action" placeholder="璇疯緭鍏ヤ笂浼犲湴鍧�" clearable /> + </el-form-item> + <el-form-item v-if="activeData['list-type'] !== undefined" label="鍒楄〃绫诲瀷"> + <el-radio-group v-model="activeData['list-type']" size="small"> + <el-radio-button label="text"> + text + </el-radio-button> + <el-radio-button label="picture"> + picture + </el-radio-button> + <el-radio-button label="picture-card"> + picture-card + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item + v-if="activeData.buttonText !== undefined" + v-show="'picture-card' !== activeData['list-type']" + label="鎸夐挳鏂囧瓧" + > + <el-input v-model="activeData.buttonText" placeholder="璇疯緭鍏ユ寜閽枃瀛�" /> + </el-form-item> + <el-form-item v-if="activeData['range-separator'] !== undefined" label="鍒嗛殧绗�"> + <el-input v-model="activeData['range-separator']" placeholder="璇疯緭鍏ュ垎闅旂" /> + </el-form-item> + <el-form-item v-if="activeData['picker-options'] !== undefined" label="鏃堕棿娈�"> + <el-input + v-model="activeData['picker-options'].selectableRange" + placeholder="璇疯緭鍏ユ椂闂存" + /> + </el-form-item> + <el-form-item v-if="activeData.format !== undefined" label="鏃堕棿鏍煎紡"> + <el-input + :value="activeData.format" + placeholder="璇疯緭鍏ユ椂闂存牸寮�" + @input="setTimeValue($event)" + /> + </el-form-item> + <template v-if="['el-checkbox-group', 'el-radio-group', 'el-select'].indexOf(activeData.tag) > -1"> + <el-divider>閫夐」</el-divider> + <draggable + :list="activeData.options" + :animation="340" + group="selectItem" + handle=".option-drag" + > + <div v-for="(item, index) in activeData.options" :key="index" class="select-item"> + <div class="select-line-icon option-drag"> + <i class="el-icon-s-operation" /> + </div> + <el-input v-model="item.label" placeholder="閫夐」鍚�" size="small" /> + <el-input + placeholder="閫夐」鍊�" + size="small" + :value="item.value" + @input="setOptionValue(item, $event)" + /> + <div class="close-btn select-line-icon" @click="activeData.options.splice(index, 1)"> + <i class="el-icon-remove-outline" /> + </div> + </div> + </draggable> + <div style="margin-left: 20px;"> + <el-button + style="padding-bottom: 0" + icon="el-icon-circle-plus-outline" + type="text" + @click="addSelectItem" + > + 娣诲姞閫夐」 + </el-button> + </div> + <el-divider /> + </template> + + <template v-if="['el-cascader'].indexOf(activeData.tag) > -1"> + <el-divider>閫夐」</el-divider> + <el-form-item label="鏁版嵁绫诲瀷"> + <el-radio-group v-model="activeData.dataType" size="small"> + <el-radio-button label="dynamic"> + 鍔ㄦ�佹暟鎹� + </el-radio-button> + <el-radio-button label="static"> + 闈欐�佹暟鎹� + </el-radio-button> + </el-radio-group> + </el-form-item> + + <template v-if="activeData.dataType === 'dynamic'"> + <el-form-item label="鏍囩閿悕"> + <el-input v-model="activeData.labelKey" placeholder="璇疯緭鍏ユ爣绛鹃敭鍚�" /> + </el-form-item> + <el-form-item label="鍊奸敭鍚�"> + <el-input v-model="activeData.valueKey" placeholder="璇疯緭鍏ュ�奸敭鍚�" /> + </el-form-item> + <el-form-item label="瀛愮骇閿悕"> + <el-input v-model="activeData.childrenKey" placeholder="璇疯緭鍏ュ瓙绾ч敭鍚�" /> + </el-form-item> + </template> + + <el-tree + v-if="activeData.dataType === 'static'" + draggable + :data="activeData.options" + node-key="id" + :expand-on-click-node="false" + :render-content="renderContent" + /> + <div v-if="activeData.dataType === 'static'" style="margin-left: 20px"> + <el-button + style="padding-bottom: 0" + icon="el-icon-circle-plus-outline" + type="text" + @click="addTreeItem" + > + 娣诲姞鐖剁骇 + </el-button> + </div> + <el-divider /> + </template> + + <el-form-item v-if="activeData.optionType !== undefined" label="閫夐」鏍峰紡"> + <el-radio-group v-model="activeData.optionType"> + <el-radio-button label="default"> + 榛樿 + </el-radio-button> + <el-radio-button label="button"> + 鎸夐挳 + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item v-if="activeData['active-color'] !== undefined" label="寮�鍚鑹�"> + <el-color-picker v-model="activeData['active-color']" /> + </el-form-item> + <el-form-item v-if="activeData['inactive-color'] !== undefined" label="鍏抽棴棰滆壊"> + <el-color-picker v-model="activeData['inactive-color']" /> + </el-form-item> + + <el-form-item v-if="activeData['allow-half'] !== undefined" label="鍏佽鍗婇��"> + <el-switch v-model="activeData['allow-half']" /> + </el-form-item> + <el-form-item v-if="activeData['show-text'] !== undefined" label="杈呭姪鏂囧瓧"> + <el-switch v-model="activeData['show-text']" @change="rateTextChange" /> + </el-form-item> + <el-form-item v-if="activeData['show-score'] !== undefined" label="鏄剧ず鍒嗘暟"> + <el-switch v-model="activeData['show-score']" @change="rateScoreChange" /> + </el-form-item> + <el-form-item v-if="activeData['show-stops'] !== undefined" label="鏄剧ず闂存柇鐐�"> + <el-switch v-model="activeData['show-stops']" /> + </el-form-item> + <el-form-item v-if="activeData.range !== undefined" label="鑼冨洿閫夋嫨"> + <el-switch v-model="activeData.range" @change="rangeChange" /> + </el-form-item> + <el-form-item + v-if="activeData.border !== undefined && activeData.optionType === 'default'" + label="鏄惁甯﹁竟妗�" + > + <el-switch v-model="activeData.border" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-color-picker'" label="棰滆壊鏍煎紡"> + <el-select + v-model="activeData['color-format']" + placeholder="璇烽�夋嫨棰滆壊鏍煎紡" + :style="{ width: '100%' }" + @change="colorFormatChange" + > + <el-option + v-for="(item, index) in colorFormatOptions" + :key="index" + :label="item.label" + :value="item.value" + /> + </el-select> + </el-form-item> + <el-form-item + v-if="activeData.size !== undefined && + (activeData.optionType === 'button' || + activeData.border || + activeData.tag === 'el-color-picker')" + label="閫夐」灏哄" + > + <el-radio-group v-model="activeData.size"> + <el-radio-button label="medium"> + 涓瓑 + </el-radio-button> + <el-radio-button label="small"> + 杈冨皬 + </el-radio-button> + <el-radio-button label="mini"> + 杩蜂綘 + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item v-if="activeData['show-word-limit'] !== undefined" label="杈撳叆缁熻"> + <el-switch v-model="activeData['show-word-limit']" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-input-number'" label="涓ユ牸姝ユ暟"> + <el-switch v-model="activeData['step-strictly']" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-cascader'" label="鏄惁澶氶��"> + <el-switch v-model="activeData.props.props.multiple" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-cascader'" label="灞曠ず鍏ㄨ矾寰�"> + <el-switch v-model="activeData['show-all-levels']" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-cascader'" label="鍙惁绛涢��"> + <el-switch v-model="activeData.filterable" /> + </el-form-item> + <el-form-item v-if="activeData.clearable !== undefined" label="鑳藉惁娓呯┖"> + <el-switch v-model="activeData.clearable" /> + </el-form-item> + <el-form-item v-if="activeData.showTip !== undefined" label="鏄剧ず鎻愮ず"> + <el-switch v-model="activeData.showTip" /> + </el-form-item> + <el-form-item v-if="activeData.multiple !== undefined" label="澶氶�夋枃浠�"> + <el-switch v-model="activeData.multiple" /> + </el-form-item> + <el-form-item v-if="activeData['auto-upload'] !== undefined" label="鑷姩涓婁紶"> + <el-switch v-model="activeData['auto-upload']" /> + </el-form-item> + <el-form-item v-if="activeData.readonly !== undefined" label="鏄惁鍙"> + <el-switch v-model="activeData.readonly" /> + </el-form-item> + <el-form-item v-if="activeData.disabled !== undefined" label="鏄惁绂佺敤"> + <el-switch v-model="activeData.disabled" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-select'" label="鏄惁鍙悳绱�"> + <el-switch v-model="activeData.filterable" /> + </el-form-item> + <el-form-item v-if="activeData.tag === 'el-select'" label="鏄惁澶氶��"> + <el-switch v-model="activeData.multiple" @change="multipleChange" /> + </el-form-item> + <el-form-item v-if="activeData.required !== undefined" label="鏄惁蹇呭~"> + <el-switch v-model="activeData.required" /> + </el-form-item> + + <template v-if="activeData.layoutTree"> + <el-divider>甯冨眬缁撴瀯鏍�</el-divider> + <el-tree + :data="[activeData]" + :props="layoutTreeProps" + node-key="renderKey" + default-expand-all + draggable + > + <span slot-scope="{ node, data }"> + <span class="node-label"> + <svg-icon class="node-icon" :icon-class="data.tagIcon" /> + {{ node.label }} + </span> + </span> + </el-tree> + </template> + + <template v-if="activeData.layout === 'colFormItem' && activeData.tag !== 'el-button'"> + <el-divider>姝e垯鏍¢獙</el-divider> + <div + v-for="(item, index) in activeData.regList" + :key="index" + class="reg-item" + > + <span class="close-btn" @click="activeData.regList.splice(index, 1)"> + <i class="el-icon-close" /> + </span> + <el-form-item label="琛ㄨ揪寮�"> + <el-input v-model="item.pattern" placeholder="璇疯緭鍏ユ鍒�" /> + </el-form-item> + <el-form-item label="閿欒鎻愮ず" style="margin-bottom:0"> + <el-input v-model="item.message" placeholder="璇疯緭鍏ラ敊璇彁绀�" /> + </el-form-item> + </div> + <div style="margin-left: 20px"> + <el-button icon="el-icon-circle-plus-outline" type="text" @click="addReg"> + 娣诲姞瑙勫垯 + </el-button> + </div> + </template> + </el-form> + <!-- 琛ㄥ崟灞炴�� --> + <el-form v-show="currentTab === 'form'" size="small" label-width="90px"> + <el-form-item label="琛ㄥ崟鍚�"> + <el-input v-model="formConf.formRef" placeholder="璇疯緭鍏ヨ〃鍗曞悕锛坮ef锛�" /> + </el-form-item> + <el-form-item label="琛ㄥ崟妯″瀷"> + <el-input v-model="formConf.formModel" placeholder="璇疯緭鍏ユ暟鎹ā鍨�" /> + </el-form-item> + <el-form-item label="鏍¢獙妯″瀷"> + <el-input v-model="formConf.formRules" placeholder="璇疯緭鍏ユ牎楠屾ā鍨�" /> + </el-form-item> + <el-form-item label="琛ㄥ崟灏哄"> + <el-radio-group v-model="formConf.size"> + <el-radio-button label="medium"> + 涓瓑 + </el-radio-button> + <el-radio-button label="small"> + 杈冨皬 + </el-radio-button> + <el-radio-button label="mini"> + 杩蜂綘 + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item label="鏍囩瀵归綈"> + <el-radio-group v-model="formConf.labelPosition"> + <el-radio-button label="left"> + 宸﹀榻� + </el-radio-button> + <el-radio-button label="right"> + 鍙冲榻� + </el-radio-button> + <el-radio-button label="top"> + 椤堕儴瀵归綈 + </el-radio-button> + </el-radio-group> + </el-form-item> + <el-form-item label="鏍囩瀹藉害"> + <el-input-number v-model="formConf.labelWidth" placeholder="鏍囩瀹藉害" /> + </el-form-item> + <el-form-item label="鏍呮牸闂撮殧"> + <el-input-number v-model="formConf.gutter" :min="0" placeholder="鏍呮牸闂撮殧" /> + </el-form-item> + <el-form-item label="绂佺敤琛ㄥ崟"> + <el-switch v-model="formConf.disabled" /> + </el-form-item> + <el-form-item label="琛ㄥ崟鎸夐挳"> + <el-switch v-model="formConf.formBtns" /> + </el-form-item> + <el-form-item label="鏄剧ず鏈�変腑缁勪欢杈规"> + <el-switch v-model="formConf.unFocusedComponentBorder" /> + </el-form-item> + </el-form> + </el-scrollbar> + </div> + + <treeNode-dialog :visible.sync="dialogVisible" title="娣诲姞閫夐」" @commit="addNode" /> + <icons-dialog :visible.sync="iconsVisible" :current="activeData[currentIconModel]" @select="setIcon" /> + </div> +</template> + +<script> +import { isArray } from 'util' +import draggable from 'vuedraggable' +import TreeNodeDialog from './TreeNodeDialog' +import { isNumberStr } from '@/utils/index' +import IconsDialog from './IconsDialog' +import { + inputComponents, + selectComponents, + layoutComponents +} from '@/utils/generator/config' + +const dateTimeFormat = { + date: 'yyyy-MM-dd', + week: 'yyyy 绗� WW 鍛�', + month: 'yyyy-MM', + year: 'yyyy', + datetime: 'yyyy-MM-dd HH:mm:ss', + daterange: 'yyyy-MM-dd', + monthrange: 'yyyy-MM', + datetimerange: 'yyyy-MM-dd HH:mm:ss' +} + +export default { + components: { + draggable, + TreeNodeDialog, + IconsDialog + }, + props: ['showField', 'activeData', 'formConf'], + data() { + return { + currentTab: 'field', + currentNode: null, + dialogVisible: false, + iconsVisible: false, + currentIconModel: null, + dateTypeOptions: [ + { + label: '鏃�(date)', + value: 'date' + }, + { + label: '鍛�(week)', + value: 'week' + }, + { + label: '鏈�(month)', + value: 'month' + }, + { + label: '骞�(year)', + value: 'year' + }, + { + label: '鏃ユ湡鏃堕棿(datetime)', + value: 'datetime' + } + ], + dateRangeTypeOptions: [ + { + label: '鏃ユ湡鑼冨洿(daterange)', + value: 'daterange' + }, + { + label: '鏈堣寖鍥�(monthrange)', + value: 'monthrange' + }, + { + label: '鏃ユ湡鏃堕棿鑼冨洿(datetimerange)', + value: 'datetimerange' + } + ], + colorFormatOptions: [ + { + label: 'hex', + value: 'hex' + }, + { + label: 'rgb', + value: 'rgb' + }, + { + label: 'rgba', + value: 'rgba' + }, + { + label: 'hsv', + value: 'hsv' + }, + { + label: 'hsl', + value: 'hsl' + } + ], + justifyOptions: [ + { + label: 'start', + value: 'start' + }, + { + label: 'end', + value: 'end' + }, + { + label: 'center', + value: 'center' + }, + { + label: 'space-around', + value: 'space-around' + }, + { + label: 'space-between', + value: 'space-between' + } + ], + layoutTreeProps: { + label(data, node) { + return data.componentName || `${data.label}: ${data.vModel}` + } + } + } + }, + computed: { + documentLink() { + return ( + this.activeData.document + || 'https://element.eleme.cn/#/zh-CN/component/installation' + ) + }, + dateOptions() { + if ( + this.activeData.type !== undefined + && this.activeData.tag === 'el-date-picker' + ) { + if (this.activeData['start-placeholder'] === undefined) { + return this.dateTypeOptions + } + return this.dateRangeTypeOptions + } + return [] + }, + tagList() { + return [ + { + label: '杈撳叆鍨嬬粍浠�', + options: inputComponents + }, + { + label: '閫夋嫨鍨嬬粍浠�', + options: selectComponents + } + ] + } + }, + methods: { + addReg() { + this.activeData.regList.push({ + pattern: '', + message: '' + }) + }, + addSelectItem() { + this.activeData.options.push({ + label: '', + value: '' + }) + }, + addTreeItem() { + ++this.idGlobal + this.dialogVisible = true + this.currentNode = this.activeData.options + }, + renderContent(h, { node, data, store }) { + return ( + <div class="custom-tree-node"> + <span>{node.label}</span> + <span class="node-operation"> + <i on-click={() => this.append(data)} + class="el-icon-plus" + title="娣诲姞" + ></i> + <i on-click={() => this.remove(node, data)} + class="el-icon-delete" + title="鍒犻櫎" + ></i> + </span> + </div> + ) + }, + append(data) { + if (!data.children) { + this.$set(data, 'children', []) + } + this.dialogVisible = true + this.currentNode = data.children + }, + remove(node, data) { + const { parent } = node + const children = parent.data.children || parent.data + const index = children.findIndex(d => d.id === data.id) + children.splice(index, 1) + }, + addNode(data) { + this.currentNode.push(data) + }, + setOptionValue(item, val) { + item.value = isNumberStr(val) ? +val : val + }, + setDefaultValue(val) { + if (Array.isArray(val)) { + return val.join(',') + } + if (['string', 'number'].indexOf(val) > -1) { + return val + } + if (typeof val === 'boolean') { + return `${val}` + } + return val + }, + onDefaultValueInput(str) { + if (isArray(this.activeData.defaultValue)) { + // 鏁扮粍 + this.$set( + this.activeData, + 'defaultValue', + str.split(',').map(val => (isNumberStr(val) ? +val : val)) + ) + } else if (['true', 'false'].indexOf(str) > -1) { + // 甯冨皵 + this.$set(this.activeData, 'defaultValue', JSON.parse(str)) + } else { + // 瀛楃涓插拰鏁板瓧 + this.$set( + this.activeData, + 'defaultValue', + isNumberStr(str) ? +str : str + ) + } + }, + onSwitchValueInput(val, name) { + if (['true', 'false'].indexOf(val) > -1) { + this.$set(this.activeData, name, JSON.parse(val)) + } else { + this.$set(this.activeData, name, isNumberStr(val) ? +val : val) + } + }, + setTimeValue(val, type) { + const valueFormat = type === 'week' ? dateTimeFormat.date : val + this.$set(this.activeData, 'defaultValue', null) + this.$set(this.activeData, 'value-format', valueFormat) + this.$set(this.activeData, 'format', val) + }, + spanChange(val) { + this.formConf.span = val + }, + multipleChange(val) { + this.$set(this.activeData, 'defaultValue', val ? [] : '') + }, + dateTypeChange(val) { + this.setTimeValue(dateTimeFormat[val], val) + }, + rangeChange(val) { + this.$set( + this.activeData, + 'defaultValue', + val ? [this.activeData.min, this.activeData.max] : this.activeData.min + ) + }, + rateTextChange(val) { + if (val) this.activeData['show-score'] = false + }, + rateScoreChange(val) { + if (val) this.activeData['show-text'] = false + }, + colorFormatChange(val) { + this.activeData.defaultValue = null + this.activeData['show-alpha'] = val.indexOf('a') > -1 + this.activeData.renderKey = +new Date() // 鏇存柊renderKey,閲嶆柊娓叉煋璇ョ粍浠� + }, + openIconsDialog(model) { + this.iconsVisible = true + this.currentIconModel = model + }, + setIcon(val) { + this.activeData[this.currentIconModel] = val + }, + tagChange(tagIcon) { + let target = inputComponents.find(item => item.tagIcon === tagIcon) + if (!target) target = selectComponents.find(item => item.tagIcon === tagIcon) + this.$emit('tag-change', target) + } + } +} +</script> + +<style lang="scss" scoped> +.right-board { + width: 350px; + position: absolute; + right: 0; + top: 0; + padding-top: 3px; + .field-box { + position: relative; + height: calc(100vh - 42px); + box-sizing: border-box; + overflow: hidden; + } + .el-scrollbar { + height: 100%; + } +} +.select-item { + display: flex; + border: 1px dashed #fff; + box-sizing: border-box; + & .close-btn { + cursor: pointer; + color: #f56c6c; + } + & .el-input + .el-input { + margin-left: 4px; + } +} +.select-item + .select-item { + margin-top: 4px; +} +.select-item.sortable-chosen { + border: 1px dashed #409eff; +} +.select-line-icon { + line-height: 32px; + font-size: 22px; + padding: 0 4px; + color: #777; +} +.option-drag { + cursor: move; +} +.time-range { + .el-date-editor { + width: 227px; + } + ::v-deep .el-icon-time { + display: none; + } +} +.document-link { + position: absolute; + display: block; + width: 26px; + height: 26px; + top: 0; + left: 0; + cursor: pointer; + background: #409eff; + z-index: 1; + border-radius: 0 0 6px 0; + text-align: center; + line-height: 26px; + color: #fff; + font-size: 18px; +} +.node-label{ + font-size: 14px; +} +.node-icon{ + color: #bebfc3; +} +</style> diff --git a/src/views/tool/build/TreeNodeDialog.vue b/src/views/tool/build/TreeNodeDialog.vue new file mode 100644 index 0000000..fa7f0b2 --- /dev/null +++ b/src/views/tool/build/TreeNodeDialog.vue @@ -0,0 +1,149 @@ +<template> + <div> + <el-dialog + v-bind="$attrs" + :close-on-click-modal="false" + :modal-append-to-body="false" + v-on="$listeners" + @open="onOpen" + @close="onClose" + > + <el-row :gutter="0"> + <el-form + ref="elForm" + :model="formData" + :rules="rules" + size="small" + label-width="100px" + > + <el-col :span="24"> + <el-form-item + label="閫夐」鍚�" + prop="label" + > + <el-input + v-model="formData.label" + placeholder="璇疯緭鍏ラ�夐」鍚�" + clearable + /> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item + label="閫夐」鍊�" + prop="value" + > + <el-input + v-model="formData.value" + placeholder="璇疯緭鍏ラ�夐」鍊�" + clearable + > + <el-select + slot="append" + v-model="dataType" + :style="{width: '100px'}" + > + <el-option + v-for="(item, index) in dataTypeOptions" + :key="index" + :label="item.label" + :value="item.value" + :disabled="item.disabled" + /> + </el-select> + </el-input> + </el-form-item> + </el-col> + </el-form> + </el-row> + <div slot="footer"> + <el-button + type="primary" + @click="handleConfirm" + > + 纭畾 + </el-button> + <el-button @click="close"> + 鍙栨秷 + </el-button> + </div> + </el-dialog> + </div> +</template> +<script> +import { isNumberStr } from '@/utils/index' + +export default { + components: {}, + inheritAttrs: false, + props: [], + data() { + return { + id: 100, + formData: { + label: undefined, + value: undefined + }, + rules: { + label: [ + { + required: true, + message: '璇疯緭鍏ラ�夐」鍚�', + trigger: 'blur' + } + ], + value: [ + { + required: true, + message: '璇疯緭鍏ラ�夐」鍊�', + trigger: 'blur' + } + ] + }, + dataType: 'string', + dataTypeOptions: [ + { + label: '瀛楃涓�', + value: 'string' + }, + { + label: '鏁板瓧', + value: 'number' + } + ] + } + }, + computed: {}, + watch: { + // eslint-disable-next-line func-names + 'formData.value': function (val) { + this.dataType = isNumberStr(val) ? 'number' : 'string' + } + }, + created() {}, + mounted() {}, + methods: { + onOpen() { + this.formData = { + label: undefined, + value: undefined + } + }, + onClose() {}, + close() { + this.$emit('update:visible', false) + }, + handleConfirm() { + this.$refs.elForm.validate(valid => { + if (!valid) return + if (this.dataType === 'number') { + this.formData.value = parseFloat(this.formData.value) + } + this.formData.id = this.id++ + this.$emit('commit', this.formData) + this.close() + }) + } + } +} +</script> diff --git a/src/views/tool/build/index.vue b/src/views/tool/build/index.vue new file mode 100644 index 0000000..2bd298b --- /dev/null +++ b/src/views/tool/build/index.vue @@ -0,0 +1,768 @@ +<template> + <div class="container"> + <div class="left-board"> + <div class="logo-wrapper"> + <div class="logo"> + <img :src="logo" alt="logo"> Form Generator + </div> + </div> + <el-scrollbar class="left-scrollbar"> + <div class="components-list"> + <div class="components-title"> + <svg-icon icon-class="component" />杈撳叆鍨嬬粍浠� + </div> + <draggable + class="components-draggable" + :list="inputComponents" + :group="{ name: 'componentsGroup', pull: 'clone', put: false }" + :clone="cloneComponent" + draggable=".components-item" + :sort="false" + @end="onEnd" + > + <div + v-for="(element, index) in inputComponents" :key="index" class="components-item" + @click="addComponent(element)" + > + <div class="components-body"> + <svg-icon :icon-class="element.tagIcon" /> + {{ element.label }} + </div> + </div> + </draggable> + <div class="components-title"> + <svg-icon icon-class="component" />閫夋嫨鍨嬬粍浠� + </div> + <draggable + class="components-draggable" + :list="selectComponents" + :group="{ name: 'componentsGroup', pull: 'clone', put: false }" + :clone="cloneComponent" + draggable=".components-item" + :sort="false" + @end="onEnd" + > + <div + v-for="(element, index) in selectComponents" + :key="index" + class="components-item" + @click="addComponent(element)" + > + <div class="components-body"> + <svg-icon :icon-class="element.tagIcon" /> + {{ element.label }} + </div> + </div> + </draggable> + <div class="components-title"> + <svg-icon icon-class="component" /> 甯冨眬鍨嬬粍浠� + </div> + <draggable + class="components-draggable" :list="layoutComponents" + :group="{ name: 'componentsGroup', pull: 'clone', put: false }" :clone="cloneComponent" + draggable=".components-item" :sort="false" @end="onEnd" + > + <div + v-for="(element, index) in layoutComponents" :key="index" class="components-item" + @click="addComponent(element)" + > + <div class="components-body"> + <svg-icon :icon-class="element.tagIcon" /> + {{ element.label }} + </div> + </div> + </draggable> + </div> + </el-scrollbar> + </div> + + <div class="center-board"> + <div class="action-bar"> + <el-button icon="el-icon-download" type="text" @click="download"> + 瀵煎嚭vue鏂囦欢 + </el-button> + <el-button class="copy-btn-main" icon="el-icon-document-copy" type="text" @click="copy"> + 澶嶅埗浠g爜 + </el-button> + <el-button class="delete-btn" icon="el-icon-delete" type="text" @click="empty"> + 娓呯┖ + </el-button> + </div> + <el-scrollbar class="center-scrollbar"> + <el-row class="center-board-row" :gutter="formConf.gutter"> + <el-form + :size="formConf.size" + :label-position="formConf.labelPosition" + :disabled="formConf.disabled" + :label-width="formConf.labelWidth + 'px'" + > + <draggable class="drawing-board" :list="drawingList" :animation="340" group="componentsGroup"> + <draggable-item + v-for="(element, index) in drawingList" + :key="element.renderKey" + :drawing-list="drawingList" + :element="element" + :index="index" + :active-id="activeId" + :form-conf="formConf" + @activeItem="activeFormItem" + @copyItem="drawingItemCopy" + @deleteItem="drawingItemDelete" + /> + </draggable> + <div v-show="!drawingList.length" class="empty-info"> + 浠庡乏渚ф嫋鍏ユ垨鐐归�夌粍浠惰繘琛岃〃鍗曡璁� + </div> + </el-form> + </el-row> + </el-scrollbar> + </div> + + <right-panel + :active-data="activeData" + :form-conf="formConf" + :show-field="!!drawingList.length" + @tag-change="tagChange" + /> + + <code-type-dialog + :visible.sync="dialogVisible" + title="閫夋嫨鐢熸垚绫诲瀷" + :show-file-name="showFileName" + @confirm="generate" + /> + <input id="copyNode" type="hidden"> + </div> +</template> + +<script> +import draggable from 'vuedraggable' +import beautifier from 'js-beautify' +import ClipboardJS from 'clipboard' +import render from '@/utils/generator/render' +import RightPanel from './RightPanel' +import { inputComponents, selectComponents, layoutComponents, formConf } from '@/utils/generator/config' +import { beautifierConf, titleCase } from '@/utils/index' +import { makeUpHtml, vueTemplate, vueScript, cssStyle } from '@/utils/generator/html' +import { makeUpJs } from '@/utils/generator/js' +import { makeUpCss } from '@/utils/generator/css' +import drawingDefault from '@/utils/generator/drawingDefault' +import logo from '@/assets/logo/logo.png' +import CodeTypeDialog from './CodeTypeDialog' +import DraggableItem from './DraggableItem' + +let oldActiveId +let tempActiveData + +export default { + components: { + draggable, + render, + RightPanel, + CodeTypeDialog, + DraggableItem + }, + data() { + return { + logo, + idGlobal: 100, + formConf, + inputComponents, + selectComponents, + layoutComponents, + labelWidth: 100, + drawingList: drawingDefault, + drawingData: {}, + activeId: drawingDefault[0].formId, + drawerVisible: false, + formData: {}, + dialogVisible: false, + generateConf: null, + showFileName: false, + activeData: drawingDefault[0] + } + }, + created() { + // 闃叉 firefox 涓� 鎷栨嫿 浼氭柊鎵撳崱涓�涓�夐」鍗� + document.body.ondrop = event => { + event.preventDefault() + event.stopPropagation() + } + }, + watch: { + // eslint-disable-next-line func-names + 'activeData.label': function (val, oldVal) { + if ( + this.activeData.placeholder === undefined + || !this.activeData.tag + || oldActiveId !== this.activeId + ) { + return + } + this.activeData.placeholder = this.activeData.placeholder.replace(oldVal, '') + val + }, + activeId: { + handler(val) { + oldActiveId = val + }, + immediate: true + } + }, + mounted() { + const clipboard = new ClipboardJS('#copyNode', { + text: trigger => { + const codeStr = this.generateCode() + this.$notify({ + title: '鎴愬姛', + message: '浠g爜宸插鍒跺埌鍓垏鏉匡紝鍙矘璐淬��', + type: 'success' + }) + return codeStr + } + }) + clipboard.on('error', e => { + this.$message.error('浠g爜澶嶅埗澶辫触') + }) + }, + methods: { + activeFormItem(element) { + this.activeData = element + this.activeId = element.formId + }, + onEnd(obj, a) { + if (obj.from !== obj.to) { + this.activeData = tempActiveData + this.activeId = this.idGlobal + } + }, + addComponent(item) { + const clone = this.cloneComponent(item) + this.drawingList.push(clone) + this.activeFormItem(clone) + }, + cloneComponent(origin) { + const clone = JSON.parse(JSON.stringify(origin)) + clone.formId = ++this.idGlobal + clone.span = formConf.span + clone.renderKey = +new Date() // 鏀瑰彉renderKey鍚庡彲浠ュ疄鐜板己鍒舵洿鏂扮粍浠� + if (!clone.layout) clone.layout = 'colFormItem' + if (clone.layout === 'colFormItem') { + clone.vModel = `field${this.idGlobal}` + clone.placeholder !== undefined && (clone.placeholder += clone.label) + tempActiveData = clone + } else if (clone.layout === 'rowFormItem') { + delete clone.label + clone.componentName = `row${this.idGlobal}` + clone.gutter = this.formConf.gutter + tempActiveData = clone + } + return tempActiveData + }, + AssembleFormData() { + this.formData = { + fields: JSON.parse(JSON.stringify(this.drawingList)), + ...this.formConf + } + }, + generate(data) { + const func = this[`exec${titleCase(this.operationType)}`] + this.generateConf = data + func && func(data) + }, + execRun(data) { + this.AssembleFormData() + this.drawerVisible = true + }, + execDownload(data) { + const codeStr = this.generateCode() + const blob = new Blob([codeStr], { type: 'text/plain;charset=utf-8' }) + this.$download.saveAs(blob, data.fileName) + }, + execCopy(data) { + document.getElementById('copyNode').click() + }, + empty() { + this.$confirm('纭畾瑕佹竻绌烘墍鏈夌粍浠跺悧锛�', '鎻愮ず', { type: 'warning' }).then( + () => { + this.drawingList = [] + } + ) + }, + drawingItemCopy(item, parent) { + let clone = JSON.parse(JSON.stringify(item)) + clone = this.createIdAndKey(clone) + parent.push(clone) + this.activeFormItem(clone) + }, + createIdAndKey(item) { + item.formId = ++this.idGlobal + item.renderKey = +new Date() + if (item.layout === 'colFormItem') { + item.vModel = `field${this.idGlobal}` + } else if (item.layout === 'rowFormItem') { + item.componentName = `row${this.idGlobal}` + } + if (Array.isArray(item.children)) { + item.children = item.children.map(childItem => this.createIdAndKey(childItem)) + } + return item + }, + drawingItemDelete(index, parent) { + parent.splice(index, 1) + this.$nextTick(() => { + const len = this.drawingList.length + if (len) { + this.activeFormItem(this.drawingList[len - 1]) + } + }) + }, + generateCode() { + const { type } = this.generateConf + this.AssembleFormData() + const script = vueScript(makeUpJs(this.formData, type)) + const html = vueTemplate(makeUpHtml(this.formData, type)) + const css = cssStyle(makeUpCss(this.formData)) + return beautifier.html(html + script + css, beautifierConf.html) + }, + download() { + this.dialogVisible = true + this.showFileName = true + this.operationType = 'download' + }, + run() { + this.dialogVisible = true + this.showFileName = false + this.operationType = 'run' + }, + copy() { + this.dialogVisible = true + this.showFileName = false + this.operationType = 'copy' + }, + tagChange(newTag) { + newTag = this.cloneComponent(newTag) + newTag.vModel = this.activeData.vModel + newTag.formId = this.activeId + newTag.span = this.activeData.span + delete this.activeData.tag + delete this.activeData.tagIcon + delete this.activeData.document + Object.keys(newTag).forEach(key => { + if (this.activeData[key] !== undefined + && typeof this.activeData[key] === typeof newTag[key]) { + newTag[key] = this.activeData[key] + } + }) + this.activeData = newTag + this.updateDrawingList(newTag, this.drawingList) + }, + updateDrawingList(newTag, list) { + const index = list.findIndex(item => item.formId === this.activeId) + if (index > -1) { + list.splice(index, 1, newTag) + } else { + list.forEach(item => { + if (Array.isArray(item.children)) this.updateDrawingList(newTag, item.children) + }) + } + } + } +} +</script> + +<style lang='scss'> +.editor-tabs{ + background: #121315; + .el-tabs__header{ + margin: 0; + border-bottom-color: #121315; + .el-tabs__nav{ + border-color: #121315; + } + } + .el-tabs__item{ + height: 32px; + line-height: 32px; + color: #888a8e; + border-left: 1px solid #121315 !important; + background: #363636; + margin-right: 5px; + user-select: none; + } + .el-tabs__item.is-active{ + background: #1e1e1e; + border-bottom-color: #1e1e1e!important; + color: #fff; + } + .el-icon-edit{ + color: #f1fa8c; + } + .el-icon-document{ + color: #a95812; + } +} + +// home +.right-scrollbar { + .el-scrollbar__view { + padding: 12px 18px 15px 15px; + } +} +.left-scrollbar .el-scrollbar__wrap { + box-sizing: border-box; + overflow-x: hidden !important; + margin-bottom: 0 !important; +} +.center-tabs{ + .el-tabs__header{ + margin-bottom: 0!important; + } + .el-tabs__item{ + width: 50%; + text-align: center; + } + .el-tabs__nav{ + width: 100%; + } +} +.reg-item{ + padding: 12px 6px; + background: #f8f8f8; + position: relative; + border-radius: 4px; + .close-btn{ + position: absolute; + right: -6px; + top: -6px; + display: block; + width: 16px; + height: 16px; + line-height: 16px; + background: rgba(0, 0, 0, 0.2); + border-radius: 50%; + color: #fff; + text-align: center; + z-index: 1; + cursor: pointer; + font-size: 12px; + &:hover{ + background: rgba(210, 23, 23, 0.5) + } + } + & + .reg-item{ + margin-top: 18px; + } +} +.action-bar{ + & .el-button+.el-button { + margin-left: 15px; + } + & i { + font-size: 20px; + vertical-align: middle; + position: relative; + top: -1px; + } +} + +.custom-tree-node{ + width: 100%; + font-size: 14px; + .node-operation{ + float: right; + } + i[class*="el-icon"] + i[class*="el-icon"]{ + margin-left: 6px; + } + .el-icon-plus{ + color: #409EFF; + } + .el-icon-delete{ + color: #157a0c; + } +} + +.left-scrollbar .el-scrollbar__view{ + overflow-x: hidden; +} + +.el-rate{ + display: inline-block; + vertical-align: text-top; +} +.el-upload__tip{ + line-height: 1.2; +} + +$selectedColor: #f6f7ff; +$lighterBlue: #409EFF; + +.container { + position: relative; + width: 100%; + height: 100%; +} + +.components-list { + padding: 8px; + box-sizing: border-box; + height: 100%; + .components-item { + display: inline-block; + width: 48%; + margin: 1%; + transition: transform 0ms !important; + } +} +.components-draggable{ + padding-bottom: 20px; +} +.components-title{ + font-size: 14px; + color: #222; + margin: 6px 2px; + .svg-icon{ + color: #666; + font-size: 18px; + } +} + +.components-body { + padding: 8px 10px; + background: $selectedColor; + font-size: 12px; + cursor: move; + border: 1px dashed $selectedColor; + border-radius: 3px; + .svg-icon{ + color: #777; + font-size: 15px; + } + &:hover { + border: 1px dashed #787be8; + color: #787be8; + .svg-icon { + color: #787be8; + } + } +} + +.left-board { + width: 260px; + position: absolute; + left: 0; + top: 0; + height: 100vh; +} +.left-scrollbar{ + height: calc(100vh - 42px); + overflow: hidden; +} +.center-scrollbar { + height: calc(100vh - 42px); + overflow: hidden; + border-left: 1px solid #f1e8e8; + border-right: 1px solid #f1e8e8; + box-sizing: border-box; +} +.center-board { + height: 100vh; + width: auto; + margin: 0 350px 0 260px; + box-sizing: border-box; +} +.empty-info{ + position: absolute; + top: 46%; + left: 0; + right: 0; + text-align: center; + font-size: 18px; + color: #ccb1ea; + letter-spacing: 4px; +} +.action-bar{ + position: relative; + height: 42px; + text-align: right; + padding: 0 15px; + box-sizing: border-box;; + border: 1px solid #f1e8e8; + border-top: none; + border-left: none; + .delete-btn{ + color: #F56C6C; + } +} +.logo-wrapper{ + position: relative; + height: 42px; + background: #fff; + border-bottom: 1px solid #f1e8e8; + box-sizing: border-box; +} +.logo{ + position: absolute; + left: 12px; + top: 6px; + line-height: 30px; + color: #00afff; + font-weight: 600; + font-size: 17px; + white-space: nowrap; + > img{ + width: 30px; + height: 30px; + vertical-align: top; + } + .github{ + display: inline-block; + vertical-align: sub; + margin-left: 15px; + > img{ + height: 22px; + } + } +} + +.center-board-row { + padding: 12px 12px 15px 12px; + box-sizing: border-box; + & > .el-form { + // 69 = 12+15+42 + height: calc(100vh - 69px); + } +} +.drawing-board { + height: 100%; + position: relative; + .components-body { + padding: 0; + margin: 0; + font-size: 0; + } + .sortable-ghost { + position: relative; + display: block; + overflow: hidden; + &::before { + content: " "; + position: absolute; + left: 0; + right: 0; + top: 0; + height: 3px; + background: rgb(89, 89, 223); + z-index: 2; + } + } + .components-item.sortable-ghost { + width: 100%; + height: 60px; + background-color: $selectedColor; + } + .active-from-item { + & > .el-form-item{ + background: $selectedColor; + border-radius: 6px; + } + & > .drawing-item-copy, & > .drawing-item-delete{ + display: initial; + } + & > .component-name{ + color: $lighterBlue; + } + } + .el-form-item{ + margin-bottom: 15px; + } +} +.drawing-item{ + position: relative; + cursor: move; + &.unfocus-bordered:not(.activeFromItem) > div:first-child { + border: 1px dashed #ccc; + } + .el-form-item{ + padding: 12px 10px; + } +} +.drawing-row-item{ + position: relative; + cursor: move; + box-sizing: border-box; + border: 1px dashed #ccc; + border-radius: 3px; + padding: 0 2px; + margin-bottom: 15px; + .drawing-row-item { + margin-bottom: 2px; + } + .el-col{ + margin-top: 22px; + } + .el-form-item{ + margin-bottom: 0; + } + .drag-wrapper{ + min-height: 80px; + } + &.active-from-item{ + border: 1px dashed $lighterBlue; + } + .component-name{ + position: absolute; + top: 0; + left: 0; + font-size: 12px; + color: #bbb; + display: inline-block; + padding: 0 6px; + } +} +.drawing-item, .drawing-row-item{ + &:hover { + & > .el-form-item{ + background: $selectedColor; + border-radius: 6px; + } + & > .drawing-item-copy, & > .drawing-item-delete{ + display: initial; + } + } + & > .drawing-item-copy, & > .drawing-item-delete{ + display: none; + position: absolute; + top: -10px; + width: 22px; + height: 22px; + line-height: 22px; + text-align: center; + border-radius: 50%; + font-size: 12px; + border: 1px solid; + cursor: pointer; + z-index: 1; + } + & > .drawing-item-copy{ + right: 56px; + border-color: $lighterBlue; + color: $lighterBlue; + background: #fff; + &:hover{ + background: $lighterBlue; + color: #fff; + } + } + & > .drawing-item-delete{ + right: 24px; + border-color: #F56C6C; + color: #F56C6C; + background: #fff; + &:hover{ + background: #F56C6C; + color: #fff; + } + } +} +</style> diff --git a/src/views/tool/gen/basicInfoForm.vue b/src/views/tool/gen/basicInfoForm.vue new file mode 100644 index 0000000..7029529 --- /dev/null +++ b/src/views/tool/gen/basicInfoForm.vue @@ -0,0 +1,60 @@ +<template> + <el-form ref="basicInfoForm" :model="info" :rules="rules" label-width="150px"> + <el-row> + <el-col :span="12"> + <el-form-item label="琛ㄥ悕绉�" prop="tableName"> + <el-input placeholder="璇疯緭鍏ヤ粨搴撳悕绉�" v-model="info.tableName" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="琛ㄦ弿杩�" prop="tableComment"> + <el-input placeholder="璇疯緭鍏�" v-model="info.tableComment" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="瀹炰綋绫诲悕绉�" prop="className"> + <el-input placeholder="璇疯緭鍏�" v-model="info.className" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="浣滆��" prop="functionAuthor"> + <el-input placeholder="璇疯緭鍏�" v-model="info.functionAuthor" /> + </el-form-item> + </el-col> + <el-col :span="24"> + <el-form-item label="澶囨敞" prop="remark"> + <el-input type="textarea" :rows="3" v-model="info.remark"></el-input> + </el-form-item> + </el-col> + </el-row> + </el-form> +</template> + +<script> +export default { + props: { + info: { + type: Object, + default: null + } + }, + data() { + return { + rules: { + tableName: [ + { required: true, message: "璇疯緭鍏ヨ〃鍚嶇О", trigger: "blur" } + ], + tableComment: [ + { required: true, message: "璇疯緭鍏ヨ〃鎻忚堪", trigger: "blur" } + ], + className: [ + { required: true, message: "璇疯緭鍏ュ疄浣撶被鍚嶇О", trigger: "blur" } + ], + functionAuthor: [ + { required: true, message: "璇疯緭鍏ヤ綔鑰�", trigger: "blur" } + ] + } + }; + } +}; +</script> diff --git a/src/views/tool/gen/editTable.vue b/src/views/tool/gen/editTable.vue new file mode 100644 index 0000000..951497a --- /dev/null +++ b/src/views/tool/gen/editTable.vue @@ -0,0 +1,234 @@ +<template> + <el-card> + <el-tabs v-model="activeName"> + <el-tab-pane label="鍩烘湰淇℃伅" name="basic"> + <basic-info-form ref="basicInfo" :info="info" /> + </el-tab-pane> + <el-tab-pane label="瀛楁淇℃伅" name="columnInfo"> + <el-table ref="dragTable" :data="columns" row-key="columnId" :max-height="tableHeight"> + <el-table-column label="搴忓彿" type="index" min-width="5%" class-name="allowDrag" /> + <el-table-column + label="瀛楁鍒楀悕" + prop="columnName" + min-width="10%" + :show-overflow-tooltip="true" + /> + <el-table-column label="瀛楁鎻忚堪" min-width="10%"> + <template slot-scope="scope"> + <el-input v-model="scope.row.columnComment"></el-input> + </template> + </el-table-column> + <el-table-column + label="鐗╃悊绫诲瀷" + prop="columnType" + min-width="10%" + :show-overflow-tooltip="true" + /> + <el-table-column label="Java绫诲瀷" min-width="11%"> + <template slot-scope="scope"> + <el-select v-model="scope.row.javaType"> + <el-option label="Long" value="Long" /> + <el-option label="String" value="String" /> + <el-option label="Integer" value="Integer" /> + <el-option label="Double" value="Double" /> + <el-option label="BigDecimal" value="BigDecimal" /> + <el-option label="Date" value="Date" /> + <el-option label="Boolean" value="Boolean" /> + </el-select> + </template> + </el-table-column> + <el-table-column label="java灞炴��" min-width="10%"> + <template slot-scope="scope"> + <el-input v-model="scope.row.javaField"></el-input> + </template> + </el-table-column> + + <el-table-column label="鎻掑叆" min-width="5%"> + <template slot-scope="scope"> + <el-checkbox true-label="1" false-label="0" v-model="scope.row.isInsert"></el-checkbox> + </template> + </el-table-column> + <el-table-column label="缂栬緫" min-width="5%"> + <template slot-scope="scope"> + <el-checkbox true-label="1" false-label="0" v-model="scope.row.isEdit"></el-checkbox> + </template> + </el-table-column> + <el-table-column label="鍒楄〃" min-width="5%"> + <template slot-scope="scope"> + <el-checkbox true-label="1" false-label="0" v-model="scope.row.isList"></el-checkbox> + </template> + </el-table-column> + <el-table-column label="鏌ヨ" min-width="5%"> + <template slot-scope="scope"> + <el-checkbox true-label="1" false-label="0" v-model="scope.row.isQuery"></el-checkbox> + </template> + </el-table-column> + <el-table-column label="鏌ヨ鏂瑰紡" min-width="10%"> + <template slot-scope="scope"> + <el-select v-model="scope.row.queryType"> + <el-option label="=" value="EQ" /> + <el-option label="!=" value="NE" /> + <el-option label=">" value="GT" /> + <el-option label=">=" value="GTE" /> + <el-option label="<" value="LT" /> + <el-option label="<=" value="LTE" /> + <el-option label="LIKE" value="LIKE" /> + <el-option label="BETWEEN" value="BETWEEN" /> + </el-select> + </template> + </el-table-column> + <el-table-column label="蹇呭~" min-width="5%"> + <template slot-scope="scope"> + <el-checkbox true-label="1" false-label="0" v-model="scope.row.isRequired"></el-checkbox> + </template> + </el-table-column> + <el-table-column label="鏄剧ず绫诲瀷" min-width="12%"> + <template slot-scope="scope"> + <el-select v-model="scope.row.htmlType"> + <el-option label="鏂囨湰妗�" value="input" /> + <el-option label="鏂囨湰鍩�" value="textarea" /> + <el-option label="涓嬫媺妗�" value="select" /> + <el-option label="鍗曢�夋" value="radio" /> + <el-option label="澶嶉�夋" value="checkbox" /> + <el-option label="鏃ユ湡鎺т欢" value="datetime" /> + <el-option label="鍥剧墖涓婁紶" value="imageUpload" /> + <el-option label="鏂囦欢涓婁紶" value="fileUpload" /> + <el-option label="瀵屾枃鏈帶浠�" value="editor" /> + </el-select> + </template> + </el-table-column> + <el-table-column label="瀛楀吀绫诲瀷" min-width="12%"> + <template slot-scope="scope"> + <el-select v-model="scope.row.dictType" clearable filterable placeholder="璇烽�夋嫨"> + <el-option + v-for="dict in dictOptions" + :key="dict.dictType" + :label="dict.dictName" + :value="dict.dictType"> + <span style="float: left">{{ dict.dictName }}</span> + <span style="float: right; color: #8492a6; font-size: 13px">{{ dict.dictType }}</span> + </el-option> + </el-select> + </template> + </el-table-column> + </el-table> + </el-tab-pane> + <el-tab-pane label="鐢熸垚淇℃伅" name="genInfo"> + <gen-info-form ref="genInfo" :info="info" :tables="tables" :menus="menus"/> + </el-tab-pane> + </el-tabs> + <el-form label-width="100px"> + <el-form-item style="text-align: center;margin-left:-100px;margin-top:10px;"> + <el-button type="primary" @click="submitForm()">鎻愪氦</el-button> + <el-button @click="close()">杩斿洖</el-button> + </el-form-item> + </el-form> + </el-card> +</template> + +<script> +import { getGenTable, updateGenTable } from "@/api/tool/gen"; +import { optionselect as getDictOptionselect } from "@/api/system/dict/type"; +import { listMenu as getMenuTreeselect } from "@/api/system/menu"; +import basicInfoForm from "./basicInfoForm"; +import genInfoForm from "./genInfoForm"; +import Sortable from 'sortablejs' + +export default { + name: "GenEdit", + components: { + basicInfoForm, + genInfoForm + }, + data() { + return { + // 閫変腑閫夐」鍗$殑 name + activeName: "columnInfo", + // 琛ㄦ牸鐨勯珮搴� + tableHeight: document.documentElement.scrollHeight - 245 + "px", + // 琛ㄤ俊鎭� + tables: [], + // 琛ㄥ垪淇℃伅 + columns: [], + // 瀛楀吀淇℃伅 + dictOptions: [], + // 鑿滃崟淇℃伅 + menus: [], + // 琛ㄨ缁嗕俊鎭� + info: {} + }; + }, + created() { + const tableId = this.$route.params && this.$route.params.tableId; + if (tableId) { + // 鑾峰彇琛ㄨ缁嗕俊鎭� + getGenTable(tableId).then(res => { + this.columns = res.data.rows; + this.info = res.data.info; + this.tables = res.data.tables; + }); + /** 鏌ヨ瀛楀吀涓嬫媺鍒楄〃 */ + getDictOptionselect().then(response => { + this.dictOptions = response.data; + }); + /** 鏌ヨ鑿滃崟涓嬫媺鍒楄〃 */ + getMenuTreeselect().then(response => { + this.menus = this.handleTree(response.data, "menuId"); + }); + } + }, + methods: { + /** 鎻愪氦鎸夐挳 */ + submitForm() { + const basicForm = this.$refs.basicInfo.$refs.basicInfoForm; + const genForm = this.$refs.genInfo.$refs.genInfoForm; + Promise.all([basicForm, genForm].map(this.getFormPromise)).then(res => { + const validateResult = res.every(item => !!item); + if (validateResult) { + const genTable = Object.assign({}, basicForm.model, genForm.model); + genTable.columns = this.columns; + genTable.params = { + treeCode: genTable.treeCode, + treeName: genTable.treeName, + treeParentCode: genTable.treeParentCode, + parentMenuId: genTable.parentMenuId + }; + updateGenTable(genTable).then(res => { + this.$modal.msgSuccess(res.msg); + if (res.code === 200) { + this.close(); + } + }); + } else { + this.$modal.msgError("琛ㄥ崟鏍¢獙鏈�氳繃锛岃閲嶆柊妫�鏌ユ彁浜ゅ唴瀹�"); + } + }); + }, + getFormPromise(form) { + return new Promise(resolve => { + form.validate(res => { + resolve(res); + }); + }); + }, + /** 鍏抽棴鎸夐挳 */ + close() { + const obj = { path: "/tool/gen", query: { t: Date.now(), pageNum: this.$route.query.pageNum } }; + this.$tab.closeOpenPage(obj); + } + }, + mounted() { + const el = this.$refs.dragTable.$el.querySelectorAll(".el-table__body-wrapper > table > tbody")[0]; + const sortable = Sortable.create(el, { + handle: ".allowDrag", + onEnd: evt => { + const targetRow = this.columns.splice(evt.oldIndex, 1)[0]; + this.columns.splice(evt.newIndex, 0, targetRow); + for (let index in this.columns) { + this.columns[index].sort = parseInt(index) + 1; + } + } + }); + } +}; +</script> diff --git a/src/views/tool/gen/genInfoForm.vue b/src/views/tool/gen/genInfoForm.vue new file mode 100644 index 0000000..3f8d67f --- /dev/null +++ b/src/views/tool/gen/genInfoForm.vue @@ -0,0 +1,299 @@ +<template> + <el-form ref="genInfoForm" :model="info" :rules="rules" label-width="150px"> + <el-row> + <el-col :span="12"> + <el-form-item prop="tplCategory"> + <span slot="label">鐢熸垚妯℃澘</span> + <el-select v-model="info.tplCategory" @change="tplSelectChange"> + <el-option label="鍗曡〃锛堝鍒犳敼鏌ワ級" value="crud" /> + <el-option label="鏍戣〃锛堝鍒犳敼鏌ワ級" value="tree" /> + <el-option label="涓诲瓙琛紙澧炲垹鏀规煡锛�" value="sub" /> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item prop="packageName"> + <span slot="label"> + 鐢熸垚鍖呰矾寰� + <el-tooltip content="鐢熸垚鍦ㄥ摢涓猨ava鍖呬笅锛屼緥濡� com.ruoyi.system" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="info.packageName" /> + </el-form-item> + </el-col> + + <el-col :span="12"> + <el-form-item prop="moduleName"> + <span slot="label"> + 鐢熸垚妯″潡鍚� + <el-tooltip content="鍙悊瑙d负瀛愮郴缁熷悕锛屼緥濡� system" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="info.moduleName" /> + </el-form-item> + </el-col> + + <el-col :span="12"> + <el-form-item prop="businessName"> + <span slot="label"> + 鐢熸垚涓氬姟鍚� + <el-tooltip content="鍙悊瑙d负鍔熻兘鑻辨枃鍚嶏紝渚嬪 user" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="info.businessName" /> + </el-form-item> + </el-col> + + <el-col :span="12"> + <el-form-item prop="functionName"> + <span slot="label"> + 鐢熸垚鍔熻兘鍚� + <el-tooltip content="鐢ㄤ綔绫绘弿杩帮紝渚嬪 鐢ㄦ埛" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="info.functionName" /> + </el-form-item> + </el-col> + + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 涓婄骇鑿滃崟 + <el-tooltip content="鍒嗛厤鍒版寚瀹氳彍鍗曚笅锛屼緥濡� 绯荤粺绠$悊" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <treeselect + :append-to-body="true" + v-model="info.parentMenuId" + :options="menus" + :normalizer="normalizer" + :show-count="true" + placeholder="璇烽�夋嫨绯荤粺鑿滃崟" + /> + </el-form-item> + </el-col> + + <el-col :span="12"> + <el-form-item prop="genType"> + <span slot="label"> + 鐢熸垚浠g爜鏂瑰紡 + <el-tooltip content="榛樿涓簔ip鍘嬬缉鍖呬笅杞斤紝涔熷彲浠ヨ嚜瀹氫箟鐢熸垚璺緞" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-radio v-model="info.genType" label="0">zip鍘嬬缉鍖�</el-radio> + <el-radio v-model="info.genType" label="1">鑷畾涔夎矾寰�</el-radio> + </el-form-item> + </el-col> + + <el-col :span="24" v-if="info.genType == '1'"> + <el-form-item prop="genPath"> + <span slot="label"> + 鑷畾涔夎矾寰� + <el-tooltip content="濉啓纾佺洏缁濆璺緞锛岃嫢涓嶅~鍐欙紝鍒欑敓鎴愬埌褰撳墠Web椤圭洰涓�" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-input v-model="info.genPath"> + <el-dropdown slot="append"> + <el-button type="primary"> + 鏈�杩戣矾寰勫揩閫熼�夋嫨 + <i class="el-icon-arrow-down el-icon--right"></i> + </el-button> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item @click.native="info.genPath = '/'">鎭㈠榛樿鐨勭敓鎴愬熀纭�璺緞</el-dropdown-item> + </el-dropdown-menu> + </el-dropdown> + </el-input> + </el-form-item> + </el-col> + </el-row> + + <el-row v-show="info.tplCategory == 'tree'"> + <h4 class="form-header">鍏朵粬淇℃伅</h4> + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 鏍戠紪鐮佸瓧娈� + <el-tooltip content="鏍戞樉绀虹殑缂栫爜瀛楁鍚嶏紝 濡傦細dept_id" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-select v-model="info.treeCode" placeholder="璇烽�夋嫨"> + <el-option + v-for="(column, index) in info.columns" + :key="index" + :label="column.columnName + '锛�' + column.columnComment" + :value="column.columnName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 鏍戠埗缂栫爜瀛楁 + <el-tooltip content="鏍戞樉绀虹殑鐖剁紪鐮佸瓧娈靛悕锛� 濡傦細parent_Id" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-select v-model="info.treeParentCode" placeholder="璇烽�夋嫨"> + <el-option + v-for="(column, index) in info.columns" + :key="index" + :label="column.columnName + '锛�' + column.columnComment" + :value="column.columnName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 鏍戝悕绉板瓧娈� + <el-tooltip content="鏍戣妭鐐圭殑鏄剧ず鍚嶇О瀛楁鍚嶏紝 濡傦細dept_name" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-select v-model="info.treeName" placeholder="璇烽�夋嫨"> + <el-option + v-for="(column, index) in info.columns" + :key="index" + :label="column.columnName + '锛�' + column.columnComment" + :value="column.columnName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + <el-row v-show="info.tplCategory == 'sub'"> + <h4 class="form-header">鍏宠仈淇℃伅</h4> + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 鍏宠仈瀛愯〃鐨勮〃鍚� + <el-tooltip content="鍏宠仈瀛愯〃鐨勮〃鍚嶏紝 濡傦細sys_user" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-select v-model="info.subTableName" placeholder="璇烽�夋嫨" @change="subSelectChange"> + <el-option + v-for="(table, index) in tables" + :key="index" + :label="table.tableName + '锛�' + table.tableComment" + :value="table.tableName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item> + <span slot="label"> + 瀛愯〃鍏宠仈鐨勫閿悕 + <el-tooltip content="瀛愯〃鍏宠仈鐨勫閿悕锛� 濡傦細user_id" placement="top"> + <i class="el-icon-question"></i> + </el-tooltip> + </span> + <el-select v-model="info.subTableFkName" placeholder="璇烽�夋嫨"> + <el-option + v-for="(column, index) in subColumns" + :key="index" + :label="column.columnName + '锛�' + column.columnComment" + :value="column.columnName" + ></el-option> + </el-select> + </el-form-item> + </el-col> + </el-row> + </el-form> +</template> + +<script> +import Treeselect from "@riophae/vue-treeselect"; +import "@riophae/vue-treeselect/dist/vue-treeselect.css"; + +export default { + components: { Treeselect }, + props: { + info: { + type: Object, + default: null + }, + tables: { + type: Array, + default: null + }, + menus: { + type: Array, + default: [] + }, + }, + data() { + return { + subColumns: [], + rules: { + tplCategory: [ + { required: true, message: "璇烽�夋嫨鐢熸垚妯℃澘", trigger: "blur" } + ], + packageName: [ + { required: true, message: "璇疯緭鍏ョ敓鎴愬寘璺緞", trigger: "blur" } + ], + moduleName: [ + { required: true, message: "璇疯緭鍏ョ敓鎴愭ā鍧楀悕", trigger: "blur" } + ], + businessName: [ + { required: true, message: "璇疯緭鍏ョ敓鎴愪笟鍔″悕", trigger: "blur" } + ], + functionName: [ + { required: true, message: "璇疯緭鍏ョ敓鎴愬姛鑳藉悕", trigger: "blur" } + ], + } + }; + }, + created() {}, + watch: { + 'info.subTableName': function(val) { + this.setSubTableColumns(val); + } + }, + methods: { + /** 杞崲鑿滃崟鏁版嵁缁撴瀯 */ + normalizer(node) { + if (node.children && !node.children.length) { + delete node.children; + } + return { + id: node.menuId, + label: node.menuName, + children: node.children + }; + }, + /** 閫夋嫨瀛愯〃鍚嶈Е鍙� */ + subSelectChange(value) { + this.info.subTableFkName = ''; + }, + /** 閫夋嫨鐢熸垚妯℃澘瑙﹀彂 */ + tplSelectChange(value) { + if(value !== 'sub') { + this.info.subTableName = ''; + this.info.subTableFkName = ''; + } + }, + /** 璁剧疆鍏宠仈澶栭敭 */ + setSubTableColumns(value) { + for (var item in this.tables) { + const name = this.tables[item].tableName; + if (value === name) { + this.subColumns = this.tables[item].columns; + break; + } + } + } + } +}; +</script> diff --git a/src/views/tool/gen/importTable.vue b/src/views/tool/gen/importTable.vue new file mode 100644 index 0000000..3ea9532 --- /dev/null +++ b/src/views/tool/gen/importTable.vue @@ -0,0 +1,120 @@ +<template> + <!-- 瀵煎叆琛� --> + <el-dialog title="瀵煎叆琛�" :visible.sync="visible" width="800px" top="5vh" append-to-body> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true"> + <el-form-item label="琛ㄥ悕绉�" prop="tableName"> + <el-input + v-model="queryParams.tableName" + placeholder="璇疯緭鍏ヨ〃鍚嶇О" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="琛ㄦ弿杩�" prop="tableComment"> + <el-input + v-model="queryParams.tableComment" + placeholder="璇疯緭鍏ヨ〃鎻忚堪" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + <el-row> + <el-table @row-click="clickRow" ref="table" :data="dbTableList" @selection-change="handleSelectionChange" height="260px"> + <el-table-column type="selection" width="55"></el-table-column> + <el-table-column prop="tableName" label="琛ㄥ悕绉�" :show-overflow-tooltip="true"></el-table-column> + <el-table-column prop="tableComment" label="琛ㄦ弿杩�" :show-overflow-tooltip="true"></el-table-column> + <el-table-column prop="createTime" label="鍒涘缓鏃堕棿"></el-table-column> + <el-table-column prop="updateTime" label="鏇存柊鏃堕棿"></el-table-column> + </el-table> + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + </el-row> + <div slot="footer" class="dialog-footer"> + <el-button type="primary" @click="handleImportTable">纭� 瀹�</el-button> + <el-button @click="visible = false">鍙� 娑�</el-button> + </div> + </el-dialog> +</template> + +<script> +import { listDbTable, importTable } from "@/api/tool/gen"; +export default { + data() { + return { + // 閬僵灞� + visible: false, + // 閫変腑鏁扮粍鍊� + tables: [], + // 鎬绘潯鏁� + total: 0, + // 琛ㄦ暟鎹� + dbTableList: [], + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + tableName: undefined, + tableComment: undefined + } + }; + }, + methods: { + // 鏄剧ず寮规 + show() { + this.getList(); + this.visible = true; + }, + clickRow(row) { + this.$refs.table.toggleRowSelection(row); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.tables = selection.map(item => item.tableName); + }, + // 鏌ヨ琛ㄦ暟鎹� + getList() { + listDbTable(this.queryParams).then(res => { + if (res.code === 200) { + this.dbTableList = res.rows; + this.total = res.total; + } + }); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 瀵煎叆鎸夐挳鎿嶄綔 */ + handleImportTable() { + const tableNames = this.tables.join(","); + if (tableNames == "") { + this.$modal.msgError("璇烽�夋嫨瑕佸鍏ョ殑琛�"); + return; + } + importTable({ tables: tableNames }).then(res => { + this.$modal.msgSuccess(res.msg); + if (res.code === 200) { + this.visible = false; + this.$emit("ok"); + } + }); + } + } +}; +</script> diff --git a/src/views/tool/gen/index.vue b/src/views/tool/gen/index.vue new file mode 100644 index 0000000..3f1f930 --- /dev/null +++ b/src/views/tool/gen/index.vue @@ -0,0 +1,337 @@ +<template> + <div class="app-container"> + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px"> + <el-form-item label="琛ㄥ悕绉�" prop="tableName"> + <el-input + v-model="queryParams.tableName" + placeholder="璇疯緭鍏ヨ〃鍚嶇О" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="琛ㄦ弿杩�" prop="tableComment"> + <el-input + v-model="queryParams.tableComment" + placeholder="璇疯緭鍏ヨ〃鎻忚堪" + clearable + @keyup.enter.native="handleQuery" + /> + </el-form-item> + <el-form-item label="鍒涘缓鏃堕棿"> + <el-date-picker + v-model="dateRange" + style="width: 240px" + value-format="yyyy-MM-dd" + type="daterange" + range-separator="-" + start-placeholder="寮�濮嬫棩鏈�" + end-placeholder="缁撴潫鏃ユ湡" + ></el-date-picker> + </el-form-item> + <el-form-item> + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button> + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button> + </el-form-item> + </el-form> + + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button + type="primary" + plain + icon="el-icon-download" + size="mini" + @click="handleGenTable" + v-hasPermi="['tool:gen:code']" + >鐢熸垚</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="info" + plain + icon="el-icon-upload" + size="mini" + @click="openImportTable" + v-hasPermi="['tool:gen:import']" + >瀵煎叆</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="success" + plain + icon="el-icon-edit" + size="mini" + :disabled="single" + @click="handleEditTable" + v-hasPermi="['tool:gen:edit']" + >淇敼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button + type="danger" + plain + icon="el-icon-delete" + size="mini" + :disabled="multiple" + @click="handleDelete" + v-hasPermi="['tool:gen:remove']" + >鍒犻櫎</el-button> + </el-col> + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> + </el-row> + + <el-table v-loading="loading" :data="tableList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" align="center" width="55"></el-table-column> + <el-table-column label="搴忓彿" type="index" width="50" align="center"> + <template slot-scope="scope"> + <span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span> + </template> + </el-table-column> + <el-table-column + label="琛ㄥ悕绉�" + align="center" + prop="tableName" + :show-overflow-tooltip="true" + width="120" + /> + <el-table-column + label="琛ㄦ弿杩�" + align="center" + prop="tableComment" + :show-overflow-tooltip="true" + width="120" + /> + <el-table-column + label="瀹炰綋" + align="center" + prop="className" + :show-overflow-tooltip="true" + width="120" + /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="160" /> + <el-table-column label="鏇存柊鏃堕棿" align="center" prop="updateTime" width="160" /> + <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <template slot-scope="scope"> + <el-button + type="text" + size="small" + icon="el-icon-view" + @click="handlePreview(scope.row)" + v-hasPermi="['tool:gen:preview']" + >棰勮</el-button> + <el-button + type="text" + size="small" + icon="el-icon-edit" + @click="handleEditTable(scope.row)" + v-hasPermi="['tool:gen:edit']" + >缂栬緫</el-button> + <el-button + type="text" + size="small" + icon="el-icon-delete" + @click="handleDelete(scope.row)" + v-hasPermi="['tool:gen:remove']" + >鍒犻櫎</el-button> + <el-button + type="text" + size="small" + icon="el-icon-refresh" + @click="handleSynchDb(scope.row)" + v-hasPermi="['tool:gen:edit']" + >鍚屾</el-button> + <el-button + type="text" + size="small" + icon="el-icon-download" + @click="handleGenTable(scope.row)" + v-hasPermi="['tool:gen:code']" + >鐢熸垚浠g爜</el-button> + </template> + </el-table-column> + </el-table> + <pagination + v-show="total>0" + :total="total" + :page.sync="queryParams.pageNum" + :limit.sync="queryParams.pageSize" + @pagination="getList" + /> + <!-- 棰勮鐣岄潰 --> + <el-dialog :title="preview.title" :visible.sync="preview.open" width="80%" top="5vh" append-to-body class="scrollbar"> + <el-tabs v-model="preview.activeName"> + <el-tab-pane + v-for="(value, key) in preview.data" + :label="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))" + :name="key.substring(key.lastIndexOf('/')+1,key.indexOf('.vm'))" + :key="key" + > + <el-link :underline="false" icon="el-icon-document-copy" v-clipboard:copy="value" v-clipboard:success="clipboardSuccess" style="float:right">澶嶅埗</el-link> + <pre><code class="hljs" v-html="highlightedCode(value, key)"></code></pre> + </el-tab-pane> + </el-tabs> + </el-dialog> + <import-table ref="import" @ok="handleQuery" /> + </div> +</template> + +<script> +import { listTable, previewTable, delTable, genCode, synchDb } from "@/api/tool/gen"; +import importTable from "./importTable"; +import hljs from "highlight.js/lib/highlight"; +import "highlight.js/styles/github-gist.css"; +hljs.registerLanguage("java", require("highlight.js/lib/languages/java")); +hljs.registerLanguage("xml", require("highlight.js/lib/languages/xml")); +hljs.registerLanguage("html", require("highlight.js/lib/languages/xml")); +hljs.registerLanguage("vue", require("highlight.js/lib/languages/xml")); +hljs.registerLanguage("javascript", require("highlight.js/lib/languages/javascript")); +hljs.registerLanguage("sql", require("highlight.js/lib/languages/sql")); + +export default { + name: "Gen", + components: { importTable }, + data() { + return { + // 閬僵灞� + loading: true, + // 鍞竴鏍囪瘑绗� + uniqueId: "", + // 閫変腑鏁扮粍 + ids: [], + // 閫変腑琛ㄦ暟缁� + tableNames: [], + // 闈炲崟涓鐢� + single: true, + // 闈炲涓鐢� + multiple: true, + // 鏄剧ず鎼滅储鏉′欢 + showSearch: true, + // 鎬绘潯鏁� + total: 0, + // 琛ㄦ暟鎹� + tableList: [], + // 鏃ユ湡鑼冨洿 + dateRange: "", + // 鏌ヨ鍙傛暟 + queryParams: { + pageNum: 1, + pageSize: 10, + tableName: undefined, + tableComment: undefined + }, + // 棰勮鍙傛暟 + preview: { + open: false, + title: "浠g爜棰勮", + data: {}, + activeName: "domain.java" + } + }; + }, + created() { + this.getList(); + }, + activated() { + const time = this.$route.query.t; + if (time != null && time != this.uniqueId) { + this.uniqueId = time; + this.queryParams.pageNum = Number(this.$route.query.pageNum); + this.getList(); + } + }, + methods: { + /** 鏌ヨ琛ㄩ泦鍚� */ + getList() { + this.loading = true; + listTable(this.addDateRange(this.queryParams, this.dateRange)).then(response => { + this.tableList = response.rows; + this.total = response.total; + this.loading = false; + } + ); + }, + /** 鎼滅储鎸夐挳鎿嶄綔 */ + handleQuery() { + this.queryParams.pageNum = 1; + this.getList(); + }, + /** 鐢熸垚浠g爜鎿嶄綔 */ + handleGenTable(row) { + const tableNames = row.tableName || this.tableNames; + if (tableNames == "") { + this.$modal.msgError("璇烽�夋嫨瑕佺敓鎴愮殑鏁版嵁"); + return; + } + if(row.genType === "1") { + genCode(row.tableName).then(response => { + this.$modal.msgSuccess("鎴愬姛鐢熸垚鍒拌嚜瀹氫箟璺緞锛�" + row.genPath); + }); + } else { + this.$download.zip("/tool/gen/batchGenCode?tables=" + tableNames, "ruoyi.zip"); + } + }, + /** 鍚屾鏁版嵁搴撴搷浣� */ + handleSynchDb(row) { + const tableName = row.tableName; + this.$modal.confirm('纭瑕佸己鍒跺悓姝�"' + tableName + '"琛ㄧ粨鏋勫悧锛�').then(function() { + return synchDb(tableName); + }).then(() => { + this.$modal.msgSuccess("鍚屾鎴愬姛"); + }).catch(() => {}); + }, + /** 鎵撳紑瀵煎叆琛ㄥ脊绐� */ + openImportTable() { + this.$refs.import.show(); + }, + /** 閲嶇疆鎸夐挳鎿嶄綔 */ + resetQuery() { + this.dateRange = []; + this.resetForm("queryForm"); + this.handleQuery(); + }, + /** 棰勮鎸夐挳 */ + handlePreview(row) { + previewTable(row.tableId).then(response => { + this.preview.data = response.data; + this.preview.open = true; + this.preview.activeName = "domain.java"; + }); + }, + /** 楂樹寒鏄剧ず */ + highlightedCode(code, key) { + const vmName = key.substring(key.lastIndexOf("/") + 1, key.indexOf(".vm")); + var language = vmName.substring(vmName.indexOf(".") + 1, vmName.length); + const result = hljs.highlight(language, code || "", true); + return result.value || ' '; + }, + /** 澶嶅埗浠g爜鎴愬姛 */ + clipboardSuccess() { + this.$modal.msgSuccess("澶嶅埗鎴愬姛"); + }, + // 澶氶�夋閫変腑鏁版嵁 + handleSelectionChange(selection) { + this.ids = selection.map(item => item.tableId); + this.tableNames = selection.map(item => item.tableName); + this.single = selection.length != 1; + this.multiple = !selection.length; + }, + /** 淇敼鎸夐挳鎿嶄綔 */ + handleEditTable(row) { + const tableId = row.tableId || this.ids[0]; + const tableName = row.tableName || this.tableNames[0]; + const params = { pageNum: this.queryParams.pageNum }; + this.$tab.openPage("淇敼[" + tableName + "]鐢熸垚閰嶇疆", '/tool/gen-edit/index/' + tableId, params); + }, + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ + handleDelete(row) { + const tableIds = row.tableId || this.ids; + this.$modal.confirm('鏄惁纭鍒犻櫎琛ㄧ紪鍙蜂负"' + tableIds + '"鐨勬暟鎹」锛�').then(function() { + return delTable(tableIds); + }).then(() => { + this.getList(); + this.$modal.msgSuccess("鍒犻櫎鎴愬姛"); + }).catch(() => {}); + } + } +}; +</script> diff --git a/src/views/tool/swagger/index.vue b/src/views/tool/swagger/index.vue new file mode 100644 index 0000000..b8becc6 --- /dev/null +++ b/src/views/tool/swagger/index.vue @@ -0,0 +1,15 @@ +<template> + <i-frame :src="url" /> +</template> +<script> +import iFrame from "@/components/iFrame/index"; +export default { + name: "Swagger", + components: { iFrame }, + data() { + return { + url: process.env.VUE_APP_BASE_API + "/swagger-ui/index.html" + }; + }, +}; +</script> diff --git a/vue.config.js b/vue.config.js new file mode 100644 index 0000000..574b531 --- /dev/null +++ b/vue.config.js @@ -0,0 +1,137 @@ +'use strict' +const path = require('path') + +function resolve(dir) { + return path.join(__dirname, dir) +} + +const CompressionPlugin = require('compression-webpack-plugin') + +const name = process.env.VUE_APP_TITLE || '鏁板瓧鍖栫鐞嗙郴缁�' // 缃戦〉鏍囬 + +const port = process.env.port || process.env.npm_config_port || 80 // 绔彛 + +// vue.config.js 閰嶇疆璇存槑 +//瀹樻柟vue.config.js 鍙傝�冩枃妗� https://cli.vuejs.org/zh/config/#css-loaderoptions +// 杩欓噷鍙垪涓�閮ㄥ垎锛屽叿浣撻厤缃弬鑰冩枃妗� +module.exports = { + // 閮ㄧ讲鐢熶骇鐜鍜屽紑鍙戠幆澧冧笅鐨刄RL銆� + // 榛樿鎯呭喌涓嬶紝Vue CLI 浼氬亣璁句綘鐨勫簲鐢ㄦ槸琚儴缃插湪涓�涓煙鍚嶇殑鏍硅矾寰勪笂 + // 渚嬪 https://www.ruoyi.vip/銆傚鏋滃簲鐢ㄨ閮ㄧ讲鍦ㄤ竴涓瓙璺緞涓婏紝浣犲氨闇�瑕佺敤杩欎釜閫夐」鎸囧畾杩欎釜瀛愯矾寰勩�備緥濡傦紝濡傛灉浣犵殑搴旂敤琚儴缃插湪 https://www.ruoyi.vip/admin/锛屽垯璁剧疆 baseUrl 涓� /admin/銆� + publicPath: process.env.NODE_ENV === "production" ? "/rYdist/" : "/", + // 鍦╪pm run build 鎴� yarn build 鏃� 锛岀敓鎴愭枃浠剁殑鐩綍鍚嶇О锛堣鍜宐aseUrl鐨勭敓浜х幆澧冭矾寰勪竴鑷达級锛堥粯璁ist锛� + outputDir: 'dist', + // 鐢ㄤ簬鏀剧疆鐢熸垚鐨勯潤鎬佽祫婧� (js銆乧ss銆乮mg銆乫onts) 鐨勶紱锛堥」鐩墦鍖呬箣鍚庯紝闈欐�佽祫婧愪細鏀惧湪杩欎釜鏂囦欢澶逛笅锛� + assetsDir: 'static', + // 鏄惁寮�鍚痚slint淇濆瓨妫�娴嬶紝鏈夋晥鍊硷細ture | false | 'error' + lintOnSave: process.env.NODE_ENV === 'development', + // 濡傛灉浣犱笉闇�瑕佺敓浜х幆澧冪殑 source map锛屽彲浠ュ皢鍏惰缃负 false 浠ュ姞閫熺敓浜х幆澧冩瀯寤恒�� + productionSourceMap: false, + // webpack-dev-server 鐩稿叧閰嶇疆 + devServer: { + host: '0.0.0.0', + port: port, + open: true, + hot:true, + // proxy: { + // // detail: https://cli.vuejs.org/config/#devserver-proxy + // [process.env.VUE_APP_BASE_API]: { + // target: `http://localhost:8080`, + // changeOrigin: true, + // pathRewrite: { + // ['^' + process.env.VUE_APP_BASE_API]: '' + // } + // } + // }, + disableHostCheck: true, + }, + css: { + loaderOptions: { + sass: { + sassOptions: { outputStyle: "expanded" } + } + } + }, + configureWebpack: { + name: name, + devtool:"source-map", + mode:"development", + resolve: { + alias: { + '@': resolve('src') + } + }, + plugins: [ + // http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#浣跨敤gzip瑙e帇缂╅潤鎬佹枃浠� + new CompressionPlugin({ + cache: false, // 涓嶅惎鐢ㄦ枃浠剁紦瀛� + test: /\.(js|css|html)?$/i, // 鍘嬬缉鏂囦欢鏍煎紡 + filename: '[path].gz[query]', // 鍘嬬缉鍚庣殑鏂囦欢鍚� + algorithm: 'gzip', // 浣跨敤gzip鍘嬬缉 + minRatio: 0.8 // 鍘嬬缉鐜囧皬浜�1鎵嶄細鍘嬬缉 + }) + ], + }, + chainWebpack(config) { + config.plugins.delete('preload') // TODO: need test + config.plugins.delete('prefetch') // TODO: need test + + // set svg-sprite-loader + config.module + .rule('svg') + .exclude.add(resolve('src/assets/icons')) + .end() + config.module + .rule('icons') + .test(/\.svg$/) + .include.add(resolve('src/assets/icons')) + .end() + .use('svg-sprite-loader') + .loader('svg-sprite-loader') + .options({ + symbolId: 'icon-[name]' + }) + .end() + + config.when(process.env.NODE_ENV !== 'development', config => { + config + .plugin('ScriptExtHtmlWebpackPlugin') + .after('html') + .use('script-ext-html-webpack-plugin', [{ + // `runtime` must same as runtimeChunk name. default is `runtime` + inline: /runtime\..*\.js$/ + }]) + .end() + + config.optimization.splitChunks({ + chunks: 'all', + cacheGroups: { + libs: { + name: 'chunk-libs', + test: /[\\/]node_modules[\\/]/, + priority: 10, + chunks: 'initial' // only package third parties that are initially dependent + }, + elementUI: { + name: 'chunk-elementUI', // split elementUI into a single package + test: /[\\/]node_modules[\\/]_?element-ui(.*)/, // in order to adapt to cnpm + priority: 20 // the weight needs to be larger than libs and app or it will be packaged into libs or app + }, + commons: { + name: 'chunk-commons', + test: resolve('src/components'), // can customize your rules + minChunks: 3, // minimum common number + priority: 5, + reuseExistingChunk: true + } + } + }) + + config.optimization.runtimeChunk('single'), + { + from: path.resolve(__dirname, './public/robots.txt'), //闃茬埇铏枃浠� + to: './' //鍒版牴鐩綍涓� + } + }) + } +} -- Gitblit v1.9.3