feature:升级到vue3和element-plus
parent
0f641c0f08
commit
96be359eab
|
|
@ -1,3 +0,0 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not ie <= 8
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
example.html
|
||||
favicon.ico
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
|
@ -11,6 +11,7 @@ favicon.ico
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
|
@ -19,4 +20,4 @@ yarn-error.log*
|
|||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
*.sw?
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"tabWidth": 4,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 140
|
||||
}
|
||||
108
README.md
108
README.md
|
|
@ -16,7 +16,8 @@
|
|||
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||
</a>
|
||||
|
||||
基于 Vue + Element UI 的后台管理系统解决方案。[线上地址](https://lin-xin.gitee.io/example/work/)
|
||||
基于 Vue3 + Element Plus 的后台管理系统解决方案。[线上地址](https://lin-xin.gitee.io/example/work/)
|
||||
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)
|
||||
|
||||
|
|
@ -28,47 +29,39 @@
|
|||
|
||||

|
||||
|
||||
### 默认皮肤
|
||||
### 首页
|
||||
|
||||

|
||||
|
||||
### 浅绿色皮肤
|
||||
|
||||

|
||||
|
||||
## 赞赏
|
||||
|
||||
请作者喝杯咖啡吧!(微信号:linxin_20)
|
||||
|
||||

|
||||
|
||||
## 特别鸣谢
|
||||
|
||||
- [实验楼](https://www.shiyanlou.com?source=vue-manage-system)
|
||||
|
||||
## 前言
|
||||
|
||||
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 vue.js,使用 vue-cli3 脚手架,引用 Element UI 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
|
||||
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 Vue3,使用 vue-cli3 脚手架,引用 Element Plus 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
|
||||
|
||||
## 功能
|
||||
|
||||
- [x] Element UI
|
||||
- [x] Element Plus
|
||||
- [x] 登录/注销
|
||||
- [x] Dashboard
|
||||
- [x] 表格
|
||||
- [x] Tab 选项卡
|
||||
- [x] 表单
|
||||
- [x] 图表 :bar_chart:
|
||||
- [x] 富文本编辑器
|
||||
- [x] markdown 编辑器
|
||||
- [ ] 富文本编辑器
|
||||
- [ ] markdown 编辑器
|
||||
- [x] 图片拖拽/裁剪上传
|
||||
- [x] 支持切换主题色 :sparkles:
|
||||
- [x] 列表拖拽排序
|
||||
- [ ] 支持切换主题色 :sparkles:
|
||||
- [ ] 列表拖拽排序
|
||||
- [x] 权限测试
|
||||
- [x] 404 / 403
|
||||
- [x] 三级菜单
|
||||
- [x] 自定义图标
|
||||
- [x] 可拖拽弹窗
|
||||
- [ ] 可拖拽弹窗
|
||||
- [x] 国际化
|
||||
|
||||
## 安装步骤
|
||||
|
|
@ -101,36 +94,36 @@ vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://gi
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Schart from 'vue-schart'; // 导入Schart组件
|
||||
import Schart from "vue-schart"; // 导入Schart组件
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
type: 'bar',
|
||||
type: "bar",
|
||||
title: {
|
||||
text: '最近一周各品类销售图'
|
||||
text: "最近一周各品类销售图",
|
||||
},
|
||||
labels: ['周一', '周二', '周三', '周四', '周五'],
|
||||
labels: ["周一", "周二", "周三", "周四", "周五"],
|
||||
datasets: [
|
||||
{
|
||||
label: '家电',
|
||||
data: [234, 278, 270, 190, 230]
|
||||
label: "家电",
|
||||
data: [234, 278, 270, 190, 230],
|
||||
},
|
||||
{
|
||||
label: '百货',
|
||||
data: [164, 178, 190, 135, 160]
|
||||
label: "百货",
|
||||
data: [164, 178, 190, 135, 160],
|
||||
},
|
||||
{
|
||||
label: '食品',
|
||||
data: [144, 198, 150, 235, 120]
|
||||
}
|
||||
]
|
||||
}
|
||||
label: "食品",
|
||||
data: [144, 198, 150, 235, 120],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Schart
|
||||
}
|
||||
Schart,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
|
|
@ -141,57 +134,6 @@ vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://gi
|
|||
</style>
|
||||
```
|
||||
|
||||
## 其他注意事项
|
||||
|
||||
### 一、如果我不想用到上面的某些组件呢,那我怎么在模板中删除掉不影响到其他功能呢?
|
||||
|
||||
举个栗子,我不想用 Vue-Quill-Editor 这个组件,那我需要分四步走。
|
||||
|
||||
第一步:删除该组件的路由,在目录 src/router/index.js 中,找到引入改组件的路由,删除下面这段代码。
|
||||
|
||||
```JavaScript
|
||||
{
|
||||
// 富文本编辑器组件
|
||||
path: '/editor',
|
||||
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
|
||||
},
|
||||
```
|
||||
|
||||
第二步:删除引入该组件的文件。在目录 src/components/page/ 删除 VueEditor.vue 文件。
|
||||
|
||||
第三步:删除该页面的入口。在目录 src/components/common/Sidebar.vue 中,找到该入口,删除下面这段代码。
|
||||
|
||||
```js
|
||||
{
|
||||
index: 'editor',
|
||||
title: '富文本编辑器'
|
||||
},
|
||||
```
|
||||
|
||||
第四步:卸载该组件。执行以下命令:
|
||||
npm un vue-quill-editor -S
|
||||
|
||||
完成。
|
||||
|
||||
### 二、如何切换主题色呢?
|
||||
|
||||
第一步:打开 src/main.js 文件,找到引入 element 样式的地方,换成浅绿色主题。
|
||||
|
||||
```javascript
|
||||
import 'element-ui/lib/theme-default/index.css'; // 默认主题
|
||||
// import './assets/css/theme-green/index.css'; // 浅绿色主题
|
||||
```
|
||||
|
||||
第二步:打开 src/App.vue 文件,找到 style 标签引入样式的地方,切换成浅绿色主题。
|
||||
|
||||
```javascript
|
||||
@import "./assets/css/main.css";
|
||||
@import "./assets/css/color-dark.css"; /*深色主题*/
|
||||
/*@import "./assets/css/theme-green/color-green.css"; !*浅绿色主题*!*/
|
||||
```
|
||||
|
||||
第三步:打开 src/components/common/Sidebar.vue 文件,找到 el-menu 标签,把 background-color/text-color/active-text-color 属性去掉即可。
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)
|
||||
|
|
|
|||
109
README_EN.md
109
README_EN.md
|
|
@ -16,7 +16,8 @@
|
|||
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||
</a>
|
||||
|
||||
The web management system solution based on Vue2 and Element-UI。[live demo](https://lin-xin.gitee.io/example/work/)
|
||||
The web management system solution based on Vue3 and ElementPlus。[live demo](https://lin-xin.gitee.io/example/work/)
|
||||
Please check the version of vue2 in [tag V4.2.0](https://github.com/lin-xin/vue-manage-system/tree/V4.2.0)
|
||||
|
||||
## Donation
|
||||
|
||||
|
|
@ -24,7 +25,7 @@ The web management system solution based on Vue2 and Element-UI。[live demo](ht
|
|||
|
||||
## Preface
|
||||
|
||||
The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue2 and Element-UI. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.
|
||||
The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue3 and ElementPlus. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.
|
||||
|
||||
## Function
|
||||
|
||||
|
|
@ -35,11 +36,11 @@ The scheme as a set of multi-function background frame templates, suitable for m
|
|||
- [x] Tabs
|
||||
- [x] From
|
||||
- [x] Chart :bar_chart:
|
||||
- [x] Editor
|
||||
- [x] Markdown
|
||||
- [ ] Editor
|
||||
- [ ] Markdown
|
||||
- [x] Upload pictures by clipping or dragging
|
||||
- [x] Support manual switch themes :sparkles:
|
||||
- [x] List drag sort
|
||||
- [ ] Support manual switch themes :sparkles:
|
||||
- [ ] List drag sort
|
||||
- [x] Permission
|
||||
- [x] 404 / 403
|
||||
- [x] Three level menu
|
||||
|
|
@ -75,36 +76,36 @@ Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/linxin/vu
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Schart from 'vue-schart'; // 导入Schart组件
|
||||
import Schart from "vue-schart"; // 导入Schart组件
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
type: 'bar',
|
||||
type: "bar",
|
||||
title: {
|
||||
text: '最近一周各品类销售图'
|
||||
text: "最近一周各品类销售图",
|
||||
},
|
||||
labels: ['周一', '周二', '周三', '周四', '周五'],
|
||||
labels: ["周一", "周二", "周三", "周四", "周五"],
|
||||
datasets: [
|
||||
{
|
||||
label: '家电',
|
||||
data: [234, 278, 270, 190, 230]
|
||||
label: "家电",
|
||||
data: [234, 278, 270, 190, 230],
|
||||
},
|
||||
{
|
||||
label: '百货',
|
||||
data: [164, 178, 190, 135, 160]
|
||||
label: "百货",
|
||||
data: [164, 178, 190, 135, 160],
|
||||
},
|
||||
{
|
||||
label: '食品',
|
||||
data: [144, 198, 150, 235, 120]
|
||||
}
|
||||
]
|
||||
}
|
||||
label: "食品",
|
||||
data: [144, 198, 150, 235, 120],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Schart
|
||||
}
|
||||
Schart,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
|
|
@ -119,77 +120,15 @@ Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/linxin/vu
|
|||
|
||||
A desktop component library based on vue.js2.0 . Github : [element](http://element.eleme.io/#/zh-CN/component/layout)
|
||||
|
||||
### Vue-Quill-Editor
|
||||
|
||||
Quill editor component for Vue2. Github : [vue-quill-editor](https://github.com/surmon-china/vue-quill-editor)
|
||||
|
||||
### mavonEditor
|
||||
|
||||
A markdown editor based on Vue that supports a variety of personalized features. Github: [mavonEditor](https://github.com/hinesboy/mavonEditor)
|
||||
|
||||
### vue-cropperjs
|
||||
|
||||
A Vue wrapper component for cropperjs. Github: [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs)
|
||||
|
||||
## Notice
|
||||
|
||||
### 一、If I don't want to use some components, how can I delete it?
|
||||
|
||||
For example, I don't want to use the Vue-Quill-Editor component, I need to take four steps.
|
||||
|
||||
The first step to remove the component of the routing. Enter 'src/router/index.js' and delete the code below.
|
||||
|
||||
```JavaScript
|
||||
{
|
||||
path: '/editor',
|
||||
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
|
||||
},
|
||||
```
|
||||
|
||||
Second,delete the component files. Enter 'src/components/page/' and delete 'VueEditor.vue' file.
|
||||
|
||||
The third step is to delete the entry. Enter 'src/components/common/Sidebar.vue' and delete the code below.
|
||||
|
||||
```js
|
||||
{
|
||||
index: 'editor',
|
||||
title: '富文本编辑器'
|
||||
},
|
||||
```
|
||||
|
||||
Finally, uninstall this component.
|
||||
npm un vue-quill-editor -S
|
||||
|
||||
Complete!
|
||||
|
||||
### 二、How to switch themes?
|
||||
|
||||
The first step to enter 'src/main.js' and change into green theme.
|
||||
|
||||
```javascript
|
||||
import 'element-ui/lib/theme-default/index.css'; // default theme
|
||||
// import '../static/css/theme-green/index.css'; // green theme
|
||||
```
|
||||
|
||||
The second step to enter 'src/App.vue' and change into green theme.
|
||||
|
||||
```javascript
|
||||
@import "../static/css/main.css";
|
||||
@import "../static/css/color-dark.css"; /*深色主题*/
|
||||
/*@import "../static/css/theme-green/color-green.css"; !*浅绿色主题*!*/
|
||||
```
|
||||
|
||||
Finally,enter 'src/components/common/Sidebar.vue' and find el-menu Tags,delete 'background-color/text-color/active-text-color'。
|
||||
|
||||
## Screenshot
|
||||
|
||||
### Default theme
|
||||
|
||||

|
||||
|
||||
### Green theme
|
||||
### Login
|
||||
|
||||

|
||||

|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
'@vue/cli-plugin-babel/preset'
|
||||
]
|
||||
}
|
||||
|
|
|
|||
61
package.json
61
package.json
|
|
@ -1,28 +1,55 @@
|
|||
{
|
||||
"name": "vue-manage-system",
|
||||
"version": "4.2.0",
|
||||
"version": "5.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "npm run serve",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build"
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.18.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"element-ui": "^2.11.0",
|
||||
"mavon-editor": "^2.6.17",
|
||||
"vue": "^2.6.10",
|
||||
"vue-cropperjs": "^3.0.0",
|
||||
"vue-i18n": "^8.10.0",
|
||||
"vue-quill-editor": "^3.0.6",
|
||||
"vue-router": "^3.0.3",
|
||||
"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",
|
||||
"vuedraggable": "^2.17.0"
|
||||
"vuex": "~4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vue/cli-plugin-babel": "^3.9.0",
|
||||
"@vue/cli-service": "^3.9.0",
|
||||
"vue-template-compiler": "^2.6.10"
|
||||
}
|
||||
"@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"
|
||||
},
|
||||
"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"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,21 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
|
||||
<link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<title>vue-manage-system</title>
|
||||
<link rel="stylesheet" href="https://at.alicdn.com/t/font_830376_qzecyukz0s.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but vms doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
|
||||
Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 81 KiB |
12
src/App.vue
12
src/App.vue
|
|
@ -1,10 +1,12 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import "./assets/css/main.css";
|
||||
@import "./assets/css/color-dark.css"; /*深色主题*/
|
||||
/*@import "./assets/css/theme-green/color-green.css"; 浅绿色主题*/
|
||||
@import "./assets/css/color-dark.css";
|
||||
</style>
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
|
||||
[class*=" el-icon-lx"], [class^=el-icon-lx] {
|
||||
[class*=" el-icon-lx"],
|
||||
[class^=el-icon-lx] {
|
||||
font-family: lx-iconfont !important;
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
.header{
|
||||
background-color: #07c4a8;
|
||||
}
|
||||
.login-wrap{
|
||||
background: rgba(56, 157, 170, 0.82);;
|
||||
}
|
||||
.plugins-tips{
|
||||
background: #f2f2f2;
|
||||
}
|
||||
.plugins-tips a{
|
||||
color: #00d1b2;
|
||||
}
|
||||
.el-upload--text em {
|
||||
color: #00d1b2;
|
||||
}
|
||||
.pure-button{
|
||||
background: #00d1b2;
|
||||
}
|
||||
.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus {
|
||||
background-color: #00d1b2 !important;
|
||||
border-color: #00d1b2 !important;
|
||||
}
|
||||
.tags-li.active {
|
||||
border: 1px solid #00d1b2;
|
||||
background-color: #00d1b2;
|
||||
}
|
||||
.collapse-btn:hover{
|
||||
background: #00d1b2;
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 6.7 KiB |
|
|
@ -8,12 +8,6 @@
|
|||
<div class="logo">后台管理系统</div>
|
||||
<div class="header-right">
|
||||
<div class="header-user-con">
|
||||
<!-- 全屏显示 -->
|
||||
<div class="btn-fullscreen" @click="handleFullScreen">
|
||||
<el-tooltip effect="dark" :content="fullscreen?`取消全屏`:`全屏`" placement="bottom">
|
||||
<i class="el-icon-rank"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<!-- 消息中心 -->
|
||||
<div class="btn-bell">
|
||||
<el-tooltip
|
||||
|
|
@ -29,7 +23,7 @@
|
|||
</div>
|
||||
<!-- 用户头像 -->
|
||||
<div class="user-avator">
|
||||
<img src="../../assets/img/img.jpg" />
|
||||
<img src="../assets/img/img.jpg" />
|
||||
</div>
|
||||
<!-- 用户名下拉菜单 -->
|
||||
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
|
||||
|
|
@ -37,73 +31,48 @@
|
|||
{{username}}
|
||||
<i class="el-icon-caret-bottom"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
|
||||
<el-dropdown-item>项目仓库</el-dropdown-item>
|
||||
</a>
|
||||
<el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import bus from '../common/bus';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
collapse: false,
|
||||
fullscreen: false,
|
||||
name: 'linxin',
|
||||
name: "linxin",
|
||||
message: 2
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
username() {
|
||||
let username = localStorage.getItem('ms_username');
|
||||
let username = localStorage.getItem("ms_username");
|
||||
return username ? username : this.name;
|
||||
},
|
||||
collapse() {
|
||||
return this.$store.state.collapse;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 用户名下拉菜单选择事件
|
||||
handleCommand(command) {
|
||||
if (command == 'loginout') {
|
||||
localStorage.removeItem('ms_username');
|
||||
this.$router.push('/login');
|
||||
if (command == "loginout") {
|
||||
localStorage.removeItem("ms_username");
|
||||
this.$router.push("/login");
|
||||
}
|
||||
},
|
||||
// 侧边栏折叠
|
||||
collapseChage() {
|
||||
this.collapse = !this.collapse;
|
||||
bus.$emit('collapse', this.collapse);
|
||||
},
|
||||
// 全屏事件
|
||||
handleFullScreen() {
|
||||
let element = document.documentElement;
|
||||
if (this.fullscreen) {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitCancelFullScreen) {
|
||||
document.webkitCancelFullScreen();
|
||||
} else if (document.mozCancelFullScreen) {
|
||||
document.mozCancelFullScreen();
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen();
|
||||
}
|
||||
} else {
|
||||
if (element.requestFullscreen) {
|
||||
element.requestFullscreen();
|
||||
} else if (element.webkitRequestFullScreen) {
|
||||
element.webkitRequestFullScreen();
|
||||
} else if (element.mozRequestFullScreen) {
|
||||
element.mozRequestFullScreen();
|
||||
} else if (element.msRequestFullscreen) {
|
||||
// IE11
|
||||
element.msRequestFullscreen();
|
||||
}
|
||||
}
|
||||
this.fullscreen = !this.fullscreen;
|
||||
this.$store.commit("hadndleCollapse", !this.collapse);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
<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
|
||||
>
|
||||
<template v-for="item in items">
|
||||
<template v-if="item.subs">
|
||||
<el-submenu :index="item.index" :key="item.index">
|
||||
<template #title>
|
||||
<i :class="item.icon"></i>
|
||||
<span>{{ item.title }}</span>
|
||||
</template>
|
||||
<template v-for="subItem in item.subs">
|
||||
<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-submenu>
|
||||
<el-menu-item
|
||||
v-else
|
||||
:index="subItem.index"
|
||||
:key="subItem.index"
|
||||
>{{ subItem.title }}</el-menu-item>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-menu-item :index="item.index" :key="item.index">
|
||||
<i :class="item.icon"></i>
|
||||
<template #title>{{ item.title }}</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// import bus from "../common/bus";
|
||||
export default {
|
||||
data() {
|
||||
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: "支持作者"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
onRoutes() {
|
||||
return this.$route.path.replace("/", "");
|
||||
},
|
||||
collapse(){
|
||||
return this.$store.state.collapse
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sidebar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 70px;
|
||||
bottom: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
.sidebar-el-menu:not(.el-menu--collapse) {
|
||||
width: 250px;
|
||||
}
|
||||
.sidebar > ul {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<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"
|
||||
>
|
||||
<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>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tags-close-box">
|
||||
<el-dropdown @command="handleTags">
|
||||
<el-button size="mini" type="primary">
|
||||
标签选项
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu size="small">
|
||||
<el-dropdown-item command="other">关闭其他</el-dropdown-item>
|
||||
<el-dropdown-item command="all">关闭所有</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
tagsList() {
|
||||
return this.$store.state.tagsList;
|
||||
},
|
||||
showTags() {
|
||||
return this.tagsList.length > 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isActive(path) {
|
||||
return path === this.$route.fullPath;
|
||||
},
|
||||
// 关闭单个标签
|
||||
closeTags(index) {
|
||||
const delItem = this.tagsList[index];
|
||||
this.$store.commit("delTagsItem", { index });
|
||||
const item = this.tagsList[index]
|
||||
? this.tagsList[index]
|
||||
: this.tagsList[index - 1];
|
||||
if (item) {
|
||||
delItem.path === this.$route.fullPath &&
|
||||
this.$router.push(item.path);
|
||||
} else {
|
||||
this.$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 => {
|
||||
return item.path === route.fullPath;
|
||||
});
|
||||
if (!isExist) {
|
||||
if (this.tagsList.length >= 8) {
|
||||
this.$store.commit("delTagsItem", { index: 0 });
|
||||
}
|
||||
this.$store.commit("setTagsItem", {
|
||||
title: route.meta.title,
|
||||
path: route.fullPath
|
||||
});
|
||||
}
|
||||
},
|
||||
handleTags(command) {
|
||||
command === "other" ? this.closeOther() : this.closeAll();
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(newValue) {
|
||||
this.setTags(newValue);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.setTags(this.$route);
|
||||
// 关闭当前页面的标签页
|
||||
// this.$store.commit("closeCurrentTag", {
|
||||
// $router: this.$router,
|
||||
// $route: this.$route
|
||||
// });
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.tags {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
padding-right: 120px;
|
||||
box-shadow: 0 5px 10px #ddd;
|
||||
}
|
||||
|
||||
.tags ul {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tags-li {
|
||||
float: left;
|
||||
margin: 3px 5px 2px 3px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
height: 23px;
|
||||
line-height: 23px;
|
||||
border: 1px solid #e9eaec;
|
||||
background: #fff;
|
||||
padding: 0 5px 0 12px;
|
||||
vertical-align: middle;
|
||||
color: #666;
|
||||
-webkit-transition: all 0.3s ease-in;
|
||||
-moz-transition: all 0.3s ease-in;
|
||||
transition: all 0.3s ease-in;
|
||||
}
|
||||
|
||||
.tags-li:not(.active):hover {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.tags-li.active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tags-li-title {
|
||||
float: left;
|
||||
max-width: 80px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 5px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tags-li.active .tags-li-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tags-close-box {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
padding-top: 1px;
|
||||
text-align: center;
|
||||
width: 110px;
|
||||
height: 30px;
|
||||
background: #fff;
|
||||
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<template>
|
||||
<div class="wrapper">
|
||||
<v-head></v-head>
|
||||
<v-sidebar></v-sidebar>
|
||||
<div class="content-box" :class="{'content-collapse':collapse}">
|
||||
<v-tags></v-tags>
|
||||
<div class="content">
|
||||
<transition name="move" mode="out-in">
|
||||
<keep-alive :include="tagsList">
|
||||
<router-view></router-view>
|
||||
</keep-alive>
|
||||
</transition>
|
||||
<el-backtop target=".content"></el-backtop>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vHead from './Header.vue';
|
||||
import vSidebar from './Sidebar.vue';
|
||||
import vTags from './Tags.vue';
|
||||
import bus from './bus';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tagsList: [],
|
||||
collapse: false
|
||||
};
|
||||
},
|
||||
components: {
|
||||
vHead,
|
||||
vSidebar,
|
||||
vTags
|
||||
},
|
||||
created() {
|
||||
bus.$on('collapse-content', msg => {
|
||||
this.collapse = msg;
|
||||
});
|
||||
|
||||
// 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
|
||||
bus.$on('tags', msg => {
|
||||
let arr = [];
|
||||
for (let i = 0, len = msg.length; i < len; i++) {
|
||||
msg[i].name && arr.push(msg[i].name);
|
||||
}
|
||||
this.tagsList = arr;
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
<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
|
||||
>
|
||||
<template v-for="item in items">
|
||||
<template v-if="item.subs">
|
||||
<el-submenu :index="item.index" :key="item.index">
|
||||
<template slot="title">
|
||||
<i :class="item.icon"></i>
|
||||
<span slot="title">{{ item.title }}</span>
|
||||
</template>
|
||||
<template v-for="subItem in item.subs">
|
||||
<el-submenu
|
||||
v-if="subItem.subs"
|
||||
:index="subItem.index"
|
||||
:key="subItem.index"
|
||||
>
|
||||
<template slot="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-submenu>
|
||||
<el-menu-item
|
||||
v-else
|
||||
:index="subItem.index"
|
||||
:key="subItem.index"
|
||||
>{{ subItem.title }}</el-menu-item>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-menu-item :index="item.index" :key="item.index">
|
||||
<i :class="item.icon"></i>
|
||||
<span slot="title">{{ item.title }}</span>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bus from '../common/bus';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
collapse: false,
|
||||
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: '支持作者'
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
onRoutes() {
|
||||
return this.$route.path.replace('/', '');
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 通过 Event Bus 进行组件间通信,来折叠侧边栏
|
||||
bus.$on('collapse', msg => {
|
||||
this.collapse = msg;
|
||||
bus.$emit('collapse-content', msg);
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sidebar {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 70px;
|
||||
bottom: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.sidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
}
|
||||
.sidebar-el-menu:not(.el-menu--collapse) {
|
||||
width: 250px;
|
||||
}
|
||||
.sidebar > ul {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
<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">
|
||||
<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></span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tags-close-box">
|
||||
<el-dropdown @command="handleTags">
|
||||
<el-button size="mini" type="primary">
|
||||
标签选项<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu size="small" slot="dropdown">
|
||||
<el-dropdown-item command="other">关闭其他</el-dropdown-item>
|
||||
<el-dropdown-item command="all">关闭所有</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import bus from './bus';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tagsList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isActive(path) {
|
||||
return path === this.$route.fullPath;
|
||||
},
|
||||
// 关闭单个标签
|
||||
closeTags(index) {
|
||||
const delItem = this.tagsList.splice(index, 1)[0];
|
||||
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
|
||||
if (item) {
|
||||
delItem.path === this.$route.fullPath && this.$router.push(item.path);
|
||||
}else{
|
||||
this.$router.push('/');
|
||||
}
|
||||
},
|
||||
// 关闭全部标签
|
||||
closeAll(){
|
||||
this.tagsList = [];
|
||||
this.$router.push('/');
|
||||
},
|
||||
// 关闭其他标签
|
||||
closeOther(){
|
||||
const curItem = this.tagsList.filter(item => {
|
||||
return item.path === this.$route.fullPath;
|
||||
})
|
||||
this.tagsList = curItem;
|
||||
},
|
||||
// 设置标签
|
||||
setTags(route){
|
||||
const isExist = this.tagsList.some(item => {
|
||||
return item.path === route.fullPath;
|
||||
})
|
||||
if(!isExist){
|
||||
if(this.tagsList.length >= 8){
|
||||
this.tagsList.shift();
|
||||
}
|
||||
this.tagsList.push({
|
||||
title: route.meta.title,
|
||||
path: route.fullPath,
|
||||
name: route.matched[1].components.default.name
|
||||
})
|
||||
}
|
||||
bus.$emit('tags', this.tagsList);
|
||||
},
|
||||
handleTags(command){
|
||||
command === 'other' ? this.closeOther() : this.closeAll();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showTags() {
|
||||
return this.tagsList.length > 0;
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
$route(newValue, oldValue){
|
||||
this.setTags(newValue);
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.setTags(this.$route);
|
||||
// 监听关闭当前页面的标签页
|
||||
bus.$on('close_current_tags', () => {
|
||||
for (let i = 0, len = this.tagsList.length; i < len; i++) {
|
||||
const item = this.tagsList[i];
|
||||
if(item.path === this.$route.fullPath){
|
||||
if(i < len - 1){
|
||||
this.$router.push(this.tagsList[i+1].path);
|
||||
}else if(i > 0){
|
||||
this.$router.push(this.tagsList[i-1].path);
|
||||
}else{
|
||||
this.$router.push('/');
|
||||
}
|
||||
this.tagsList.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.tags {
|
||||
position: relative;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
background: #fff;
|
||||
padding-right: 120px;
|
||||
box-shadow: 0 5px 10px #ddd;
|
||||
}
|
||||
|
||||
.tags ul {
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.tags-li {
|
||||
float: left;
|
||||
margin: 3px 5px 2px 3px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
height: 23px;
|
||||
line-height: 23px;
|
||||
border: 1px solid #e9eaec;
|
||||
background: #fff;
|
||||
padding: 0 5px 0 12px;
|
||||
vertical-align: middle;
|
||||
color: #666;
|
||||
-webkit-transition: all .3s ease-in;
|
||||
-moz-transition: all .3s ease-in;
|
||||
transition: all .3s ease-in;
|
||||
}
|
||||
|
||||
.tags-li:not(.active):hover {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.tags-li.active {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tags-li-title {
|
||||
float: left;
|
||||
max-width: 80px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: 5px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.tags-li.active .tags-li-title {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tags-close-box {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
box-sizing: border-box;
|
||||
padding-top: 1px;
|
||||
text-align: center;
|
||||
width: 110px;
|
||||
height: 30px;
|
||||
background: #fff;
|
||||
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
// 使用 Event Bus
|
||||
const bus = new Vue();
|
||||
|
||||
export default bus;
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
// v-dialogDrag: 弹窗拖拽属性
|
||||
Vue.directive('dialogDrag', {
|
||||
bind(el, binding, vnode, oldVnode) {
|
||||
const dialogHeaderEl = el.querySelector('.el-dialog__header');
|
||||
const dragDom = el.querySelector('.el-dialog');
|
||||
|
||||
dialogHeaderEl.style.cssText += ';cursor:move;'
|
||||
dragDom.style.cssText += ';top:0px;'
|
||||
|
||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||
const sty = (() => {
|
||||
if (window.document.currentStyle) {
|
||||
return (dom, attr) => dom.currentStyle[attr];
|
||||
} else {
|
||||
return (dom, attr) => getComputedStyle(dom, false)[attr];
|
||||
}
|
||||
})()
|
||||
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft;
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop;
|
||||
|
||||
const screenWidth = document.body.clientWidth; // body当前宽度
|
||||
const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
|
||||
|
||||
const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
|
||||
const dragDomheight = dragDom.offsetHeight; // 对话框高度
|
||||
|
||||
const minDragDomLeft = dragDom.offsetLeft;
|
||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
|
||||
|
||||
const minDragDomTop = dragDom.offsetTop;
|
||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
|
||||
|
||||
|
||||
// 获取到的值带px 正则匹配替换
|
||||
let styL = sty(dragDom, 'left');
|
||||
let styT = sty(dragDom, 'top');
|
||||
|
||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||
if (styL.includes('%')) {
|
||||
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
|
||||
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
|
||||
} else {
|
||||
styL = +styL.replace(/\px/g, '');
|
||||
styT = +styT.replace(/\px/g, '');
|
||||
};
|
||||
|
||||
document.onmousemove = function (e) {
|
||||
// 通过事件委托,计算移动的距离
|
||||
let left = e.clientX - disX;
|
||||
let top = e.clientY - disY;
|
||||
|
||||
// 边界处理
|
||||
if (-(left) > minDragDomLeft) {
|
||||
left = -(minDragDomLeft);
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft;
|
||||
}
|
||||
|
||||
if (-(top) > minDragDomTop) {
|
||||
top = -(minDragDomTop);
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop;
|
||||
}
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
|
||||
};
|
||||
|
||||
document.onmouseup = function (e) {
|
||||
document.onmousemove = null;
|
||||
document.onmouseup = null;
|
||||
};
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
<template>
|
||||
<section class="main">
|
||||
<div class="crumbs">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item><i class="el-icon-rank"></i> 拖拽组件</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>拖拽弹框</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="container">
|
||||
<p>通过指令 v-dialogDrag 使 Dialog 对话框具有可拖拽的功能。</p>
|
||||
<br>
|
||||
<el-button type="primary" @click="visible = true;">点我弹框</el-button>
|
||||
</div>
|
||||
<el-dialog v-dialogDrag title="拖拽弹框" center :visible.sync="visible" width="30%">
|
||||
我是一个可以拖拽的对话框!
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="visible = false">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
||||
|
|
@ -1,174 +0,0 @@
|
|||
<template>
|
||||
<section class="main">
|
||||
<div class="crumbs">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item><i class="el-icon-rank"></i> 拖拽组件</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>拖拽排序</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="plugins-tips">
|
||||
Vue.Draggable:基于 Sortable.js 的 Vue 拖拽组件。
|
||||
访问地址:<a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a>
|
||||
</div>
|
||||
<div class="drag-box">
|
||||
<div class="drag-box-item">
|
||||
<div class="item-title">todo</div>
|
||||
<draggable v-model="todo" @remove="removeHandle" :options="dragOptions">
|
||||
<transition-group tag="div" id="todo" class="item-ul">
|
||||
<div v-for="item in todo" class="drag-list" :key="item.id">
|
||||
{{item.content}}
|
||||
</div>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="drag-box-item">
|
||||
<div class="item-title">doing</div>
|
||||
<draggable v-model="doing" @remove="removeHandle" :options="dragOptions">
|
||||
<transition-group tag="div" id="doing" class="item-ul">
|
||||
<div v-for="item in doing" class="drag-list" :key="item.id">
|
||||
{{item.content}}
|
||||
</div>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="drag-box-item">
|
||||
<div class="item-title">done</div>
|
||||
<draggable v-model="done" @remove="removeHandle" :options="dragOptions">
|
||||
<transition-group tag="div" id="done" class="item-ul">
|
||||
<div v-for="item in done" class="drag-list" :key="item.id">
|
||||
{{item.content}}
|
||||
</div>
|
||||
</transition-group>
|
||||
</draggable>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
export default {
|
||||
name: 'draglist',
|
||||
data() {
|
||||
return {
|
||||
dragOptions:{
|
||||
animation: 120,
|
||||
scroll: true,
|
||||
group: 'sortlist',
|
||||
ghostClass: 'ghost-style'
|
||||
},
|
||||
todo: [
|
||||
{
|
||||
id: 1,
|
||||
content: '开发图表组件'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: '开发拖拽组件'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: '开发权限测试组件'
|
||||
}
|
||||
],
|
||||
doing: [
|
||||
{
|
||||
id: 1,
|
||||
content: '开发登录注册页面'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: '开发头部组件'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
content: '开发表格相关组件'
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
content: '开发表单相关组件'
|
||||
}
|
||||
],
|
||||
done:[
|
||||
{
|
||||
id: 1,
|
||||
content: '初始化项目,生成工程目录,完成相关配置'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: '开发项目整体框架'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
components:{
|
||||
draggable
|
||||
},
|
||||
methods: {
|
||||
removeHandle(event){
|
||||
console.log(event);
|
||||
this.$message.success(`从 ${event.from.id} 移动到 ${event.to.id} `);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.drag-box{
|
||||
display: flex;
|
||||
user-select: none;
|
||||
}
|
||||
.drag-box-item {
|
||||
flex: 1;
|
||||
max-width: 330px;
|
||||
min-width: 300px;
|
||||
background-color: #eff1f5;
|
||||
margin-right: 16px;
|
||||
border-radius: 6px;
|
||||
border: 1px #e1e4e8 solid;
|
||||
}
|
||||
.item-title{
|
||||
padding: 8px 8px 8px 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: #24292e;
|
||||
font-weight: 600;
|
||||
}
|
||||
.item-ul{
|
||||
padding: 0 8px 8px;
|
||||
height: 500px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.item-ul::-webkit-scrollbar{
|
||||
width: 0;
|
||||
}
|
||||
.drag-list {
|
||||
border: 1px #e1e4e8 solid;
|
||||
padding: 10px;
|
||||
margin: 5px 0 10px;
|
||||
list-style: none;
|
||||
background-color: #fff;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
-webkit-transition: border .3s ease-in;
|
||||
transition: border .3s ease-in;
|
||||
}
|
||||
.drag-list:hover {
|
||||
border: 1px solid #20a0ff;
|
||||
}
|
||||
.drag-title {
|
||||
font-weight: 400;
|
||||
line-height: 25px;
|
||||
margin: 10px 0;
|
||||
font-size: 22px;
|
||||
color: #1f2f3d;
|
||||
}
|
||||
.ghost-style{
|
||||
display: block;
|
||||
color: transparent;
|
||||
border-style: dashed
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<div class="crumbs">
|
||||
<el-breadcrumb separator="/">
|
||||
<el-breadcrumb-item><i class="el-icon-lx-calendar"></i> 表单</el-breadcrumb-item>
|
||||
<el-breadcrumb-item>markdown编辑器</el-breadcrumb-item>
|
||||
</el-breadcrumb>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="plugins-tips">
|
||||
mavonEditor:基于Vue的markdown编辑器。
|
||||
访问地址:<a href="https://github.com/hinesboy/mavonEditor" target="_blank">mavonEditor</a>
|
||||
</div>
|
||||
<mavon-editor v-model="content" ref="md" @imgAdd="$imgAdd" @change="change" style="min-height: 600px"/>
|
||||
<el-button class="editor-btn" type="primary" @click="submit">提交</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mavonEditor } from 'mavon-editor'
|
||||
import 'mavon-editor/dist/css/index.css'
|
||||
export default {
|
||||
name: 'markdown',
|
||||
data: function(){
|
||||
return {
|
||||
content:'',
|
||||
html:'',
|
||||
configs: {
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
mavonEditor
|
||||
},
|
||||
methods: {
|
||||
// 将图片上传到服务器,返回地址替换到md中
|
||||
$imgAdd(pos, $file){
|
||||
var formdata = new FormData();
|
||||
formdata.append('file', $file);
|
||||
// 这里没有服务器供大家尝试,可将下面上传接口替换为你自己的服务器接口
|
||||
this.$axios({
|
||||
url: '/common/upload',
|
||||
method: 'post',
|
||||
data: formdata,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
}).then((url) => {
|
||||
this.$refs.md.$img2Url(pos, url);
|
||||
})
|
||||
},
|
||||
change(value, render){
|
||||
// render 为 markdown 解析后的结果
|
||||
this.html = render;
|
||||
},
|
||||
submit(){
|
||||
console.log(this.content);
|
||||
console.log(this.html);
|
||||
this.$message.success('提交成功!');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.editor-btn{
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,141 +0,0 @@
|
|||
<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="content-title">支持拖拽</div>
|
||||
<div class="plugins-tips">
|
||||
Element UI自带上传组件。
|
||||
访问地址:<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>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
|
||||
</el-upload>
|
||||
<div class="content-title">支持裁剪</div>
|
||||
<div class="plugins-tips">
|
||||
vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。
|
||||
访问地址:<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="裁剪图片" :visible.sync="dialogVisible" width="30%">
|
||||
<vue-cropper ref='cropper' :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage" style="width:100%;height:300px;"></vue-cropper>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="cancelCrop">取 消</el-button>
|
||||
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import VueCropper from 'vue-cropperjs';
|
||||
export default {
|
||||
name: 'upload',
|
||||
data: function(){
|
||||
return {
|
||||
defaultSrc: require('../../assets/img/img.jpg'),
|
||||
fileList: [],
|
||||
imgSrc: '',
|
||||
cropImg: '',
|
||||
dialogVisible: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
VueCropper
|
||||
},
|
||||
methods:{
|
||||
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.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: '图片上传接口上传失败,可更改为自己的服务器接口'
|
||||
});
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.cropImg = this.defaultSrc;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.content-title{
|
||||
font-weight: 400;
|
||||
line-height: 50px;
|
||||
margin: 10px 0;
|
||||
font-size: 22px;
|
||||
color: #1f2f3d;
|
||||
}
|
||||
.pre-img{
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: #f8f8f8;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.crop-demo{
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.crop-demo-btn{
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 20px;
|
||||
margin-left: 30px;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.crop-input{
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
<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">
|
||||
Vue-Quill-Editor:基于Quill、适用于Vue2的富文本编辑器。
|
||||
访问地址:<a href="https://github.com/surmon-china/vue-quill-editor" target="_blank">vue-quill-editor</a>
|
||||
</div>
|
||||
<quill-editor ref="myTextEditor" v-model="content" :options="editorOption"></quill-editor>
|
||||
<el-button class="editor-btn" type="primary" @click="submit">提交</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import 'quill/dist/quill.core.css';
|
||||
import 'quill/dist/quill.snow.css';
|
||||
import 'quill/dist/quill.bubble.css';
|
||||
import { quillEditor } from 'vue-quill-editor';
|
||||
export default {
|
||||
name: 'editor',
|
||||
data: function(){
|
||||
return {
|
||||
content: '',
|
||||
editorOption: {
|
||||
placeholder: 'Hello World'
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
quillEditor
|
||||
},
|
||||
methods: {
|
||||
onEditorChange({ editor, html, text }) {
|
||||
this.content = html;
|
||||
},
|
||||
submit(){
|
||||
console.log(this.content);
|
||||
this.$message.success('提交成功!');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
.editor-btn{
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
60
src/main.js
60
src/main.js
|
|
@ -1,48 +1,12 @@
|
|||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
import router from './router';
|
||||
import ElementUI from 'element-ui';
|
||||
import VueI18n from 'vue-i18n';
|
||||
import { messages } from './components/common/i18n';
|
||||
import 'element-ui/lib/theme-chalk/index.css'; // 默认主题
|
||||
// import './assets/css/theme-green/index.css'; // 浅绿色主题
|
||||
import './assets/css/icon.css';
|
||||
import './components/common/directives';
|
||||
import 'babel-polyfill';
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
Vue.use(VueI18n);
|
||||
Vue.use(ElementUI, {
|
||||
size: 'small'
|
||||
});
|
||||
const i18n = new VueI18n({
|
||||
locale: 'zh',
|
||||
messages
|
||||
});
|
||||
|
||||
//使用钩子函数对路由进行权限跳转
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = `${to.meta.title} | vue-manage-system`;
|
||||
const role = localStorage.getItem('ms_username');
|
||||
if (!role && to.path !== '/login') {
|
||||
next('/login');
|
||||
} else if (to.meta.permission) {
|
||||
// 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
|
||||
role === 'admin' ? next() : next('/403');
|
||||
} else {
|
||||
// 简单的判断IE10及以下不进入富文本编辑器,该组件不兼容
|
||||
if (navigator.userAgent.indexOf('MSIE') > -1 && to.path === '/editor') {
|
||||
Vue.prototype.$alert('vue-quill-editor组件不兼容IE10及以下浏览器,请使用更高版本的浏览器查看', '浏览器不兼容通知', {
|
||||
confirmButtonText: '确定'
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
i18n,
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
import {createApp} from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import installElementPlus from './plugins/element'
|
||||
import './assets/css/icon.css'
|
||||
const app = createApp(App)
|
||||
installElementPlus(app)
|
||||
app
|
||||
.use(store)
|
||||
.use(router)
|
||||
.mount('#app')
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import ElementPlus from 'element-plus'
|
||||
import { createI18n } from 'vue-i18n'
|
||||
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,
|
||||
fallbackLocale: localeEN.name,
|
||||
messages,
|
||||
})
|
||||
|
||||
export default (app) => {
|
||||
app.use(ElementPlus, { locale:localeZH })
|
||||
app.use(i18n)
|
||||
}
|
||||
|
|
@ -1,117 +1,154 @@
|
|||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import {createRouter, createWebHistory} from "vue-router";
|
||||
import Home from "../views/Home.vue";
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
export default new Router({
|
||||
routes: [
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/dashboard'
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: () => import(/* webpackChunkName: "home" */ '../components/common/Home.vue'),
|
||||
meta: { title: '自述文件' },
|
||||
}, {
|
||||
path: "/",
|
||||
name: "Home",
|
||||
component: Home,
|
||||
children: [
|
||||
{
|
||||
path: '/dashboard',
|
||||
component: () => import(/* webpackChunkName: "dashboard" */ '../components/page/Dashboard.vue'),
|
||||
meta: { title: '系统首页' }
|
||||
path: "/dashboard",
|
||||
name: "Dashboard",
|
||||
meta: {
|
||||
title: '系统首页'
|
||||
},
|
||||
{
|
||||
path: '/icon',
|
||||
component: () => import(/* webpackChunkName: "icon" */ '../components/page/Icon.vue'),
|
||||
meta: { title: '自定义图标' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "dashboard" */
|
||||
"../views/Dashboard.vue")
|
||||
}, {
|
||||
path: "/table",
|
||||
name: "BaseTable",
|
||||
meta: {
|
||||
title: '表格'
|
||||
},
|
||||
{
|
||||
path: '/table',
|
||||
component: () => import(/* webpackChunkName: "table" */ '../components/page/BaseTable.vue'),
|
||||
meta: { title: '基础表格' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "table" */
|
||||
"../views/BaseTable.vue")
|
||||
}, {
|
||||
path: "/charts",
|
||||
name: "BaseCharts",
|
||||
meta: {
|
||||
title: '图表'
|
||||
},
|
||||
{
|
||||
path: '/tabs',
|
||||
component: () => import(/* webpackChunkName: "tabs" */ '../components/page/Tabs.vue'),
|
||||
meta: { title: 'tab选项卡' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "charts" */
|
||||
"../views/BaseCharts.vue")
|
||||
}, {
|
||||
path: "/form",
|
||||
name: "BaseForm",
|
||||
meta: {
|
||||
title: '表单'
|
||||
},
|
||||
{
|
||||
path: '/form',
|
||||
component: () => import(/* webpackChunkName: "form" */ '../components/page/BaseForm.vue'),
|
||||
meta: { title: '基本表单' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "form" */
|
||||
"../views/BaseForm.vue")
|
||||
}, {
|
||||
path: "/tabs",
|
||||
name: "Tabs",
|
||||
meta: {
|
||||
title: 'tab标签'
|
||||
},
|
||||
{
|
||||
// 富文本编辑器组件
|
||||
path: '/editor',
|
||||
component: () => import(/* webpackChunkName: "editor" */ '../components/page/VueEditor.vue'),
|
||||
meta: { title: '富文本编辑器' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "tabs" */
|
||||
"../views/Tabs.vue")
|
||||
}, {
|
||||
path: "/donate",
|
||||
name: "Donate",
|
||||
meta: {
|
||||
title: '鼓励作者'
|
||||
},
|
||||
{
|
||||
// markdown组件
|
||||
path: '/markdown',
|
||||
component: () => import(/* webpackChunkName: "markdown" */ '../components/page/Markdown.vue'),
|
||||
meta: { title: 'markdown编辑器' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "donate" */
|
||||
"../views/Donate.vue")
|
||||
}, {
|
||||
path: "/permission",
|
||||
name: "Permission",
|
||||
meta: {
|
||||
title: '权限管理',
|
||||
permission: true
|
||||
},
|
||||
{
|
||||
// 图片上传组件
|
||||
path: '/upload',
|
||||
component: () => import(/* webpackChunkName: "upload" */ '../components/page/Upload.vue'),
|
||||
meta: { title: '文件上传' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "permission" */
|
||||
"../views/Permission.vue")
|
||||
}, {
|
||||
path: "/i18n",
|
||||
name: "I18n",
|
||||
meta: {
|
||||
title: '国际化语言'
|
||||
},
|
||||
{
|
||||
// vue-schart组件
|
||||
path: '/charts',
|
||||
component: () => import(/* webpackChunkName: "chart" */ '../components/page/BaseCharts.vue'),
|
||||
meta: { title: 'schart图表' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "i18n" */
|
||||
"../views/I18n.vue")
|
||||
}, {
|
||||
path: "/upload",
|
||||
name: "Upload",
|
||||
meta: {
|
||||
title: '上传插件'
|
||||
},
|
||||
{
|
||||
// 拖拽列表组件
|
||||
path: '/drag',
|
||||
component: () => import(/* webpackChunkName: "drag" */ '../components/page/DragList.vue'),
|
||||
meta: { title: '拖拽列表' }
|
||||
component: () => import (
|
||||
/* webpackChunkName: "upload" */
|
||||
"../views/Upload.vue")
|
||||
}, {
|
||||
path: "/icon",
|
||||
name: "Icon",
|
||||
meta: {
|
||||
title: '自定义图标'
|
||||
},
|
||||
{
|
||||
// 拖拽Dialog组件
|
||||
path: '/dialog',
|
||||
component: () => import(/* webpackChunkName: "dragdialog" */ '../components/page/DragDialog.vue'),
|
||||
meta: { title: '拖拽弹框' }
|
||||
},
|
||||
{
|
||||
// 国际化组件
|
||||
path: '/i18n',
|
||||
component: () => import(/* webpackChunkName: "i18n" */ '../components/page/I18n.vue'),
|
||||
meta: { title: '国际化' }
|
||||
},
|
||||
{
|
||||
// 权限页面
|
||||
path: '/permission',
|
||||
component: () => import(/* webpackChunkName: "permission" */ '../components/page/Permission.vue'),
|
||||
meta: { title: '权限测试', permission: true }
|
||||
},
|
||||
{
|
||||
component: () => import (
|
||||
/* webpackChunkName: "icon" */
|
||||
"../views/Icon.vue")
|
||||
}, {
|
||||
path: '/404',
|
||||
component: () => import(/* webpackChunkName: "404" */ '../components/page/404.vue'),
|
||||
meta: { title: '404' }
|
||||
name: '404',
|
||||
meta: {
|
||||
title: '找不到页面'
|
||||
},
|
||||
{
|
||||
component: () => import (/* webpackChunkName: "404" */
|
||||
'../views/404.vue')
|
||||
}, {
|
||||
path: '/403',
|
||||
component: () => import(/* webpackChunkName: "403" */ '../components/page/403.vue'),
|
||||
meta: { title: '403' }
|
||||
name: '403',
|
||||
meta: {
|
||||
title: '没有权限'
|
||||
},
|
||||
{
|
||||
path: '/donate',
|
||||
component: () => import(/* webpackChunkName: "donate" */ '../components/page/Donate.vue'),
|
||||
meta: { title: '支持作者' }
|
||||
component: () => import (/* webpackChunkName: "403" */
|
||||
'../views/403.vue')
|
||||
}
|
||||
]
|
||||
}, {
|
||||
path: "/login",
|
||||
name: "Login",
|
||||
meta: {
|
||||
title: '登录'
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
component: () => import(/* webpackChunkName: "login" */ '../components/page/Login.vue'),
|
||||
meta: { title: '登录' }
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/404'
|
||||
component: () => import (
|
||||
/* webpackChunkName: "login" */
|
||||
"../views/Login.vue")
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(process.env.BASE_URL),
|
||||
routes
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
document.title = `${to.meta.title} | vue-manage-system`;
|
||||
const role = localStorage.getItem('ms_username');
|
||||
if (!role && to.path !== '/login') {
|
||||
next('/login');
|
||||
} else if (to.meta.permission) {
|
||||
// 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
|
||||
role === 'admin'
|
||||
? next()
|
||||
: next('/403');
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
import {createStore} from 'vuex'
|
||||
|
||||
export default createStore({
|
||||
state: {
|
||||
tagsList: [],
|
||||
collapse: false
|
||||
},
|
||||
mutations: {
|
||||
delTagsItem(state, data) {
|
||||
state
|
||||
.tagsList
|
||||
.splice(data.index, 1);
|
||||
},
|
||||
setTagsItem(state, data) {
|
||||
state
|
||||
.tagsList
|
||||
.push(data)
|
||||
},
|
||||
clearTags(state) {
|
||||
state.tagsList = []
|
||||
},
|
||||
closeTagsOther(state, data) {
|
||||
state.tagsList = data;
|
||||
},
|
||||
closeCurrentTag(state, data) {
|
||||
for (let i = 0, len = state.tagsList.length; i < len; i++) {
|
||||
const item = state.tagsList[i];
|
||||
if (item.path === data.$route.fullPath) {
|
||||
if (i < len - 1) {
|
||||
data
|
||||
.$router
|
||||
.push(state.tagsList[i + 1].path);
|
||||
} else if (i > 0) {
|
||||
data
|
||||
.$router
|
||||
.push(state.tagsList[i - 1].path);
|
||||
} else {
|
||||
data
|
||||
.$router
|
||||
.push("/");
|
||||
}
|
||||
state
|
||||
.tagsList
|
||||
.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
// 侧边栏折叠
|
||||
hadndleCollapse(state, data) {
|
||||
state.collapse = data;
|
||||
}
|
||||
},
|
||||
actions: {},
|
||||
modules: {}
|
||||
})
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
export const messages = {
|
||||
'zh': {
|
||||
export default {
|
||||
'zh-cn': {
|
||||
i18n: {
|
||||
breadcrumb: '国际化产品',
|
||||
tips: '通过切换语言按钮,来改变当前内容的语言。',
|
||||
|
|
@ -7,10 +7,7 @@ export const messages = {
|
|||
title1: '常用用法',
|
||||
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
|
||||
p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
|
||||
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。',
|
||||
title2: '组件插值',
|
||||
info: 'Element组件需要国际化,请参考 {action}。',
|
||||
value: '文档'
|
||||
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。'
|
||||
}
|
||||
},
|
||||
'en': {
|
||||
|
|
@ -21,10 +18,7 @@ export const messages = {
|
|||
title1: 'Common usage',
|
||||
p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.",
|
||||
p2: "Nothing can help us endure dark times better than our faith. ",
|
||||
p3: "If you can do what you do best and be happy, you're further along in life than most people.",
|
||||
title2: 'Component interpolation',
|
||||
info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.',
|
||||
value: 'documentation'
|
||||
p3: "If you can do what you do best and be happy, you're further along in life than most people."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
type="date"
|
||||
placeholder="选择日期"
|
||||
v-model="form.date1"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 100%;"
|
||||
></el-date-picker>
|
||||
</el-col>
|
||||
|
|
@ -14,13 +14,35 @@
|
|||
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>
|
||||
>批量删除</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>
|
||||
</el-select>
|
||||
<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>
|
||||
<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"
|
||||
|
|
@ -30,14 +52,25 @@
|
|||
header-cell-class-name="table-header"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="55" align="center"></el-table-column>
|
||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<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="账户余额">
|
||||
<template slot-scope="scope">¥{{scope.row.money}}</template>
|
||||
<template #default="scope"
|
||||
>¥{{ scope.row.money }}</template
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column label="头像(查看大图)" align="center">
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-image
|
||||
class="table-td-thumb"
|
||||
:src="scope.row.thumb"
|
||||
|
|
@ -47,27 +80,36 @@
|
|||
</el-table-column>
|
||||
<el-table-column prop="address" label="地址"></el-table-column>
|
||||
<el-table-column label="状态" align="center">
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-tag
|
||||
:type="scope.row.state==='成功'?'success':(scope.row.state==='失败'?'danger':'')"
|
||||
>{{scope.row.state}}</el-tag>
|
||||
:type="
|
||||
scope.row.state === '成功'
|
||||
? 'success'
|
||||
: scope.row.state === '失败'
|
||||
? 'danger'
|
||||
: ''
|
||||
"
|
||||
>{{ 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 slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-edit"
|
||||
@click="handleEdit(scope.$index, scope.row)"
|
||||
>编辑</el-button>
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button
|
||||
type="text"
|
||||
icon="el-icon-delete"
|
||||
class="red"
|
||||
@click="handleDelete(scope.$index, scope.row)"
|
||||
>删除</el-button>
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
@ -84,7 +126,7 @@
|
|||
</div>
|
||||
|
||||
<!-- 编辑弹出框 -->
|
||||
<el-dialog title="编辑" :visible.sync="editVisible" width="30%">
|
||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
||||
<el-form ref="form" :model="form" label-width="70px">
|
||||
<el-form-item label="用户名">
|
||||
<el-input v-model="form.name"></el-input>
|
||||
|
|
@ -93,25 +135,28 @@
|
|||
<el-input v-model="form.address"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="editVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
||||
<el-button type="primary" @click="saveEdit"
|
||||
>确 定</el-button
|
||||
>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { fetchData } from '../../api/index';
|
||||
import { fetchData } from "../api/index";
|
||||
export default {
|
||||
name: 'basetable',
|
||||
data() {
|
||||
return {
|
||||
query: {
|
||||
address: '',
|
||||
name: '',
|
||||
address: "",
|
||||
name: "",
|
||||
pageIndex: 1,
|
||||
pageSize: 10
|
||||
pageSize: 10,
|
||||
},
|
||||
tableData: [],
|
||||
multipleSelection: [],
|
||||
|
|
@ -120,7 +165,7 @@ export default {
|
|||
pageTotal: 0,
|
||||
form: {},
|
||||
idx: -1,
|
||||
id: -1
|
||||
id: -1,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
|
@ -129,7 +174,7 @@ export default {
|
|||
methods: {
|
||||
// 获取 easy-mock 的模拟数据
|
||||
getData() {
|
||||
fetchData(this.query).then(res => {
|
||||
fetchData(this.query).then((res) => {
|
||||
console.log(res);
|
||||
this.tableData = res.list;
|
||||
this.pageTotal = res.pageTotal || 50;
|
||||
|
|
@ -137,17 +182,17 @@ export default {
|
|||
},
|
||||
// 触发搜索按钮
|
||||
handleSearch() {
|
||||
this.$set(this.query, 'pageIndex', 1);
|
||||
this.$set(this.query, "pageIndex", 1);
|
||||
this.getData();
|
||||
},
|
||||
// 删除操作
|
||||
handleDelete(index, row) {
|
||||
handleDelete(index) {
|
||||
// 二次确认删除
|
||||
this.$confirm('确定要删除吗?', '提示', {
|
||||
type: 'warning'
|
||||
this.$confirm("确定要删除吗?", "提示", {
|
||||
type: "warning",
|
||||
})
|
||||
.then(() => {
|
||||
this.$message.success('删除成功');
|
||||
this.$message.success("删除成功");
|
||||
this.tableData.splice(index, 1);
|
||||
})
|
||||
.catch(() => {});
|
||||
|
|
@ -158,10 +203,10 @@ export default {
|
|||
},
|
||||
delAllSelection() {
|
||||
const length = this.multipleSelection.length;
|
||||
let str = '';
|
||||
let str = "";
|
||||
this.delList = this.delList.concat(this.multipleSelection);
|
||||
for (let i = 0; i < length; i++) {
|
||||
str += this.multipleSelection[i].name + ' ';
|
||||
str += this.multipleSelection[i].name + " ";
|
||||
}
|
||||
this.$message.error(`删除了${str}`);
|
||||
this.multipleSelection = [];
|
||||
|
|
@ -180,10 +225,10 @@ export default {
|
|||
},
|
||||
// 分页导航
|
||||
handlePageChange(val) {
|
||||
this.$set(this.query, 'pageIndex', val);
|
||||
this.$set(this.query, "pageIndex", val);
|
||||
this.getData();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -4,7 +4,11 @@
|
|||
<el-col :span="8">
|
||||
<el-card shadow="hover" class="mgb20" style="height:252px;">
|
||||
<div class="user-info">
|
||||
<img src="../../assets/img/img.jpg" class="user-avator" alt />
|
||||
<img
|
||||
src="../assets/img/img.jpg"
|
||||
class="user-avator"
|
||||
alt
|
||||
/>
|
||||
<div class="user-info-cont">
|
||||
<div class="user-info-name">{{ name }}</div>
|
||||
<div>{{ role }}</div>
|
||||
|
|
@ -20,21 +24,37 @@
|
|||
</div>
|
||||
</el-card>
|
||||
<el-card shadow="hover" style="height:252px;">
|
||||
<div slot="header" class="clearfix">
|
||||
<template #header>
|
||||
<div class="clearfix">
|
||||
<span>语言详情</span>
|
||||
</div>Vue
|
||||
<el-progress :percentage="71.3" color="#42b983"></el-progress>JavaScript
|
||||
<el-progress :percentage="24.1" color="#f1e05a"></el-progress>CSS
|
||||
<el-progress :percentage="13.7"></el-progress>HTML
|
||||
<el-progress :percentage="5.9" color="#f56c6c"></el-progress>
|
||||
</div>
|
||||
</template>
|
||||
Vue
|
||||
<el-progress
|
||||
:percentage="71.3"
|
||||
color="#42b983"
|
||||
></el-progress
|
||||
>JavaScript
|
||||
<el-progress
|
||||
:percentage="24.1"
|
||||
color="#f1e05a"
|
||||
></el-progress
|
||||
>CSS <el-progress :percentage="13.7"></el-progress>HTML
|
||||
<el-progress
|
||||
:percentage="5.9"
|
||||
color="#f56c6c"
|
||||
></el-progress>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="16">
|
||||
<el-row :gutter="20" class="mgb20">
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" :body-style="{padding: '0px'}">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
:body-style="{ padding: '0px' }"
|
||||
>
|
||||
<div class="grid-content grid-con-1">
|
||||
<i class="el-icon-lx-people grid-con-icon"></i>
|
||||
<i class="el-icon-user-solid grid-con-icon"></i>
|
||||
<div class="grid-cont-right">
|
||||
<div class="grid-num">1234</div>
|
||||
<div>用户访问量</div>
|
||||
|
|
@ -43,9 +63,14 @@
|
|||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" :body-style="{padding: '0px'}">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
:body-style="{ padding: '0px' }"
|
||||
>
|
||||
<div class="grid-content grid-con-2">
|
||||
<i class="el-icon-lx-notice grid-con-icon"></i>
|
||||
<i
|
||||
class="el-icon-message-solid grid-con-icon"
|
||||
></i>
|
||||
<div class="grid-cont-right">
|
||||
<div class="grid-num">321</div>
|
||||
<div>系统消息</div>
|
||||
|
|
@ -54,9 +79,12 @@
|
|||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-card shadow="hover" :body-style="{padding: '0px'}">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
:body-style="{ padding: '0px' }"
|
||||
>
|
||||
<div class="grid-content grid-con-3">
|
||||
<i class="el-icon-lx-goods grid-con-icon"></i>
|
||||
<i class="el-icon-s-goods grid-con-icon"></i>
|
||||
<div class="grid-cont-right">
|
||||
<div class="grid-num">5000</div>
|
||||
<div>数量</div>
|
||||
|
|
@ -66,22 +94,39 @@
|
|||
</el-col>
|
||||
</el-row>
|
||||
<el-card shadow="hover" style="height:403px;">
|
||||
<div slot="header" class="clearfix">
|
||||
<template #header>
|
||||
<div class="clearfix">
|
||||
<span>待办事项</span>
|
||||
<el-button style="float: right; padding: 3px 0" type="text">添加</el-button>
|
||||
<el-button
|
||||
style="float: right; padding: 3px 0"
|
||||
type="text"
|
||||
>添加</el-button
|
||||
>
|
||||
</div>
|
||||
<el-table :show-header="false" :data="todoList" style="width:100%;">
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
:show-header="false"
|
||||
:data="todoList"
|
||||
style="width:100%;"
|
||||
>
|
||||
<el-table-column width="40">
|
||||
<template slot-scope="scope">
|
||||
<el-checkbox v-model="scope.row.status"></el-checkbox>
|
||||
<template #default="scope">
|
||||
<el-checkbox
|
||||
v-model="scope.row.status"
|
||||
></el-checkbox>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<div
|
||||
class="todo-item"
|
||||
:class="{'todo-item-del': scope.row.status}"
|
||||
>{{scope.row.title}}</div>
|
||||
:class="{
|
||||
'todo-item-del': scope.row.status,
|
||||
}"
|
||||
>
|
||||
{{ scope.row.title }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="60">
|
||||
|
|
@ -97,12 +142,22 @@
|
|||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-card shadow="hover">
|
||||
<schart ref="bar" class="schart" canvasId="bar" :options="options"></schart>
|
||||
<schart
|
||||
ref="bar"
|
||||
class="schart"
|
||||
canvasId="bar"
|
||||
:options="options"
|
||||
></schart>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-card shadow="hover">
|
||||
<schart ref="line" class="schart" canvasId="line" :options="options2"></schart>
|
||||
<schart
|
||||
ref="line"
|
||||
class="schart"
|
||||
canvasId="line"
|
||||
:options="options2"
|
||||
></schart>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
|
@ -110,141 +165,132 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import Schart from 'vue-schart';
|
||||
import bus from '../common/bus';
|
||||
import Schart from "vue-schart";
|
||||
// import bus from '../common/bus';
|
||||
export default {
|
||||
name: 'dashboard',
|
||||
name: "dashboard",
|
||||
data() {
|
||||
return {
|
||||
name: localStorage.getItem('ms_username'),
|
||||
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: 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,
|
||||
},
|
||||
{
|
||||
title: '今天要写100行代码加几个bug吧',
|
||||
status: true
|
||||
}
|
||||
title: "今天要写100行代码加几个bug吧",
|
||||
status: true,
|
||||
},
|
||||
],
|
||||
data: [
|
||||
{
|
||||
name: '2018/09/04',
|
||||
value: 1083
|
||||
name: "2018/09/04",
|
||||
value: 1083,
|
||||
},
|
||||
{
|
||||
name: '2018/09/05',
|
||||
value: 941
|
||||
name: "2018/09/05",
|
||||
value: 941,
|
||||
},
|
||||
{
|
||||
name: '2018/09/06',
|
||||
value: 1139
|
||||
name: "2018/09/06",
|
||||
value: 1139,
|
||||
},
|
||||
{
|
||||
name: '2018/09/07',
|
||||
value: 816
|
||||
name: "2018/09/07",
|
||||
value: 816,
|
||||
},
|
||||
{
|
||||
name: '2018/09/08',
|
||||
value: 327
|
||||
name: "2018/09/08",
|
||||
value: 327,
|
||||
},
|
||||
{
|
||||
name: '2018/09/09',
|
||||
value: 228
|
||||
name: "2018/09/09",
|
||||
value: 228,
|
||||
},
|
||||
{
|
||||
name: '2018/09/10',
|
||||
value: 1065
|
||||
}
|
||||
name: "2018/09/10",
|
||||
value: 1065,
|
||||
},
|
||||
],
|
||||
options: {
|
||||
type: 'bar',
|
||||
type: "bar",
|
||||
title: {
|
||||
text: '最近一周各品类销售图'
|
||||
text: "最近一周各品类销售图",
|
||||
},
|
||||
xRorate: 25,
|
||||
labels: ['周一', '周二', '周三', '周四', '周五'],
|
||||
labels: ["周一", "周二", "周三", "周四", "周五"],
|
||||
datasets: [
|
||||
{
|
||||
label: '家电',
|
||||
data: [234, 278, 270, 190, 230]
|
||||
label: "家电",
|
||||
data: [234, 278, 270, 190, 230],
|
||||
},
|
||||
{
|
||||
label: '百货',
|
||||
data: [164, 178, 190, 135, 160]
|
||||
label: "百货",
|
||||
data: [164, 178, 190, 135, 160],
|
||||
},
|
||||
{
|
||||
label: '食品',
|
||||
data: [144, 198, 150, 235, 120]
|
||||
}
|
||||
]
|
||||
label: "食品",
|
||||
data: [144, 198, 150, 235, 120],
|
||||
},
|
||||
],
|
||||
},
|
||||
options2: {
|
||||
type: 'line',
|
||||
type: "line",
|
||||
title: {
|
||||
text: '最近几个月各品类销售趋势图'
|
||||
text: "最近几个月各品类销售趋势图",
|
||||
},
|
||||
labels: ['6月', '7月', '8月', '9月', '10月'],
|
||||
labels: ["6月", "7月", "8月", "9月", "10月"],
|
||||
datasets: [
|
||||
{
|
||||
label: '家电',
|
||||
data: [234, 278, 270, 190, 230]
|
||||
label: "家电",
|
||||
data: [234, 278, 270, 190, 230],
|
||||
},
|
||||
{
|
||||
label: '百货',
|
||||
data: [164, 178, 150, 135, 160]
|
||||
label: "百货",
|
||||
data: [164, 178, 150, 135, 160],
|
||||
},
|
||||
{
|
||||
label: '食品',
|
||||
data: [74, 118, 200, 235, 90]
|
||||
}
|
||||
]
|
||||
}
|
||||
label: "食品",
|
||||
data: [74, 118, 200, 235, 90],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
components: {
|
||||
Schart
|
||||
Schart,
|
||||
},
|
||||
computed: {
|
||||
role() {
|
||||
return this.name === 'admin' ? '超级管理员' : '普通用户';
|
||||
}
|
||||
return this.name === "admin" ? "超级管理员" : "普通用户";
|
||||
},
|
||||
// created() {
|
||||
// this.handleListener();
|
||||
// this.changeDate();
|
||||
// },
|
||||
// activated() {
|
||||
// this.handleListener();
|
||||
// },
|
||||
// deactivated() {
|
||||
// window.removeEventListener('resize', this.renderChart);
|
||||
// bus.$off('collapse', this.handleBus);
|
||||
// },
|
||||
},
|
||||
|
||||
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()}`;
|
||||
item.name = `${date.getFullYear()}/${date.getMonth() +
|
||||
1}/${date.getDate()}`;
|
||||
});
|
||||
}
|
||||
},
|
||||
// handleListener() {
|
||||
// bus.$on('collapse', this.handleBus);
|
||||
// // 调用renderChart方法对图表进行重新渲染
|
||||
|
|
@ -259,11 +305,10 @@ export default {
|
|||
// this.$refs.bar.renderChart();
|
||||
// this.$refs.line.renderChart();
|
||||
// }
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.el-row {
|
||||
margin-bottom: 20px;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<template>
|
||||
<div class="about">
|
||||
<v-header />
|
||||
<v-sidebar />
|
||||
<div class="content-box" :class="{'content-collapse':collapse}">
|
||||
<v-tags></v-tags>
|
||||
<div class="content">
|
||||
<!-- <keep-alive :include="tagsList"> -->
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="move" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
<!-- </keep-alive> -->
|
||||
<!-- <el-backtop target=".content"></el-backtop> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import vHeader from "../components/Header";
|
||||
import vSidebar from "../components/Sidebar";
|
||||
import vTags from "../components/Tags.vue";
|
||||
export default {
|
||||
components: {
|
||||
vHeader,
|
||||
vSidebar,
|
||||
vTags
|
||||
},
|
||||
computed:{
|
||||
collapse(){
|
||||
return this.$store.state.collapse
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -7,29 +7,19 @@
|
|||
</div>
|
||||
<div class="container">
|
||||
<span>{{$t('i18n.tips')}}</span>
|
||||
<el-button type="primary" @click="$i18n.locale = $i18n.locale === 'zh'?'en':'zh';">{{$t('i18n.btn')}}</el-button>
|
||||
<el-button type="primary" @click="$i18n.locale = $i18n.locale === 'zh-cn'?'en':'zh-cn';">{{$t('i18n.btn')}}</el-button>
|
||||
<div class="list">
|
||||
<h2>{{$t('i18n.title1')}}</h2>
|
||||
<p>{{$t('i18n.p1')}}</p>
|
||||
<p>{{$t('i18n.p2')}}</p>
|
||||
<p>{{$t('i18n.p3')}}</p>
|
||||
</div>
|
||||
<h2>{{$t('i18n.title2')}}</h2>
|
||||
<div>
|
||||
<i18n path="i18n.info" tag="p">
|
||||
<a place="action" href="https://element.eleme.cn/2.0/#/zh-CN/component/i18n">{{ $t('i18n.value') }}</a>
|
||||
</i18n>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data(){
|
||||
return {
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
@ -40,7 +30,4 @@ export default {
|
|||
.list p{
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
a{
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,7 +5,9 @@
|
|||
<el-form :model="param" :rules="rules" ref="login" label-width="0px" class="ms-content">
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="param.username" placeholder="username">
|
||||
<el-button slot="prepend" icon="el-icon-lx-people"></el-button>
|
||||
<template #prepend>
|
||||
<el-button icon="el-icon-user"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<el-form-item prop="password">
|
||||
|
|
@ -13,9 +15,11 @@
|
|||
type="password"
|
||||
placeholder="password"
|
||||
v-model="param.password"
|
||||
@keyup.enter.native="submitForm()"
|
||||
@keyup.enter="submitForm()"
|
||||
>
|
||||
<el-button slot="prepend" icon="el-icon-lx-lock"></el-button>
|
||||
<template #prepend>
|
||||
<el-button icon="el-icon-lock"></el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
<div class="login-btn">
|
||||
|
|
@ -29,33 +33,39 @@
|
|||
|
||||
<script>
|
||||
export default {
|
||||
data: function() {
|
||||
data() {
|
||||
return {
|
||||
param: {
|
||||
username: 'admin',
|
||||
password: '123123',
|
||||
username: "admin",
|
||||
password: "123123"
|
||||
},
|
||||
rules: {
|
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
|
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
|
||||
},
|
||||
username: [
|
||||
{ required: true, message: "请输入用户名", trigger: "blur" }
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "请输入密码", trigger: "blur" }
|
||||
]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$store.commit("clearTags");
|
||||
},
|
||||
methods: {
|
||||
submitForm() {
|
||||
this.$refs.login.validate(valid => {
|
||||
if (valid) {
|
||||
this.$message.success('登录成功');
|
||||
localStorage.setItem('ms_username', this.param.username);
|
||||
this.$router.push('/');
|
||||
this.$message.success("登录成功");
|
||||
localStorage.setItem("ms_username", this.param.username);
|
||||
this.$router.push("/");
|
||||
} else {
|
||||
this.$message.error('请输入账号和密码');
|
||||
console.log('error submit!!');
|
||||
this.$message.error("请输入账号和密码");
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
@ -64,7 +74,7 @@ export default {
|
|||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(../../assets/img/login-bg.jpg);
|
||||
background-image: url(../assets/img/login-bg.jpg);
|
||||
background-size: 100%;
|
||||
}
|
||||
.ms-title {
|
||||
|
|
@ -10,13 +10,13 @@
|
|||
<el-tab-pane :label="`未读消息(${unread.length})`" name="first">
|
||||
<el-table :data="unread" :show-header="false" style="width: 100%">
|
||||
<el-table-column>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<span class="message-title">{{scope.row.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="date" width="180"></el-table-column>
|
||||
<el-table-column width="120">
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-button size="small" @click="handleRead(scope.$index)">标为已读</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -29,13 +29,13 @@
|
|||
<template v-if="message === 'second'">
|
||||
<el-table :data="read" :show-header="false" style="width: 100%">
|
||||
<el-table-column>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<span class="message-title">{{scope.row.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="date" width="150"></el-table-column>
|
||||
<el-table-column width="120">
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" @click="handleDel(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -49,13 +49,13 @@
|
|||
<template v-if="message === 'third'">
|
||||
<el-table :data="recycle" :show-header="false" style="width: 100%">
|
||||
<el-table-column>
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<span class="message-title">{{scope.row.title}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="date" width="150"></el-table-column>
|
||||
<el-table-column width="120">
|
||||
<template slot-scope="scope">
|
||||
<template #default="scope">
|
||||
<el-button @click="handleRestore(scope.$index)">还原</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -0,0 +1,176 @@
|
|||
<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="content-title">支持拖拽</div>
|
||||
<div class="plugins-tips">
|
||||
Element UI自带上传组件。
|
||||
访问地址:
|
||||
<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
|
||||
>
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">
|
||||
将文件拖到此处,或
|
||||
<em>点击上传</em>
|
||||
</div>
|
||||
<template #tip>
|
||||
<div class="el-upload__tip">只能上传 jpg/png 文件,且不超过 500kb</div>
|
||||
</template>
|
||||
</el-upload>
|
||||
|
||||
<div class="content-title">支持裁剪</div>
|
||||
<div class="plugins-tips">
|
||||
vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。
|
||||
访问地址:
|
||||
<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 {
|
||||
data() {
|
||||
return {
|
||||
defaultSrc: require("../assets/img/img.jpg"),
|
||||
fileList: [],
|
||||
imgSrc: "",
|
||||
cropImg: "",
|
||||
dialogVisible: false
|
||||
};
|
||||
},
|
||||
components: {
|
||||
VueCropper
|
||||
},
|
||||
methods: {
|
||||
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.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: "图片上传接口上传失败,可更改为自己的服务器接口"
|
||||
});
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.cropImg = this.defaultSrc;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.content-title {
|
||||
font-weight: 400;
|
||||
line-height: 50px;
|
||||
margin: 10px 0;
|
||||
font-size: 22px;
|
||||
color: #1f2f3d;
|
||||
}
|
||||
|
||||
.pre-img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: #f8f8f8;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.crop-demo {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.crop-demo-btn {
|
||||
position: relative;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 20px;
|
||||
margin-left: 30px;
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.crop-input {
|
||||
position: absolute;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue