改为typescript;升级elementplus
parent
a072752609
commit
995ab69b1e
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2016-2021 vue-manage-system
|
Copyright (c) 2016-2023 vue-manage-system
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
||||||
53
README.md
53
README.md
|
|
@ -22,16 +22,6 @@
|
||||||
|
|
||||||
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
|
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
|
||||||
|
|
||||||
## 项目截图
|
|
||||||
|
|
||||||
### 登录
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### 首页
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 赞助商
|
## 赞助商
|
||||||
|
|
||||||
### 好问
|
### 好问
|
||||||
|
|
@ -40,7 +30,7 @@
|
||||||
|
|
||||||
专业问卷服务,一对一客服,按需定制
|
专业问卷服务,一对一客服,按需定制
|
||||||
|
|
||||||
## 赞赏
|
## 支持作者
|
||||||
|
|
||||||
请作者喝杯咖啡吧!(微信号:linxin_20)
|
请作者喝杯咖啡吧!(微信号:linxin_20)
|
||||||
|
|
||||||
|
|
@ -48,26 +38,25 @@
|
||||||
|
|
||||||
## 前言
|
## 前言
|
||||||
|
|
||||||
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 Vue3 + pinia,引用 Element Plus 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
|
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统开发。基于 Vue3 + pinia,引用 Element Plus 组件库,方便开发。
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
- [x] Element Plus
|
- [x] Element Plus
|
||||||
|
- [x] vite
|
||||||
|
- [x] pinia
|
||||||
- [x] 登录/注销
|
- [x] 登录/注销
|
||||||
- [x] Dashboard
|
- [x] Dashboard
|
||||||
- [x] 表格
|
- [x] 表格
|
||||||
- [x] Tab 选项卡
|
- [x] Tab 选项卡
|
||||||
- [x] 表单
|
- [x] 表单
|
||||||
- [x] 图表 :bar_chart:
|
- [x] 图表 :bar_chart:
|
||||||
- [x] 富文本编辑器
|
- [x] 富文本/markdown编辑器
|
||||||
- [x] 图片拖拽/裁剪上传
|
- [x] 图片拖拽/裁剪上传
|
||||||
- [x] 权限测试
|
- [x] 权限管理
|
||||||
- [x] 404 / 403
|
|
||||||
- [x] 三级菜单
|
- [x] 三级菜单
|
||||||
- [x] 自定义图标
|
- [x] 自定义图标
|
||||||
- [x] 国际化
|
|
||||||
- [x] vite
|
|
||||||
- [x] pinia
|
|
||||||
|
|
||||||
## 安装步骤
|
## 安装步骤
|
||||||
|
|
||||||
|
|
@ -76,7 +65,7 @@ git clone https://github.com/lin-xin/vue-manage-system.git // 把模板下
|
||||||
cd vue-manage-system // 进入模板目录
|
cd vue-manage-system // 进入模板目录
|
||||||
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
|
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
|
||||||
|
|
||||||
// 开启服务器,浏览器访问 http://localhost:8080
|
// 运行
|
||||||
npm run dev
|
npm run dev
|
||||||
|
|
||||||
// 执行构建命令,生成的dist文件夹放在服务器下即可访问
|
// 执行构建命令,生成的dist文件夹放在服务器下即可访问
|
||||||
|
|
@ -98,12 +87,10 @@ vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://gi
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
import Schart from "vue-schart"; // 导入Schart组件
|
import Schart from "vue-schart"; // 导入Schart组件
|
||||||
export default {
|
const options = ref({
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
options: {
|
|
||||||
type: "bar",
|
type: "bar",
|
||||||
title: {
|
title: {
|
||||||
text: "最近一周各品类销售图",
|
text: "最近一周各品类销售图",
|
||||||
|
|
@ -123,13 +110,7 @@ vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://gi
|
||||||
data: [144, 198, 150, 235, 120],
|
data: [144, 198, 150, 235, 120],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
})
|
||||||
};
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Schart,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
@ -139,6 +120,16 @@ vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://gi
|
||||||
</style>
|
</style>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 项目截图
|
||||||
|
|
||||||
|
### 登录
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 首页
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)
|
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)
|
||||||
|
|
|
||||||
31
README_EN.md
31
README_EN.md
|
|
@ -37,13 +37,10 @@ The scheme as a set of multi-function background frame templates, suitable for m
|
||||||
- [x] Tabs
|
- [x] Tabs
|
||||||
- [x] From
|
- [x] From
|
||||||
- [x] Chart :bar_chart:
|
- [x] Chart :bar_chart:
|
||||||
- [ ] Editor
|
- [x] Editor
|
||||||
- [ ] Markdown
|
- [x] Markdown
|
||||||
- [x] Upload pictures by clipping or dragging
|
- [x] Upload pictures by clipping or dragging
|
||||||
- [ ] Support manual switch themes :sparkles:
|
|
||||||
- [ ] List drag sort
|
|
||||||
- [x] Permission
|
- [x] Permission
|
||||||
- [x] 404 / 403
|
|
||||||
- [x] Three level menu
|
- [x] Three level menu
|
||||||
- [x] Custom icon
|
- [x] Custom icon
|
||||||
|
|
||||||
|
|
@ -55,8 +52,7 @@ The scheme as a set of multi-function background frame templates, suitable for m
|
||||||
|
|
||||||
## Local development
|
## Local development
|
||||||
|
|
||||||
// Open server and access http://localhost:8080 in browser
|
npm run dev
|
||||||
npm run serve
|
|
||||||
|
|
||||||
## Constructing production
|
## Constructing production
|
||||||
|
|
||||||
|
|
@ -75,13 +71,10 @@ Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/lin-xin/v
|
||||||
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
|
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<script setup>
|
||||||
<script>
|
import { ref } from 'vue';
|
||||||
import Schart from "vue-schart"; // 导入Schart组件
|
import Schart from "vue-schart"; // 导入Schart组件
|
||||||
export default {
|
const options = ref({
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
options: {
|
|
||||||
type: "bar",
|
type: "bar",
|
||||||
title: {
|
title: {
|
||||||
text: "最近一周各品类销售图",
|
text: "最近一周各品类销售图",
|
||||||
|
|
@ -101,13 +94,7 @@ Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/lin-xin/v
|
||||||
data: [144, 198, 150, 235, 120],
|
data: [144, 198, 150, 235, 120],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
})
|
||||||
};
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
Schart,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
|
@ -117,10 +104,6 @@ Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/lin-xin/v
|
||||||
</style>
|
</style>
|
||||||
```
|
```
|
||||||
|
|
||||||
### element-ui
|
|
||||||
|
|
||||||
A desktop component library based on vue.js2.0 . Github : [element](http://element.eleme.io/#/zh-CN/component/layout)
|
|
||||||
|
|
||||||
## Screenshot
|
## Screenshot
|
||||||
|
|
||||||
### Default theme
|
### Default theme
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
// Generated by 'unplugin-auto-import'
|
||||||
|
export {}
|
||||||
|
declare global {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
// generated by unplugin-vue-components
|
||||||
|
// We suggest you to commit this file into source control
|
||||||
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
|
export {}
|
||||||
|
|
||||||
|
declare module '@vue/runtime-core' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
ElAvatar: typeof import('element-plus/es')['ElAvatar']
|
||||||
|
ElButton: typeof import('element-plus/es')['ElButton']
|
||||||
|
ElCard: typeof import('element-plus/es')['ElCard']
|
||||||
|
ElCascader: typeof import('element-plus/es')['ElCascader']
|
||||||
|
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
|
||||||
|
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
|
||||||
|
ElCol: typeof import('element-plus/es')['ElCol']
|
||||||
|
ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
|
||||||
|
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||||
|
ElDropdown: typeof import('element-plus/es')['ElDropdown']
|
||||||
|
ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem']
|
||||||
|
ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu']
|
||||||
|
ElForm: typeof import('element-plus/es')['ElForm']
|
||||||
|
ElFormItem: typeof import('element-plus/es')['ElFormItem']
|
||||||
|
ElIcon: typeof import('element-plus/es')['ElIcon']
|
||||||
|
ElImage: typeof import('element-plus/es')['ElImage']
|
||||||
|
ElInput: typeof import('element-plus/es')['ElInput']
|
||||||
|
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||||
|
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||||
|
ElOption: typeof import('element-plus/es')['ElOption']
|
||||||
|
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||||
|
ElProgress: typeof import('element-plus/es')['ElProgress']
|
||||||
|
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||||
|
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||||
|
ElRow: typeof import('element-plus/es')['ElRow']
|
||||||
|
ElSelect: typeof import('element-plus/es')['ElSelect']
|
||||||
|
ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
|
||||||
|
ElSwitch: typeof import('element-plus/es')['ElSwitch']
|
||||||
|
ElTable: typeof import('element-plus/es')['ElTable']
|
||||||
|
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||||
|
ElTabPane: typeof import('element-plus/es')['ElTabPane']
|
||||||
|
ElTabs: typeof import('element-plus/es')['ElTabs']
|
||||||
|
ElTag: typeof import('element-plus/es')['ElTag']
|
||||||
|
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
|
||||||
|
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||||
|
ElUpload: typeof import('element-plus/es')['ElUpload']
|
||||||
|
Header: typeof import('./src/components/header.vue')['default']
|
||||||
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
Sidebar: typeof import('./src/components/sidebar.vue')['default']
|
||||||
|
Tags: typeof import('./src/components/tags.vue')['default']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
Please enable it to continue.</strong>
|
Please enable it to continue.</strong>
|
||||||
</noscript>
|
</noscript>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
<!-- built files will be auto injected -->
|
<!-- built files will be auto injected -->
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
31
package.json
31
package.json
|
|
@ -1,28 +1,33 @@
|
||||||
{
|
{
|
||||||
"name": "vue-manage-system",
|
"name": "vue-manage-system",
|
||||||
"version": "5.2.0",
|
"version": "5.3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vue-tsc --noEmit && vite build",
|
||||||
"serve": "vite preview"
|
"serve": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.21.1",
|
"@element-plus/icons-vue": "^2.0.9",
|
||||||
"element-plus": "^1.0.2-beta.52",
|
"axios": "^0.27.2",
|
||||||
"md-editor-v3": "^2.2.0",
|
"element-plus": "^2.2.14",
|
||||||
"pinia": "^2.0.14",
|
"md-editor-v3": "^2.2.1",
|
||||||
"vue": "^3.1.2",
|
"pinia": "^2.0.20",
|
||||||
|
"vue": "^3.2.37",
|
||||||
"vue-cropperjs": "^5.0.0",
|
"vue-cropperjs": "^5.0.0",
|
||||||
"vue-i18n": "^9.0.0",
|
"vue-router": "^4.1.3",
|
||||||
"vue-router": "^4.0.10",
|
|
||||||
"vue-schart": "^2.0.0",
|
"vue-schart": "^2.0.0",
|
||||||
"wangeditor": "^4.7.4"
|
"wangeditor": "^4.7.15"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vite": "2.3.7",
|
"@vitejs/plugin-vue": "^3.0.0",
|
||||||
"@vitejs/plugin-vue": "^1.2.3",
|
"@vue/compiler-sfc": "^3.1.2",
|
||||||
"@vue/compiler-sfc": "^3.1.2"
|
"typescript": "^4.6.4",
|
||||||
|
"unplugin-auto-import": "^0.11.2",
|
||||||
|
"unplugin-vue-components": "^0.22.4",
|
||||||
|
"vite": "^3.0.0",
|
||||||
|
"vite-plugin-vue-setup-extend": "^0.4.0",
|
||||||
|
"vue-tsc": "^0.38.4"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,7 @@
|
||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@import "./assets/css/main.css";
|
@import './assets/css/main.css';
|
||||||
@import "./assets/css/color-dark.css";
|
@import './assets/css/color-dark.css';
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import request from '../utils/request';
|
import request from '../utils/request';
|
||||||
|
|
||||||
export const fetchData = query => {
|
export const fetchData = () => {
|
||||||
return request({
|
return request({
|
||||||
url: './table.json',
|
url: './table.json',
|
||||||
method: 'get',
|
method: 'get'
|
||||||
params: query
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -175,3 +175,27 @@ a {
|
||||||
.v-note-wrapper .v-note-panel {
|
.v-note-wrapper .v-note-panel {
|
||||||
min-height: 500px;
|
min-height: 500px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[class*=" el-icon-"], [class^=el-icon-] {
|
||||||
|
speak: none;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
line-height: 1;
|
||||||
|
vertical-align: baseline;
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
.el-sub-menu [class^=el-icon-] {
|
||||||
|
vertical-align: middle;
|
||||||
|
margin-right: 5px;
|
||||||
|
width: 24px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
[hidden]{
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
@ -2,30 +2,32 @@
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<!-- 折叠按钮 -->
|
<!-- 折叠按钮 -->
|
||||||
<div class="collapse-btn" @click="collapseChage">
|
<div class="collapse-btn" @click="collapseChage">
|
||||||
<i v-if="!sidebar.collapse" class="el-icon-s-fold"></i>
|
<el-icon v-if="sidebar.collapse"><Expand /></el-icon>
|
||||||
<i v-else class="el-icon-s-unfold"></i>
|
<el-icon v-else><Fold /></el-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="logo">后台管理系统</div>
|
<div class="logo">后台管理系统</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
<div class="header-user-con">
|
<div class="header-user-con">
|
||||||
<!-- 消息中心 -->
|
<!-- 消息中心 -->
|
||||||
<div class="btn-bell">
|
<div class="btn-bell" @click="router.push('/tabs')">
|
||||||
<el-tooltip effect="dark" :content="message?`有${message}条未读消息`:`消息中心`" placement="bottom">
|
<el-tooltip
|
||||||
<router-link to="/tabs">
|
effect="dark"
|
||||||
<i class="el-icon-bell"></i>
|
:content="message ? `有${message}条未读消息` : `消息中心`"
|
||||||
</router-link>
|
placement="bottom"
|
||||||
|
>
|
||||||
|
<i class="el-icon-lx-notice"></i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span class="btn-bell-badge" v-if="message"></span>
|
<span class="btn-bell-badge" v-if="message"></span>
|
||||||
</div>
|
</div>
|
||||||
<!-- 用户头像 -->
|
<!-- 用户头像 -->
|
||||||
<div class="user-avator">
|
<el-avatar class="user-avator" :size="30" :src="imgurl" />
|
||||||
<img src="../assets/img/img.jpg" />
|
|
||||||
</div>
|
|
||||||
<!-- 用户名下拉菜单 -->
|
<!-- 用户名下拉菜单 -->
|
||||||
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
|
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
|
||||||
<span class="el-dropdown-link">
|
<span class="el-dropdown-link">
|
||||||
{{ username }}
|
{{ username }}
|
||||||
<i class="el-icon-caret-bottom"></i>
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
</span>
|
</span>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu>
|
<el-dropdown-menu>
|
||||||
|
|
@ -41,14 +43,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { computed, onMounted } from "vue";
|
import { onMounted } from 'vue';
|
||||||
import { useSidebarStore } from '../store/sidebar'
|
import { useSidebarStore } from '../store/sidebar';
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
export default {
|
import imgurl from '../assets/img/img.jpg';
|
||||||
setup() {
|
|
||||||
const username = localStorage.getItem("ms_username");
|
const username: string | null = localStorage.getItem('ms_username');
|
||||||
const message = 2;
|
const message: number = 2;
|
||||||
|
|
||||||
const sidebar = useSidebarStore();
|
const sidebar = useSidebarStore();
|
||||||
// 侧边栏折叠
|
// 侧边栏折叠
|
||||||
|
|
@ -64,24 +66,14 @@ export default {
|
||||||
|
|
||||||
// 用户名下拉菜单选择事件
|
// 用户名下拉菜单选择事件
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const handleCommand = (command) => {
|
const handleCommand = (command: string) => {
|
||||||
if (command == "loginout") {
|
if (command == 'loginout') {
|
||||||
localStorage.removeItem("ms_username");
|
localStorage.removeItem('ms_username');
|
||||||
router.push("/login");
|
router.push('/login');
|
||||||
} else if (command == "user") {
|
} else if (command == 'user') {
|
||||||
router.push("/user");
|
router.push('/user');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
|
||||||
sidebar,
|
|
||||||
username,
|
|
||||||
message,
|
|
||||||
collapseChage,
|
|
||||||
handleCommand,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.header {
|
.header {
|
||||||
|
|
@ -93,10 +85,13 @@ export default {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.collapse-btn {
|
.collapse-btn {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
float: left;
|
float: left;
|
||||||
padding: 0 21px;
|
padding: 0 21px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 70px;
|
|
||||||
}
|
}
|
||||||
.header .logo {
|
.header .logo {
|
||||||
float: left;
|
float: left;
|
||||||
|
|
@ -125,18 +120,20 @@ export default {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.btn-bell-badge {
|
.btn-bell-badge {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 4px;
|
||||||
top: -2px;
|
top: 0px;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: #f56c6c;
|
background: #f56c6c;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.btn-bell .el-icon-bell {
|
.btn-bell .el-icon-lx-notice {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.user-name {
|
.user-name {
|
||||||
|
|
@ -145,15 +142,11 @@ export default {
|
||||||
.user-avator {
|
.user-avator {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
.user-avator img {
|
|
||||||
display: block;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
.el-dropdown-link {
|
.el-dropdown-link {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.el-dropdown-menu__item {
|
.el-dropdown-menu__item {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,47 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<el-menu class="sidebar-el-menu" :default-active="onRoutes" :collapse="sidebar.collapse" background-color="#324157"
|
<el-menu
|
||||||
text-color="#bfcbd9" active-text-color="#20a0ff" unique-opened router>
|
class="sidebar-el-menu"
|
||||||
|
:default-active="onRoutes"
|
||||||
|
:collapse="sidebar.collapse"
|
||||||
|
background-color="#324157"
|
||||||
|
text-color="#bfcbd9"
|
||||||
|
active-text-color="#20a0ff"
|
||||||
|
unique-opened
|
||||||
|
router
|
||||||
|
>
|
||||||
<template v-for="item in items">
|
<template v-for="item in items">
|
||||||
<template v-if="item.subs">
|
<template v-if="item.subs">
|
||||||
<el-submenu :index="item.index" :key="item.index">
|
<el-sub-menu :index="item.index" :key="item.index" v-permiss="item.permiss">
|
||||||
<template #title>
|
<template #title>
|
||||||
<i :class="item.icon"></i>
|
<el-icon>
|
||||||
|
<component :is="item.icon"></component>
|
||||||
|
</el-icon>
|
||||||
<span>{{ item.title }}</span>
|
<span>{{ item.title }}</span>
|
||||||
</template>
|
</template>
|
||||||
<template v-for="subItem in item.subs">
|
<template v-for="subItem in item.subs">
|
||||||
<el-submenu v-if="subItem.subs" :index="subItem.index" :key="subItem.index">
|
<el-sub-menu
|
||||||
|
v-if="subItem.subs"
|
||||||
|
:index="subItem.index"
|
||||||
|
:key="subItem.index"
|
||||||
|
v-permiss="item.permiss"
|
||||||
|
>
|
||||||
<template #title>{{ subItem.title }}</template>
|
<template #title>{{ subItem.title }}</template>
|
||||||
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
|
<el-menu-item v-for="(threeItem, i) in subItem.subs" :key="i" :index="threeItem.index">
|
||||||
{{ threeItem.title }}</el-menu-item>
|
{{ threeItem.title }}
|
||||||
</el-submenu>
|
</el-menu-item>
|
||||||
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}
|
</el-sub-menu>
|
||||||
|
<el-menu-item v-else :index="subItem.index" v-permiss="item.permiss">
|
||||||
|
{{ subItem.title }}
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
</el-submenu>
|
</el-sub-menu>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-menu-item :index="item.index" :key="item.index">
|
<el-menu-item :index="item.index" :key="item.index" v-permiss="item.permiss">
|
||||||
<i :class="item.icon"></i>
|
<el-icon>
|
||||||
|
<component :is="item.icon"></component>
|
||||||
|
</el-icon>
|
||||||
<template #title>{{ item.title }}</template>
|
<template #title>{{ item.title }}</template>
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -31,92 +50,89 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { computed } from "vue";
|
import { computed } from 'vue';
|
||||||
import { useSidebarStore } from '../store/sidebar'
|
import { useSidebarStore } from '../store/sidebar';
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from 'vue-router';
|
||||||
export default {
|
|
||||||
setup() {
|
|
||||||
const items = [
|
const items = [
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-home",
|
icon: 'Odometer',
|
||||||
index: "/dashboard",
|
index: '/dashboard',
|
||||||
title: "系统首页",
|
title: '系统首页',
|
||||||
|
permiss: '1'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-cascades",
|
icon: 'Calendar',
|
||||||
index: "/table",
|
index: '/table',
|
||||||
title: "基础表格",
|
title: '基础表格',
|
||||||
|
permiss: '2'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-copy",
|
icon: 'DocumentCopy',
|
||||||
index: "/tabs",
|
index: '/tabs',
|
||||||
title: "tab选项卡",
|
title: 'tab选项卡',
|
||||||
|
permiss: '3'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-calendar",
|
icon: 'Edit',
|
||||||
index: "3",
|
index: '3',
|
||||||
title: "表单相关",
|
title: '表单相关',
|
||||||
|
permiss: '4',
|
||||||
subs: [
|
subs: [
|
||||||
{
|
{
|
||||||
index: "/form",
|
index: '/form',
|
||||||
title: "基本表单",
|
title: '基本表单',
|
||||||
|
permiss: '5'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: "/upload",
|
index: '/upload',
|
||||||
title: "文件上传",
|
title: '文件上传',
|
||||||
|
permiss: '6'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: "4",
|
index: '4',
|
||||||
title: "三级菜单",
|
title: '三级菜单',
|
||||||
|
permiss: '7',
|
||||||
subs: [
|
subs: [
|
||||||
{
|
{
|
||||||
index: "/editor",
|
index: '/editor',
|
||||||
title: "富文本编辑器",
|
title: '富文本编辑器',
|
||||||
|
permiss: '8'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
index: "/markdown",
|
index: '/markdown',
|
||||||
title: "markdown编辑器",
|
title: 'markdown编辑器',
|
||||||
},
|
permiss: '9'
|
||||||
],
|
}
|
||||||
},
|
]
|
||||||
],
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-emoji",
|
icon: 'Setting',
|
||||||
index: "/icon",
|
index: '/icon',
|
||||||
title: "自定义图标",
|
title: '自定义图标',
|
||||||
|
permiss: '10'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-pie-chart",
|
icon: 'PieChart',
|
||||||
index: "/charts",
|
index: '/charts',
|
||||||
title: "schart图表",
|
title: 'schart图表',
|
||||||
|
permiss: '11'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-global",
|
icon: 'Warning',
|
||||||
index: "/i18n",
|
index: '/permission',
|
||||||
title: "国际化功能",
|
title: '权限管理',
|
||||||
|
permiss: '13'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: "el-icon-lx-warn",
|
icon: 'CoffeeCup',
|
||||||
index: "7",
|
index: '/donate',
|
||||||
title: "错误处理",
|
title: '支持作者',
|
||||||
subs: [
|
permiss: '14'
|
||||||
{
|
}
|
||||||
index: "/permission",
|
|
||||||
title: "权限测试",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
index: "/404",
|
|
||||||
title: "404页面",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
icon: "el-icon-lx-redpacket_fill",
|
|
||||||
index: "/donate",
|
|
||||||
title: "支持作者",
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
@ -125,14 +141,6 @@ export default {
|
||||||
});
|
});
|
||||||
|
|
||||||
const sidebar = useSidebarStore();
|
const sidebar = useSidebarStore();
|
||||||
|
|
||||||
return {
|
|
||||||
items,
|
|
||||||
onRoutes,
|
|
||||||
sidebar,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="tags" v-if="tags.show">
|
<div class="tags" v-if="tags.show">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="tags-li" v-for="(item,index) in tags.list" :class="{'active': isActive(item.path)}" :key="index">
|
<li
|
||||||
|
class="tags-li"
|
||||||
|
v-for="(item, index) in tags.list"
|
||||||
|
:class="{ active: isActive(item.path) }"
|
||||||
|
:key="index"
|
||||||
|
>
|
||||||
<router-link :to="item.path" class="tags-li-title">{{ item.title }}</router-link>
|
<router-link :to="item.path" class="tags-li-title">{{ item.title }}</router-link>
|
||||||
<span class="tags-li-icon" @click="closeTags(index)">
|
<el-icon @click="closeTags(index)"><Close /></el-icon>
|
||||||
<i class="el-icon-close"></i>
|
|
||||||
</span>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div class="tags-close-box">
|
<div class="tags-close-box">
|
||||||
<el-dropdown @command="handleTags">
|
<el-dropdown @command="handleTags">
|
||||||
<el-button size="mini" type="primary">
|
<el-button size="small" type="primary">
|
||||||
标签选项
|
标签选项
|
||||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
<el-icon class="el-icon--right">
|
||||||
|
<arrow-down />
|
||||||
|
</el-icon>
|
||||||
</el-button>
|
</el-button>
|
||||||
<template #dropdown>
|
<template #dropdown>
|
||||||
<el-dropdown-menu size="small">
|
<el-dropdown-menu size="small">
|
||||||
|
|
@ -25,33 +30,32 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { useTagsStore } from '../store/tags'
|
import { useTagsStore } from '../store/tags';
|
||||||
import { onBeforeRouteUpdate, useRoute, useRouter } from "vue-router";
|
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router';
|
||||||
export default {
|
|
||||||
setup() {
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const isActive = (path) => {
|
const isActive = (path: string) => {
|
||||||
return path === route.fullPath;
|
return path === route.fullPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
const tags = useTagsStore();
|
const tags = useTagsStore();
|
||||||
// 关闭单个标签
|
// 关闭单个标签
|
||||||
const closeTags = (index) => {
|
const closeTags = (index: number) => {
|
||||||
const delItem = tags.list[index];
|
const delItem = tags.list[index];
|
||||||
tags.delTagsItem(index);
|
tags.delTagsItem(index);
|
||||||
const item = tags.list[index] ? tags.list[index] : tags.list[index - 1];
|
const item = tags.list[index] ? tags.list[index] : tags.list[index - 1];
|
||||||
if (item) {
|
if (item) {
|
||||||
delItem.path === route.fullPath && router.push(item.path);
|
delItem.path === route.fullPath && router.push(item.path);
|
||||||
} else {
|
} else {
|
||||||
router.push("/");
|
router.push('/');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 设置标签
|
// 设置标签
|
||||||
const setTags = (route) => {
|
const setTags = (route: any) => {
|
||||||
const isExist = tags.list.some((item) => {
|
const isExist = tags.list.some(item => {
|
||||||
return item.path === route.fullPath;
|
return item.path === route.fullPath;
|
||||||
});
|
});
|
||||||
if (!isExist) {
|
if (!isExist) {
|
||||||
|
|
@ -59,29 +63,29 @@ export default {
|
||||||
tags.setTagsItem({
|
tags.setTagsItem({
|
||||||
name: route.name,
|
name: route.name,
|
||||||
title: route.meta.title,
|
title: route.meta.title,
|
||||||
path: route.fullPath,
|
path: route.fullPath
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
setTags(route);
|
setTags(route);
|
||||||
onBeforeRouteUpdate((to) => {
|
onBeforeRouteUpdate(to => {
|
||||||
setTags(to);
|
setTags(to);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 关闭全部标签
|
// 关闭全部标签
|
||||||
const closeAll = () => {
|
const closeAll = () => {
|
||||||
tags.clearTags();
|
tags.clearTags();
|
||||||
router.push("/");
|
router.push('/');
|
||||||
};
|
};
|
||||||
// 关闭其他标签
|
// 关闭其他标签
|
||||||
const closeOther = () => {
|
const closeOther = () => {
|
||||||
const curItem = tags.list.filter((item) => {
|
const curItem = tags.list.filter(item => {
|
||||||
return item.path === route.fullPath;
|
return item.path === route.fullPath;
|
||||||
});
|
});
|
||||||
tags.closeTagsOther(curItem);
|
tags.closeTagsOther(curItem);
|
||||||
};
|
};
|
||||||
const handleTags = (command) => {
|
const handleTags = (command: string) => {
|
||||||
command === "other" ? closeOther() : closeAll();
|
command === 'other' ? closeOther() : closeAll();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 关闭当前页面的标签页
|
// 关闭当前页面的标签页
|
||||||
|
|
@ -89,18 +93,8 @@ export default {
|
||||||
// $router: router,
|
// $router: router,
|
||||||
// $route: route
|
// $route: route
|
||||||
// });
|
// });
|
||||||
|
|
||||||
return {
|
|
||||||
isActive,
|
|
||||||
tags,
|
|
||||||
closeTags,
|
|
||||||
handleTags,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.tags {
|
.tags {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
@ -118,6 +112,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.tags-li {
|
.tags-li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
float: left;
|
float: left;
|
||||||
margin: 3px 5px 2px 3px;
|
margin: 3px 5px 2px 3px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
|
|
@ -125,11 +121,9 @@ export default {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 23px;
|
height: 23px;
|
||||||
line-height: 23px;
|
|
||||||
border: 1px solid #e9eaec;
|
border: 1px solid #e9eaec;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0 5px 0 12px;
|
padding: 0 5px 0 12px;
|
||||||
vertical-align: middle;
|
|
||||||
color: #666;
|
color: #666;
|
||||||
-webkit-transition: all 0.3s ease-in;
|
-webkit-transition: all 0.3s ease-in;
|
||||||
-moz-transition: all 0.3s ease-in;
|
-moz-transition: all 0.3s ease-in;
|
||||||
|
|
|
||||||
11
src/main.js
11
src/main.js
|
|
@ -1,11 +0,0 @@
|
||||||
import {createApp} from 'vue'
|
|
||||||
import { createPinia } from 'pinia'
|
|
||||||
import App from './App.vue'
|
|
||||||
import router from './router'
|
|
||||||
import installElementPlus from './plugins/element'
|
|
||||||
import './assets/css/icon.css'
|
|
||||||
const app = createApp(App)
|
|
||||||
installElementPlus(app)
|
|
||||||
app.use(createPinia())
|
|
||||||
.use(router)
|
|
||||||
.mount('#app')
|
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import {createApp} from 'vue'
|
||||||
|
import { createPinia } from 'pinia'
|
||||||
|
import ElementPlus from 'element-plus'
|
||||||
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
import { usePermissStore } from './store/permiss'
|
||||||
|
import 'element-plus/dist/index.css'
|
||||||
|
import './assets/css/icon.css'
|
||||||
|
|
||||||
|
|
||||||
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.use(createPinia())
|
||||||
|
app.use(router)
|
||||||
|
app.use(ElementPlus)
|
||||||
|
// 注册elementplus图标
|
||||||
|
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||||
|
app.component(key, component)
|
||||||
|
}
|
||||||
|
// 自定义权限指令
|
||||||
|
const permiss = usePermissStore()
|
||||||
|
app.directive('permiss', {
|
||||||
|
mounted(el, binding) {
|
||||||
|
if(!permiss.key.includes(String(binding.value))){
|
||||||
|
el['hidden'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
app.mount('#app')
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
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'
|
|
||||||
|
|
||||||
const i18n = createI18n({
|
|
||||||
locale: localeZH.name,
|
|
||||||
fallbackLocale: localeEN.name,
|
|
||||||
messages,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default (app) => {
|
|
||||||
app.use(ElementPlus, { locale:localeZH })
|
|
||||||
app.use(i18n)
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
import {createRouter, createWebHashHistory} from "vue-router";
|
import {createRouter, createWebHashHistory, RouteRecordRaw} from "vue-router";
|
||||||
|
import { usePermissStore } from '../store/permiss'
|
||||||
import Home from "../views/Home.vue";
|
import Home from "../views/Home.vue";
|
||||||
|
|
||||||
const routes = [
|
const routes:RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: '/dashboard'
|
redirect: '/dashboard'
|
||||||
|
|
@ -14,108 +15,97 @@ const routes = [
|
||||||
path: "/dashboard",
|
path: "/dashboard",
|
||||||
name: "dashboard",
|
name: "dashboard",
|
||||||
meta: {
|
meta: {
|
||||||
title: '系统首页'
|
title: '系统首页',
|
||||||
|
permiss: '1'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "dashboard" */ "../views/Dashboard.vue")
|
component: () => import ( /* webpackChunkName: "dashboard" */ "../views/dashboard.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/table",
|
path: "/table",
|
||||||
name: "basetable",
|
name: "basetable",
|
||||||
meta: {
|
meta: {
|
||||||
title: '表格'
|
title: '表格',
|
||||||
|
permiss: '2'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "table" */ "../views/BaseTable.vue")
|
component: () => import ( /* webpackChunkName: "table" */ "../views/table.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/charts",
|
path: "/charts",
|
||||||
name: "basecharts",
|
name: "basecharts",
|
||||||
meta: {
|
meta: {
|
||||||
title: '图表'
|
title: '图表',
|
||||||
|
permiss: '11'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "charts" */ "../views/BaseCharts.vue")
|
component: () => import ( /* webpackChunkName: "charts" */ "../views/charts.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/form",
|
path: "/form",
|
||||||
name: "baseform",
|
name: "baseform",
|
||||||
meta: {
|
meta: {
|
||||||
title: '表单'
|
title: '表单',
|
||||||
|
permiss: '5'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "form" */ "../views/BaseForm.vue")
|
component: () => import ( /* webpackChunkName: "form" */ "../views/form.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/tabs",
|
path: "/tabs",
|
||||||
name: "tabs",
|
name: "tabs",
|
||||||
meta: {
|
meta: {
|
||||||
title: 'tab标签'
|
title: 'tab标签',
|
||||||
|
permiss: '3'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "tabs" */ "../views/Tabs.vue")
|
component: () => import ( /* webpackChunkName: "tabs" */ "../views/tabs.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/donate",
|
path: "/donate",
|
||||||
name: "donate",
|
name: "donate",
|
||||||
meta: {
|
meta: {
|
||||||
title: '鼓励作者'
|
title: '鼓励作者',
|
||||||
|
permiss: '14'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "donate" */ "../views/Donate.vue")
|
component: () => import ( /* webpackChunkName: "donate" */ "../views/donate.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/permission",
|
path: "/permission",
|
||||||
name: "permission",
|
name: "permission",
|
||||||
meta: {
|
meta: {
|
||||||
title: '权限管理',
|
title: '权限管理',
|
||||||
permission: true
|
permiss: '13'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "permission" */ "../views/Permission.vue")
|
component: () => import ( /* webpackChunkName: "permission" */ "../views/permission.vue")
|
||||||
}, {
|
|
||||||
path: "/i18n",
|
|
||||||
name: "i18n",
|
|
||||||
meta: {
|
|
||||||
title: '国际化语言'
|
|
||||||
},
|
|
||||||
component: () => import ( /* webpackChunkName: "i18n" */ "../views/I18n.vue")
|
|
||||||
}, {
|
}, {
|
||||||
path: "/upload",
|
path: "/upload",
|
||||||
name: "upload",
|
name: "upload",
|
||||||
meta: {
|
meta: {
|
||||||
title: '上传插件'
|
title: '上传插件',
|
||||||
|
permiss: '6'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "upload" */ "../views/Upload.vue")
|
component: () => import ( /* webpackChunkName: "upload" */ "../views/upload.vue")
|
||||||
}, {
|
}, {
|
||||||
path: "/icon",
|
path: "/icon",
|
||||||
name: "icon",
|
name: "icon",
|
||||||
meta: {
|
meta: {
|
||||||
title: '自定义图标'
|
title: '自定义图标',
|
||||||
|
permiss: '10'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "icon" */ "../views/Icon.vue")
|
component: () => import ( /* webpackChunkName: "icon" */ "../views/icon.vue")
|
||||||
}, {
|
|
||||||
path: '/404',
|
|
||||||
name: '404',
|
|
||||||
meta: {
|
|
||||||
title: '找不到页面'
|
|
||||||
},
|
|
||||||
component: () => import (/* webpackChunkName: "404" */ '../views/404.vue')
|
|
||||||
}, {
|
|
||||||
path: '/403',
|
|
||||||
name: '403',
|
|
||||||
meta: {
|
|
||||||
title: '没有权限'
|
|
||||||
},
|
|
||||||
component: () => import (/* webpackChunkName: "403" */ '../views/403.vue')
|
|
||||||
}, {
|
}, {
|
||||||
path: '/user',
|
path: '/user',
|
||||||
name: 'user',
|
name: 'user',
|
||||||
meta: {
|
meta: {
|
||||||
title: '个人中心'
|
title: '个人中心'
|
||||||
},
|
},
|
||||||
component: () => import (/* webpackChunkName: "user" */ '../views/User.vue')
|
component: () => import (/* webpackChunkName: "user" */ '../views/user.vue')
|
||||||
}, {
|
}, {
|
||||||
path: '/editor',
|
path: '/editor',
|
||||||
name: 'editor',
|
name: 'editor',
|
||||||
meta: {
|
meta: {
|
||||||
title: '富文本编辑器'
|
title: '富文本编辑器',
|
||||||
|
permiss: '8'
|
||||||
},
|
},
|
||||||
component: () => import (/* webpackChunkName: "editor" */ '../views/Editor.vue')
|
component: () => import (/* webpackChunkName: "editor" */ '../views/editor.vue')
|
||||||
}, {
|
}, {
|
||||||
path: '/markdown',
|
path: '/markdown',
|
||||||
name: 'markdown',
|
name: 'markdown',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'markdown编辑器'
|
title: 'markdown编辑器',
|
||||||
|
permiss: '9'
|
||||||
},
|
},
|
||||||
component: () => import (/* webpackChunkName: "markdown" */ '../views/Markdown.vue')
|
component: () => import (/* webpackChunkName: "markdown" */ '../views/markdown.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}, {
|
}, {
|
||||||
|
|
@ -124,8 +114,15 @@ const routes = [
|
||||||
meta: {
|
meta: {
|
||||||
title: '登录'
|
title: '登录'
|
||||||
},
|
},
|
||||||
component: () => import ( /* webpackChunkName: "login" */ "../views/Login.vue")
|
component: () => import ( /* webpackChunkName: "login" */ "../views/login.vue")
|
||||||
}
|
}, {
|
||||||
|
path: '/403',
|
||||||
|
name: '403',
|
||||||
|
meta: {
|
||||||
|
title: '没有权限'
|
||||||
|
},
|
||||||
|
component: () => import (/* webpackChunkName: "403" */ '../views/403.vue')
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
|
|
@ -136,13 +133,12 @@ const router = createRouter({
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
document.title = `${to.meta.title} | vue-manage-system`;
|
document.title = `${to.meta.title} | vue-manage-system`;
|
||||||
const role = localStorage.getItem('ms_username');
|
const role = localStorage.getItem('ms_username');
|
||||||
|
const permiss = usePermissStore();
|
||||||
if (!role && to.path !== '/login') {
|
if (!role && to.path !== '/login') {
|
||||||
next('/login');
|
next('/login');
|
||||||
} else if (to.meta.permission) {
|
} else if (to.meta.permiss && !permiss.key.includes(to.meta.permiss)) {
|
||||||
// 如果是管理员权限则可进入,这里只是简单的模拟管理员权限而已
|
// 如果没有权限,则进入403
|
||||||
role === 'admin'
|
next('/403');
|
||||||
? next()
|
|
||||||
: next('/403');
|
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
interface ObjectList {
|
||||||
|
[key: string]: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePermissStore = defineStore('permiss', {
|
||||||
|
state: () => {
|
||||||
|
const keys = localStorage.getItem('ms_keys');
|
||||||
|
return {
|
||||||
|
key: keys ? JSON.parse(keys) : <string[]>[],
|
||||||
|
defaultList: <ObjectList>{
|
||||||
|
admin: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16'],
|
||||||
|
user: ['1', '2', '3', '11', '13', '14', '15']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
handleSet(val: string[]) {
|
||||||
|
this.key = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useSidebarStore = defineStore('sidebar', {
|
|
||||||
state: () => {
|
|
||||||
return {
|
|
||||||
collapse: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
handleCollapse() {
|
|
||||||
this.collapse = !this.collapse;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
export const useSidebarStore = defineStore('sidebar', {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
collapse: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getters: {},
|
||||||
|
actions: {
|
||||||
|
handleCollapse() {
|
||||||
|
this.collapse = !this.collapse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,48 +0,0 @@
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useTagsStore = defineStore('tags', {
|
|
||||||
state: () => {
|
|
||||||
return {
|
|
||||||
list: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getters: {
|
|
||||||
show: (state) => {
|
|
||||||
return state.list.length > 0;
|
|
||||||
},
|
|
||||||
nameList: (state) => {
|
|
||||||
return state.list.map(item => item.name);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
delTagsItem(index) {
|
|
||||||
this.list.splice(index, 1);
|
|
||||||
},
|
|
||||||
setTagsItem(data) {
|
|
||||||
this.list.push(data)
|
|
||||||
},
|
|
||||||
clearTags() {
|
|
||||||
this.list = []
|
|
||||||
},
|
|
||||||
closeTagsOther(data) {
|
|
||||||
this.list = data;
|
|
||||||
},
|
|
||||||
closeCurrentTag(data) {
|
|
||||||
console.log(data)
|
|
||||||
for (let i = 0, len = this.list.length; i < len; i++) {
|
|
||||||
const item = this.list[i];
|
|
||||||
if (item.path === data.$route.fullPath) {
|
|
||||||
if (i < len - 1) {
|
|
||||||
data.$router.push(this.list[i + 1].path);
|
|
||||||
} else if (i > 0) {
|
|
||||||
data.$router.push(this.list[i - 1].path);
|
|
||||||
} else {
|
|
||||||
data.$router.push("/");
|
|
||||||
}
|
|
||||||
this.list.splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { defineStore } from 'pinia';
|
||||||
|
|
||||||
|
interface ListItem {
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
title: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useTagsStore = defineStore('tags', {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
list: <ListItem[]>[]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getters: {
|
||||||
|
show: state => {
|
||||||
|
return state.list.length > 0;
|
||||||
|
},
|
||||||
|
nameList: state => {
|
||||||
|
return state.list.map(item => item.name);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
delTagsItem(index: number) {
|
||||||
|
this.list.splice(index, 1);
|
||||||
|
},
|
||||||
|
setTagsItem(data: ListItem) {
|
||||||
|
this.list.push(data);
|
||||||
|
},
|
||||||
|
clearTags() {
|
||||||
|
this.list = [];
|
||||||
|
},
|
||||||
|
closeTagsOther(data: ListItem[]) {
|
||||||
|
this.list = data;
|
||||||
|
},
|
||||||
|
closeCurrentTag(data: any) {
|
||||||
|
for (let i = 0, len = this.list.length; i < len; i++) {
|
||||||
|
const item = this.list[i];
|
||||||
|
if (item.path === data.$route.fullPath) {
|
||||||
|
if (i < len - 1) {
|
||||||
|
data.$router.push(this.list[i + 1].path);
|
||||||
|
} else if (i > 0) {
|
||||||
|
data.$router.push(this.list[i - 1].path);
|
||||||
|
} else {
|
||||||
|
data.$router.push('/');
|
||||||
|
}
|
||||||
|
this.list.splice(i, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
export default {
|
|
||||||
'zh-cn': {
|
|
||||||
i18n: {
|
|
||||||
breadcrumb: '国际化产品',
|
|
||||||
tips: '通过切换语言按钮,来改变当前内容的语言。',
|
|
||||||
btn: '切换英文',
|
|
||||||
title1: '常用用法',
|
|
||||||
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
|
|
||||||
p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
|
|
||||||
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'en': {
|
|
||||||
i18n: {
|
|
||||||
breadcrumb: 'International Products',
|
|
||||||
tips: 'Click on the button to change the current language. ',
|
|
||||||
btn: 'Switch Chinese',
|
|
||||||
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."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +1,28 @@
|
||||||
import axios from 'axios';
|
import axios, {AxiosInstance, AxiosError, AxiosResponse, AxiosRequestConfig} from 'axios';
|
||||||
|
|
||||||
const service = axios.create({
|
const service:AxiosInstance = axios.create({
|
||||||
// process.env.NODE_ENV === 'development' 来判断是否开发环境
|
|
||||||
// easy-mock服务挂了,暂时不使用了
|
|
||||||
// baseURL: 'https://www.easy-mock.com/mock/592501a391470c0ac1fab128',
|
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
});
|
});
|
||||||
|
|
||||||
service.interceptors.request.use(
|
service.interceptors.request.use(
|
||||||
config => {
|
(config: AxiosRequestConfig) => {
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
error => {
|
(error: AxiosError) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
response => {
|
(response: AxiosResponse) => {
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
return response.data;
|
return response;
|
||||||
} else {
|
} else {
|
||||||
Promise.reject();
|
Promise.reject();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
(error: AxiosError) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
}
|
}
|
||||||
|
|
@ -11,23 +11,15 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="403">
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
export default {
|
|
||||||
name: "404",
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
router.go(-1);
|
router.go(-2);
|
||||||
};
|
|
||||||
return {
|
|
||||||
goBack,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.error-page {
|
.error-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -11,23 +11,15 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="404">
|
||||||
import { useRouter } from "vue-router";
|
import { useRouter } from 'vue-router';
|
||||||
export default {
|
|
||||||
name: "404",
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
router.go(-1);
|
router.go(-1);
|
||||||
};
|
};
|
||||||
return {
|
|
||||||
goBack,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.error-page {
|
.error-page {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-pie-chart"></i> schart图表
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
|
||||||
<div class="plugins-tips">
|
|
||||||
vue-schart:vue.js封装sChart.js的图表组件。
|
|
||||||
访问地址:
|
|
||||||
<a href="https://github.com/lin-xin/vue-schart" target="_blank">vue-schart</a>
|
|
||||||
</div>
|
|
||||||
<div class="schart-box">
|
|
||||||
<div class="content-title">柱状图</div>
|
|
||||||
<schart class="schart" canvasId="bar" :options="options1"></schart>
|
|
||||||
</div>
|
|
||||||
<div class="schart-box">
|
|
||||||
<div class="content-title">折线图</div>
|
|
||||||
<schart class="schart" canvasId="line" :options="options2"></schart>
|
|
||||||
</div>
|
|
||||||
<div class="schart-box">
|
|
||||||
<div class="content-title">饼状图</div>
|
|
||||||
<schart class="schart" canvasId="pie" :options="options3"></schart>
|
|
||||||
</div>
|
|
||||||
<div class="schart-box">
|
|
||||||
<div class="content-title">环形图</div>
|
|
||||||
<schart class="schart" canvasId="ring" :options="options4"></schart>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import Schart from "vue-schart";
|
|
||||||
export default {
|
|
||||||
name: "basecharts",
|
|
||||||
components: {
|
|
||||||
Schart,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const options1 = {
|
|
||||||
type: "bar",
|
|
||||||
title: {
|
|
||||||
text: "最近一周各品类销售图",
|
|
||||||
},
|
|
||||||
bgColor: "#fbfbfb",
|
|
||||||
labels: ["周一", "周二", "周三", "周四", "周五"],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "家电",
|
|
||||||
fillColor: "rgba(241, 49, 74, 0.5)",
|
|
||||||
data: [234, 278, 270, 190, 230],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "百货",
|
|
||||||
data: [164, 178, 190, 135, 160],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "食品",
|
|
||||||
data: [144, 198, 150, 235, 120],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const options2 = {
|
|
||||||
type: "line",
|
|
||||||
title: {
|
|
||||||
text: "最近几个月各品类销售趋势图",
|
|
||||||
},
|
|
||||||
bgColor: "#fbfbfb",
|
|
||||||
labels: ["6月", "7月", "8月", "9月", "10月"],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
label: "家电",
|
|
||||||
data: [234, 278, 270, 190, 230],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "百货",
|
|
||||||
data: [164, 178, 150, 135, 160],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "食品",
|
|
||||||
data: [114, 138, 200, 235, 190],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const options3 = {
|
|
||||||
type: "pie",
|
|
||||||
title: {
|
|
||||||
text: "服装品类销售饼状图",
|
|
||||||
},
|
|
||||||
legend: {
|
|
||||||
position: "left",
|
|
||||||
},
|
|
||||||
bgColor: "#fbfbfb",
|
|
||||||
labels: [
|
|
||||||
"T恤",
|
|
||||||
"牛仔裤",
|
|
||||||
"连衣裙",
|
|
||||||
"毛衣",
|
|
||||||
"七分裤",
|
|
||||||
"短裙",
|
|
||||||
"羽绒服",
|
|
||||||
],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
data: [334, 278, 190, 235, 260, 200, 141],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const options4 = {
|
|
||||||
type: "ring",
|
|
||||||
title: {
|
|
||||||
text: "环形三等分",
|
|
||||||
},
|
|
||||||
showValue: false,
|
|
||||||
legend: {
|
|
||||||
position: "bottom",
|
|
||||||
bottom: 40,
|
|
||||||
},
|
|
||||||
bgColor: "#fbfbfb",
|
|
||||||
labels: ["vue", "react", "angular"],
|
|
||||||
datasets: [
|
|
||||||
{
|
|
||||||
data: [500, 500, 500],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
return {
|
|
||||||
options1,
|
|
||||||
options2,
|
|
||||||
options3,
|
|
||||||
options4,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.schart-box {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 20px;
|
|
||||||
}
|
|
||||||
.schart {
|
|
||||||
width: 600px;
|
|
||||||
height: 400px;
|
|
||||||
}
|
|
||||||
.content-title {
|
|
||||||
clear: both;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 50px;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-size: 22px;
|
|
||||||
color: #1f2f3d;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,174 +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="form-box">
|
|
||||||
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px">
|
|
||||||
<el-form-item label="表单名称" prop="name">
|
|
||||||
<el-input v-model="form.name"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="选择器" prop="region">
|
|
||||||
<el-select v-model="form.region" placeholder="请选择">
|
|
||||||
<el-option key="bbk" label="步步高" value="bbk"></el-option>
|
|
||||||
<el-option key="xtc" label="小天才" value="xtc"></el-option>
|
|
||||||
<el-option key="imoo" label="imoo" value="imoo"></el-option>
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="日期时间">
|
|
||||||
<el-col :span="11">
|
|
||||||
<el-form-item prop="date1">
|
|
||||||
<el-date-picker type="date" placeholder="选择日期" v-model="form.date1"
|
|
||||||
style="width: 100%;"></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col class="line" :span="2">-</el-col>
|
|
||||||
<el-col :span="11">
|
|
||||||
<el-form-item prop="date2">
|
|
||||||
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%;">
|
|
||||||
</el-time-picker>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="城市级联" prop="options">
|
|
||||||
<el-cascader :options="options" v-model="form.options"></el-cascader>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="选择开关" prop="delivery">
|
|
||||||
<el-switch v-model="form.delivery"></el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="多选框" prop="type">
|
|
||||||
<el-checkbox-group v-model="form.type">
|
|
||||||
<el-checkbox label="步步高" name="type"></el-checkbox>
|
|
||||||
<el-checkbox label="小天才" name="type"></el-checkbox>
|
|
||||||
<el-checkbox label="imoo" name="type"></el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="单选框" prop="resource">
|
|
||||||
<el-radio-group v-model="form.resource">
|
|
||||||
<el-radio label="步步高"></el-radio>
|
|
||||||
<el-radio label="小天才"></el-radio>
|
|
||||||
<el-radio label="imoo"></el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="文本框" prop="desc">
|
|
||||||
<el-input type="textarea" rows="5" v-model="form.desc"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" @click="onSubmit">表单提交</el-button>
|
|
||||||
<el-button @click="onReset">重置表单</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { reactive, ref } from "vue";
|
|
||||||
import { ElMessage } from "element-plus";
|
|
||||||
export default {
|
|
||||||
name: "baseform",
|
|
||||||
setup() {
|
|
||||||
const options = [
|
|
||||||
{
|
|
||||||
value: "guangdong",
|
|
||||||
label: "广东省",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: "guangzhou",
|
|
||||||
label: "广州市",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: "tianhe",
|
|
||||||
label: "天河区",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "haizhu",
|
|
||||||
label: "海珠区",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "dongguan",
|
|
||||||
label: "东莞市",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: "changan",
|
|
||||||
label: "长安镇",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "humen",
|
|
||||||
label: "虎门镇",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: "hunan",
|
|
||||||
label: "湖南省",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: "changsha",
|
|
||||||
label: "长沙市",
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: "yuelu",
|
|
||||||
label: "岳麓区",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const rules = {
|
|
||||||
name: [
|
|
||||||
{ required: true, message: "请输入表单名称", trigger: "blur" },
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const formRef = ref(null);
|
|
||||||
const form = reactive({
|
|
||||||
name: "",
|
|
||||||
region: "",
|
|
||||||
date1: "",
|
|
||||||
date2: "",
|
|
||||||
delivery: true,
|
|
||||||
type: ["步步高"],
|
|
||||||
resource: "小天才",
|
|
||||||
desc: "",
|
|
||||||
options: [],
|
|
||||||
});
|
|
||||||
// 提交
|
|
||||||
const onSubmit = () => {
|
|
||||||
// 表单校验
|
|
||||||
formRef.value.validate((valid) => {
|
|
||||||
if (valid) {
|
|
||||||
console.log(form);
|
|
||||||
ElMessage.success("提交成功!");
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
// 重置
|
|
||||||
const onReset = () => {
|
|
||||||
formRef.value.resetFields();
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
options,
|
|
||||||
rules,
|
|
||||||
formRef,
|
|
||||||
form,
|
|
||||||
onSubmit,
|
|
||||||
onReset,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
@ -1,196 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-lx-cascades"></i> 基础表格
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
|
||||||
<div class="handle-box">
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
|
|
||||||
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
|
||||||
<el-table-column prop="name" label="用户名"></el-table-column>
|
|
||||||
<el-table-column label="账户余额">
|
|
||||||
<template #default="scope">¥{{ scope.row.money }}</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="头像(查看大图)" align="center">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-image class="table-td-thumb" :src="scope.row.thumb" :preview-src-list="[scope.row.thumb]">
|
|
||||||
</el-image>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="address" label="地址"></el-table-column>
|
|
||||||
<el-table-column label="状态" align="center">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-tag :type="
|
|
||||||
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 #default="scope">
|
|
||||||
<el-button type="text" icon="el-icon-edit" @click="handleEdit(scope.$index, scope.row)">编辑
|
|
||||||
</el-button>
|
|
||||||
<el-button type="text" icon="el-icon-delete" class="red"
|
|
||||||
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<div class="pagination">
|
|
||||||
<el-pagination background layout="total, prev, pager, next" :current-page="query.pageIndex"
|
|
||||||
:page-size="query.pageSize" :total="pageTotal" @current-change="handlePageChange"></el-pagination>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 编辑弹出框 -->
|
|
||||||
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
|
||||||
<el-form label-width="70px">
|
|
||||||
<el-form-item label="用户名">
|
|
||||||
<el-input v-model="form.name"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="地址">
|
|
||||||
<el-input v-model="form.address"></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
|
||||||
<template #footer>
|
|
||||||
<span class="dialog-footer">
|
|
||||||
<el-button @click="editVisible = false">取 消</el-button>
|
|
||||||
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ref, reactive } from "vue";
|
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
|
||||||
import { fetchData } from "../api/index";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: "basetable",
|
|
||||||
setup() {
|
|
||||||
const query = reactive({
|
|
||||||
address: "",
|
|
||||||
name: "",
|
|
||||||
pageIndex: 1,
|
|
||||||
pageSize: 10,
|
|
||||||
});
|
|
||||||
const tableData = ref([]);
|
|
||||||
const pageTotal = ref(0);
|
|
||||||
// 获取表格数据
|
|
||||||
const getData = () => {
|
|
||||||
fetchData(query).then((res) => {
|
|
||||||
tableData.value = res.list;
|
|
||||||
pageTotal.value = res.pageTotal || 50;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
getData();
|
|
||||||
|
|
||||||
// 查询操作
|
|
||||||
const handleSearch = () => {
|
|
||||||
query.pageIndex = 1;
|
|
||||||
getData();
|
|
||||||
};
|
|
||||||
// 分页导航
|
|
||||||
const handlePageChange = (val) => {
|
|
||||||
query.pageIndex = val;
|
|
||||||
getData();
|
|
||||||
};
|
|
||||||
|
|
||||||
// 删除操作
|
|
||||||
const handleDelete = (index) => {
|
|
||||||
// 二次确认删除
|
|
||||||
ElMessageBox.confirm("确定要删除吗?", "提示", {
|
|
||||||
type: "warning",
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
ElMessage.success("删除成功");
|
|
||||||
tableData.value.splice(index, 1);
|
|
||||||
})
|
|
||||||
.catch(() => {});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 表格编辑时弹窗和保存
|
|
||||||
const editVisible = ref(false);
|
|
||||||
let form = reactive({
|
|
||||||
name: "",
|
|
||||||
address: "",
|
|
||||||
});
|
|
||||||
let idx = -1;
|
|
||||||
const handleEdit = (index, row) => {
|
|
||||||
idx = index;
|
|
||||||
Object.keys(form).forEach((item) => {
|
|
||||||
form[item] = row[item];
|
|
||||||
});
|
|
||||||
editVisible.value = true;
|
|
||||||
};
|
|
||||||
const saveEdit = () => {
|
|
||||||
editVisible.value = false;
|
|
||||||
ElMessage.success(`修改第 ${idx + 1} 行成功`);
|
|
||||||
Object.keys(form).forEach((item) => {
|
|
||||||
tableData.value[idx][item] = form[item];
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
query,
|
|
||||||
tableData,
|
|
||||||
pageTotal,
|
|
||||||
editVisible,
|
|
||||||
form,
|
|
||||||
handleSearch,
|
|
||||||
handlePageChange,
|
|
||||||
handleDelete,
|
|
||||||
handleEdit,
|
|
||||||
saveEdit,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.handle-box {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handle-select {
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.handle-input {
|
|
||||||
width: 300px;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
.table {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.red {
|
|
||||||
color: #ff0000;
|
|
||||||
}
|
|
||||||
.mr10 {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
.table-td-thumb {
|
|
||||||
display: block;
|
|
||||||
margin: auto;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -2,9 +2,9 @@
|
||||||
<div>
|
<div>
|
||||||
<el-row :gutter="20">
|
<el-row :gutter="20">
|
||||||
<el-col :span="8">
|
<el-col :span="8">
|
||||||
<el-card shadow="hover" class="mgb20" style="height:252px;">
|
<el-card shadow="hover" class="mgb20" style="height: 252px">
|
||||||
<div class="user-info">
|
<div class="user-info">
|
||||||
<img src="../assets/img/img.jpg" class="user-avator" alt />
|
<el-avatar :size="120" :src="imgurl" />
|
||||||
<div class="user-info-cont">
|
<div class="user-info-cont">
|
||||||
<div class="user-info-name">{{ name }}</div>
|
<div class="user-info-name">{{ name }}</div>
|
||||||
<div>{{ role }}</div>
|
<div>{{ role }}</div>
|
||||||
|
|
@ -12,14 +12,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info-list">
|
<div class="user-info-list">
|
||||||
上次登录时间:
|
上次登录时间:
|
||||||
<span>2019-11-01</span>
|
<span>2022-10-01</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-info-list">
|
<div class="user-info-list">
|
||||||
上次登录地点:
|
上次登录地点:
|
||||||
<span>东莞</span>
|
<span>东莞</span>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
<el-card shadow="hover" style="height:252px;">
|
<el-card shadow="hover" style="height: 252px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<span>语言详情</span>
|
<span>语言详情</span>
|
||||||
|
|
@ -37,7 +37,7 @@
|
||||||
<el-col :span="8">
|
<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">
|
<div class="grid-content grid-con-1">
|
||||||
<i class="el-icon-user-solid grid-con-icon"></i>
|
<el-icon class="grid-con-icon"><User /></el-icon>
|
||||||
<div class="grid-cont-right">
|
<div class="grid-cont-right">
|
||||||
<div class="grid-num">1234</div>
|
<div class="grid-num">1234</div>
|
||||||
<div>用户访问量</div>
|
<div>用户访问量</div>
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
<el-col :span="8">
|
<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">
|
<div class="grid-content grid-con-2">
|
||||||
<i class="el-icon-message-solid grid-con-icon"></i>
|
<el-icon class="grid-con-icon"><ChatDotRound /></el-icon>
|
||||||
<div class="grid-cont-right">
|
<div class="grid-cont-right">
|
||||||
<div class="grid-num">321</div>
|
<div class="grid-num">321</div>
|
||||||
<div>系统消息</div>
|
<div>系统消息</div>
|
||||||
|
|
@ -59,24 +59,24 @@
|
||||||
<el-col :span="8">
|
<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">
|
<div class="grid-content grid-con-3">
|
||||||
<i class="el-icon-s-goods grid-con-icon"></i>
|
<el-icon class="grid-con-icon"><Goods /></el-icon>
|
||||||
<div class="grid-cont-right">
|
<div class="grid-cont-right">
|
||||||
<div class="grid-num">5000</div>
|
<div class="grid-num">5000</div>
|
||||||
<div>数量</div>
|
<div>商品数量</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-card shadow="hover" style="height:403px;">
|
<el-card shadow="hover" style="height: 403px">
|
||||||
<template #header>
|
<template #header>
|
||||||
<div class="clearfix">
|
<div class="clearfix">
|
||||||
<span>待办事项</span>
|
<span>待办事项</span>
|
||||||
<el-button style="float: right; padding: 3px 0" type="text">添加</el-button>
|
<el-button style="float: right; padding: 3px 0" text>添加</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<el-table :show-header="false" :data="todoList" style="width:100%;">
|
<el-table :show-header="false" :data="todoList" style="width: 100%">
|
||||||
<el-table-column width="40">
|
<el-table-column width="40">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-checkbox v-model="scope.row.status"></el-checkbox>
|
<el-checkbox v-model="scope.row.status"></el-checkbox>
|
||||||
|
|
@ -84,15 +84,14 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column>
|
<el-table-column>
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="todo-item" :class="{
|
<div
|
||||||
'todo-item-del': scope.row.status,
|
class="todo-item"
|
||||||
}">{{ scope.row.title }}</div>
|
:class="{
|
||||||
</template>
|
'todo-item-del': scope.row.status
|
||||||
</el-table-column>
|
}"
|
||||||
<el-table-column width="60">
|
>
|
||||||
<template>
|
{{ scope.row.title }}
|
||||||
<i class="el-icon-edit"></i>
|
</div>
|
||||||
<i class="el-icon-delete"></i>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -114,126 +113,83 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="dashboard">
|
||||||
import Schart from "vue-schart";
|
import Schart from 'vue-schart';
|
||||||
import { reactive } from "vue";
|
import { reactive } from 'vue';
|
||||||
export default {
|
import imgurl from '../assets/img/img.jpg';
|
||||||
name: "dashboard",
|
|
||||||
components: { Schart },
|
const name = localStorage.getItem('ms_username');
|
||||||
setup() {
|
const role: string = name === 'admin' ? '超级管理员' : '普通用户';
|
||||||
const name = localStorage.getItem("ms_username");
|
|
||||||
const role = name === "admin" ? "超级管理员" : "普通用户";
|
|
||||||
|
|
||||||
const data = reactive([
|
|
||||||
{
|
|
||||||
name: "2018/09/04",
|
|
||||||
value: 1083,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/05",
|
|
||||||
value: 941,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/06",
|
|
||||||
value: 1139,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/07",
|
|
||||||
value: 816,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/08",
|
|
||||||
value: 327,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/09",
|
|
||||||
value: 228,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "2018/09/10",
|
|
||||||
value: 1065,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
const options = {
|
const options = {
|
||||||
type: "bar",
|
type: 'bar',
|
||||||
title: {
|
title: {
|
||||||
text: "最近一周各品类销售图",
|
text: '最近一周各品类销售图'
|
||||||
},
|
},
|
||||||
xRorate: 25,
|
xRorate: 25,
|
||||||
labels: ["周一", "周二", "周三", "周四", "周五"],
|
labels: ['周一', '周二', '周三', '周四', '周五'],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "家电",
|
label: '家电',
|
||||||
data: [234, 278, 270, 190, 230],
|
data: [234, 278, 270, 190, 230]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "百货",
|
label: '百货',
|
||||||
data: [164, 178, 190, 135, 160],
|
data: [164, 178, 190, 135, 160]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "食品",
|
label: '食品',
|
||||||
data: [144, 198, 150, 235, 120],
|
data: [144, 198, 150, 235, 120]
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
const options2 = {
|
const options2 = {
|
||||||
type: "line",
|
type: 'line',
|
||||||
title: {
|
title: {
|
||||||
text: "最近几个月各品类销售趋势图",
|
text: '最近几个月各品类销售趋势图'
|
||||||
},
|
},
|
||||||
labels: ["6月", "7月", "8月", "9月", "10月"],
|
labels: ['6月', '7月', '8月', '9月', '10月'],
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "家电",
|
label: '家电',
|
||||||
data: [234, 278, 270, 190, 230],
|
data: [234, 278, 270, 190, 230]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "百货",
|
label: '百货',
|
||||||
data: [164, 178, 150, 135, 160],
|
data: [164, 178, 150, 135, 160]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "食品",
|
label: '食品',
|
||||||
data: [74, 118, 200, 235, 90],
|
data: [74, 118, 200, 235, 90]
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
};
|
};
|
||||||
const todoList = reactive([
|
const todoList = reactive([
|
||||||
{
|
{
|
||||||
title: "今天要修复100个bug",
|
title: '今天要修复100个bug',
|
||||||
status: false,
|
status: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "今天要修复100个bug",
|
title: '今天要修复100个bug',
|
||||||
status: false,
|
status: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "今天要写100行代码加几个bug吧",
|
title: '今天要写100行代码加几个bug吧',
|
||||||
status: false,
|
status: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "今天要修复100个bug",
|
title: '今天要修复100个bug',
|
||||||
status: false,
|
status: false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "今天要修复100个bug",
|
title: '今天要修复100个bug',
|
||||||
status: true,
|
status: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "今天要写100行代码加几个bug吧",
|
title: '今天要写100行代码加几个bug吧',
|
||||||
status: true,
|
status: true
|
||||||
},
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
data,
|
|
||||||
options,
|
|
||||||
options2,
|
|
||||||
todoList,
|
|
||||||
role,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
@ -281,7 +237,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-con-2 .grid-num {
|
.grid-con-2 .grid-num {
|
||||||
color: rgb(45, 140, 240);
|
color: rgb(100, 213, 114);
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-con-3 .grid-con-icon {
|
.grid-con-3 .grid-con-icon {
|
||||||
|
|
@ -300,12 +256,6 @@ export default {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-avator {
|
|
||||||
width: 120px;
|
|
||||||
height: 120px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info-cont {
|
.user-info-cont {
|
||||||
padding-left: 50px;
|
padding-left: 50px;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-lx-redpacket_fill"></i> 支持作者
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="plugins-tips">如果该框架对你有帮助,那就请作者喝杯饮料吧!加微信号linxin_20探讨问题。</div>
|
<div class="plugins-tips">
|
||||||
|
如果该框架对你有帮助,那就请作者喝杯饮料吧!<el-icon><ColdDrink /></el-icon> 加微信号linxin_20探讨问题。
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img src="https://lin-xin.gitee.io/images/weixin.jpg" />
|
<img src="https://lin-xin.gitee.io/images/weixin.jpg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="donate"></script>
|
||||||
export default {
|
|
||||||
name: "donate"
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,24 @@
|
||||||
<template>
|
<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="container">
|
||||||
<div class="plugins-tips">
|
<div class="plugins-tips">
|
||||||
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。
|
wangEditor:轻量级 web 富文本编辑器,配置方便,使用简单。 访问地址:
|
||||||
访问地址:
|
|
||||||
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
<a href="https://www.wangeditor.com/doc/" target="_blank">wangEditor</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="mgb20" ref='editor'></div>
|
<div class="mgb20" ref="editor"></div>
|
||||||
<el-button type="primary" @click="syncHTML">提交</el-button>
|
<el-button type="primary" @click="syncHTML">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="editor">
|
||||||
import WangEditor from "wangeditor";
|
import WangEditor from 'wangeditor';
|
||||||
import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
|
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue';
|
||||||
export default {
|
|
||||||
name: "editor",
|
|
||||||
setup() {
|
|
||||||
const editor = ref(null);
|
const editor = ref(null);
|
||||||
const content = reactive({
|
const content = reactive({
|
||||||
html: "",
|
html: '',
|
||||||
text: "",
|
text: ''
|
||||||
});
|
});
|
||||||
let instance;
|
let instance: any;
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
instance = new WangEditor(editor.value);
|
instance = new WangEditor(editor.value);
|
||||||
instance.config.zIndex = 1;
|
instance.config.zIndex = 1;
|
||||||
|
|
@ -45,14 +32,6 @@ export default {
|
||||||
content.html = instance.txt.html();
|
content.html = instance.txt.html();
|
||||||
console.log(content.html);
|
console.log(content.html);
|
||||||
};
|
};
|
||||||
return {
|
|
||||||
syncHTML,
|
|
||||||
editor,
|
|
||||||
content,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="about">
|
|
||||||
<v-header />
|
<v-header />
|
||||||
<v-sidebar />
|
<v-sidebar />
|
||||||
<div class="content-box" :class="{ 'content-collapse': sidebar.collapse }">
|
<div class="content-box" :class="{ 'content-collapse': sidebar.collapse }">
|
||||||
|
|
@ -8,34 +7,20 @@
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<transition name="move" mode="out-in">
|
<transition name="move" mode="out-in">
|
||||||
<keep-alive :include="tags.nameList">
|
<keep-alive :include="tags.nameList">
|
||||||
<component :is="Component" />
|
<component :is="Component"></component>
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
<!-- <el-backtop target=".content"></el-backtop> -->
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { useSidebarStore } from '../store/sidebar'
|
import { useSidebarStore } from '../store/sidebar';
|
||||||
import { useTagsStore } from '../store/tags'
|
import { useTagsStore } from '../store/tags';
|
||||||
import vHeader from "../components/Header.vue";
|
import vHeader from '../components/header.vue';
|
||||||
import vSidebar from "../components/Sidebar.vue";
|
import vSidebar from '../components/sidebar.vue';
|
||||||
import vTags from "../components/Tags.vue";
|
import vTags from '../components/tags.vue';
|
||||||
export default {
|
|
||||||
components: {
|
|
||||||
vHeader,
|
|
||||||
vSidebar,
|
|
||||||
vTags,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const sidebar = useSidebarStore();
|
const sidebar = useSidebarStore();
|
||||||
const tags = useTagsStore();
|
const tags = useTagsStore();
|
||||||
return {
|
|
||||||
tags,
|
|
||||||
sidebar,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
<template>
|
|
||||||
<section class="main">
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-lx-global"></i>
|
|
||||||
{{$t('i18n.breadcrumb')}}
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
|
||||||
<span>{{$t('i18n.tips')}}</span>
|
|
||||||
<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>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "i18n"
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.list {
|
|
||||||
padding: 30px 0;
|
|
||||||
}
|
|
||||||
.list p {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,15 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-lx-emoji"></i> 自定义图标
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>使用方法</h2>
|
<h2>使用方法</h2>
|
||||||
<p style="line-height: 50px;">直接通过设置类名为 el-icon-lx-iconName 来使用即可。例如:(共{{iconList.length}}个图标)</p>
|
<p style="line-height: 50px">
|
||||||
|
直接通过设置类名为 el-icon-lx-iconName 来使用即可。例如:(共{{ iconList.length }}个图标)
|
||||||
|
</p>
|
||||||
<p class="example-p">
|
<p class="example-p">
|
||||||
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px; color: #ff5900"></i>
|
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px; color: #ff5900"></i>
|
||||||
<span><i class="el-icon-lx-redpacket_fill"></i></span>
|
<span><i class="el-icon-lx-redpacket_fill"></i></span>
|
||||||
|
|
@ -36,155 +30,144 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="icon">
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref } from 'vue';
|
||||||
export default {
|
|
||||||
name: "icon",
|
const iconList: Array<string> = [
|
||||||
setup() {
|
'attentionforbid',
|
||||||
const iconList = [
|
'attentionforbidfill',
|
||||||
"attentionforbid",
|
'attention',
|
||||||
"attentionforbidfill",
|
'attentionfill',
|
||||||
"attention",
|
'tag',
|
||||||
"attentionfill",
|
'tagfill',
|
||||||
"tag",
|
'people',
|
||||||
"tagfill",
|
'peoplefill',
|
||||||
"people",
|
'notice',
|
||||||
"peoplefill",
|
'noticefill',
|
||||||
"notice",
|
'mobile',
|
||||||
"noticefill",
|
'mobilefill',
|
||||||
"mobile",
|
'voice',
|
||||||
"mobilefill",
|
'voicefill',
|
||||||
"voice",
|
'unlock',
|
||||||
"voicefill",
|
'lock',
|
||||||
"unlock",
|
'home',
|
||||||
"lock",
|
'homefill',
|
||||||
"home",
|
'delete',
|
||||||
"homefill",
|
'deletefill',
|
||||||
"delete",
|
'notification',
|
||||||
"deletefill",
|
'notificationfill',
|
||||||
"notification",
|
'notificationforbidfill',
|
||||||
"notificationfill",
|
'like',
|
||||||
"notificationforbidfill",
|
'likefill',
|
||||||
"like",
|
'comment',
|
||||||
"likefill",
|
'commentfill',
|
||||||
"comment",
|
'camera',
|
||||||
"commentfill",
|
'camerafill',
|
||||||
"camera",
|
'warn',
|
||||||
"camerafill",
|
'warnfill',
|
||||||
"warn",
|
'time',
|
||||||
"warnfill",
|
'timefill',
|
||||||
"time",
|
'location',
|
||||||
"timefill",
|
'locationfill',
|
||||||
"location",
|
'favor',
|
||||||
"locationfill",
|
'favorfill',
|
||||||
"favor",
|
'skin',
|
||||||
"favorfill",
|
'skinfill',
|
||||||
"skin",
|
'news',
|
||||||
"skinfill",
|
'newsfill',
|
||||||
"news",
|
'record',
|
||||||
"newsfill",
|
'recordfill',
|
||||||
"record",
|
'emoji',
|
||||||
"recordfill",
|
'emojifill',
|
||||||
"emoji",
|
'message',
|
||||||
"emojifill",
|
'messagefill',
|
||||||
"message",
|
'goods',
|
||||||
"messagefill",
|
'goodsfill',
|
||||||
"goods",
|
'crown',
|
||||||
"goodsfill",
|
'crownfill',
|
||||||
"crown",
|
'move',
|
||||||
"crownfill",
|
'add',
|
||||||
"move",
|
'hot',
|
||||||
"add",
|
'hotfill',
|
||||||
"hot",
|
'service',
|
||||||
"hotfill",
|
'servicefill',
|
||||||
"service",
|
'present',
|
||||||
"servicefill",
|
'presentfill',
|
||||||
"present",
|
'pic',
|
||||||
"presentfill",
|
'picfill',
|
||||||
"pic",
|
'rank',
|
||||||
"picfill",
|
'rankfill',
|
||||||
"rank",
|
'male',
|
||||||
"rankfill",
|
'female',
|
||||||
"male",
|
'down',
|
||||||
"female",
|
'top',
|
||||||
"down",
|
'recharge',
|
||||||
"top",
|
'rechargefill',
|
||||||
"recharge",
|
'forward',
|
||||||
"rechargefill",
|
'forwardfill',
|
||||||
"forward",
|
'info',
|
||||||
"forwardfill",
|
'infofill',
|
||||||
"info",
|
'redpacket',
|
||||||
"infofill",
|
'redpacket_fill',
|
||||||
"redpacket",
|
'roundadd',
|
||||||
"redpacket_fill",
|
'roundaddfill',
|
||||||
"roundadd",
|
'friendadd',
|
||||||
"roundaddfill",
|
'friendaddfill',
|
||||||
"friendadd",
|
'cart',
|
||||||
"friendaddfill",
|
'cartfill',
|
||||||
"cart",
|
'more',
|
||||||
"cartfill",
|
'moreandroid',
|
||||||
"more",
|
'back',
|
||||||
"moreandroid",
|
'right',
|
||||||
"back",
|
'shop',
|
||||||
"right",
|
'shopfill',
|
||||||
"shop",
|
'question',
|
||||||
"shopfill",
|
'questionfill',
|
||||||
"question",
|
'roundclose',
|
||||||
"questionfill",
|
'roundclosefill',
|
||||||
"roundclose",
|
'roundcheck',
|
||||||
"roundclosefill",
|
'roundcheckfill',
|
||||||
"roundcheck",
|
'global',
|
||||||
"roundcheckfill",
|
'mail',
|
||||||
"global",
|
'punch',
|
||||||
"mail",
|
'exit',
|
||||||
"punch",
|
'upload',
|
||||||
"exit",
|
'read',
|
||||||
"upload",
|
'file',
|
||||||
"read",
|
'link',
|
||||||
"file",
|
'full',
|
||||||
"link",
|
'group',
|
||||||
"full",
|
'friend',
|
||||||
"group",
|
'profile',
|
||||||
"friend",
|
'addressbook',
|
||||||
"profile",
|
'calendar',
|
||||||
"addressbook",
|
'text',
|
||||||
"calendar",
|
'copy',
|
||||||
"text",
|
'share',
|
||||||
"copy",
|
'wifi',
|
||||||
"share",
|
'vipcard',
|
||||||
"wifi",
|
'weibo',
|
||||||
"vipcard",
|
'remind',
|
||||||
"weibo",
|
'refresh',
|
||||||
"remind",
|
'filter',
|
||||||
"refresh",
|
'settings',
|
||||||
"filter",
|
'scan',
|
||||||
"settings",
|
'qrcode',
|
||||||
"scan",
|
'cascades',
|
||||||
"qrcode",
|
'apps',
|
||||||
"cascades",
|
'sort',
|
||||||
"apps",
|
'searchlist',
|
||||||
"sort",
|
'search',
|
||||||
"searchlist",
|
'edit'
|
||||||
"search",
|
|
||||||
"edit",
|
|
||||||
];
|
];
|
||||||
const keyword = ref("");
|
const keyword = ref('');
|
||||||
const list = computed(() => {
|
const list = computed(() => {
|
||||||
return iconList.filter((item) => {
|
return iconList.filter(item => {
|
||||||
return item.indexOf(keyword.value) !== -1;
|
return item.indexOf(keyword.value) !== -1;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
|
||||||
iconList,
|
|
||||||
keyword,
|
|
||||||
list,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,24 @@
|
||||||
<el-form-item prop="username">
|
<el-form-item prop="username">
|
||||||
<el-input v-model="param.username" placeholder="username">
|
<el-input v-model="param.username" placeholder="username">
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-button icon="el-icon-user"></el-button>
|
<el-button :icon="User"></el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item prop="password">
|
<el-form-item prop="password">
|
||||||
<el-input type="password" placeholder="password" v-model="param.password"
|
<el-input
|
||||||
@keyup.enter="submitForm()">
|
type="password"
|
||||||
|
placeholder="password"
|
||||||
|
v-model="param.password"
|
||||||
|
@keyup.enter="submitForm(login)"
|
||||||
|
>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<el-button icon="el-icon-lock"></el-button>
|
<el-button :icon="Lock"></el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-input>
|
</el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="login-btn">
|
<div class="login-btn">
|
||||||
<el-button type="primary" @click="submitForm()">登录</el-button>
|
<el-button type="primary" @click="submitForm(login)">登录</el-button>
|
||||||
</div>
|
</div>
|
||||||
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
<p class="login-tips">Tips : 用户名和密码随便填。</p>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
@ -27,41 +31,50 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts">
|
||||||
import { ref, reactive } from "vue";
|
import { ref, reactive } from 'vue';
|
||||||
import { useTagsStore } from '../store/tags'
|
import { useTagsStore } from '../store/tags';
|
||||||
import { useRouter } from "vue-router";
|
import { usePermissStore } from '../store/permiss';
|
||||||
import { ElMessage } from "element-plus";
|
import { useRouter } from 'vue-router';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus';
|
||||||
|
import { Lock, User } from '@element-plus/icons-vue';
|
||||||
|
|
||||||
|
interface LoginInfo {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
|
||||||
setup() {
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const param = reactive({
|
const param = reactive<LoginInfo>({
|
||||||
username: "admin",
|
username: 'admin',
|
||||||
password: "123123",
|
password: '123123'
|
||||||
});
|
});
|
||||||
|
|
||||||
const rules = {
|
const rules: FormRules = {
|
||||||
username: [
|
username: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: "请输入用户名",
|
message: '请输入用户名',
|
||||||
trigger: "blur",
|
trigger: 'blur'
|
||||||
},
|
}
|
||||||
],
|
|
||||||
password: [
|
|
||||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
|
||||||
],
|
],
|
||||||
|
password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
|
||||||
};
|
};
|
||||||
const login = ref(null);
|
const permiss = usePermissStore();
|
||||||
const submitForm = () => {
|
const login = ref<FormInstance>();
|
||||||
login.value.validate((valid) => {
|
const submitForm = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate((valid: boolean) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
ElMessage.success("登录成功");
|
ElMessage.success('登录成功');
|
||||||
localStorage.setItem("ms_username", param.username);
|
localStorage.setItem('ms_username', param.username);
|
||||||
router.push("/");
|
const keys = permiss.defaultList[param.username == 'admin' ? 'admin' : 'user'];
|
||||||
|
permiss.handleSet(keys);
|
||||||
|
localStorage.setItem('ms_keys', JSON.stringify(keys));
|
||||||
|
router.push('/');
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error("登录成功");
|
ElMessage.error('登录成功');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -69,15 +82,6 @@ export default {
|
||||||
|
|
||||||
const tags = useTagsStore();
|
const tags = useTagsStore();
|
||||||
tags.clearTags();
|
tags.clearTags();
|
||||||
|
|
||||||
return {
|
|
||||||
param,
|
|
||||||
rules,
|
|
||||||
login,
|
|
||||||
submitForm,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,21 @@
|
||||||
<template>
|
<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="container">
|
||||||
<div class="plugins-tips">
|
<div class="plugins-tips">
|
||||||
md-editor-v3:vue3版本的 markdown 编辑器,配置丰富,请详看文档。
|
md-editor-v3:vue3版本的 markdown 编辑器,配置丰富,请详看文档。 访问地址:
|
||||||
访问地址:
|
|
||||||
<a href="https://imzbf.github.io/md-editor-v3/index" target="_blank">md-editor-v3</a>
|
<a href="https://imzbf.github.io/md-editor-v3/index" target="_blank">md-editor-v3</a>
|
||||||
</div>
|
</div>
|
||||||
<md-editor class="mgb20" v-model="text" @on-upload-img="onUploadImg" />
|
<md-editor class="mgb20" v-model="text" @on-upload-img="onUploadImg" />
|
||||||
<el-button type="primary">提交</el-button>
|
<el-button type="primary">提交</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts" name="md">
|
||||||
import { ref} from "vue";
|
import { ref } from 'vue';
|
||||||
import MdEditor from 'md-editor-v3';
|
import MdEditor from 'md-editor-v3';
|
||||||
import 'md-editor-v3/lib/style.css';
|
import 'md-editor-v3/lib/style.css';
|
||||||
|
|
||||||
const text = ref('Hello Editor!');
|
const text = ref('Hello Editor!');
|
||||||
const onUploadImg = (files)=>{
|
const onUploadImg = (files: any) => {
|
||||||
console.log(files)
|
console.log(files);
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -1,40 +1,137 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item>
|
|
||||||
<i class="el-icon-lx-warn"></i> 权限测试
|
|
||||||
</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>管理员权限页面</h1>
|
<div class="plugins-tips">通过 v-permiss 自定义指令实现权限管理,使用非 admin 账号登录,可查看效果。</div>
|
||||||
<p>只有用 admin 账号登录的才拥有管理员权限,才能进到这个页面,其他账号想进来都会跳到403页面,重新用管理员账号登录才有权限。</p>
|
<div class="mgb20">
|
||||||
<p>
|
<span class="label">角色:</span>
|
||||||
想尝试一下,请
|
<el-select v-model="role" @change="handleChange">
|
||||||
<router-link to="/login" class="logout">退出登录</router-link>,随便输入个账号名,再进来试试看。
|
<el-option label="超级管理员" value="admin"></el-option>
|
||||||
</p>
|
<el-option label="普通用户" value="user"></el-option>
|
||||||
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mgb20 tree-wrapper">
|
||||||
|
<el-tree
|
||||||
|
ref="tree"
|
||||||
|
:data="data"
|
||||||
|
node-key="id"
|
||||||
|
default-expand-all
|
||||||
|
show-checkbox
|
||||||
|
:default-checked-keys="checkedKeys"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<el-button type="primary" @click="onSubmit">保存权限</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="permission">
|
||||||
export default {
|
import { ref } from 'vue';
|
||||||
name: "permission"
|
import { ElTree } from 'element-plus';
|
||||||
|
import { usePermissStore } from '../store/permiss';
|
||||||
|
|
||||||
|
const role = ref<string>('admin');
|
||||||
|
|
||||||
|
interface Tree {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
children?: Tree[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const data: Tree[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
label: '系统首页'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
label: '基础表格',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '15',
|
||||||
|
label: '编辑'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '16',
|
||||||
|
label: '删除'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
label: 'tab选项卡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
label: '表单相关',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
label: '基本表单'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
label: '文件上传'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
label: '三级菜单',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
label: '富文本编辑器'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9',
|
||||||
|
label: 'markdown编辑器'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
label: '自定义图标'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '11',
|
||||||
|
label: 'schart图表'
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
id: '13',
|
||||||
|
label: '权限管理'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '14',
|
||||||
|
label: '支持作者'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const permiss = usePermissStore();
|
||||||
|
|
||||||
|
// 获取当前权限
|
||||||
|
const checkedKeys = ref<string[]>([]);
|
||||||
|
const getPremission = () => {
|
||||||
|
// 请求接口返回权限
|
||||||
|
checkedKeys.value = permiss.defaultList[role.value];
|
||||||
|
};
|
||||||
|
getPremission();
|
||||||
|
|
||||||
|
// 保存权限
|
||||||
|
const tree = ref<InstanceType<typeof ElTree>>();
|
||||||
|
const onSubmit = () => {
|
||||||
|
// 获取选中的权限
|
||||||
|
console.log(tree.value!.getCheckedKeys(false));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (val: string[]) => {
|
||||||
|
tree.value!.setCheckedKeys(permiss.defaultList[role.value]);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
h1 {
|
.tree-wrapper {
|
||||||
text-align: center;
|
max-width: 500px;
|
||||||
margin: 30px 0;
|
|
||||||
}
|
}
|
||||||
p {
|
.label {
|
||||||
line-height: 30px;
|
font-size: 14px;
|
||||||
margin-bottom: 10px;
|
|
||||||
text-indent: 2em;
|
|
||||||
}
|
|
||||||
.logout {
|
|
||||||
color: #409eff;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,10 +1,4 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="">
|
|
||||||
<div class="crumbs">
|
|
||||||
<el-breadcrumb separator="/">
|
|
||||||
<el-breadcrumb-item><i class="el-icon-lx-copy"></i> tab选项卡</el-breadcrumb-item>
|
|
||||||
</el-breadcrumb>
|
|
||||||
</div>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<el-tabs v-model="message">
|
<el-tabs v-model="message">
|
||||||
<el-tab-pane :label="`未读消息(${state.unread.length})`" name="first">
|
<el-tab-pane :label="`未读消息(${state.unread.length})`" name="first">
|
||||||
|
|
@ -67,63 +61,49 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="tabs">
|
||||||
import { ref, reactive } from "vue";
|
import { ref, reactive } from 'vue';
|
||||||
export default {
|
|
||||||
name: "tabs",
|
const message = ref('first');
|
||||||
setup() {
|
|
||||||
const message = ref("first");
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
unread: [
|
unread: [
|
||||||
{
|
{
|
||||||
date: "2018-04-19 20:00:00",
|
date: '2018-04-19 20:00:00',
|
||||||
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
|
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
date: "2018-04-19 21:00:00",
|
date: '2018-04-19 21:00:00',
|
||||||
title: "今晚12点整发大红包,先到先得",
|
title: '今晚12点整发大红包,先到先得'
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
read: [
|
read: [
|
||||||
{
|
{
|
||||||
date: "2018-04-19 20:00:00",
|
date: '2018-04-19 20:00:00',
|
||||||
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
|
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
recycle: [
|
recycle: [
|
||||||
{
|
{
|
||||||
date: "2018-04-19 20:00:00",
|
date: '2018-04-19 20:00:00',
|
||||||
title: "【系统通知】该系统将于今晚凌晨2点到5点进行升级维护",
|
title: '【系统通知】该系统将于今晚凌晨2点到5点进行升级维护'
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleRead = (index) => {
|
const handleRead = (index: number) => {
|
||||||
const item = state.unread.splice(index, 1);
|
const item = state.unread.splice(index, 1);
|
||||||
console.log(item);
|
|
||||||
state.read = item.concat(state.read);
|
state.read = item.concat(state.read);
|
||||||
};
|
};
|
||||||
const handleDel = (index) => {
|
const handleDel = (index: number) => {
|
||||||
const item = state.read.splice(index, 1);
|
const item = state.read.splice(index, 1);
|
||||||
state.recycle = item.concat(state.recycle);
|
state.recycle = item.concat(state.recycle);
|
||||||
};
|
};
|
||||||
const handleRestore = (index) => {
|
const handleRestore = (index: number) => {
|
||||||
const item = state.recycle.splice(index, 1);
|
const item = state.recycle.splice(index, 1);
|
||||||
state.read = item.concat(state.read);
|
state.read = item.concat(state.read);
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
|
||||||
message,
|
|
||||||
state,
|
|
||||||
handleRead,
|
|
||||||
handleDel,
|
|
||||||
handleRestore,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
@ -134,4 +114,3 @@ export default {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,12 @@
|
||||||
<template>
|
<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="container">
|
||||||
<div class="content-title">支持拖拽</div>
|
<div class="content-title">支持拖拽</div>
|
||||||
<div class="plugins-tips">
|
<div class="plugins-tips">
|
||||||
Element UI自带上传组件。
|
Element Plus自带上传组件。 访问地址:
|
||||||
访问地址:
|
<a href="https://element-plus.org/zh-CN/component/upload.html" target="_blank">Element Plus Upload</a>
|
||||||
<a href="http://element.eleme.io/#/zh-CN/component/upload" target="_blank">Element UI Upload</a>
|
|
||||||
</div>
|
</div>
|
||||||
<el-upload class="upload-demo" drag action="http://jsonplaceholder.typicode.com/api/posts/" multiple>
|
<el-upload class="upload-demo" drag action="http://jsonplaceholder.typicode.com/api/posts/" multiple>
|
||||||
<i class="el-icon-upload"></i>
|
<el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
||||||
<div class="el-upload__text">
|
<div class="el-upload__text">
|
||||||
将文件拖到此处,或
|
将文件拖到此处,或
|
||||||
<em>点击上传</em>
|
<em>点击上传</em>
|
||||||
|
|
@ -28,66 +18,13 @@
|
||||||
|
|
||||||
<div class="content-title">支持裁剪</div>
|
<div class="content-title">支持裁剪</div>
|
||||||
<div class="plugins-tips">
|
<div class="plugins-tips">
|
||||||
vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。
|
vue-cropperjs:一个封装了 cropperjs 的 Vue 组件。 访问地址:
|
||||||
访问地址:
|
<a href="https://github.com/Agontuk/vue-cropperjs" target="_blank">vue-cropperjs</a>。 示例请查看
|
||||||
<a href="https://github.com/Agontuk/vue-cropperjs" target="_blank">vue-cropperjs</a>
|
<router-link to="/user">个人中心</router-link>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
|
||||||
import { ref } from "vue";
|
|
||||||
import VueCropper from "vue-cropperjs";
|
|
||||||
import "cropperjs/dist/cropper.css";
|
|
||||||
import defaultSrc from "../assets/img/img.jpg";
|
|
||||||
export default {
|
|
||||||
name: "upload",
|
|
||||||
components: {
|
|
||||||
VueCropper,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const imgSrc = ref("");
|
|
||||||
const cropImg = ref(defaultSrc);
|
|
||||||
const dialogVisible = ref(false);
|
|
||||||
const cropper = ref(null);
|
|
||||||
|
|
||||||
const setImage = (e) => {
|
|
||||||
const file = e.target.files[0];
|
|
||||||
if (!file.type.includes("image/")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = (event) => {
|
|
||||||
dialogVisible.value = true;
|
|
||||||
imgSrc.value = event.target.result;
|
|
||||||
cropper.value && cropper.value.replace(event.target.result);
|
|
||||||
};
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
};
|
|
||||||
|
|
||||||
const cropImage = () => {
|
|
||||||
cropImg.value = cropper.value.getCroppedCanvas().toDataURL();
|
|
||||||
};
|
|
||||||
|
|
||||||
const cancelCrop = () => {
|
|
||||||
dialogVisible.value = false;
|
|
||||||
cropImg.value = defaultSrc;
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
cropper,
|
|
||||||
imgSrc,
|
|
||||||
cropImg,
|
|
||||||
dialogVisible,
|
|
||||||
setImage,
|
|
||||||
cropImage,
|
|
||||||
cancelCrop,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.content-title {
|
.content-title {
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<div class="info-image" @click="showDialog">
|
<div class="info-image" @click="showDialog">
|
||||||
<img :src="avatarImg" />
|
<el-avatar :size="100" :src="avatarImg" />
|
||||||
<span class="info-edit">
|
<span class="info-edit">
|
||||||
<i class="el-icon-lx-camerafill"></i>
|
<i class="el-icon-lx-camerafill"></i>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -46,12 +46,19 @@
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-dialog title="裁剪图片" v-model="dialogVisible" width="600px">
|
<el-dialog title="裁剪图片" v-model="dialogVisible" width="600px">
|
||||||
<vue-cropper ref="cropper" :src="imgSrc" :ready="cropImage" :zoom="cropImage" :cropmove="cropImage"
|
<vue-cropper
|
||||||
style="width: 100%; height: 400px"></vue-cropper>
|
ref="cropper"
|
||||||
|
:src="imgSrc"
|
||||||
|
:ready="cropImage"
|
||||||
|
:zoom="cropImage"
|
||||||
|
:cropmove="cropImage"
|
||||||
|
style="width: 100%; height: 400px"
|
||||||
|
></vue-cropper>
|
||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<span class="dialog-footer">
|
<span class="dialog-footer">
|
||||||
<el-button class="crop-demo-btn" type="primary">选择图片
|
<el-button class="crop-demo-btn" type="primary"
|
||||||
|
>选择图片
|
||||||
<input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" />
|
<input class="crop-input" type="file" name="image" accept="image/*" @change="setImage" />
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" @click="saveAvatar">上传并保存</el-button>
|
<el-button type="primary" @click="saveAvatar">上传并保存</el-button>
|
||||||
|
|
@ -61,43 +68,38 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup lang="ts" name="user">
|
||||||
import { reactive, ref } from "vue";
|
import { reactive, ref } from 'vue';
|
||||||
import VueCropper from "vue-cropperjs";
|
import VueCropper from 'vue-cropperjs';
|
||||||
import "cropperjs/dist/cropper.css";
|
import 'cropperjs/dist/cropper.css';
|
||||||
import avatar from "../assets/img/img.jpg";
|
import avatar from '../assets/img/img.jpg';
|
||||||
export default {
|
|
||||||
name: "user",
|
const name = localStorage.getItem('ms_username');
|
||||||
components: {
|
|
||||||
VueCropper,
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
const name = localStorage.getItem("ms_username");
|
|
||||||
const form = reactive({
|
const form = reactive({
|
||||||
old: "",
|
old: '',
|
||||||
new: "",
|
new: '',
|
||||||
desc: "不可能!我的代码怎么可能会有bug!",
|
desc: '不可能!我的代码怎么可能会有bug!'
|
||||||
});
|
});
|
||||||
const onSubmit = () => {};
|
const onSubmit = () => {};
|
||||||
|
|
||||||
const avatarImg = ref(avatar);
|
const avatarImg = ref(avatar);
|
||||||
const imgSrc = ref("");
|
const imgSrc = ref('');
|
||||||
const cropImg = ref("");
|
const cropImg = ref('');
|
||||||
const dialogVisible = ref(false);
|
const dialogVisible = ref(false);
|
||||||
const cropper = ref(null);
|
const cropper: any = ref();
|
||||||
|
|
||||||
const showDialog = () => {
|
const showDialog = () => {
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
imgSrc.value = avatarImg.value;
|
imgSrc.value = avatarImg.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setImage = (e) => {
|
const setImage = (e: any) => {
|
||||||
const file = e.target.files[0];
|
const file = e.target.files[0];
|
||||||
if (!file.type.includes("image/")) {
|
if (!file.type.includes('image/')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (event) => {
|
reader.onload = (event: any) => {
|
||||||
dialogVisible.value = true;
|
dialogVisible.value = true;
|
||||||
imgSrc.value = event.target.result;
|
imgSrc.value = event.target.result;
|
||||||
cropper.value && cropper.value.replace(event.target.result);
|
cropper.value && cropper.value.replace(event.target.result);
|
||||||
|
|
@ -113,23 +115,6 @@ export default {
|
||||||
avatarImg.value = cropImg.value;
|
avatarImg.value = cropImg.value;
|
||||||
dialogVisible.value = false;
|
dialogVisible.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
form,
|
|
||||||
onSubmit,
|
|
||||||
cropper,
|
|
||||||
avatarImg,
|
|
||||||
imgSrc,
|
|
||||||
cropImg,
|
|
||||||
showDialog,
|
|
||||||
dialogVisible,
|
|
||||||
setImage,
|
|
||||||
cropImage,
|
|
||||||
saveAvatar,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
@ -147,10 +132,7 @@ export default {
|
||||||
border-radius: 50px;
|
border-radius: 50px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.info-image img {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.info-edit {
|
.info-edit {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="plugins-tips">
|
||||||
|
vue-schart:vue.js封装sChart.js的图表组件。 访问地址:
|
||||||
|
<a href="https://github.com/lin-xin/vue-schart" target="_blank">vue-schart</a>
|
||||||
|
</div>
|
||||||
|
<div class="schart-box">
|
||||||
|
<div class="content-title">柱状图</div>
|
||||||
|
<schart class="schart" canvasId="bar" :options="options1"></schart>
|
||||||
|
</div>
|
||||||
|
<div class="schart-box">
|
||||||
|
<div class="content-title">折线图</div>
|
||||||
|
<schart class="schart" canvasId="line" :options="options2"></schart>
|
||||||
|
</div>
|
||||||
|
<div class="schart-box">
|
||||||
|
<div class="content-title">饼状图</div>
|
||||||
|
<schart class="schart" canvasId="pie" :options="options3"></schart>
|
||||||
|
</div>
|
||||||
|
<div class="schart-box">
|
||||||
|
<div class="content-title">环形图</div>
|
||||||
|
<schart class="schart" canvasId="ring" :options="options4"></schart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="basecharts">
|
||||||
|
import Schart from 'vue-schart';
|
||||||
|
|
||||||
|
const options1 = {
|
||||||
|
type: 'bar',
|
||||||
|
title: {
|
||||||
|
text: '最近一周各品类销售图'
|
||||||
|
},
|
||||||
|
bgColor: '#fbfbfb',
|
||||||
|
labels: ['周一', '周二', '周三', '周四', '周五'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: '家电',
|
||||||
|
fillColor: 'rgba(241, 49, 74, 0.5)',
|
||||||
|
data: [234, 278, 270, 190, 230]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '百货',
|
||||||
|
data: [164, 178, 190, 135, 160]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '食品',
|
||||||
|
data: [144, 198, 150, 235, 120]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const options2 = {
|
||||||
|
type: 'line',
|
||||||
|
title: {
|
||||||
|
text: '最近几个月各品类销售趋势图'
|
||||||
|
},
|
||||||
|
bgColor: '#fbfbfb',
|
||||||
|
labels: ['6月', '7月', '8月', '9月', '10月'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: '家电',
|
||||||
|
data: [234, 278, 270, 190, 230]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '百货',
|
||||||
|
data: [164, 178, 150, 135, 160]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '食品',
|
||||||
|
data: [114, 138, 200, 235, 190]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const options3 = {
|
||||||
|
type: 'pie',
|
||||||
|
title: {
|
||||||
|
text: '服装品类销售饼状图'
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
position: 'left'
|
||||||
|
},
|
||||||
|
bgColor: '#fbfbfb',
|
||||||
|
labels: ['T恤', '牛仔裤', '连衣裙', '毛衣', '七分裤', '短裙', '羽绒服'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: [334, 278, 190, 235, 260, 200, 141]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
const options4 = {
|
||||||
|
type: 'ring',
|
||||||
|
title: {
|
||||||
|
text: '环形三等分'
|
||||||
|
},
|
||||||
|
showValue: false,
|
||||||
|
legend: {
|
||||||
|
position: 'bottom',
|
||||||
|
bottom: 40
|
||||||
|
},
|
||||||
|
bgColor: '#fbfbfb',
|
||||||
|
labels: ['vue', 'react', 'angular'],
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
data: [500, 500, 500]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.schart-box {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
.schart {
|
||||||
|
width: 600px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
.content-title {
|
||||||
|
clear: both;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 50px;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-size: 22px;
|
||||||
|
color: #1f2f3d;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="form-box">
|
||||||
|
<el-form ref="formRef" :rules="rules" :model="form" label-width="80px">
|
||||||
|
<el-form-item label="表单名称" prop="name">
|
||||||
|
<el-input v-model="form.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="选择器" prop="region">
|
||||||
|
<el-select v-model="form.region" placeholder="请选择">
|
||||||
|
<el-option key="bbk" label="步步高" value="bbk"></el-option>
|
||||||
|
<el-option key="xtc" label="小天才" value="xtc"></el-option>
|
||||||
|
<el-option key="imoo" label="imoo" value="imoo"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="日期时间">
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item prop="date1">
|
||||||
|
<el-date-picker
|
||||||
|
type="date"
|
||||||
|
placeholder="选择日期"
|
||||||
|
v-model="form.date1"
|
||||||
|
style="width: 100%"
|
||||||
|
></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="line" :span="2">-</el-col>
|
||||||
|
<el-col :span="11">
|
||||||
|
<el-form-item prop="date2">
|
||||||
|
<el-time-picker placeholder="选择时间" v-model="form.date2" style="width: 100%">
|
||||||
|
</el-time-picker>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="城市级联" prop="options">
|
||||||
|
<el-cascader :options="options" v-model="form.options"></el-cascader>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="选择开关" prop="delivery">
|
||||||
|
<el-switch v-model="form.delivery"></el-switch>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="多选框" prop="type">
|
||||||
|
<el-checkbox-group v-model="form.type">
|
||||||
|
<el-checkbox label="步步高" name="type"></el-checkbox>
|
||||||
|
<el-checkbox label="小天才" name="type"></el-checkbox>
|
||||||
|
<el-checkbox label="imoo" name="type"></el-checkbox>
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="单选框" prop="resource">
|
||||||
|
<el-radio-group v-model="form.resource">
|
||||||
|
<el-radio label="步步高"></el-radio>
|
||||||
|
<el-radio label="小天才"></el-radio>
|
||||||
|
<el-radio label="imoo"></el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="文本框" prop="desc">
|
||||||
|
<el-input type="textarea" rows="5" v-model="form.desc"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="onSubmit(formRef)">表单提交</el-button>
|
||||||
|
<el-button @click="onReset(formRef)">重置表单</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="baseform">
|
||||||
|
import { reactive, ref } from 'vue';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus';
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{
|
||||||
|
value: 'guangdong',
|
||||||
|
label: '广东省',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'guangzhou',
|
||||||
|
label: '广州市',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'tianhe',
|
||||||
|
label: '天河区'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'haizhu',
|
||||||
|
label: '海珠区'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'dongguan',
|
||||||
|
label: '东莞市',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'changan',
|
||||||
|
label: '长安镇'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'humen',
|
||||||
|
label: '虎门镇'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'hunan',
|
||||||
|
label: '湖南省',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'changsha',
|
||||||
|
label: '长沙市',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
value: 'yuelu',
|
||||||
|
label: '岳麓区'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const rules: FormRules = {
|
||||||
|
name: [{ required: true, message: '请输入表单名称', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
const formRef = ref<FormInstance>();
|
||||||
|
const form = reactive({
|
||||||
|
name: '',
|
||||||
|
region: '',
|
||||||
|
date1: '',
|
||||||
|
date2: '',
|
||||||
|
delivery: true,
|
||||||
|
type: ['步步高'],
|
||||||
|
resource: '小天才',
|
||||||
|
desc: '',
|
||||||
|
options: []
|
||||||
|
});
|
||||||
|
// 提交
|
||||||
|
const onSubmit = (formEl: FormInstance | undefined) => {
|
||||||
|
// 表单校验
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.validate(valid => {
|
||||||
|
if (valid) {
|
||||||
|
console.log(form);
|
||||||
|
ElMessage.success('提交成功!');
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 重置
|
||||||
|
const onReset = (formEl: FormInstance | undefined) => {
|
||||||
|
if (!formEl) return;
|
||||||
|
formEl.resetFields();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="container">
|
||||||
|
<div class="handle-box">
|
||||||
|
<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="Search" @click="handleSearch">搜索</el-button>
|
||||||
|
<el-button type="primary" :icon="Plus">新增</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table :data="tableData" border class="table" ref="multipleTable" header-cell-class-name="table-header">
|
||||||
|
<el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
|
||||||
|
<el-table-column prop="name" label="用户名"></el-table-column>
|
||||||
|
<el-table-column label="账户余额">
|
||||||
|
<template #default="scope">¥{{ scope.row.money }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="头像(查看大图)" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-image
|
||||||
|
class="table-td-thumb"
|
||||||
|
:src="scope.row.thumb"
|
||||||
|
:z-index="10"
|
||||||
|
:preview-src-list="[scope.row.thumb]"
|
||||||
|
preview-teleported
|
||||||
|
>
|
||||||
|
</el-image>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="address" label="地址"></el-table-column>
|
||||||
|
<el-table-column label="状态" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="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="220" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button text :icon="Edit" @click="handleEdit(scope.$index, scope.row)" v-permiss="15">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
<el-button text :icon="Delete" class="red" @click="handleDelete(scope.$index)" v-permiss="16">
|
||||||
|
删除
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<div class="pagination">
|
||||||
|
<el-pagination
|
||||||
|
background
|
||||||
|
layout="total, prev, pager, next"
|
||||||
|
:current-page="query.pageIndex"
|
||||||
|
:page-size="query.pageSize"
|
||||||
|
:total="pageTotal"
|
||||||
|
@current-change="handlePageChange"
|
||||||
|
></el-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 编辑弹出框 -->
|
||||||
|
<el-dialog title="编辑" v-model="editVisible" width="30%">
|
||||||
|
<el-form label-width="70px">
|
||||||
|
<el-form-item label="用户名">
|
||||||
|
<el-input v-model="form.name"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="地址">
|
||||||
|
<el-input v-model="form.address"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="editVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="saveEdit">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts" name="basetable">
|
||||||
|
import { ref, reactive } from 'vue';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import { Delete, Edit, Search, Plus } from '@element-plus/icons-vue';
|
||||||
|
import { fetchData } from '../api/index';
|
||||||
|
|
||||||
|
interface TableItem {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
money: string;
|
||||||
|
state: string;
|
||||||
|
date: string;
|
||||||
|
address: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query = reactive({
|
||||||
|
address: '',
|
||||||
|
name: '',
|
||||||
|
pageIndex: 1,
|
||||||
|
pageSize: 10
|
||||||
|
});
|
||||||
|
const tableData = ref<TableItem[]>([]);
|
||||||
|
const pageTotal = ref(0);
|
||||||
|
// 获取表格数据
|
||||||
|
const getData = () => {
|
||||||
|
fetchData().then(res => {
|
||||||
|
tableData.value = res.data.list;
|
||||||
|
pageTotal.value = res.data.pageTotal || 50;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
getData();
|
||||||
|
|
||||||
|
// 查询操作
|
||||||
|
const handleSearch = () => {
|
||||||
|
query.pageIndex = 1;
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
// 分页导航
|
||||||
|
const handlePageChange = (val: number) => {
|
||||||
|
query.pageIndex = val;
|
||||||
|
getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 删除操作
|
||||||
|
const handleDelete = (index: number) => {
|
||||||
|
// 二次确认删除
|
||||||
|
ElMessageBox.confirm('确定要删除吗?', '提示', {
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
ElMessage.success('删除成功');
|
||||||
|
tableData.value.splice(index, 1);
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表格编辑时弹窗和保存
|
||||||
|
const editVisible = ref(false);
|
||||||
|
let form = reactive({
|
||||||
|
name: '',
|
||||||
|
address: ''
|
||||||
|
});
|
||||||
|
let idx: number = -1;
|
||||||
|
const handleEdit = (index: number, row: any) => {
|
||||||
|
idx = index;
|
||||||
|
form.name = row.name;
|
||||||
|
form.address = row.address;
|
||||||
|
editVisible.value = true;
|
||||||
|
};
|
||||||
|
const saveEdit = () => {
|
||||||
|
editVisible.value = false;
|
||||||
|
ElMessage.success(`修改第 ${idx + 1} 行成功`);
|
||||||
|
tableData.value[idx].name = form.name;
|
||||||
|
tableData.value[idx].address = form.address;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.handle-box {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.handle-select {
|
||||||
|
width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.handle-input {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.red {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
.mr10 {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.table-td-thumb {
|
||||||
|
display: block;
|
||||||
|
margin: auto;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
import type { DefineComponent } from 'vue'
|
||||||
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
export default component
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module 'vue-schart';
|
||||||
|
declare module 'vue-cropperjs';
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ESNext",
|
||||||
|
"useDefineForClassFields": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"strict": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"sourceMap": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"lib": ["ESNext", "DOM"],
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.d.ts","src/**/*.vue"],
|
||||||
|
"references": [{ "path": "./tsconfig.node.json" }]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "Node",
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["vite.config.ts"]
|
||||||
|
}
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
base: './',
|
|
||||||
plugins: [vue()],
|
|
||||||
optimizeDeps: {
|
|
||||||
include: ['schart.js']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
import VueSetupExtend from 'vite-plugin-vue-setup-extend';
|
||||||
|
import AutoImport from 'unplugin-auto-import/vite';
|
||||||
|
import Components from 'unplugin-vue-components/vite';
|
||||||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers';
|
||||||
|
export default defineConfig({
|
||||||
|
base: './',
|
||||||
|
plugins: [
|
||||||
|
vue(),
|
||||||
|
VueSetupExtend(),
|
||||||
|
AutoImport({
|
||||||
|
resolvers: [ElementPlusResolver()]
|
||||||
|
}),
|
||||||
|
Components({
|
||||||
|
resolvers: [ElementPlusResolver()]
|
||||||
|
})
|
||||||
|
],
|
||||||
|
optimizeDeps: {
|
||||||
|
include: ['schart.js']
|
||||||
|
}
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue