feat:升级vite2和组合式api

pull/297/head
lin-xin 2021-06-27 14:48:07 +08:00
parent 4dd1b4aae6
commit 9bc43e2efc
27 changed files with 2029 additions and 1183 deletions

View File

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016-2019 vue-manage-system
Copyright (c) 2016-2021 vue-manage-system
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -20,8 +20,6 @@
> Vue2 版本请看 [tag-V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0)
> React + Ant Design 的版本正在开发中,仓库地址:[react-manage-system](https://github.com/lin-xin/react-manage-system)
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
## 项目截图
@ -53,16 +51,12 @@
- [x] Tab 选项卡
- [x] 表单
- [x] 图表 :bar_chart:
- [ ] 富文本编辑器
- [ ] markdown 编辑器
- [x] 富文本编辑器
- [x] 图片拖拽/裁剪上传
- [ ] 支持切换主题色 :sparkles:
- [ ] 列表拖拽排序
- [x] 权限测试
- [x] 404 / 403
- [x] 三级菜单
- [x] 自定义图标
- [ ] 可拖拽弹窗
- [x] 国际化
## 安装步骤
@ -73,7 +67,7 @@ cd vue-manage-system // 进入模板目录
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
// 开启服务器,浏览器访问 http://localhost:8080
npm run serve
npm run dev
// 执行构建命令生成的dist文件夹放在服务器下即可访问
npm run build

View File

@ -1,5 +0,0 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

View File

@ -15,6 +15,7 @@
Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<!-- built files will be auto injected -->
</body>

700
package-lock.json generated Normal file
View File

@ -0,0 +1,700 @@
{
"name": "vue-manage-system",
"version": "5.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@babel/helper-validator-identifier": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz",
"integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg=="
},
"@babel/parser": {
"version": "7.14.7",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.7.tgz",
"integrity": "sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA=="
},
"@babel/runtime": {
"version": "7.14.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz",
"integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==",
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"@babel/runtime-corejs3": {
"version": "7.14.7",
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.7.tgz",
"integrity": "sha512-Wvzcw4mBYbTagyBVZpAJWI06auSIj033T/yNE0Zn1xcup83MieCddZA7ls3kme17L4NOGBrQ09Q+nKB41RLWBA==",
"requires": {
"core-js-pure": "^3.15.0",
"regenerator-runtime": "^0.13.4"
}
},
"@babel/types": {
"version": "7.14.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz",
"integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==",
"requires": {
"@babel/helper-validator-identifier": "^7.14.5",
"to-fast-properties": "^2.0.0"
}
},
"@intlify/core-base": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.1.6.tgz",
"integrity": "sha512-d5GDPpsQbqPkisSJA5b6nJFEkalY/IHAd7vOLNd/Sj4YaNRzXtInu2FoqKiOv8e/lQnXGTpurdCZg5Jxq1Gsxw==",
"requires": {
"@intlify/devtools-if": "9.1.6",
"@intlify/message-compiler": "9.1.6",
"@intlify/message-resolver": "9.1.6",
"@intlify/runtime": "9.1.6",
"@intlify/shared": "9.1.6",
"@intlify/vue-devtools": "9.1.6"
}
},
"@intlify/devtools-if": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.1.6.tgz",
"integrity": "sha512-m8Api+kh+BtFa2FZ/JjIdr1ibsGGqBjdKCzWo5BZecEUxBquIeOQZwpokPh/0K5j+/PZleFXkVAMC5mNt+9WdA==",
"requires": {
"@intlify/shared": "9.1.6"
}
},
"@intlify/message-compiler": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.1.6.tgz",
"integrity": "sha512-DR8645VOrVK6x/8tkaCpHnckMAIcoOgeNS5j0wB12RfZoXYQp7vAXMaOP511KMll2mXCREgIB0ojpajiof7yzQ==",
"requires": {
"@intlify/message-resolver": "9.1.6",
"@intlify/shared": "9.1.6",
"source-map": "0.6.1"
}
},
"@intlify/message-resolver": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/message-resolver/-/message-resolver-9.1.6.tgz",
"integrity": "sha512-UUnbawQa5U9sffd5wRIscqtyY1xWlwJbyfwCLPEWLvBhyAnCwPYlvaHGnnO0CSi0fzJTVwlV9DYzobh3agDeMA=="
},
"@intlify/runtime": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/runtime/-/runtime-9.1.6.tgz",
"integrity": "sha512-U1QZ+TPf3kQQvWo4BA2mj3cHAxMRHXNTBhu2u+deh6ubTqXdZ19XGBTMSasrXG6RE+zSio9oM+ndoLja7JGtPg==",
"requires": {
"@intlify/message-compiler": "9.1.6",
"@intlify/message-resolver": "9.1.6",
"@intlify/shared": "9.1.6"
}
},
"@intlify/shared": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.1.6.tgz",
"integrity": "sha512-6MtsKulyfZxdD7OuxjaODjj8QWoHCnLFAk4wkWiHqBCa6UCTC0qXjtEeZ1MxpQihvFmmJZauBUu25EvtngW5qQ=="
},
"@intlify/vue-devtools": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.1.6.tgz",
"integrity": "sha512-UdNovg4OML9rIr1sOGZzTfNr1nUy4UQpDf5ni4dNC93T6FIkVJz0n1Np7Vp7e6gDjcmufRYcV99tEwjQSN9+5A==",
"requires": {
"@intlify/message-resolver": "9.1.6",
"@intlify/runtime": "9.1.6",
"@intlify/shared": "9.1.6"
}
},
"@popperjs/core": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.2.tgz",
"integrity": "sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q=="
},
"@types/estree": {
"version": "0.0.48",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.48.tgz",
"integrity": "sha512-LfZwXoGUDo0C3me81HXgkBg5CTQYb6xzEl+fNmbO4JdRiSKQ8A0GD1OBBvKAIsbCUgoyAty7m99GqqMQe784ew==",
"dev": true
},
"@types/lodash": {
"version": "4.14.170",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
"integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q=="
},
"@vitejs/plugin-vue": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.2.3.tgz",
"integrity": "sha512-LlnLpObkGKZ+b7dcpL4T24l13nPSHLjo+6Oc7MbZiKz5PMAUzADfNJ3EKfYIQ0l0969nxf2jp/9vsfnuJ7h6fw==",
"dev": true
},
"@vue/compiler-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.2.tgz",
"integrity": "sha512-nHmq7vLjq/XM2IMbZUcKWoH5sPXa2uR/nIKZtjbK5F3TcbnYE/zKsrSUR9WZJ03unlwotNBX1OyxVt9HbWD7/Q==",
"requires": {
"@babel/parser": "^7.12.0",
"@babel/types": "^7.12.0",
"@vue/shared": "3.1.2",
"estree-walker": "^2.0.1",
"source-map": "^0.6.1"
}
},
"@vue/compiler-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.1.2.tgz",
"integrity": "sha512-k2+SWcWH0jL6WQAX7Or2ONqu5MbtTgTO0dJrvebQYzgqaKMXNI90RNeWeCxS4BnNFMDONpHBeFgbwbnDWIkmRg==",
"requires": {
"@vue/compiler-core": "3.1.2",
"@vue/shared": "3.1.2"
}
},
"@vue/compiler-sfc": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.1.2.tgz",
"integrity": "sha512-SeG/2+DvwejQ7oAiSx8BrDh5qOdqCYHGClPiTvVIHTfSIHiS2JjMbCANdDCjHkTOh/O7WZzo2JhdKm98bRBxTw==",
"dev": true,
"requires": {
"@babel/parser": "^7.13.9",
"@babel/types": "^7.13.0",
"@types/estree": "^0.0.48",
"@vue/compiler-core": "3.1.2",
"@vue/compiler-dom": "3.1.2",
"@vue/compiler-ssr": "3.1.2",
"@vue/shared": "3.1.2",
"consolidate": "^0.16.0",
"estree-walker": "^2.0.1",
"hash-sum": "^2.0.0",
"lru-cache": "^5.1.1",
"magic-string": "^0.25.7",
"merge-source-map": "^1.1.0",
"postcss": "^8.1.10",
"postcss-modules": "^4.0.0",
"postcss-selector-parser": "^6.0.4",
"source-map": "^0.6.1"
}
},
"@vue/compiler-ssr": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.1.2.tgz",
"integrity": "sha512-BwXo9LFk5OSWdMyZQ4bX1ELHX0Z/9F+ld/OaVnpUPzAZCHslBYLvyKUVDwv2C/lpLjRffpC2DOUEdl1+RP1aGg==",
"dev": true,
"requires": {
"@vue/compiler-dom": "3.1.2",
"@vue/shared": "3.1.2"
}
},
"@vue/devtools-api": {
"version": "6.0.0-beta.14",
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.0.0-beta.14.tgz",
"integrity": "sha512-44fPrrN1cqcs6bFkT0C+yxTM6PZXLbR+ESh1U1j8UD22yO04gXvxH62HApMjLbS3WqJO/iCNC+CYT+evPQh2EQ=="
},
"@vue/reactivity": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.2.tgz",
"integrity": "sha512-glJzJoN2xE7I2lRvwKM5u1BHRPTd1yc8iaf//Lai/78/uYAvE5DXp5HzWRFOwMlbRvMGJHIQjOqoxj87cDAaag==",
"requires": {
"@vue/shared": "3.1.2"
}
},
"@vue/runtime-core": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.1.2.tgz",
"integrity": "sha512-gsPZG4dRIkixuuKmoj4P9IHgfT0yaFLcqWOM5F/bCk0nxQn1XtxH8oUehWuET726KhbukvDoJfe9G2CKviy80w==",
"requires": {
"@vue/reactivity": "3.1.2",
"@vue/shared": "3.1.2"
}
},
"@vue/runtime-dom": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.1.2.tgz",
"integrity": "sha512-QvINxjLucEZFzp5f0NVu7JqWYCv5TKQfkH2FDs/N6QNE4iKcYtKrWdT0HKfABnVXG28Znqv6rIH0dH4ZAOwxpA==",
"requires": {
"@vue/runtime-core": "3.1.2",
"@vue/shared": "3.1.2",
"csstype": "^2.6.8"
}
},
"@vue/shared": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.2.tgz",
"integrity": "sha512-EmH/poaDWBPJaPILXNI/1fvUbArJQmmTyVCwvvyDYDFnkPoTclAbHRAtyIvqfez7jybTDn077HTNILpxlsoWhg=="
},
"async-validator": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.5.2.tgz",
"integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ=="
},
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true
},
"bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
"dev": true
},
"colorette": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
"dev": true
},
"consolidate": {
"version": "0.16.0",
"resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.16.0.tgz",
"integrity": "sha512-Nhl1wzCslqXYTJVDyJCu3ODohy9OfBMB5uD2BiBTzd7w+QY0lBzafkR8y8755yMYHAaMD4NuzbAw03/xzfw+eQ==",
"dev": true,
"requires": {
"bluebird": "^3.7.2"
}
},
"core-js-pure": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.1.tgz",
"integrity": "sha512-OZuWHDlYcIda8sJLY4Ec6nWq2hRjlyCqCZ+jCflyleMkVt3tPedDVErvHslyS2nbO+SlBFMSBJYvtLMwxnrzjA=="
},
"cropperjs": {
"version": "1.5.12",
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.12.tgz",
"integrity": "sha512-re7UdjE5UnwdrovyhNzZ6gathI4Rs3KGCBSc8HCIjUo5hO42CtzyblmWLj6QWVw7huHyDMfpKxhiO2II77nhDw=="
},
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
},
"csstype": {
"version": "2.6.17",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz",
"integrity": "sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A=="
},
"dayjs": {
"version": "1.10.5",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz",
"integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g=="
},
"element-plus": {
"version": "1.0.2-beta.52",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-1.0.2-beta.52.tgz",
"integrity": "sha512-oAuJHwXyvM4dsuOz7HSDPIBVPqRJ1KEzFzGqYdqbBjQ/aw79uCJxvS9Q4q9/XrPMfPire09+bPTypiIaHkNBhA==",
"requires": {
"@popperjs/core": "^2.4.4",
"@types/lodash": "^4.14.161",
"async-validator": "^3.4.0",
"dayjs": "1.x",
"lodash": "^4.17.20",
"mitt": "^2.1.0",
"normalize-wheel": "^1.0.1",
"resize-observer-polyfill": "^1.5.1"
}
},
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true
},
"esbuild": {
"version": "0.12.9",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.9.tgz",
"integrity": "sha512-MWRhAbMOJ9RJygCrt778rz/qNYgA4ZVj6aXnNPxFjs7PmIpb0fuB9Gmg5uWrr6n++XKwwm/RmSz6RR5JL2Ocsw==",
"dev": true
},
"estree-walker": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"follow-redirects": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz",
"integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg=="
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
"generic-names": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/generic-names/-/generic-names-2.0.1.tgz",
"integrity": "sha512-kPCHWa1m9wGG/OwQpeweTwM/PYiQLrUIxXbt/P4Nic3LbGjCP0YwrALHW1uNLKZ0LIMg+RF+XRlj2ekT9ZlZAQ==",
"dev": true,
"requires": {
"loader-utils": "^1.1.0"
}
},
"has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
"requires": {
"function-bind": "^1.1.1"
}
},
"hash-sum": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
"integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
"dev": true
},
"icss-replace-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
"integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=",
"dev": true
},
"icss-utils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true
},
"is-core-module": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
"integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
"dev": true,
"requires": {
"has": "^1.0.3"
}
},
"json5": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
"integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
"dev": true,
"requires": {
"minimist": "^1.2.0"
}
},
"loader-utils": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
"integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^1.0.1"
}
},
"lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash.camelcase": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=",
"dev": true
},
"lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"requires": {
"yallist": "^3.0.2"
}
},
"magic-string": {
"version": "0.25.7",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz",
"integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==",
"dev": true,
"requires": {
"sourcemap-codec": "^1.4.4"
}
},
"merge-source-map": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
"integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
"dev": true,
"requires": {
"source-map": "^0.6.1"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mitt": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mitt/-/mitt-2.1.0.tgz",
"integrity": "sha512-ILj2TpLiysu2wkBbWjAmww7TkZb65aiQO+DkVdUTBpBXq+MHYiETENkKFMtsJZX1Lf4pe4QOrTSjIfUwN5lRdg=="
},
"nanoid": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
"integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
"dev": true
},
"normalize-wheel": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
"integrity": "sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU="
},
"path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"dev": true
},
"postcss": {
"version": "8.3.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz",
"integrity": "sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA==",
"dev": true,
"requires": {
"colorette": "^1.2.2",
"nanoid": "^3.1.23",
"source-map-js": "^0.6.2"
}
},
"postcss-modules": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.1.3.tgz",
"integrity": "sha512-dBT39hrXe4OAVYJe/2ZuIZ9BzYhOe7t+IhedYeQ2OxKwDpAGlkEN/fR0fGnrbx4BvgbMReRX4hCubYK9cE/pJQ==",
"dev": true,
"requires": {
"generic-names": "^2.0.1",
"icss-replace-symbols": "^1.1.0",
"lodash.camelcase": "^4.3.0",
"postcss-modules-extract-imports": "^3.0.0",
"postcss-modules-local-by-default": "^4.0.0",
"postcss-modules-scope": "^3.0.0",
"postcss-modules-values": "^4.0.0",
"string-hash": "^1.1.1"
}
},
"postcss-modules-extract-imports": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
"dev": true
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz",
"integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==",
"dev": true,
"requires": {
"icss-utils": "^5.0.0",
"postcss-selector-parser": "^6.0.2",
"postcss-value-parser": "^4.1.0"
}
},
"postcss-modules-scope": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
"integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
"dev": true,
"requires": {
"postcss-selector-parser": "^6.0.4"
}
},
"postcss-modules-values": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
"integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
"dev": true,
"requires": {
"icss-utils": "^5.0.0"
}
},
"postcss-selector-parser": {
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz",
"integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
}
},
"postcss-value-parser": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz",
"integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==",
"dev": true
},
"regenerator-runtime": {
"version": "0.13.7",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
},
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"resolve": {
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
"dev": true,
"requires": {
"is-core-module": "^2.2.0",
"path-parse": "^1.0.6"
}
},
"rollup": {
"version": "2.52.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.52.3.tgz",
"integrity": "sha512-QF3Sju8Kl2z0osI4unyOLyUudyhOMK6G0AeqJWgfiyigqLAlnNrfBcDWDx+f1cqn+JU2iIYVkDrgQ6/KtwEfrg==",
"dev": true,
"requires": {
"fsevents": "~2.3.2"
}
},
"schart.js": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/schart.js/-/schart.js-3.0.4.tgz",
"integrity": "sha512-uylb2u9rrHX1jyAuSAJUQON8XTfyDKI9kWj1J3fUlCQCkLVZ4HG4+IiV8qm//Z71dqvLI78QZ/fCBw0reB22Zw=="
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-js": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
"integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
"dev": true
},
"sourcemap-codec": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
"dev": true
},
"string-hash": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
"dev": true
},
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"tslib": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
"vite": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/vite/-/vite-2.3.7.tgz",
"integrity": "sha512-Y0xRz11MPYu/EAvzN94+FsOZHbSvO6FUvHv127CyG7mV6oDoay2bw+g5y9wW3Blf8OY3chaz3nc/DcRe1IQ3Nw==",
"dev": true,
"requires": {
"esbuild": "^0.12.5",
"fsevents": "~2.3.1",
"postcss": "^8.3.0",
"resolve": "^1.19.0",
"rollup": "^2.38.5"
}
},
"vue": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.1.2.tgz",
"integrity": "sha512-q/rbKpb7aofax4ugqu2k/uj7BYuNPcd6Z5/qJtfkJQsE0NkwVoCyeSh7IZGH61hChwYn3CEkh4bHolvUPxlQ+w==",
"requires": {
"@vue/compiler-dom": "3.1.2",
"@vue/runtime-dom": "3.1.2",
"@vue/shared": "3.1.2"
}
},
"vue-cropperjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/vue-cropperjs/-/vue-cropperjs-5.0.0.tgz",
"integrity": "sha512-RhnC8O33uRZNkn74aiHZwNHnBJOXWlS4P6gsRI0lw4cZlWjKSCywZI9oSI9POlIPI6OYv30jvnHMXGch85tw7w==",
"requires": {
"cropperjs": "^1.5.6"
}
},
"vue-i18n": {
"version": "9.1.6",
"resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.1.6.tgz",
"integrity": "sha512-FEC4HZkTH6QRIu/A0wlo0VS/GH3w/fuCC6xfvoC8IyhhtbG9A+go9NfW+HZ1ZXdAcO4EWcVQi04M+iSwuxgixw==",
"requires": {
"@intlify/core-base": "9.1.6",
"@intlify/shared": "9.1.6",
"@intlify/vue-devtools": "9.1.6",
"@vue/devtools-api": "^6.0.0-beta.7"
}
},
"vue-router": {
"version": "4.0.10",
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.10.tgz",
"integrity": "sha512-YbPf6QnZpyyWfnk7CUt2Bme+vo7TLfg1nGZNkvYqKYh4vLaFw6Gn8bPGdmt5m4qrGnKoXLqc4htAsd3dIukICA==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.14"
}
},
"vue-schart": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vue-schart/-/vue-schart-2.0.0.tgz",
"integrity": "sha512-qAu3e5wfMcq26wK1xeHExEWfGpnjfoN1R/9QXblNi+AsU/p52X7tTwhi+Fw7H/otfEufhEY2X7z7emaoF4QO+g==",
"requires": {
"schart.js": "^3.0.0"
}
},
"vuex": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.0.2.tgz",
"integrity": "sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
},
"wangeditor": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/wangeditor/-/wangeditor-4.7.4.tgz",
"integrity": "sha512-MVWJyFZm3SOhIGFsxDwD6Q0ahIWQTYU0/otHxq85EnfdxtJBJ8c55iKDp3zIvBZaiBawBiYCpRmbn8HOedNj5w==",
"requires": {
"@babel/runtime": "^7.11.2",
"@babel/runtime-corejs3": "^7.11.2",
"tslib": "^2.1.0"
}
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true
}
}
}

View File

@ -1,56 +1,31 @@
{
"name": "vue-manage-system",
"version": "5.0.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "~3.9.1",
"element-plus": "1.0.2-beta.33",
"vue": "~3.0.7",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.0.0",
"vue-loader-v16": "^16.0.0-beta.5.4",
"vue-router": "~4.0.4",
"vue-schart": "^2.0.0",
"vuex": "~4.0.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.11",
"@vue/cli-plugin-eslint": "~4.5.11",
"@vue/cli-plugin-router": "~4.5.11",
"@vue/cli-plugin-vuex": "~4.5.11",
"@vue/cli-service": "~4.5.11",
"@vue/compiler-sfc": "~3.0.7",
"babel-eslint": "~10.1.0",
"eslint": "~6.8.0",
"eslint-plugin-vue": "~7.7.0",
"sass": "~1.32.8",
"sass-loader": "~8.0.2",
"vue-cli-plugin-element-plus": "0.0.13",
"webpack": "4.44.2"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
"name": "vue-manage-system",
"version": "5.1.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"axios": "^0.21.1",
"element-plus": "1.0.2-beta.52",
"vue": "^3.1.2",
"vue-cropperjs": "^5.0.0",
"vue-i18n": "^9.0.0",
"vue-router": "^4.0.10",
"vue-schart": "^2.0.0",
"vuex": "^4.0.2",
"wangeditor": "^4.7.4"
},
"devDependencies": {
"vite": "2.3.7",
"@vitejs/plugin-vue": "^1.2.3",
"@vue/compiler-sfc": "^3.1.2"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}

View File

@ -10,11 +10,7 @@
<div class="header-user-con">
<!-- 消息中心 -->
<div class="btn-bell">
<el-tooltip
effect="dark"
:content="message?`有${message}条未读消息`:`消息中心`"
placement="bottom"
>
<el-tooltip effect="dark" :content="message?`有${message}条未读消息`:`消息中心`" placement="bottom">
<router-link to="/tabs">
<i class="el-icon-bell"></i>
</router-link>
@ -36,6 +32,7 @@
<a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
<el-dropdown-item>项目仓库</el-dropdown-item>
</a>
<el-dropdown-item command="user">个人中心</el-dropdown-item>
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
@ -45,41 +42,46 @@
</div>
</template>
<script>
import { computed, onMounted } from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
export default {
data() {
return {
fullscreen: false,
name: "linxin",
message: 2
setup() {
const username = localStorage.getItem("ms_username");
const message = 2;
const store = useStore();
const collapse = computed(() => store.state.collapse);
//
const collapseChage = () => {
store.commit("handleCollapse", !collapse.value);
};
},
computed: {
username() {
let username = localStorage.getItem("ms_username");
return username ? username : this.name;
},
collapse() {
return this.$store.state.collapse;
}
},
methods: {
onMounted(() => {
if (document.body.clientWidth < 1500) {
collapseChage();
}
});
//
handleCommand(command) {
const router = useRouter();
const handleCommand = (command) => {
if (command == "loginout") {
localStorage.removeItem("ms_username");
this.$router.push("/login");
router.push("/login");
} else if (command == "user") {
router.push("/user");
}
},
//
collapseChage() {
this.$store.commit("hadndleCollapse", !this.collapse);
}
};
return {
username,
message,
collapse,
collapseChage,
handleCommand,
};
},
mounted() {
if (document.body.clientWidth < 1500) {
this.collapseChage();
}
}
};
</script>
<style scoped>

View File

@ -1,15 +1,7 @@
<template>
<div class="sidebar">
<el-menu
class="sidebar-el-menu"
:default-active="onRoutes"
:collapse="collapse"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#20a0ff"
unique-opened
router
>
<el-menu class="sidebar-el-menu" :default-active="onRoutes" :collapse="collapse" background-color="#324157"
text-color="#bfcbd9" active-text-color="#20a0ff" unique-opened router>
<template v-for="item in items">
<template v-if="item.subs">
<el-submenu :index="item.index" :key="item.index">
@ -18,23 +10,13 @@
<span>{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu
v-if="subItem.subs"
:index="subItem.index"
:key="subItem.index"
>
<el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
<template #title>{{ subItem.title }}</template>
<el-menu-item
v-for="(threeItem, i) in subItem.subs"
:key="i"
:index="threeItem.index"
>{{ threeItem.title }}</el-menu-item>
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
{{ threeItem.title }}</el-menu-item>
</el-submenu>
<el-menu-item
v-else
:index="subItem.index"
:key="subItem.index"
>{{ subItem.title }}</el-menu-item>
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}
</el-menu-item>
</template>
</el-submenu>
</template>
@ -50,116 +32,104 @@
</template>
<script>
// import bus from "../common/bus";
import { computed, watch } from "vue";
import { useStore } from "vuex";
import { useRoute } from "vue-router";
export default {
data() {
setup() {
const items = [
{
icon: "el-icon-lx-home",
index: "/dashboard",
title: "系统首页",
},
{
icon: "el-icon-lx-cascades",
index: "/table",
title: "基础表格",
},
{
icon: "el-icon-lx-copy",
index: "/tabs",
title: "tab选项卡",
},
{
icon: "el-icon-lx-calendar",
index: "3",
title: "表单相关",
subs: [
{
index: "/form",
title: "基本表单",
},
{
index: "/upload",
title: "文件上传",
},
{
index: "4",
title: "三级菜单",
subs: [
{
index: "/editor",
title: "富文本编辑器",
},
],
},
],
},
{
icon: "el-icon-lx-emoji",
index: "/icon",
title: "自定义图标",
},
{
icon: "el-icon-pie-chart",
index: "/charts",
title: "schart图表",
},
{
icon: "el-icon-lx-global",
index: "/i18n",
title: "国际化功能",
},
{
icon: "el-icon-lx-warn",
index: "7",
title: "错误处理",
subs: [
{
index: "/permission",
title: "权限测试",
},
{
index: "/404",
title: "404页面",
},
],
},
{
icon: "el-icon-lx-redpacket_fill",
index: "/donate",
title: "支持作者",
},
];
const route = useRoute();
const onRoutes = computed(() => {
return route.path;
});
const store = useStore();
const collapse = computed(() => store.state.collapse);
return {
items: [
{
icon: "el-icon-lx-home",
index: "dashboard",
title: "系统首页"
},
{
icon: "el-icon-lx-cascades",
index: "table",
title: "基础表格"
},
{
icon: "el-icon-lx-copy",
index: "tabs",
title: "tab选项卡"
},
{
icon: "el-icon-lx-calendar",
index: "3",
title: "表单相关",
subs: [
{
index: "form",
title: "基本表单"
},
// {
// index: "3-2",
// title: "",
// subs: [
// {
// index: "editor",
// title: ""
// },
// {
// index: "markdown",
// title: "markdown"
// }
// ]
// },
{
index: "upload",
title: "文件上传"
}
]
},
{
icon: "el-icon-lx-emoji",
index: "icon",
title: "自定义图标"
},
{
icon: "el-icon-pie-chart",
index: "charts",
title: "schart图表"
},
// {
// icon: "el-icon-rank",
// index: "6",
// title: "",
// subs: [
// {
// index: "drag",
// title: ""
// },
// {
// index: "dialog",
// title: ""
// }
// ]
// },
{
icon: "el-icon-lx-global",
index: "i18n",
title: "国际化功能"
},
{
icon: "el-icon-lx-warn",
index: "7",
title: "错误处理",
subs: [
{
index: "permission",
title: "权限测试"
},
{
index: "404",
title: "404页面"
}
]
},
{
icon: "el-icon-lx-redpacket_fill",
index: "/donate",
title: "支持作者"
}
]
items,
onRoutes,
collapse,
};
},
computed: {
onRoutes() {
return this.$route.path.replace("/", "");
},
collapse(){
return this.$store.state.collapse
}
}
};
</script>

View File

@ -1,12 +1,7 @@
<template>
<div class="tags" v-if="showTags">
<ul>
<li
class="tags-li"
v-for="(item,index) in tagsList"
:class="{'active': isActive(item.path)}"
:key="index"
>
<li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index">
<router-link :to="item.path" class="tags-li-title">{{item.title}}</router-link>
<span class="tags-li-icon" @click="closeTags(index)">
<i class="el-icon-close"></i>
@ -31,78 +26,86 @@
</template>
<script>
import { computed } from "vue";
import { useStore } from "vuex";
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
export default {
computed: {
tagsList() {
return this.$store.state.tagsList;
},
showTags() {
return this.tagsList.length > 0;
}
},
methods: {
isActive(path) {
return path === this.$route.fullPath;
},
setup() {
const route = useRoute();
const router = useRouter();
const isActive = (path) => {
return path === route.fullPath;
};
const store = useStore();
const tagsList = computed(() => store.state.tagsList);
const showTags = computed(() => tagsList.value.length > 0);
//
closeTags(index) {
const delItem = this.tagsList[index];
this.$store.commit("delTagsItem", { index });
const item = this.tagsList[index]
? this.tagsList[index]
: this.tagsList[index - 1];
const closeTags = (index) => {
const delItem = tagsList.value[index];
store.commit("delTagsItem", { index });
const item = tagsList.value[index]
? tagsList.value[index]
: tagsList.value[index - 1];
if (item) {
delItem.path === this.$route.fullPath &&
this.$router.push(item.path);
delItem.path === route.fullPath && router.push(item.path);
} else {
this.$router.push("/");
router.push("/");
}
},
//
closeAll() {
this.$store.commit("clearTags");
this.$router.push("/");
},
//
closeOther() {
const curItem = this.tagsList.filter(item => {
return item.path === this.$route.fullPath;
});
this.$store.commit("closeTagsOther", curItem);
},
};
//
setTags(route) {
const isExist = this.tagsList.some(item => {
const setTags = (route) => {
const isExist = tagsList.value.some((item) => {
return item.path === route.fullPath;
});
if (!isExist) {
if (this.tagsList.length >= 8) {
this.$store.commit("delTagsItem", { index: 0 });
if (tagsList.value.length >= 8) {
store.commit("delTagsItem", { index: 0 });
}
this.$store.commit("setTagsItem", {
store.commit("setTagsItem", {
name: route.name,
title: route.meta.title,
path: route.fullPath
path: route.fullPath,
});
}
},
handleTags(command) {
command === "other" ? this.closeOther() : this.closeAll();
}
},
watch: {
$route(newValue) {
this.setTags(newValue);
}
},
created() {
this.setTags(this.$route);
};
setTags(route);
onBeforeRouteUpdate((to) => {
setTags(to);
});
//
const closeAll = () => {
store.commit("clearTags");
router.push("/");
};
//
const closeOther = () => {
const curItem = tagsList.value.filter((item) => {
return item.path === route.fullPath;
});
store.commit("closeTagsOther", curItem);
};
const handleTags = (command) => {
command === "other" ? closeOther() : closeAll();
};
//
// this.$store.commit("closeCurrentTag", {
// $router: this.$router,
// $route: this.$route
// store.commit("closeCurrentTag", {
// $router: router,
// $route: route
// });
}
return {
isActive,
tagsList,
showTags,
closeTags,
handleTags,
};
},
};
</script>

View File

@ -4,18 +4,6 @@ import 'element-plus/lib/theme-chalk/index.css'
import localeZH from 'element-plus/lib/locale/lang/zh-cn'
import localeEN from 'element-plus/lib/locale/lang/en'
import messages from '../utils/i18n'
// console.log(msg)
// const messages = {
// [localeEN.name]: {
// el: localeEN.el,
// i18n: msg.en.i18n,
// },
// [localeZH.name]: {
// el: localeZH.el,
// i18n: msg.zh.i18n,
// },
// }
const i18n = createI18n({
locale: localeZH.name,

View File

@ -1,4 +1,4 @@
import {createRouter, createWebHistory} from "vue-router";
import {createRouter, createWebHashHistory} from "vue-router";
import Home from "../views/Home.vue";
const routes = [
@ -16,54 +16,42 @@ const routes = [
meta: {
title: '系统首页'
},
component: () => import (
/* webpackChunkName: "dashboard" */
"../views/Dashboard.vue")
component: () => import ( /* webpackChunkName: "dashboard" */ "../views/Dashboard.vue")
}, {
path: "/table",
name: "basetable",
meta: {
title: '表格'
},
component: () => import (
/* webpackChunkName: "table" */
"../views/BaseTable.vue")
component: () => import ( /* webpackChunkName: "table" */ "../views/BaseTable.vue")
}, {
path: "/charts",
name: "basecharts",
meta: {
title: '图表'
},
component: () => import (
/* webpackChunkName: "charts" */
"../views/BaseCharts.vue")
component: () => import ( /* webpackChunkName: "charts" */ "../views/BaseCharts.vue")
}, {
path: "/form",
name: "baseform",
meta: {
title: '表单'
},
component: () => import (
/* webpackChunkName: "form" */
"../views/BaseForm.vue")
component: () => import ( /* webpackChunkName: "form" */ "../views/BaseForm.vue")
}, {
path: "/tabs",
name: "tabs",
meta: {
title: 'tab标签'
},
component: () => import (
/* webpackChunkName: "tabs" */
"../views/Tabs.vue")
component: () => import ( /* webpackChunkName: "tabs" */ "../views/Tabs.vue")
}, {
path: "/donate",
name: "donate",
meta: {
title: '鼓励作者'
},
component: () => import (
/* webpackChunkName: "donate" */
"../views/Donate.vue")
component: () => import ( /* webpackChunkName: "donate" */ "../views/Donate.vue")
}, {
path: "/permission",
name: "permission",
@ -71,52 +59,56 @@ const routes = [
title: '权限管理',
permission: true
},
component: () => import (
/* webpackChunkName: "permission" */
"../views/Permission.vue")
component: () => import ( /* webpackChunkName: "permission" */ "../views/Permission.vue")
}, {
path: "/i18n",
name: "i18n",
meta: {
title: '国际化语言'
},
component: () => import (
/* webpackChunkName: "i18n" */
"../views/I18n.vue")
component: () => import ( /* webpackChunkName: "i18n" */ "../views/I18n.vue")
}, {
path: "/upload",
name: "upload",
meta: {
title: '上传插件'
},
component: () => import (
/* webpackChunkName: "upload" */
"../views/Upload.vue")
component: () => import ( /* webpackChunkName: "upload" */ "../views/Upload.vue")
}, {
path: "/icon",
name: "icon",
meta: {
title: '自定义图标'
},
component: () => import (
/* webpackChunkName: "icon" */
"../views/Icon.vue")
component: () => import ( /* webpackChunkName: "icon" */ "../views/Icon.vue")
}, {
path: '/404',
name: '404',
meta: {
title: '找不到页面'
},
component: () => import (/* webpackChunkName: "404" */
'../views/404.vue')
component: () => import (/* webpackChunkName: "404" */ '../views/404.vue')
}, {
path: '/403',
name: '403',
meta: {
title: '没有权限'
},
component: () => import (/* webpackChunkName: "403" */
'../views/403.vue')
component: () => import (/* webpackChunkName: "403" */ '../views/403.vue')
}, {
path: '/user',
name: 'user',
meta: {
title: '个人中心'
},
component: () => import (/* webpackChunkName: "user" */ '../views/User.vue')
}, {
path: '/editor',
name: 'editor',
meta: {
title: '富文本编辑器'
},
component: () => import (/* webpackChunkName: "editor" */ '../views/Editor.vue')
}
]
}, {
@ -125,14 +117,12 @@ const routes = [
meta: {
title: '登录'
},
component: () => import (
/* webpackChunkName: "login" */
"../views/Login.vue")
component: () => import ( /* webpackChunkName: "login" */ "../views/Login.vue")
}
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
history: createWebHashHistory(),
routes
});

View File

@ -47,7 +47,7 @@ export default createStore({
}
},
// 侧边栏折叠
hadndleCollapse(state, data) {
handleCollapse(state, data) {
state.collapse = data;
}
},

View File

@ -1,56 +1,62 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>3</div>
<div class="error-desc">啊哦~ 你没有权限访问该页面哦</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack"></el-button>
</div>
</div>
<div class="error-page">
<div class="error-code">4<span>0</span>3</div>
<div class="error-desc">啊哦~ 你没有权限访问该页面哦</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack"></el-button>
</div>
</div>
</template>
<script>
import { useRouter } from "vue-router";
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
name: "404",
setup() {
const router = useRouter();
const goBack = () => {
router.go(-1);
};
return {
goBack,
};
},
};
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #f02d2d;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
.error-page {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code {
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #f02d2d;
}
.error-code span {
color: #00a854;
}
.error-desc {
font-size: 30px;
color: #777;
}
.error-handle {
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn {
margin-left: 100px;
}
</style>

View File

@ -1,56 +1,62 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>4</div>
<div class="error-desc">啊哦~ 你所访问的页面不存在</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack"></el-button>
</div>
</div>
<div class="error-page">
<div class="error-code">4<span>0</span>4</div>
<div class="error-desc">啊哦~ 你所访问的页面不存在</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack"></el-button>
</div>
</div>
</template>
<script>
import { useRouter } from "vue-router";
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
name: "404",
setup() {
const router = useRouter();
const goBack = () => {
router.go(-1);
};
return {
goBack,
};
},
};
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #2d8cf0;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
.error-page {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code {
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #2d8cf0;
}
.error-code span {
color: #00a854;
}
.error-desc {
font-size: 30px;
color: #777;
}
.error-handle {
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn {
margin-left: 100px;
}
</style>

View File

@ -1,5 +0,0 @@
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>

View File

@ -11,10 +11,7 @@
<div class="plugins-tips">
vue-schartvue.js封装sChart.js的图表组件
访问地址
<a
href="https://github.com/lin-xin/vue-schart"
target="_blank"
>vue-schart</a>
<a href="https://github.com/lin-xin/vue-schart" target="_blank">vue-schart</a>
</div>
<div class="schart-box">
<div class="content-title">柱状图</div>
@ -37,95 +34,107 @@
</template>
<script>
import Schart from 'vue-schart';
import Schart from "vue-schart";
export default {
name: 'basecharts',
name: "basecharts",
components: {
Schart
Schart,
},
data() {
return {
options1: {
type: 'bar',
title: {
text: '最近一周各品类销售图'
},
bgColor: '#fbfbfb',
labels: ['周一', '周二', '周三', '周四', '周五'],
datasets: [
{
label: '家电',
fillColor: 'rgba(241, 49, 74, 0.5)',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 190, 135, 160]
},
{
label: '食品',
data: [144, 198, 150, 235, 120]
}
]
setup() {
const options1 = {
type: "bar",
title: {
text: "最近一周各品类销售图",
},
options2: {
type: 'line',
title: {
text: '最近几个月各品类销售趋势图'
bgColor: "#fbfbfb",
labels: ["周一", "周二", "周三", "周四", "周五"],
datasets: [
{
label: "家电",
fillColor: "rgba(241, 49, 74, 0.5)",
data: [234, 278, 270, 190, 230],
},
bgColor: '#fbfbfb',
labels: ['6月', '7月', '8月', '9月', '10月'],
datasets: [
{
label: '家电',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 150, 135, 160]
},
{
label: '食品',
data: [114, 138, 200, 235, 190]
}
]
},
options3: {
type: 'pie',
title: {
text: '服装品类销售饼状图'
{
label: "百货",
data: [164, 178, 190, 135, 160],
},
legend: {
position: 'left'
{
label: "食品",
data: [144, 198, 150, 235, 120],
},
bgColor: '#fbfbfb',
labels: ['T恤', '牛仔裤', '连衣裙', '毛衣', '七分裤', '短裙', '羽绒服'],
datasets: [
{
data: [334, 278, 190, 235, 260, 200, 141]
}
]
},
options4: {
type: 'ring',
title: {
text: '环形三等分'
},
showValue: false,
legend: {
position: 'bottom',
bottom: 40
},
bgColor: '#fbfbfb',
labels: ['vue', 'react', 'angular'],
datasets: [
{
data: [500, 500, 500]
}
]
}
],
};
}
const options2 = {
type: "line",
title: {
text: "最近几个月各品类销售趋势图",
},
bgColor: "#fbfbfb",
labels: ["6月", "7月", "8月", "9月", "10月"],
datasets: [
{
label: "家电",
data: [234, 278, 270, 190, 230],
},
{
label: "百货",
data: [164, 178, 150, 135, 160],
},
{
label: "食品",
data: [114, 138, 200, 235, 190],
},
],
};
const options3 = {
type: "pie",
title: {
text: "服装品类销售饼状图",
},
legend: {
position: "left",
},
bgColor: "#fbfbfb",
labels: [
"T恤",
"牛仔裤",
"连衣裙",
"毛衣",
"七分裤",
"短裙",
"羽绒服",
],
datasets: [
{
data: [334, 278, 190, 235, 260, 200, 141],
},
],
};
const options4 = {
type: "ring",
title: {
text: "环形三等分",
},
showValue: false,
legend: {
position: "bottom",
bottom: 40,
},
bgColor: "#fbfbfb",
labels: ["vue", "react", "angular"],
datasets: [
{
data: [500, 500, 500],
},
],
};
return {
options1,
options2,
options3,
options4,
};
},
};
</script>

View File

@ -10,11 +10,11 @@
</div>
<div class="container">
<div class="form-box">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="表单名称">
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px">
<el-form-item label="表单名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="选择器">
<el-form-item label="选择器" prop="region">
<el-select v-model="form.region" placeholder="请选择">
<el-option key="bbk" label="步步高" value="bbk"></el-option>
<el-option key="xtc" label="小天才" value="xtc"></el-option>
@ -23,48 +23,45 @@
</el-form-item>
<el-form-item label="日期时间">
<el-col :span="11">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.date1"
style="width: 100%;"
></el-date-picker>
<el-form-item prop="date1">
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
style="width: 100%;"></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker
placeholder="选择时间"
v-model="form.date2"
style="width: 100%;"
></el-time-picker>
<el-form-item prop="date2">
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;">
</el-time-picker>
</el-form-item>
</el-col>
</el-form-item>
<el-form-item label="城市级联">
<el-form-item label="城市级联" prop="options">
<el-cascader :options="options" v-model="form.options"></el-cascader>
</el-form-item>
<el-form-item label="选择开关">
<el-form-item label="选择开关" prop="delivery">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="多选框">
<el-form-item label="多选框" prop="type">
<el-checkbox-group v-model="form.type">
<el-checkbox label="步步高" name="type"></el-checkbox>
<el-checkbox label="小天才" name="type"></el-checkbox>
<el-checkbox label="imoo" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="单选框">
<el-form-item label="单选框" prop="resource">
<el-radio-group v-model="form.resource">
<el-radio label="步步高"></el-radio>
<el-radio label="小天才"></el-radio>
<el-radio label="imoo"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="文本框">
<el-form-item label="文本框" prop="desc">
<el-input type="textarea" rows="5" v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit"></el-button>
<el-button>取消</el-button>
<el-button @click="onReset"></el-button>
</el-form-item>
</el-form>
</div>
@ -73,79 +70,105 @@
</template>
<script>
import { reactive, ref } from "vue";
import { ElMessage } from "element-plus";
export default {
name: 'baseform',
data() {
return {
options: [
{
value: 'guangdong',
label: '广东省',
children: [
{
value: 'guangzhou',
label: '广州市',
children: [
{
value: 'tianhe',
label: '天河区'
},
{
value: 'haizhu',
label: '海珠区'
}
]
},
{
value: 'dongguan',
label: '东莞市',
children: [
{
value: 'changan',
label: '长安镇'
},
{
value: 'humen',
label: '虎门镇'
}
]
}
]
},
{
value: 'hunan',
label: '湖南省',
children: [
{
value: 'changsha',
label: '长沙市',
children: [
{
value: 'yuelu',
label: '岳麓区'
}
]
}
]
}
name: "baseform",
setup() {
const options = [
{
value: "guangdong",
label: "广东省",
children: [
{
value: "guangzhou",
label: "广州市",
children: [
{
value: "tianhe",
label: "天河区",
},
{
value: "haizhu",
label: "海珠区",
},
],
},
{
value: "dongguan",
label: "东莞市",
children: [
{
value: "changan",
label: "长安镇",
},
{
value: "humen",
label: "虎门镇",
},
],
},
],
},
{
value: "hunan",
label: "湖南省",
children: [
{
value: "changsha",
label: "长沙市",
children: [
{
value: "yuelu",
label: "岳麓区",
},
],
},
],
},
];
const rules = {
name: [
{ required: true, message: "请输入表单名称", trigger: "blur" },
],
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: true,
type: ['步步高'],
resource: '小天才',
desc: '',
options: []
}
};
const formRef = ref(null);
const form = reactive({
name: "",
region: "",
date1: "",
date2: "",
delivery: true,
type: ["步步高"],
resource: "小天才",
desc: "",
options: [],
});
//
const onSubmit = () => {
//
formRef.value.validate((valid) => {
if (valid) {
console.log(form);
ElMessage.success("提交成功!");
} else {
return false;
}
});
};
//
const onReset = () => {
formRef.value.resetFields();
};
return {
options,
rules,
formRef,
form,
onSubmit,
onReset,
};
},
methods: {
onSubmit() {
this.$message.success('提交成功!');
}
}
};
</script>

View File

@ -9,12 +9,6 @@
</div>
<div class="container">
<div class="handle-box">
<el-button
type="primary"
icon="el-icon-delete"
class="handle-del mr10"
@click="delAllSelection"
>批量删除</el-button>
<el-select v-model="query.address" placeholder="地址" class="handle-select mr10">
<el-option key="1" label="广东省" value="广东省"></el-option>
<el-option key="2" label="湖南省" value="湖南省"></el-option>
@ -22,15 +16,7 @@
<el-input v-model="query.name" placeholder="用户名" class="handle-input mr10"></el-input>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"></el-button>
</div>
<el-table
:data="tableData"
border
class="table"
ref="multipleTable"
header-cell-class-name="table-header"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
<el-table-column prop="name" label="用户名"></el-table-column>
<el-table-column label="账户余额">
@ -38,60 +24,42 @@
</el-table-column>
<el-table-column label="头像(查看大图)" align="center">
<template #default="scope">
<el-image
class="table-td-thumb"
:src="scope.row.thumb"
:preview-src-list="[scope.row.thumb]"
></el-image>
<el-image class="table-td-thumb" :src="scope.row.thumb" :preview-src-list="[scope.row.thumb]">
</el-image>
</template>
</el-table-column>
<el-table-column prop="address" label="地址"></el-table-column>
<el-table-column label="状态" align="center">
<template #default="scope">
<el-tag
:type="
<el-tag :type="
scope.row.state === '成功'
? 'success'
: scope.row.state === '失败'
? 'danger'
: ''
"
>{{ scope.row.state }}</el-tag>
">{{ scope.row.state }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="date" label="注册时间"></el-table-column>
<el-table-column label="操作" width="180" align="center">
<template #default="scope">
<el-button
type="text"
icon="el-icon-edit"
@click="handleEdit(scope.$index, scope.row)"
>编辑</el-button>
<el-button
type="text"
icon="el-icon-delete"
class="red"
@click="handleDelete(scope.$index, scope.row)"
>删除</el-button>
<el-button type="text" icon="el-icon-edit" @click="handleEdit(scope.$index, scope.row)">编辑
</el-button>
<el-button type="text" icon="el-icon-delete" class="red"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
layout="total, prev, pager, next"
:current-page="query.pageIndex"
:page-size="query.pageSize"
:total="pageTotal"
@current-change="handlePageChange"
></el-pagination>
<el-pagination background layout="total, prev, pager, next" :current-page="query.pageIndex"
:page-size="query.pageSize" :total="pageTotal" @current-change="handlePageChange"></el-pagination>
</div>
</div>
<!-- 编辑弹出框 -->
<el-dialog title="编辑" v-model="editVisible" width="30%">
<el-form ref="form" :model="form" label-width="70px">
<el-form label-width="70px">
<el-form-item label="用户名">
<el-input v-model="form.name"></el-input>
</el-form-item>
@ -110,88 +78,89 @@
</template>
<script>
import { ref, reactive } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { fetchData } from "../api/index";
export default {
name: "basetable",
data() {
return {
query: {
address: "",
name: "",
pageIndex: 1,
pageSize: 10
},
tableData: [],
multipleSelection: [],
delList: [],
editVisible: false,
pageTotal: 0,
form: {},
idx: -1,
id: -1
};
},
created() {
this.getData();
},
methods: {
// easy-mock
getData() {
fetchData(this.query).then(res => {
console.log(res);
this.tableData = res.list;
this.pageTotal = res.pageTotal || 50;
setup() {
const query = reactive({
address: "",
name: "",
pageIndex: 1,
pageSize: 10,
});
const tableData = ref([]);
const pageTotal = ref(0);
//
const getData = () => {
fetchData(query).then((res) => {
tableData.value = res.list;
pageTotal.value = res.pageTotal || 50;
});
},
//
handleSearch() {
this.$set(this.query, "pageIndex", 1);
this.getData();
},
};
getData();
//
const handleSearch = () => {
query.pageIndex = 1;
getData();
};
//
const handlePageChange = (val) => {
query.pageIndex = val;
getData();
};
//
handleDelete(index) {
const handleDelete = (index) => {
//
this.$confirm("确定要删除吗?", "提示", {
type: "warning"
ElMessageBox.confirm("确定要删除吗?", "提示", {
type: "warning",
})
.then(() => {
this.$message.success("删除成功");
this.tableData.splice(index, 1);
ElMessage.success("删除成功");
tableData.value.splice(index, 1);
})
.catch(() => {});
},
//
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
const length = this.multipleSelection.length;
let str = "";
this.delList = this.delList.concat(this.multipleSelection);
for (let i = 0; i < length; i++) {
str += this.multipleSelection[i].name + " ";
}
this.$message.error(`删除了${str}`);
this.multipleSelection = [];
},
//
handleEdit(index, row) {
this.idx = index;
this.form = row;
this.editVisible = true;
},
//
saveEdit() {
this.editVisible = false;
this.$message.success(`修改第 ${this.idx + 1} 行成功`);
this.$set(this.tableData, this.idx, this.form);
},
//
handlePageChange(val) {
this.$set(this.query, "pageIndex", val);
this.getData();
}
}
};
//
const editVisible = ref(false);
let form = reactive({
name: "",
address: "",
});
let idx = -1;
const handleEdit = (index, row) => {
idx = index;
Object.keys(form).forEach((item) => {
form[item] = row[item];
});
editVisible.value = true;
};
const saveEdit = () => {
editVisible.value = false;
ElMessage.success(`修改第 ${idx + 1} 行成功`);
Object.keys(form).forEach((item) => {
tableData.value[idx][item] = form[item];
});
};
return {
query,
tableData,
pageTotal,
editVisible,
form,
handleSearch,
handlePageChange,
handleDelete,
handleEdit,
saveEdit,
};
},
};
</script>

View File

@ -84,12 +84,9 @@
</el-table-column>
<el-table-column>
<template #default="scope">
<div
class="todo-item"
:class="{
<div class="todo-item" :class="{
'todo-item-del': scope.row.status,
}"
>{{ scope.row.title }}</div>
}">{{ scope.row.title }}</div>
</template>
</el-table-column>
<el-table-column width="60">
@ -119,131 +116,123 @@
<script>
import Schart from "vue-schart";
import { reactive } from "vue";
export default {
name: "dashboard",
data() {
return {
name: localStorage.getItem("ms_username"),
todoList: [
{
title: "今天要修复100个bug",
status: false
},
{
title: "今天要修复100个bug",
status: false
},
{
title: "今天要写100行代码加几个bug吧",
status: false
},
{
title: "今天要修复100个bug",
status: false
},
{
title: "今天要修复100个bug",
status: true
},
{
title: "今天要写100行代码加几个bug吧",
status: true
}
],
data: [
{
name: "2018/09/04",
value: 1083
},
{
name: "2018/09/05",
value: 941
},
{
name: "2018/09/06",
value: 1139
},
{
name: "2018/09/07",
value: 816
},
{
name: "2018/09/08",
value: 327
},
{
name: "2018/09/09",
value: 228
},
{
name: "2018/09/10",
value: 1065
}
],
options: {
type: "bar",
title: {
text: "最近一周各品类销售图"
},
xRorate: 25,
labels: ["周一", "周二", "周三", "周四", "周五"],
datasets: [
{
label: "家电",
data: [234, 278, 270, 190, 230]
},
{
label: "百货",
data: [164, 178, 190, 135, 160]
},
{
label: "食品",
data: [144, 198, 150, 235, 120]
}
]
components: { Schart },
setup() {
const name = localStorage.getItem("ms_username");
const role = name === "admin" ? "超级管理员" : "普通用户";
const data = reactive([
{
name: "2018/09/04",
value: 1083,
},
options2: {
type: "line",
title: {
text: "最近几个月各品类销售趋势图"
{
name: "2018/09/05",
value: 941,
},
{
name: "2018/09/06",
value: 1139,
},
{
name: "2018/09/07",
value: 816,
},
{
name: "2018/09/08",
value: 327,
},
{
name: "2018/09/09",
value: 228,
},
{
name: "2018/09/10",
value: 1065,
},
]);
const options = {
type: "bar",
title: {
text: "最近一周各品类销售图",
},
xRorate: 25,
labels: ["周一", "周二", "周三", "周四", "周五"],
datasets: [
{
label: "家电",
data: [234, 278, 270, 190, 230],
},
labels: ["6月", "7月", "8月", "9月", "10月"],
datasets: [
{
label: "家电",
data: [234, 278, 270, 190, 230]
},
{
label: "百货",
data: [164, 178, 150, 135, 160]
},
{
label: "食品",
data: [74, 118, 200, 235, 90]
}
]
}
{
label: "百货",
data: [164, 178, 190, 135, 160],
},
{
label: "食品",
data: [144, 198, 150, 235, 120],
},
],
};
const options2 = {
type: "line",
title: {
text: "最近几个月各品类销售趋势图",
},
labels: ["6月", "7月", "8月", "9月", "10月"],
datasets: [
{
label: "家电",
data: [234, 278, 270, 190, 230],
},
{
label: "百货",
data: [164, 178, 150, 135, 160],
},
{
label: "食品",
data: [74, 118, 200, 235, 90],
},
],
};
const todoList = reactive([
{
title: "今天要修复100个bug",
status: false,
},
{
title: "今天要修复100个bug",
status: false,
},
{
title: "今天要写100行代码加几个bug吧",
status: false,
},
{
title: "今天要修复100个bug",
status: false,
},
{
title: "今天要修复100个bug",
status: true,
},
{
title: "今天要写100行代码加几个bug吧",
status: true,
},
]);
return {
name,
data,
options,
options2,
todoList,
role,
};
},
components: {
Schart
},
computed: {
role() {
return this.name === "admin" ? "超级管理员" : "普通用户";
}
},
methods: {
changeDate() {
const now = new Date().getTime();
this.data.forEach((item, index) => {
const date = new Date(now - (6 - index) * 86400000);
item.name = `${date.getFullYear()}/${date.getMonth() +
1}/${date.getDate()}`;
});
}
}
};
</script>

58
src/views/Editor.vue Normal file
View File

@ -0,0 +1,58 @@
<template>
<div>
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item>
<i class="el-icon-lx-calendar"></i> 表单
</el-breadcrumb-item>
<el-breadcrumb-item>富文本编辑器</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<div class="plugins-tips">
wangEditor轻量级 web 富文本编辑器配置方便使用简单
访问地址
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
</div>
<div class="mgb20" ref='editor'></div>
<el-button type="primary" @click="syncHTML"></el-button>
</div>
</div>
</template>
<script>
import WangEditor from "wangEditor";
import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
export default {
name: "editor",
setup() {
const editor = ref(null);
const content = reactive({
html: "",
text: "",
});
let instance;
onMounted(() => {
instance = new WangEditor(editor.value);
instance.config.zIndex = 1;
instance.create();
});
onBeforeUnmount(() => {
instance.destroy();
instance = null;
});
const syncHTML = () => {
content.html = instance.txt.html();
console.log(content.html);
};
return {
syncHTML,
editor,
content,
};
},
};
</script>
<style>
</style>

View File

@ -18,22 +18,27 @@
</div>
</template>
<script>
import vHeader from "../components/Header";
import vSidebar from "../components/Sidebar";
import { computed } from "vue";
import { useStore } from "vuex";
import vHeader from "../components/Header.vue";
import vSidebar from "../components/Sidebar.vue";
import vTags from "../components/Tags.vue";
export default {
components: {
vHeader,
vSidebar,
vTags
vTags,
},
setup() {
const store = useStore();
const tagsList = computed(() =>
store.state.tagsList.map((item) => item.name)
);
const collapse = computed(() => store.state.collapse);
return {
tagsList,
collapse,
};
},
computed: {
tagsList() {
return this.$store.state.tagsList.map(item => item.name);
},
collapse() {
return this.$store.state.collapse;
}
}
};
</script>

View File

@ -9,9 +9,7 @@
</div>
<div class="container">
<h2>使用方法</h2>
<p
style="line-height: 50px;"
>直接通过设置类名为 el-icon-lx-iconName 来使用即可例如{{iconList.length}}个图标</p>
<p style="line-height: 50px;">直接通过设置类名为 el-icon-lx-iconName 来使用即可例如{{iconList.length}}个图标</p>
<p class="example-p">
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px;color: #ff5900"></i>
<span>&lt;i class=&quot;el-icon-lx-redpacket_fill&quot;&gt;&lt;/i&gt;</span>
@ -27,13 +25,7 @@
<br />
<h2>图标</h2>
<div class="search-box">
<el-input
class="search"
size="large"
v-model="keyword"
clearable
placeholder="请输入图标名称"
></el-input>
<el-input class="search" size="large" v-model="keyword" clearable placeholder="请输入图标名称"></el-input>
</div>
<ul>
<li class="icon-li" v-for="(item,index) in list" :key="index">
@ -48,147 +40,150 @@
</template>
<script>
import { computed, ref } from "vue";
export default {
name: "icon",
data() {
setup() {
const iconList = [
"attentionforbid",
"attentionforbidfill",
"attention",
"attentionfill",
"tag",
"tagfill",
"people",
"peoplefill",
"notice",
"noticefill",
"mobile",
"mobilefill",
"voice",
"voicefill",
"unlock",
"lock",
"home",
"homefill",
"delete",
"deletefill",
"notification",
"notificationfill",
"notificationforbidfill",
"like",
"likefill",
"comment",
"commentfill",
"camera",
"camerafill",
"warn",
"warnfill",
"time",
"timefill",
"location",
"locationfill",
"favor",
"favorfill",
"skin",
"skinfill",
"news",
"newsfill",
"record",
"recordfill",
"emoji",
"emojifill",
"message",
"messagefill",
"goods",
"goodsfill",
"crown",
"crownfill",
"move",
"add",
"hot",
"hotfill",
"service",
"servicefill",
"present",
"presentfill",
"pic",
"picfill",
"rank",
"rankfill",
"male",
"female",
"down",
"top",
"recharge",
"rechargefill",
"forward",
"forwardfill",
"info",
"infofill",
"redpacket",
"redpacket_fill",
"roundadd",
"roundaddfill",
"friendadd",
"friendaddfill",
"cart",
"cartfill",
"more",
"moreandroid",
"back",
"right",
"shop",
"shopfill",
"question",
"questionfill",
"roundclose",
"roundclosefill",
"roundcheck",
"roundcheckfill",
"global",
"mail",
"punch",
"exit",
"upload",
"read",
"file",
"link",
"full",
"group",
"friend",
"profile",
"addressbook",
"calendar",
"text",
"copy",
"share",
"wifi",
"vipcard",
"weibo",
"remind",
"refresh",
"filter",
"settings",
"scan",
"qrcode",
"cascades",
"apps",
"sort",
"searchlist",
"search",
"edit",
];
const keyword = ref("");
const list = computed(() => {
return iconList.filter((item) => {
return item.indexOf(keyword.value) !== -1;
});
});
return {
keyword: "",
iconList: [
"attentionforbid",
"attentionforbidfill",
"attention",
"attentionfill",
"tag",
"tagfill",
"people",
"peoplefill",
"notice",
"noticefill",
"mobile",
"mobilefill",
"voice",
"voicefill",
"unlock",
"lock",
"home",
"homefill",
"delete",
"deletefill",
"notification",
"notificationfill",
"notificationforbidfill",
"like",
"likefill",
"comment",
"commentfill",
"camera",
"camerafill",
"warn",
"warnfill",
"time",
"timefill",
"location",
"locationfill",
"favor",
"favorfill",
"skin",
"skinfill",
"news",
"newsfill",
"record",
"recordfill",
"emoji",
"emojifill",
"message",
"messagefill",
"goods",
"goodsfill",
"crown",
"crownfill",
"move",
"add",
"hot",
"hotfill",
"service",
"servicefill",
"present",
"presentfill",
"pic",
"picfill",
"rank",
"rankfill",
"male",
"female",
"down",
"top",
"recharge",
"rechargefill",
"forward",
"forwardfill",
"info",
"infofill",
"redpacket",
"redpacket_fill",
"roundadd",
"roundaddfill",
"friendadd",
"friendaddfill",
"cart",
"cartfill",
"more",
"moreandroid",
"back",
"right",
"shop",
"shopfill",
"question",
"questionfill",
"roundclose",
"roundclosefill",
"roundcheck",
"roundcheckfill",
"global",
"mail",
"punch",
"exit",
"upload",
"read",
"file",
"link",
"full",
"group",
"friend",
"profile",
"addressbook",
"calendar",
"text",
"copy",
"share",
"wifi",
"vipcard",
"weibo",
"remind",
"refresh",
"filter",
"settings",
"scan",
"qrcode",
"cascades",
"apps",
"sort",
"searchlist",
"search",
"edit"
]
iconList,
keyword,
list,
};
},
computed: {
list() {
return this.iconList.filter(item => {
return item.indexOf(this.keyword) !== -1;
});
}
}
};
</script>

View File

@ -11,12 +11,8 @@
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
type="password"
placeholder="password"
v-model="param.password"
@keyup.enter="submitForm()"
>
<el-input type="password" placeholder="password" v-model="param.password"
@keyup.enter="submitForm()">
<template #prepend>
<el-button icon="el-icon-lock"></el-button>
</template>
@ -32,40 +28,55 @@
</template>
<script>
import { ref, reactive } from "vue";
import { useStore } from "vuex";
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
export default {
data() {
return {
param: {
username: "admin",
password: "123123"
},
rules: {
username: [
{ required: true, message: "请输入用户名", trigger: "blur" }
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" }
]
}
setup() {
const router = useRouter();
const param = reactive({
username: "admin",
password: "123123",
});
const rules = {
username: [
{
required: true,
message: "请输入用户名",
trigger: "blur",
},
],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
],
};
},
created() {
this.$store.commit("clearTags");
},
methods: {
submitForm() {
this.$refs.login.validate(valid => {
const login = ref(null);
const submitForm = () => {
login.value.validate((valid) => {
if (valid) {
this.$message.success("登录成功");
localStorage.setItem("ms_username", this.param.username);
this.$router.push("/");
ElMessage.success("登录成功");
localStorage.setItem("ms_username", param.username);
router.push("/");
} else {
this.$message.error("请输入账号和密码");
ElMessage.error("登录成功");
return false;
}
});
}
}
};
const store = useStore();
store.commit("clearTags");
return {
param,
rules,
login,
submitForm,
};
},
};
</script>

View File

@ -7,8 +7,8 @@
</div>
<div class="container">
<el-tabs v-model="message">
<el-tab-pane :label="`未读消息(${unread.length})`" name="first">
<el-table :data="unread" :show-header="false" style="width: 100%">
<el-tab-pane :label="`未读消息(${state.unread.length})`" name="first">
<el-table :data="state.unread" :show-header="false" style="width: 100%">
<el-table-column>
<template #default="scope">
<span class="message-title">{{scope.row.title}}</span>
@ -25,9 +25,9 @@
<el-button type="primary">全部标为已读</el-button>
</div>
</el-tab-pane>
<el-tab-pane :label="`已读消息(${read.length})`" name="second">
<el-tab-pane :label="`已读消息(${state.read.length})`" name="second">
<template v-if="message === 'second'">
<el-table :data="read" :show-header="false" style="width: 100%">
<el-table :data="state.read" :show-header="false" style="width: 100%">
<el-table-column>
<template #default="scope">
<span class="message-title">{{scope.row.title}}</span>
@ -45,9 +45,9 @@
</div>
</template>
</el-tab-pane>
<el-tab-pane :label="`回收站(${recycle.length})`" name="third">
<el-tab-pane :label="`回收站(${state.recycle.length})`" name="third">
<template v-if="message === 'third'">
<el-table :data="recycle" :show-header="false" style="width: 100%">
<el-table :data="state.recycle" :show-header="false" style="width: 100%">
<el-table-column>
<template #default="scope">
<span class="message-title">{{scope.row.title}}</span>
@ -71,58 +71,66 @@
</template>
<script>
export default {
name: 'tabs',
data() {
return {
message: 'first',
showHeader: false,
unread: [{
date: '2018-04-19 20:00:00',
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护',
},{
date: '2018-04-19 21:00:00',
title: '今晚12点整发大红包先到先得',
}],
read: [{
date: '2018-04-19 20:00:00',
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'
}],
recycle: [{
date: '2018-04-19 20:00:00',
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'
}]
}
},
methods: {
handleRead(index) {
const item = this.unread.splice(index, 1);
console.log(item);
this.read = item.concat(this.read);
},
handleDel(index) {
const item = this.read.splice(index, 1);
this.recycle = item.concat(this.recycle);
},
handleRestore(index) {
const item = this.recycle.splice(index, 1);
this.read = item.concat(this.read);
}
},
computed: {
unreadNum(){
return this.unread.length;
}
}
}
import { ref, reactive } from "vue";
export default {
name: "tabs",
setup() {
const message = ref("first");
const state = reactive({
unread: [
{
date: "2018-04-19 20:00:00",
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
},
{
date: "2018-04-19 21:00:00",
title: "今晚12点整发大红包先到先得",
},
],
read: [
{
date: "2018-04-19 20:00:00",
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
},
],
recycle: [
{
date: "2018-04-19 20:00:00",
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
},
],
});
const handleRead = (index) => {
const item = state.unread.splice(index, 1);
console.log(item);
state.read = item.concat(state.read);
};
const handleDel = (index) => {
const item = state.read.splice(index, 1);
state.recycle = item.concat(state.recycle);
};
const handleRestore = (index) => {
const item = state.recycle.splice(index, 1);
state.read = item.concat(state.read);
};
return {
message,
state,
handleRead,
handleDel,
handleRestore,
};
},
};
</script>
<style>
.message-title{
.message-title {
cursor: pointer;
}
.handle-row{
.handle-row {
margin-top: 30px;
}
</style>

View File

@ -13,17 +13,9 @@
<div class="plugins-tips">
Element UI自带上传组件
访问地址
<a
href="http://element.eleme.io/#/zh-CN/component/upload"
target="_blank"
>Element UI Upload</a>
<a href="http://element.eleme.io/#/zh-CN/component/upload" target="_blank">Element UI Upload</a>
</div>
<el-upload
class="upload-demo"
drag
action="http://jsonplaceholder.typicode.com/api/posts/"
multiple
>
<el-upload class="upload-demo" drag action="http://jsonplaceholder.typicode.com/api/posts/" multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">
将文件拖到此处
@ -38,97 +30,58 @@
<div class="plugins-tips">
vue-cropperjs一个封装了 cropperjs Vue 组件
访问地址
<a
href="https://github.com/Agontuk/vue-cropperjs"
target="_blank"
>vue-cropperjs</a>
<a href="https://github.com/Agontuk/vue-cropperjs" target="_blank">vue-cropperjs</a>
</div>
<div class="crop-demo">
<img :src="cropImg" class="pre-img" />
<div class="crop-demo-btn">
选择图片
<input
class="crop-input"
type="file"
name="image"
accept="image/*"
@change="setImage"
/>
</div>
</div>
<el-dialog title="裁剪图片" v-model="dialogVisible" width="600px">
<vue-cropper
ref="cropper"
:src="imgSrc"
:ready="cropImage"
:zoom="cropImage"
:cropmove="cropImage"
style="width:100%;height:300px;"
></vue-cropper>
<template #footer>
<span class="dialog-footer">
<el-button @click="cancelCrop"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</template>
</el-dialog>
</div>
</div>
</template>
<script>
import VueCropper from "vue-cropperjs";
import "cropperjs/dist/cropper.css";
export default {
name: "upload",
data() {
return {
defaultSrc: require("../assets/img/img.jpg"),
fileList: [],
imgSrc: "",
cropImg: "",
dialogVisible: false
};
},
components: {
VueCropper
VueCropper,
},
methods: {
setImage(e) {
setup() {
const imgSrc = ref("");
const cropImg = ref(defaultSrc);
const dialogVisible = ref(false);
const cropper = ref(null);
const setImage = (e) => {
const file = e.target.files[0];
if (!file.type.includes("image/")) {
return;
}
const reader = new FileReader();
reader.onload = event => {
this.dialogVisible = true;
this.imgSrc = event.target.result;
this.$refs.cropper &&
this.$refs.cropper.replace(event.target.result);
reader.onload = (event) => {
dialogVisible.value = true;
imgSrc.value = event.target.result;
cropper.value && cropper.value.replace(event.target.result);
};
reader.readAsDataURL(file);
},
cropImage() {
this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
},
cancelCrop() {
this.dialogVisible = false;
this.cropImg = this.defaultSrc;
},
imageuploaded(res) {
console.log(res);
},
handleError() {
this.$notify.error({
title: "上传失败",
message: "图片上传接口上传失败,可更改为自己的服务器接口"
});
}
};
const cropImage = () => {
cropImg.value = cropper.value.getCroppedCanvas().toDataURL();
};
const cancelCrop = () => {
dialogVisible.value = false;
cropImg.value = defaultSrc;
};
return {
cropper,
imgSrc,
cropImg,
dialogVisible,
setImage,
cropImage,
cancelCrop,
};
},
created() {
this.cropImg = this.defaultSrc;
}
};
</script>

192
src/views/User.vue Normal file
View File

@ -0,0 +1,192 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="12">
<el-card shadow="hover">
<template #header>
<div class="clearfix">
<span>基础信息</span>
</div>
</template>
<div class="info">
<div class="info-image" @click="showDialog">
<img :src="avatarImg" />
<span class="info-edit">
<i class="el-icon-lx-camerafill"></i>
</span>
</div>
<div class="info-name">{{ name }}</div>
<div class="info-desc">不可能我的代码怎么可能会有bug</div>
</div>
</el-card>
</el-col>
<el-col :span="12">
<el-card shadow="hover">
<template #header>
<div class="clearfix">
<span>账户编辑</span>
</div>
</template>
<el-form label-width="90px">
<el-form-item label="用户名:"> {{ name }} </el-form-item>
<el-form-item label="旧密码:">
<el-input type="password" v-model="form.old"></el-input>
</el-form-item>
<el-form-item label="新密码:">
<el-input type="password" v-model="form.new"></el-input>
</el-form-item>
<el-form-item label="个人简介:">
<el-input v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit"></el-button>
</el-form-item>
</el-form>
</el-card>
</el-col>
</el-row>
<el-dialog title="裁剪图片" v-model="dialogVisible" width="600px">
<vue-cropper ref="cropper" :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage"
style="width: 100%; height: 400px"></vue-cropper>
<template #footer>
<span class="dialog-footer">
<el-button class="crop-demo-btn" type="primary">选择图片
<input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" />
</el-button>
<el-button type="primary" @click="saveAvatar"></el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script>
import { reactive, ref } from "vue";
import VueCropper from "vue-cropperjs";
import "cropperjs/dist/cropper.css";
import avatar from "../assets/img/img.jpg";
export default {
name: "user",
components: {
VueCropper,
},
setup() {
const name = localStorage.getItem("ms_username");
const form = reactive({
old: "",
new: "",
desc: "不可能我的代码怎么可能会有bug",
});
const onSubmit = () => {};
const avatarImg = ref(avatar);
const imgSrc = ref("");
const cropImg = ref("");
const dialogVisible = ref(false);
const cropper = ref(null);
const showDialog = () => {
dialogVisible.value = true;
imgSrc.value = avatarImg.value;
};
const setImage = (e) => {
const file = e.target.files[0];
if (!file.type.includes("image/")) {
return;
}
const reader = new FileReader();
reader.onload = (event) => {
dialogVisible.value = true;
imgSrc.value = event.target.result;
cropper.value && cropper.value.replace(event.target.result);
};
reader.readAsDataURL(file);
};
const cropImage = () => {
cropImg.value = cropper.value.getCroppedCanvas().toDataURL();
};
const saveAvatar = () => {
avatarImg.value = cropImg.value;
dialogVisible.value = false;
};
return {
name,
form,
onSubmit,
cropper,
avatarImg,
imgSrc,
cropImg,
showDialog,
dialogVisible,
setImage,
cropImage,
saveAvatar,
};
},
};
</script>
<style scoped>
.info {
text-align: center;
padding: 35px 0;
}
.info-image {
position: relative;
margin: auto;
width: 100px;
height: 100px;
background: #f8f8f8;
border: 1px solid #eee;
border-radius: 50px;
overflow: hidden;
}
.info-image img {
width: 100%;
height: 100%;
}
.info-edit {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
opacity: 0;
transition: opacity 0.3s ease;
}
.info-edit i {
color: #eee;
font-size: 25px;
}
.info-image:hover .info-edit {
opacity: 1;
}
.info-name {
margin: 15px 0 10px;
font-size: 24px;
font-weight: 500;
color: #262626;
}
.crop-demo-btn {
position: relative;
}
.crop-input {
position: absolute;
width: 100px;
height: 40px;
left: 0;
top: 0;
opacity: 0;
cursor: pointer;
}
</style>

9
vite.config.js Normal file
View File

@ -0,0 +1,9 @@
import vue from '@vitejs/plugin-vue'
export default {
base: './',
plugins: [vue()],
optimizeDeps: {
include: ['schart.js']
}
}