update
This commit is contained in:
parent
33fda82dd9
commit
bbf03e66fb
46
.eslintrc.js
46
.eslintrc.js
@ -1,22 +1,52 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
|
||||
parserOptions: {
|
||||
"parser": "babel-eslint"
|
||||
"parser": "babel-eslint",
|
||||
"sourceType": 'module',
|
||||
"ecmaVersion": 2020,
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-console": 0,
|
||||
'no-use-before-define': 'off',
|
||||
'no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
},
|
||||
],
|
||||
'no-prototype-builtins': 'off',
|
||||
'space-before-function-paren': 'off',
|
||||
'vue/custom-event-name-casing': 'off',
|
||||
'vue/attributes-order': 'off',
|
||||
'vue/one-component-per-file': 'off',
|
||||
'vue/html-closing-bracket-newline': 'off',
|
||||
'vue/max-attributes-per-line': 'off',
|
||||
'vue/multiline-html-element-content-newline': 'off',
|
||||
'vue/singleline-html-element-content-newline': 'off',
|
||||
'vue/attribute-hyphenation': 'off',
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/no-unused-components': 'warn',
|
||||
'vue/no-setup-props-destructure': 'off',
|
||||
"prettier/prettier": [
|
||||
"warn",
|
||||
{
|
||||
// singleQuote: none,
|
||||
// semi: false,
|
||||
trailingComma: "es5",
|
||||
},
|
||||
],
|
||||
'printWidth': 80, // 每行代码长度(默认80)
|
||||
'tabWidth': 2, // 每个tab相当于多少个空格(默认2)
|
||||
'useTabs': false, // 是否使用tab进行缩进(默认false)
|
||||
'singleQuote': true, // 使用单引号(默认false)
|
||||
'semi': true, // 声明结尾使用分号(默认true)
|
||||
'trailingComma': 'es5', // 多行使用拖尾逗号(默认none)
|
||||
'bracketSpacing': true, // 对象字面量的大括号间使用空格(默认true)
|
||||
'jsxBracketSameLine': false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)
|
||||
'arrowParens': 'avoid', // 只有一个参数的箭头函数的参数是否带括号(默认avoid)
|
||||
}
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
"build": "vite build",
|
||||
"build:mock": "vite build --mode mock",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue src"
|
||||
"lint": "eslint --fix --ext .js,.vue src"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
module.exports = {
|
||||
printWidth: 80, // 每行代码长度(默认80)
|
||||
tabWidth: 2, // 每个tab相当于多少个空格(默认2)
|
||||
useTabs: false, // 是否使用tab进行缩进(默认false)
|
||||
singleQuote: false, // 使用单引号(默认false)
|
||||
semi: true, // 声明结尾使用分号(默认true)
|
||||
trailingComma: 'es5', // 多行使用拖尾逗号(默认none)
|
||||
bracketSpacing: true, // 对象字面量的大括号间使用空格(默认true)
|
||||
jsxBracketSameLine: false, // 多行JSX中的>放置在最后一行的结尾,而不是另起一行(默认false)
|
||||
arrowParens: "avoid", // 只有一个参数的箭头函数的参数是否带圆括号(默认avoid)
|
||||
};
|
||||
@ -10,4 +10,4 @@ body,
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import request from '@/utils/request'
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 登录接口
|
||||
export const Login = data => {
|
||||
return request({
|
||||
url: "/api/login",
|
||||
method: "post",
|
||||
url: '/api/login',
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
};
|
||||
@ -12,7 +12,7 @@ export const Login = data => {
|
||||
// 获取登录用户信息
|
||||
export const GetUserinfo = () => {
|
||||
return request({
|
||||
url: "/api/userinfo",
|
||||
method: "get"
|
||||
url: '/api/userinfo',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
import request from '@/utils/request';
|
||||
|
||||
// 获取菜单
|
||||
export const GetMenus = () => {
|
||||
return request({
|
||||
url: "/api/menus",
|
||||
method: "get"
|
||||
url: '/api/menus',
|
||||
method: 'get',
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
@ -212,42 +212,42 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, reactive, toRefs, onBeforeMount } from "vue";
|
||||
import { defineComponent, reactive, toRefs, onBeforeMount } from 'vue';
|
||||
const formatDate = (date, format) => {
|
||||
var obj = {
|
||||
"M+": date.getMonth() + 1,
|
||||
"D+": date.getDate(),
|
||||
"H+": date.getHours(),
|
||||
"m+": date.getMinutes(),
|
||||
"s+": date.getSeconds(),
|
||||
"q+": Math.floor((date.getMonth() + 3) / 3),
|
||||
"S+": date.getMilliseconds(),
|
||||
'M+': date.getMonth() + 1,
|
||||
'D+': date.getDate(),
|
||||
'H+': date.getHours(),
|
||||
'm+': date.getMinutes(),
|
||||
's+': date.getSeconds(),
|
||||
'q+': Math.floor((date.getMonth() + 3) / 3),
|
||||
'S+': date.getMilliseconds(),
|
||||
};
|
||||
if (/(y+)/i.test(format)) {
|
||||
format = format.replace(
|
||||
RegExp.$1,
|
||||
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
|
||||
(date.getFullYear() + '').substr(4 - RegExp.$1.length)
|
||||
);
|
||||
}
|
||||
for (var k in obj) {
|
||||
if (new RegExp("(" + k + ")").test(format)) {
|
||||
if (new RegExp('(' + k + ')').test(format)) {
|
||||
format = format.replace(
|
||||
RegExp.$1,
|
||||
RegExp.$1.length == 1
|
||||
? obj[k]
|
||||
: ("00" + obj[k]).substr(("" + obj[k]).length)
|
||||
: ('00' + obj[k]).substr(('' + obj[k]).length)
|
||||
);
|
||||
}
|
||||
}
|
||||
return format;
|
||||
};
|
||||
const getSearchModel = (search) => {
|
||||
const getSearchModel = search => {
|
||||
const searchModel = {};
|
||||
if (search && search.fields) {
|
||||
search.fields.forEach((item) => {
|
||||
search.fields.forEach(item => {
|
||||
switch (item.type) {
|
||||
case "checkbox":
|
||||
case "checkbox-button":
|
||||
case 'checkbox':
|
||||
case 'checkbox-button':
|
||||
searchModel[item.name] = [];
|
||||
break;
|
||||
default:
|
||||
@ -257,7 +257,7 @@ const getSearchModel = (search) => {
|
||||
searchModel[item.name] = item.defaultValue;
|
||||
// 日期范围和时间范围真实变量默认值
|
||||
if (
|
||||
(item.type === "daterange" || item.type === "datetimerange") &&
|
||||
(item.type === 'daterange' || item.type === 'datetimerange') &&
|
||||
!!item.trueNames &&
|
||||
Array.isArray(item.defaultValue)
|
||||
) {
|
||||
@ -279,7 +279,7 @@ export default defineComponent({
|
||||
// 表格标题
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: '',
|
||||
},
|
||||
// 是否隐藏标题栏
|
||||
hideTitleBar: {
|
||||
@ -298,14 +298,12 @@ export default defineComponent({
|
||||
// 表头配置
|
||||
columns: {
|
||||
type: Array,
|
||||
default: function (params) {
|
||||
return [];
|
||||
},
|
||||
default: () => [],
|
||||
},
|
||||
// 行数据的Key,同elementUI的table组件的row-key
|
||||
rowKey: {
|
||||
type: String,
|
||||
default: "id",
|
||||
default: 'id',
|
||||
},
|
||||
// 分页配置,false表示不显示分页
|
||||
pagination: {
|
||||
@ -317,18 +315,18 @@ export default defineComponent({
|
||||
// 优化搜索字段,
|
||||
// 1、如果搜索配置有transform处理函数,执行transform
|
||||
// 2、删除日期范围默认的name字段
|
||||
const optimizeFields = (search) => {
|
||||
const optimizeFields = search => {
|
||||
const searchModel = JSON.parse(JSON.stringify(state.searchModel));
|
||||
if (search && search.fields) {
|
||||
search.fields.forEach((item) => {
|
||||
search.fields.forEach(item => {
|
||||
if (!searchModel.hasOwnProperty(item.name)) {
|
||||
return;
|
||||
}
|
||||
if (!!item.transform) {
|
||||
if (item.transform) {
|
||||
searchModel[item.name] = item.transform(searchModel[item.name]);
|
||||
}
|
||||
if (
|
||||
(item.type === "daterange" || item.type === "datetimerange") &&
|
||||
(item.type === 'daterange' || item.type === 'datetimerange') &&
|
||||
!!item.trueNames
|
||||
) {
|
||||
delete searchModel[item.name];
|
||||
@ -373,7 +371,7 @@ export default defineComponent({
|
||||
},
|
||||
// 重置函数
|
||||
handleReset() {
|
||||
if (JSON.stringify(state.searchModel) === "{}") {
|
||||
if (JSON.stringify(state.searchModel) === '{}') {
|
||||
return;
|
||||
}
|
||||
state.pageNum = 1;
|
||||
@ -386,52 +384,52 @@ export default defineComponent({
|
||||
},
|
||||
|
||||
// 当前页变化
|
||||
handleCurrentChange(page) {
|
||||
handleCurrentChange() {
|
||||
getTableData();
|
||||
},
|
||||
// 改变每页size数量
|
||||
handleSizeChange(value) {
|
||||
handleSizeChange() {
|
||||
state.pageNum = 1;
|
||||
getTableData();
|
||||
},
|
||||
// 全选
|
||||
handleSelectionChange(arr) {
|
||||
emit("selectionChange", arr);
|
||||
emit('selectionChange', arr);
|
||||
},
|
||||
// 过滤方法
|
||||
filterHandler(value, row, column) {
|
||||
const property = column["property"];
|
||||
const property = column['property'];
|
||||
return row[property] === value;
|
||||
},
|
||||
// 日期范围
|
||||
handleDateChange(date, item, format) {
|
||||
state.searchModel[item.name] = !!date ? formatDate(date, format) : "";
|
||||
state.searchModel[item.name] = date ? formatDate(date, format) : '';
|
||||
},
|
||||
handleRangeChange(date, item, format) {
|
||||
const arr = !!date && date.map((d) => formatDate(d, format));
|
||||
state.searchModel[item.name] = !!arr ? arr : [];
|
||||
const arr = !!date && date.map(d => formatDate(d, format));
|
||||
state.searchModel[item.name] = arr ? arr : [];
|
||||
|
||||
if (!item.trueNames) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!!arr) {
|
||||
if (arr) {
|
||||
arr.forEach((val, index) => {
|
||||
state.searchModel[item.trueNames[index]] = val;
|
||||
});
|
||||
} else {
|
||||
item.trueNames.forEach((key) => {
|
||||
item.trueNames.forEach(key => {
|
||||
delete state.searchModel[key];
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
if (typeof props.pagination === "object") {
|
||||
if (typeof props.pagination === 'object') {
|
||||
const { layout, pageSizes, style } = props.pagination;
|
||||
state.paginationConfig = {
|
||||
show: true,
|
||||
layout: layout || "total, sizes, prev, pager, next, jumper",
|
||||
layout: layout || 'total, sizes, prev, pager, next, jumper',
|
||||
pageSizes: pageSizes || [10, 20, 30, 40, 50, 100],
|
||||
style: style || {},
|
||||
};
|
||||
@ -491,4 +489,3 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@ -1,21 +1,18 @@
|
||||
<template>
|
||||
<svg
|
||||
class="icon"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<svg class="icon" aria-hidden="true">
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed } from "vue";
|
||||
import { defineComponent, computed } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: "SvgIcon",
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
prefix: {
|
||||
type: String,
|
||||
default: "icon",
|
||||
default: 'icon',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
@ -37,4 +34,4 @@ export default defineComponent({
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
export { default as SvgIcon } from "@/components/SvgIcon/index.vue";
|
||||
export { default as ProTable } from "@/components/ProTable/index.vue";
|
||||
export { default as SvgIcon } from '@/components/SvgIcon/index.vue';
|
||||
export { default as ProTable } from '@/components/ProTable/index.vue';
|
||||
|
||||
@ -6,9 +6,9 @@
|
||||
</router-view>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useStore } from "vuex";
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
<template>
|
||||
<i
|
||||
v-if="isElementIcon"
|
||||
:class="`icon ${icon}`"
|
||||
/>
|
||||
<svg-icon
|
||||
class="icon"
|
||||
v-else-if="!!icon"
|
||||
:name="icon"
|
||||
/>
|
||||
<span>{{title}}</span>
|
||||
<i v-if="isElementIcon" :class="`icon ${icon}`" />
|
||||
<svg-icon class="icon" v-else-if="!!icon" :name="icon" />
|
||||
<span>{{ title }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { computed, defineComponent } from "vue";
|
||||
import { computed, defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: ["title", "icon"],
|
||||
props: ['title', 'icon'],
|
||||
setup({ icon }) {
|
||||
const isElementIcon = computed(() => icon && icon.startsWith("el-icon"));
|
||||
const isElementIcon = computed(() => icon && icon.startsWith('el-icon'));
|
||||
|
||||
return {
|
||||
isElementIcon,
|
||||
@ -34,4 +27,4 @@ export default defineComponent({
|
||||
text-align: center;
|
||||
color: currentColor;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,22 +1,18 @@
|
||||
<template>
|
||||
<div class="brand">
|
||||
<img
|
||||
class="logo"
|
||||
src="~@/assets/logo.svg"
|
||||
@click="goHome"
|
||||
>
|
||||
<img class="logo" src="~@/assets/logo.svg" @click="goHome" />
|
||||
<div class="title">Vue3 Element Admin</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { defineComponent } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const router = useRouter();
|
||||
const goHome = () => {
|
||||
router.push("/");
|
||||
router.push('/');
|
||||
};
|
||||
return { goHome };
|
||||
},
|
||||
@ -44,4 +40,3 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@ -15,11 +15,11 @@
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from "vue";
|
||||
import Submenu from "./Submenu.vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRoute } from "vue-router";
|
||||
import config from "./config/menu.module.scss";
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import Submenu from './Submenu.vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRoute } from 'vue-router';
|
||||
import config from './config/menu.module.scss';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -35,7 +35,7 @@ export default defineComponent({
|
||||
const route = useRoute();
|
||||
const store = useStore();
|
||||
store.dispatch(
|
||||
"menu/generateMenus",
|
||||
'menu/generateMenus',
|
||||
store.state.account.userinfo && store.state.account.userinfo.role
|
||||
);
|
||||
|
||||
@ -80,7 +80,7 @@ export default defineComponent({
|
||||
background-color: $collapseMenuActiveBg !important;
|
||||
color: $collapseMenuActiveColor !important;
|
||||
&::before {
|
||||
content: "";
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@ -104,4 +104,4 @@ export default defineComponent({
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,23 +1,10 @@
|
||||
<template>
|
||||
<el-menu-item
|
||||
v-if="!menu.children"
|
||||
:index="menu.url"
|
||||
>
|
||||
<item
|
||||
:icon="menu.icon"
|
||||
:title="menu.title"
|
||||
/>
|
||||
<el-menu-item v-if="!menu.children" :index="menu.url">
|
||||
<item :icon="menu.icon" :title="menu.title" />
|
||||
</el-menu-item>
|
||||
<el-submenu
|
||||
v-else
|
||||
:index="menu.url"
|
||||
>
|
||||
<el-submenu v-else :index="menu.url">
|
||||
<template #title>
|
||||
<item
|
||||
:icon="menu.icon"
|
||||
:title="menu.title"
|
||||
/>
|
||||
|
||||
<item :icon="menu.icon" :title="menu.title" />
|
||||
</template>
|
||||
<submenu
|
||||
v-for="submenu in menu.children"
|
||||
@ -28,10 +15,10 @@
|
||||
</el-submenu>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import Item from "./Item.vue";
|
||||
import { defineComponent } from 'vue';
|
||||
import Item from './Item.vue';
|
||||
export default defineComponent({
|
||||
name: "Submenu",
|
||||
name: 'Submenu',
|
||||
components: {
|
||||
Item,
|
||||
},
|
||||
@ -46,4 +33,4 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
||||
@ -10,10 +10,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, computed } from "vue";
|
||||
import Logo from "./Logo.vue";
|
||||
import Menus from "./Menus.vue";
|
||||
import { useStore } from "vuex";
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import Logo from './Logo.vue';
|
||||
import Menus from './Menus.vue';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -26,7 +26,7 @@ export default defineComponent({
|
||||
const device = computed(() => store.state.app.device);
|
||||
|
||||
const closeSidebar = () => {
|
||||
store.commit("app/setCollapse", 1);
|
||||
store.commit('app/setCollapse', 1);
|
||||
};
|
||||
|
||||
return {
|
||||
@ -75,4 +75,4 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,98 +1,102 @@
|
||||
import { onMounted, onBeforeUnmount, reactive, toRefs, nextTick } from 'vue';
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex'
|
||||
import { isAffix } from './useTags'
|
||||
import { useStore } from 'vuex';
|
||||
import { isAffix } from './useTags';
|
||||
|
||||
export const useContextMenu = (tagList) => {
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
export const useContextMenu = tagList => {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
|
||||
const state = reactive({
|
||||
visible: false,
|
||||
top: 0,
|
||||
left: 0,
|
||||
selectedTag: {},
|
||||
openMenu (tag, e) {
|
||||
openMenu(tag, e) {
|
||||
state.visible = true;
|
||||
state.left = e.clientX;
|
||||
state.top = e.clientY;
|
||||
state.selectedTag = tag;
|
||||
},
|
||||
closeMenu () {
|
||||
closeMenu() {
|
||||
state.visible = false;
|
||||
},
|
||||
refreshSelectedTag (tag) {
|
||||
store.dispatch("tags/delCacheList", tag)
|
||||
refreshSelectedTag(tag) {
|
||||
store.dispatch('tags/delCacheList', tag);
|
||||
const { fullPath } = tag;
|
||||
nextTick(() => {
|
||||
router.replace({
|
||||
path: "/redirect" + fullPath,
|
||||
path: '/redirect' + fullPath,
|
||||
});
|
||||
});
|
||||
},
|
||||
closeTag (tag) {
|
||||
closeTag(tag) {
|
||||
if (isAffix(tag)) return;
|
||||
|
||||
const closedTagIndex = tagList.value.findIndex(
|
||||
(item) => item.fullPath === tag.fullPath
|
||||
item => item.fullPath === tag.fullPath
|
||||
);
|
||||
store.dispatch("tags/delTag", tag)
|
||||
store.dispatch('tags/delTag', tag);
|
||||
if (isActive(tag)) {
|
||||
toLastTag(closedTagIndex - 1);
|
||||
}
|
||||
},
|
||||
closeOtherTags () {
|
||||
store.dispatch("tags/delOtherTags", state.selectedTag)
|
||||
closeOtherTags() {
|
||||
store.dispatch('tags/delOtherTags', state.selectedTag);
|
||||
router.push(state.selectedTag);
|
||||
},
|
||||
closeLeftTags () {
|
||||
state.closeSomeTags('left')
|
||||
|
||||
closeLeftTags() {
|
||||
state.closeSomeTags('left');
|
||||
},
|
||||
closeRightTags () {
|
||||
state.closeSomeTags('right')
|
||||
|
||||
closeRightTags() {
|
||||
state.closeSomeTags('right');
|
||||
},
|
||||
closeSomeTags (direction) {
|
||||
closeSomeTags(direction) {
|
||||
const index = tagList.value.findIndex(
|
||||
(item) => item.fullPath === state.selectedTag.fullPath
|
||||
item => item.fullPath === state.selectedTag.fullPath
|
||||
);
|
||||
|
||||
if ((direction === 'left' && index <= 0) || (direction === 'right' && index >= tagList.value.length - 1)) {
|
||||
if (
|
||||
(direction === 'left' && index <= 0) ||
|
||||
(direction === 'right' && index >= tagList.value.length - 1)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const needToClose = direction === 'left' ? tagList.value.slice(0, index) : tagList.value.slice(index + 1)
|
||||
store.dispatch("tags/delSomeTags", needToClose)
|
||||
const needToClose =
|
||||
direction === 'left'
|
||||
? tagList.value.slice(0, index)
|
||||
: tagList.value.slice(index + 1);
|
||||
store.dispatch('tags/delSomeTags', needToClose);
|
||||
router.push(state.selectedTag);
|
||||
},
|
||||
closeAllTags () {
|
||||
store.dispatch("tags/delAllTags")
|
||||
router.push("/");
|
||||
}
|
||||
})
|
||||
closeAllTags() {
|
||||
store.dispatch('tags/delAllTags');
|
||||
router.push('/');
|
||||
},
|
||||
});
|
||||
|
||||
const isActive = (tag) => {
|
||||
const isActive = tag => {
|
||||
return tag.fullPath === route.fullPath;
|
||||
}
|
||||
};
|
||||
|
||||
const toLastTag = (lastTagIndex) => {
|
||||
const toLastTag = lastTagIndex => {
|
||||
const lastTag = tagList.value[lastTagIndex];
|
||||
if (!!lastTag) {
|
||||
if (lastTag) {
|
||||
router.push(lastTag.fullPath);
|
||||
} else {
|
||||
router.push("/");
|
||||
router.push('/');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
document.addEventListener("click", state.closeMenu);
|
||||
document.addEventListener('click', state.closeMenu);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.removeEventListener("click", state.closeMenu);
|
||||
document.removeEventListener('click', state.closeMenu);
|
||||
});
|
||||
|
||||
return toRefs(state)
|
||||
}
|
||||
return toRefs(state);
|
||||
};
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
import { ref } from 'vue'
|
||||
import { ref } from 'vue';
|
||||
|
||||
export const useScrollbar = (tagsItem) => {
|
||||
export const useScrollbar = tagsItem => {
|
||||
const scrollContainer = ref(null);
|
||||
|
||||
const handleScroll = (e) => {
|
||||
const handleScroll = e => {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY;
|
||||
scrollContainer.value.wrap.scrollLeft -= eventDelta / 4;
|
||||
};
|
||||
|
||||
|
||||
const moveToTarget = (currentTag) => {
|
||||
const moveToTarget = currentTag => {
|
||||
const containerWidth = scrollContainer.value.scrollbar.offsetWidth;
|
||||
const scrollWrapper = scrollContainer.value.wrap;
|
||||
const tagList = tagsItem.value;
|
||||
@ -26,8 +25,11 @@ export const useScrollbar = (tagsItem) => {
|
||||
} else if (lastTag === currentTag) {
|
||||
scrollWrapper.scrollLeft = scrollWrapper.scrollWidth - containerWidth;
|
||||
} else {
|
||||
const el = currentTag.$el.nextElementSibling
|
||||
scrollWrapper.scrollLeft = el.offsetLeft + el.offsetWidth > containerWidth ? el.offsetLeft - el.offsetWidth : 0
|
||||
const el = currentTag.$el.nextElementSibling;
|
||||
scrollWrapper.scrollLeft =
|
||||
el.offsetLeft + el.offsetWidth > containerWidth
|
||||
? el.offsetLeft - el.offsetWidth
|
||||
: 0;
|
||||
}
|
||||
};
|
||||
|
||||
@ -36,4 +38,4 @@ export const useScrollbar = (tagsItem) => {
|
||||
handleScroll,
|
||||
moveToTarget,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,69 +1,71 @@
|
||||
import { useScrollbar } from "./useScrollbar";
|
||||
import { useScrollbar } from './useScrollbar';
|
||||
import { watch, computed, ref, nextTick, onBeforeMount } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex'
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export const isAffix = (tag) => {
|
||||
export const isAffix = tag => {
|
||||
return !!tag.meta && !!tag.meta.affix;
|
||||
};
|
||||
|
||||
export const useTags = () => {
|
||||
const store = useStore()
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const route = router.currentRoute;
|
||||
const routes = computed(() => router.getRoutes());
|
||||
const tagList = computed(() => store.state.tags.tagList);
|
||||
|
||||
const tagsItem = ref([])
|
||||
const tagsItem = ref([]);
|
||||
|
||||
const setItemRef = (i, el) => {
|
||||
tagsItem.value[i] = el
|
||||
}
|
||||
tagsItem.value[i] = el;
|
||||
};
|
||||
|
||||
const scrollbar = useScrollbar(tagsItem);
|
||||
|
||||
watch(() => tagList.value.length, () => {
|
||||
tagsItem.value = []
|
||||
})
|
||||
watch(
|
||||
() => tagList.value.length,
|
||||
() => {
|
||||
tagsItem.value = [];
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
const filterAffixTags = (routes) => {
|
||||
return routes.filter((route) => isAffix(route));
|
||||
const filterAffixTags = routes => {
|
||||
return routes.filter(route => isAffix(route));
|
||||
};
|
||||
|
||||
const initTags = () => {
|
||||
const affixTags = filterAffixTags(routes.value);
|
||||
|
||||
for (const tag of affixTags) {
|
||||
if (!!tag.name) {
|
||||
store.dispatch("tags/addTagList", tag);
|
||||
if (tag.name) {
|
||||
store.dispatch('tags/addTagList', tag);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const addTag = () => {
|
||||
const tag = route.value;
|
||||
if (!!tag.name && tag.matched[0].components.default.name === "layout") {
|
||||
store.dispatch("tags/addTag", tag);
|
||||
if (!!tag.name && tag.matched[0].components.default.name === 'layout') {
|
||||
store.dispatch('tags/addTag', tag);
|
||||
}
|
||||
};
|
||||
|
||||
const saveActivePosition = (tag) => {
|
||||
const saveActivePosition = tag => {
|
||||
const index = tagList.value.findIndex(
|
||||
(item) => item.fullPath === tag.fullPath
|
||||
item => item.fullPath === tag.fullPath
|
||||
);
|
||||
|
||||
store.dispatch("tags/saveActivePosition", Math.max(0, index));
|
||||
store.dispatch('tags/saveActivePosition', Math.max(0, index));
|
||||
};
|
||||
|
||||
const moveToCurrentTag = () => {
|
||||
nextTick(() => {
|
||||
for (const tag of tagsItem.value) {
|
||||
if (!!tag && (tag.to.path === route.value.path)) {
|
||||
if (!!tag && tag.to.path === route.value.path) {
|
||||
scrollbar.moveToTarget(tag);
|
||||
|
||||
if (tag.to.fullPath !== route.value.fullPath) {
|
||||
store.dispatch("tags/updateTagList", route.value);
|
||||
store.dispatch('tags/updateTagList', route.value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -71,8 +73,6 @@ export const useTags = () => {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
onBeforeMount(() => {
|
||||
initTags();
|
||||
addTag();
|
||||
@ -89,6 +89,6 @@ export const useTags = () => {
|
||||
tagList,
|
||||
setItemRef,
|
||||
isAffix,
|
||||
...scrollbar
|
||||
}
|
||||
}
|
||||
...scrollbar,
|
||||
};
|
||||
};
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
v-for="(tag, i) in tagList"
|
||||
:key="tag.fullPath"
|
||||
:to="tag"
|
||||
:ref="(el) => setItemRef(i, el)"
|
||||
:ref="el => setItemRef(i, el)"
|
||||
custom
|
||||
v-slot="{ navigate, isExactActive }"
|
||||
>
|
||||
@ -46,17 +46,17 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { useTags } from "./hooks/useTags";
|
||||
import { useContextMenu } from "./hooks/useContextMenu";
|
||||
import { defineComponent } from 'vue';
|
||||
import { useTags } from './hooks/useTags';
|
||||
import { useContextMenu } from './hooks/useContextMenu';
|
||||
|
||||
export default defineComponent({
|
||||
name: "Tagsbar",
|
||||
name: 'Tagsbar',
|
||||
setup() {
|
||||
const tags = useTags();
|
||||
const contextMenu = useContextMenu(tags.tagList);
|
||||
|
||||
const onScroll = (e) => {
|
||||
const onScroll = e => {
|
||||
tags.handleScroll(e);
|
||||
contextMenu.closeMenu.value();
|
||||
};
|
||||
|
||||
@ -15,9 +15,9 @@
|
||||
</el-breadcrumb>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed, ref, onBeforeMount, watch } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useStore } from "vuex";
|
||||
import { defineComponent, computed, ref, onBeforeMount, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
@ -27,13 +27,13 @@ export default defineComponent({
|
||||
const route = router.currentRoute; // 这里不使用useRoute获取当前路由,否则下面watch监听路由的时候会有警告
|
||||
const breadcrumbs = ref([]);
|
||||
|
||||
const getBreadcrumbs = (route) => {
|
||||
const home = [{ path: "/", meta: { title: "首页" } }];
|
||||
if (route.name === "home") {
|
||||
const getBreadcrumbs = route => {
|
||||
const home = [{ path: '/', meta: { title: '首页' } }];
|
||||
if (route.name === 'home') {
|
||||
return home;
|
||||
} else {
|
||||
const matched = route.matched.filter(
|
||||
(item) => !!item.meta && !!item.meta.title
|
||||
item => !!item.meta && !!item.meta.title
|
||||
);
|
||||
|
||||
return [...home, ...matched];
|
||||
@ -44,7 +44,7 @@ export default defineComponent({
|
||||
breadcrumbs.value = getBreadcrumbs(route.value);
|
||||
});
|
||||
|
||||
watch(route, (newRoute) => {
|
||||
watch(route, newRoute => {
|
||||
breadcrumbs.value = getBreadcrumbs(newRoute);
|
||||
});
|
||||
|
||||
@ -78,4 +78,4 @@ export default defineComponent({
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -6,15 +6,15 @@
|
||||
></i>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const collapse = computed(() => !!store.state.app.sidebar.collapse);
|
||||
const handleToggleMenu = () => {
|
||||
store.commit("app/setCollapse", +!collapse.value);
|
||||
store.commit('app/setCollapse', +!collapse.value);
|
||||
};
|
||||
return {
|
||||
collapse,
|
||||
@ -36,4 +36,4 @@ export default defineComponent({
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -21,19 +21,19 @@
|
||||
</el-dropdown>
|
||||
</template>
|
||||
<script>
|
||||
import { computed, defineComponent } from "vue";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter } from "vue-router";
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter } from 'vue-router';
|
||||
export default defineComponent({
|
||||
setup() {
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const userinfo = computed(() => store.state.account.userinfo);
|
||||
const logout = () => {
|
||||
store.commit("app/clearToken");
|
||||
store.commit("account/clearUserinfo");
|
||||
store.dispatch("tags/delAllTags");
|
||||
router.push("/login");
|
||||
store.commit('app/clearToken');
|
||||
store.commit('account/clearUserinfo');
|
||||
store.dispatch('tags/delAllTags');
|
||||
router.push('/login');
|
||||
};
|
||||
return {
|
||||
userinfo,
|
||||
@ -64,4 +64,4 @@ export default defineComponent({
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -11,12 +11,12 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, computed } from "vue";
|
||||
import Logo from "@/layout/components/Sidebar/Logo.vue";
|
||||
import Hamburger from "./Hamburger.vue";
|
||||
import Breadcrumbs from "./Breadcrumbs.vue";
|
||||
import Userinfo from "./Userinfo.vue";
|
||||
import { useStore } from "vuex";
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import Logo from '@/layout/components/Sidebar/Logo.vue';
|
||||
import Hamburger from './Hamburger.vue';
|
||||
import Breadcrumbs from './Breadcrumbs.vue';
|
||||
import Userinfo from './Userinfo.vue';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -57,4 +57,4 @@ export default defineComponent({
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,38 +1,38 @@
|
||||
import { onBeforeMount, onBeforeUnmount, watch } from "vue"
|
||||
import { useRouter } from "vue-router"
|
||||
import { useStore } from "vuex"
|
||||
import { onBeforeMount, onBeforeUnmount /*watch*/ } from 'vue';
|
||||
// import { useRouter } from 'vue-router';
|
||||
import { useStore } from 'vuex';
|
||||
|
||||
const WIDTH = 768
|
||||
const WIDTH = 768;
|
||||
export const useResizeHandler = () => {
|
||||
const store = useStore()
|
||||
const router = useRouter()
|
||||
const route = router.currentRoute
|
||||
const store = useStore();
|
||||
// const router = useRouter();
|
||||
// const route = router.currentRoute;
|
||||
|
||||
const isMobile = () => {
|
||||
return window.innerWidth < WIDTH
|
||||
}
|
||||
return window.innerWidth < WIDTH;
|
||||
};
|
||||
|
||||
const resizeHandler = () => {
|
||||
if (isMobile()) {
|
||||
store.commit('app/setDevice', 'mobile')
|
||||
store.commit('app/setCollapse', 1)
|
||||
store.commit('app/setDevice', 'mobile');
|
||||
store.commit('app/setCollapse', 1);
|
||||
} else {
|
||||
store.commit('app/setDevice', 'desktop')
|
||||
store.commit('app/setCollapse', 0)
|
||||
store.commit('app/setDevice', 'desktop');
|
||||
store.commit('app/setCollapse', 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (isMobile()) {
|
||||
store.commit('app/setDevice', 'mobile')
|
||||
store.commit('app/setCollapse', 1)
|
||||
store.commit('app/setDevice', 'mobile');
|
||||
store.commit('app/setCollapse', 1);
|
||||
}
|
||||
window.addEventListener('resize', resizeHandler)
|
||||
})
|
||||
window.addEventListener('resize', resizeHandler);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', resizeHandler)
|
||||
})
|
||||
window.removeEventListener('resize', resizeHandler);
|
||||
});
|
||||
|
||||
// // 监听路由的时候不能使用useRoute获取路由,否则会有警告
|
||||
// watch(route, () => {
|
||||
@ -40,7 +40,4 @@ export const useResizeHandler = () => {
|
||||
// store.commit('app/setCollapse', 1)
|
||||
// }
|
||||
// })
|
||||
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
@ -7,21 +7,21 @@
|
||||
<tagsbar />
|
||||
</div>
|
||||
<div class="main">
|
||||
<content />
|
||||
<Content />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import Sidebar from "./components/Sidebar/index.vue";
|
||||
import Topbar from "./components/Topbar/index.vue";
|
||||
import Tagsbar from "./components/Tagsbar/index.vue";
|
||||
import Content from "./components/Content/index.vue";
|
||||
import { useResizeHandler } from "./hooks/useResizeHandler";
|
||||
import { defineComponent } from 'vue';
|
||||
import Sidebar from './components/Sidebar/index.vue';
|
||||
import Topbar from './components/Topbar/index.vue';
|
||||
import Tagsbar from './components/Tagsbar/index.vue';
|
||||
import Content from './components/Content/index.vue';
|
||||
import { useResizeHandler } from './hooks/useResizeHandler';
|
||||
|
||||
export default defineComponent({
|
||||
name: "layout",
|
||||
name: 'layout',
|
||||
components: {
|
||||
Sidebar,
|
||||
Topbar,
|
||||
@ -55,4 +55,4 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
24
src/main.js
24
src/main.js
@ -1,29 +1,29 @@
|
||||
import { createApp } from "vue";
|
||||
import App from "./App.vue";
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
// 引入element-plus
|
||||
import ElementPlus from "element-plus";
|
||||
import "./assets/style/element-variables.scss";
|
||||
import ElementPlus from 'element-plus';
|
||||
import './assets/style/element-variables.scss';
|
||||
// 引入中文语言包
|
||||
import "dayjs/locale/zh-cn";
|
||||
import locale from "element-plus/lib/locale/lang/zh-cn";
|
||||
import 'dayjs/locale/zh-cn';
|
||||
import locale from 'element-plus/lib/locale/lang/zh-cn';
|
||||
|
||||
// 引入路由
|
||||
import router from "./router";
|
||||
import router from './router';
|
||||
|
||||
// 引入store
|
||||
import store from "./store";
|
||||
import store from './store';
|
||||
|
||||
// 权限控制
|
||||
import "./permission";
|
||||
import './permission';
|
||||
|
||||
// 引入svg图标注册脚本
|
||||
import "vite-plugin-svg-icons/register";
|
||||
import 'vite-plugin-svg-icons/register';
|
||||
|
||||
// 注册全局组件
|
||||
import * as Components from "./global-components";
|
||||
import * as Components from './global-components';
|
||||
Object.entries(Components).forEach(([key, component]) => {
|
||||
app.component(key, component);
|
||||
});
|
||||
@ -32,4 +32,4 @@ app
|
||||
.use(ElementPlus, { locale })
|
||||
.use(store)
|
||||
.use(router)
|
||||
.mount("#app");
|
||||
.mount('#app');
|
||||
|
||||
@ -1,49 +1,50 @@
|
||||
import router from '@/router'
|
||||
import store from '@/store'
|
||||
import { TOKEN } from '@/store/modules/app' // TOKEN变量名
|
||||
import router from '@/router';
|
||||
import store from '@/store';
|
||||
import { TOKEN } from '@/store/modules/app'; // TOKEN变量名
|
||||
|
||||
const getPageTitle = title => {
|
||||
const appTitle = store.state.app.title;
|
||||
if (title) {
|
||||
return `${title} - ${appTitle}`
|
||||
return `${title} - ${appTitle}`;
|
||||
}
|
||||
return appTitle
|
||||
}
|
||||
return appTitle;
|
||||
};
|
||||
|
||||
// 白名单,里面是路由对象的name
|
||||
const WhiteList = ['login', 'forbidden', 'server-error', 'not-found']
|
||||
const WhiteList = ['login', 'forbidden', 'server-error', 'not-found'];
|
||||
|
||||
// vue-router4的路由守卫不再是通过next放行,而是通过return返回true或false或者一个路由地址
|
||||
router.beforeEach(async (to) => {
|
||||
|
||||
document.title = getPageTitle(!!to.meta && to.meta.title)
|
||||
router.beforeEach(async to => {
|
||||
document.title = getPageTitle(!!to.meta && to.meta.title);
|
||||
|
||||
if (WhiteList.includes(to.name)) {
|
||||
return true
|
||||
return true;
|
||||
}
|
||||
if (!window.localStorage[TOKEN]) {
|
||||
return {
|
||||
name: 'login',
|
||||
query: {
|
||||
redirect: to.path // redirect是指登录之后可以跳回到redirect指定的页面
|
||||
redirect: to.path, // redirect是指登录之后可以跳回到redirect指定的页面
|
||||
},
|
||||
replace: true
|
||||
}
|
||||
replace: true,
|
||||
};
|
||||
} else {
|
||||
let userinfo = store.state.account.userinfo
|
||||
let userinfo = store.state.account.userinfo;
|
||||
if (!userinfo) {
|
||||
try {
|
||||
// 获取用户信息
|
||||
userinfo = await store.dispatch("account/getUserinfo");
|
||||
userinfo = await store.dispatch('account/getUserinfo');
|
||||
} catch (err) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
// 如果没有权限,跳转到403页面
|
||||
if (!!to.meta && !!to.meta.roles && !to.meta.roles.includes(userinfo.role)) {
|
||||
return { path: '/403', replace: true }
|
||||
if (
|
||||
!!to.meta &&
|
||||
!!to.meta.roles &&
|
||||
!to.meta.roles.includes(userinfo.role)
|
||||
) {
|
||||
return { path: '/403', replace: true };
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
@ -1,18 +1,14 @@
|
||||
// index.js
|
||||
import { createRouter, createWebHashHistory } from "vue-router"
|
||||
|
||||
import redirect from './modules/redirect'
|
||||
import error from './modules/error'
|
||||
import login from './modules/login'
|
||||
import home from './modules/home'
|
||||
import test from './modules/test'
|
||||
import { createRouter, createWebHashHistory } from 'vue-router';
|
||||
|
||||
import redirect from './modules/redirect';
|
||||
import error from './modules/error';
|
||||
import login from './modules/login';
|
||||
import home from './modules/home';
|
||||
import test from './modules/test';
|
||||
|
||||
// 左侧菜单
|
||||
export const allMenus = [
|
||||
...home,
|
||||
...test,
|
||||
]
|
||||
export const allMenus = [...home, ...test];
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
@ -24,15 +20,15 @@ const router = createRouter({
|
||||
...redirect, // 统一的重定向配置
|
||||
...login,
|
||||
...allMenus,
|
||||
...error
|
||||
...error,
|
||||
],
|
||||
scrollBehavior (to, from, savedPosition) {
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (savedPosition) {
|
||||
return savedPosition
|
||||
return savedPosition;
|
||||
} else {
|
||||
return { left: 0, top: 0 }
|
||||
return { left: 0, top: 0 };
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
export default router;
|
||||
export default router;
|
||||
|
||||
@ -1,18 +1,15 @@
|
||||
import store from '@/store'
|
||||
import store from '@/store';
|
||||
|
||||
const checkUserinfo = (code) => {
|
||||
const userinfo = store.state.account.userinfo
|
||||
if (!!userinfo) {
|
||||
return `/error/${code}`
|
||||
const checkUserinfo = code => {
|
||||
const userinfo = store.state.account.userinfo;
|
||||
if (userinfo) {
|
||||
return `/error/${code}`;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Error = () => import("@/views/error/index.vue");
|
||||
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Error = () => import('@/views/error/index.vue');
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -25,8 +22,8 @@ export default [
|
||||
component: Error,
|
||||
meta: { title: '403' },
|
||||
props: {
|
||||
error: '403'
|
||||
}
|
||||
error: '403',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '500',
|
||||
@ -34,8 +31,8 @@ export default [
|
||||
component: Error,
|
||||
meta: { title: '500' },
|
||||
props: {
|
||||
error: '500'
|
||||
}
|
||||
error: '500',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '404',
|
||||
@ -43,42 +40,42 @@ export default [
|
||||
component: Error,
|
||||
meta: { title: '404' },
|
||||
props: {
|
||||
error: '404'
|
||||
}
|
||||
}
|
||||
]
|
||||
error: '404',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/403',
|
||||
name: 'forbidden',
|
||||
component: Error,
|
||||
props: {
|
||||
error: '403'
|
||||
error: '403',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('403');
|
||||
},
|
||||
beforeEnter () {
|
||||
return checkUserinfo('403')
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/500',
|
||||
name: 'server-error',
|
||||
component: Error,
|
||||
props: {
|
||||
error: '500'
|
||||
error: '500',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('500');
|
||||
},
|
||||
beforeEnter () {
|
||||
return checkUserinfo('500')
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)',
|
||||
name: 'not-found',
|
||||
component: Error,
|
||||
props: {
|
||||
error: '404'
|
||||
error: '404',
|
||||
},
|
||||
beforeEnter() {
|
||||
return checkUserinfo('404');
|
||||
},
|
||||
beforeEnter () {
|
||||
return checkUserinfo('404')
|
||||
}
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
@ -1,27 +1,26 @@
|
||||
// home.js
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Home = () => import("@/views/home/index.vue");
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Home = () => import('@/views/home/index.vue');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/home',
|
||||
component: Layout,
|
||||
name: "Dashboard",
|
||||
name: 'Dashboard',
|
||||
meta: {
|
||||
title: "Dashboard",
|
||||
title: 'Dashboard',
|
||||
},
|
||||
icon: 'home',
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "home",
|
||||
path: '',
|
||||
name: 'home',
|
||||
component: Home,
|
||||
meta: {
|
||||
title: "首页",
|
||||
affix: true
|
||||
}
|
||||
}
|
||||
]
|
||||
title: '首页',
|
||||
affix: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
// login.js
|
||||
const Login = () => import("@/views/login/index.vue");
|
||||
const Login = () => import('@/views/login/index.vue');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: "/login",
|
||||
name: "login",
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: Login,
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const Redirect = () => import("@/views/redirect/index.vue");
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const Redirect = () => import('@/views/redirect/index.vue');
|
||||
|
||||
export default [
|
||||
{
|
||||
@ -9,7 +9,7 @@ export default [
|
||||
{
|
||||
path: '',
|
||||
component: Redirect,
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,112 +1,112 @@
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
const List = () => import("@/views/test/index.vue");
|
||||
const Add = () => import("@/views/test/Add.vue");
|
||||
const Auth = () => import("@/views/test/Auth.vue");
|
||||
const NoAuth = () => import("@/views/test/NoAuth.vue");
|
||||
const Nest = () => import("@/views/test/Nest.vue");
|
||||
const NestPage1 = () => import("@/views/test/nest/Page1.vue");
|
||||
const NestPage2 = () => import("@/views/test/nest/Page2.vue");
|
||||
const Iscache = () => import("@/views/test/Cache.vue");
|
||||
const Nocache = () => import("@/views/test/Nocache.vue");
|
||||
const Layout = () => import('@/layout/index.vue');
|
||||
const List = () => import('@/views/test/index.vue');
|
||||
const Add = () => import('@/views/test/Add.vue');
|
||||
const Auth = () => import('@/views/test/Auth.vue');
|
||||
const NoAuth = () => import('@/views/test/NoAuth.vue');
|
||||
const Nest = () => import('@/views/test/Nest.vue');
|
||||
const NestPage1 = () => import('@/views/test/nest/Page1.vue');
|
||||
const NestPage2 = () => import('@/views/test/nest/Page2.vue');
|
||||
const Iscache = () => import('@/views/test/Cache.vue');
|
||||
const Nocache = () => import('@/views/test/Nocache.vue');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/test',
|
||||
component: Layout,
|
||||
name: "test",
|
||||
name: 'test',
|
||||
meta: {
|
||||
title: "测试页面",
|
||||
title: '测试页面',
|
||||
},
|
||||
icon: 'el-icon-location',
|
||||
roles: ["admin", "visitor"],
|
||||
roles: ['admin', 'visitor'],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
name: "testList",
|
||||
path: '',
|
||||
name: 'testList',
|
||||
component: List,
|
||||
meta: {
|
||||
title: "列表",
|
||||
roles: ["admin", "visitor"],
|
||||
title: '列表',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "add",
|
||||
name: "testAdd",
|
||||
path: 'add',
|
||||
name: 'testAdd',
|
||||
component: Add,
|
||||
meta: {
|
||||
title: "添加",
|
||||
roles: ["admin", "visitor"],
|
||||
title: '添加',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
hidden: true, // 不在菜单中显示
|
||||
},
|
||||
{
|
||||
path: "auth",
|
||||
name: "testAuth",
|
||||
path: 'auth',
|
||||
name: 'testAuth',
|
||||
component: Auth,
|
||||
meta: {
|
||||
title: "权限测试",
|
||||
roles: ["admin", "visitor"],
|
||||
}
|
||||
title: '权限测试',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "noauth",
|
||||
name: "testNoAuth",
|
||||
path: 'noauth',
|
||||
name: 'testNoAuth',
|
||||
component: NoAuth,
|
||||
meta: {
|
||||
title: "权限页面",
|
||||
roles: ["admin"],
|
||||
title: '权限页面',
|
||||
roles: ['admin'],
|
||||
},
|
||||
hidden: true
|
||||
hidden: true,
|
||||
},
|
||||
{
|
||||
path: "cache",
|
||||
name: "test-cache",
|
||||
path: 'cache',
|
||||
name: 'test-cache',
|
||||
component: Iscache,
|
||||
meta: {
|
||||
title: "该页面可缓存",
|
||||
roles: ["admin", "visitor"]
|
||||
}
|
||||
title: '该页面可缓存',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "nocache",
|
||||
name: "test-no-cache",
|
||||
path: 'nocache',
|
||||
name: 'test-no-cache',
|
||||
component: Nocache,
|
||||
meta: {
|
||||
title: "该页面不缓存",
|
||||
roles: ["admin", "visitor"],
|
||||
title: '该页面不缓存',
|
||||
roles: ['admin', 'visitor'],
|
||||
noCache: true, // 不缓存页面
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "nest",
|
||||
name: "nest",
|
||||
path: 'nest',
|
||||
name: 'nest',
|
||||
component: Nest,
|
||||
redirect: '/test/nest/page1',
|
||||
meta: {
|
||||
title: "二级菜单",
|
||||
roles: ["admin", "visitor"],
|
||||
title: '二级菜单',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: "page1",
|
||||
name: "nestPage1",
|
||||
path: 'page1',
|
||||
name: 'nestPage1',
|
||||
component: NestPage1,
|
||||
meta: {
|
||||
title: "page1",
|
||||
roles: ["admin", "visitor"],
|
||||
title: 'page1',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: "page2",
|
||||
name: "nestPage2",
|
||||
path: 'page2',
|
||||
name: 'nestPage2',
|
||||
component: NestPage2,
|
||||
meta: {
|
||||
title: "page2",
|
||||
roles: ["admin", "visitor"],
|
||||
title: 'page2',
|
||||
roles: ['admin', 'visitor'],
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
//index.js
|
||||
import { createStore } from "vuex";
|
||||
import app from "./modules/app";
|
||||
import account from "./modules/account";
|
||||
import menu from "./modules/menu";
|
||||
import tags from "./modules/tags";
|
||||
import { createStore } from 'vuex';
|
||||
import app from './modules/app';
|
||||
import account from './modules/account';
|
||||
import menu from './modules/menu';
|
||||
import tags from './modules/tags';
|
||||
|
||||
export default createStore({
|
||||
modules: {
|
||||
app,
|
||||
account,
|
||||
menu,
|
||||
tags
|
||||
tags,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,28 +1,28 @@
|
||||
import { GetUserinfo } from '@/api/login'
|
||||
import { GetUserinfo } from '@/api/login';
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
userinfo: null
|
||||
userinfo: null,
|
||||
},
|
||||
mutations: {
|
||||
// 保存用户信息
|
||||
setUserinfo (state, data) {
|
||||
setUserinfo(state, data) {
|
||||
state.userinfo = data;
|
||||
},
|
||||
// 清除用户信息
|
||||
clearUserinfo (state) {
|
||||
clearUserinfo(state) {
|
||||
state.userinfo = null;
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
// 获取用户信息
|
||||
async getUserinfo ({ commit }) {
|
||||
async getUserinfo({ commit }) {
|
||||
const { code, data } = await GetUserinfo();
|
||||
if (+code === 200) {
|
||||
commit("setUserinfo", data);
|
||||
return Promise.resolve(data)
|
||||
commit('setUserinfo', data);
|
||||
return Promise.resolve(data);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { getItem, setItem, removeItem } from "@/utils/storage"; //getItem和setItem是封装的操作localStorage的方法
|
||||
export const TOKEN = "VEA-TOKEN";
|
||||
const COLLAPSE = "VEA-COLLAPSE";
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage'; //getItem和setItem是封装的操作localStorage的方法
|
||||
export const TOKEN = 'VEA-TOKEN';
|
||||
const COLLAPSE = 'VEA-COLLAPSE';
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
@ -8,34 +8,34 @@ export default {
|
||||
title: 'Vue3 Element Admin',
|
||||
authorization: getItem(TOKEN),
|
||||
sidebar: {
|
||||
collapse: getItem(COLLAPSE)
|
||||
collapse: getItem(COLLAPSE),
|
||||
},
|
||||
device: 'desktop',
|
||||
},
|
||||
mutations: {
|
||||
setToken (state, data) {
|
||||
setToken(state, data) {
|
||||
state.authorization = data;
|
||||
// 保存到localStorage
|
||||
setItem(TOKEN, data);
|
||||
},
|
||||
clearToken (state) {
|
||||
clearToken(state) {
|
||||
state.authorization = '';
|
||||
|
||||
removeItem(TOKEN);
|
||||
},
|
||||
setCollapse (state, data) {
|
||||
setCollapse(state, data) {
|
||||
state.sidebar.collapse = data;
|
||||
// 保存到localStorage
|
||||
setItem(COLLAPSE, data);
|
||||
},
|
||||
clearCollapse (state) {
|
||||
clearCollapse(state) {
|
||||
state.sidebar.collapse = '';
|
||||
|
||||
removeItem(COLLAPSE);
|
||||
},
|
||||
setDevice (state, device) {
|
||||
state.device = device
|
||||
setDevice(state, device) {
|
||||
state.device = device;
|
||||
},
|
||||
},
|
||||
actions: {},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,16 +1,20 @@
|
||||
import { allMenus } from '@/router'
|
||||
import { GetMenus } from '@/api/menu'
|
||||
import { allMenus } from '@/router';
|
||||
// import { GetMenus } from '@/api/menu';
|
||||
|
||||
const hasPermission = (role, route) => {
|
||||
if (!!route.meta && !!route.meta.roles && !route.meta.roles.includes(role)) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const generateUrl = (path, parentPath) => {
|
||||
return path.startsWith('/') ? path : (!!path ? `${parentPath}/${path}` : parentPath)
|
||||
}
|
||||
return path.startsWith('/')
|
||||
? path
|
||||
: path
|
||||
? `${parentPath}/${path}`
|
||||
: parentPath;
|
||||
};
|
||||
|
||||
const getFilterMenus = (arr, role, parentPath = '') => {
|
||||
const menus = [];
|
||||
@ -21,43 +25,42 @@ const getFilterMenus = (arr, role, parentPath = '') => {
|
||||
url: generateUrl(item.path, parentPath),
|
||||
title: item.meta.title,
|
||||
icon: item.icon,
|
||||
}
|
||||
};
|
||||
if (item.children) {
|
||||
if (item.children.length === 1) {
|
||||
menu.url = generateUrl(item.children[0].path, menu.url)
|
||||
menu.url = generateUrl(item.children[0].path, menu.url);
|
||||
} else {
|
||||
menu.children = getFilterMenus(item.children, role, menu.url)
|
||||
menu.children = getFilterMenus(item.children, role, menu.url);
|
||||
}
|
||||
}
|
||||
menus.push(menu)
|
||||
menus.push(menu);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return menus
|
||||
}
|
||||
return menus;
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state: {
|
||||
menus: []
|
||||
menus: [],
|
||||
},
|
||||
mutations: {
|
||||
SET_MENUS (state, data) {
|
||||
SET_MENUS(state, data) {
|
||||
state.menus = data;
|
||||
}
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async generateMenus ({ commit }, role) {
|
||||
async generateMenus({ commit }, role) {
|
||||
// 方式一:根据角色生成菜单
|
||||
const menus = getFilterMenus(allMenus, role)
|
||||
commit('SET_MENUS', menus)
|
||||
const menus = getFilterMenus(allMenus, role);
|
||||
commit('SET_MENUS', menus);
|
||||
|
||||
// // 方式二:从后台获取菜单
|
||||
// const { code, data } = await GetMenus();
|
||||
// if (+code === 200) {
|
||||
// commit('SET_MENUS', data)
|
||||
// }
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { getItem, setItem, removeItem } from "@/utils/storage"; //getItem和setItem是封装的操作localStorage的方法
|
||||
import { getItem, setItem, removeItem } from '@/utils/storage'; //getItem和setItem是封装的操作localStorage的方法
|
||||
|
||||
const TAGLIST = 'VEA-TAGLIST'
|
||||
const TAGLIST = 'VEA-TAGLIST';
|
||||
|
||||
const state = {
|
||||
tagList: getItem(TAGLIST) || [],
|
||||
cacheList: [],
|
||||
activePosition: 0
|
||||
}
|
||||
activePosition: 0,
|
||||
};
|
||||
|
||||
const mutations = {
|
||||
ADD_TAG_LIST: (state, { path, fullPath, name, meta }) => {
|
||||
@ -15,138 +15,144 @@ const mutations = {
|
||||
state.tagList.splice(
|
||||
state.activePosition + 1,
|
||||
0,
|
||||
Object.assign({}, { path, fullPath, name, meta }, {
|
||||
title: meta.title || '未命名',
|
||||
fullPath: fullPath || path
|
||||
})
|
||||
)
|
||||
Object.assign(
|
||||
{},
|
||||
{ path, fullPath, name, meta },
|
||||
{
|
||||
title: meta.title || '未命名',
|
||||
fullPath: fullPath || path,
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
},
|
||||
ADD_CACHE_LIST: (state, tag) => {
|
||||
if (state.cacheList.includes(tag.name)) return
|
||||
if (state.cacheList.includes(tag.name)) return;
|
||||
if (!tag.meta.noCache) {
|
||||
state.cacheList.push(tag.name)
|
||||
state.cacheList.push(tag.name);
|
||||
}
|
||||
},
|
||||
|
||||
DEL_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(v => v.path !== tag.path)
|
||||
state.tagList = state.tagList.filter(v => v.path !== tag.path);
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
},
|
||||
DEL_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v !== tag.name)
|
||||
|
||||
state.cacheList = state.cacheList.filter(v => v !== tag.name);
|
||||
},
|
||||
|
||||
DEL_OTHER_TAG_LIST: (state, tag) => {
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix || v.path === tag.path)
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || v.path === tag.path
|
||||
);
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
},
|
||||
DEL_OTHER_CACHE_LIST: (state, tag) => {
|
||||
state.cacheList = state.cacheList.filter(v => v === tag.name)
|
||||
|
||||
state.cacheList = state.cacheList.filter(v => v === tag.name);
|
||||
},
|
||||
|
||||
DEL_SOME_TAG_LIST: (state, tags) => {
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix || tags.every(tag => tag.path !== v.path))
|
||||
state.tagList = state.tagList.filter(
|
||||
v => !!v.meta.affix || tags.every(tag => tag.path !== v.path)
|
||||
);
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
},
|
||||
|
||||
DEL_SOME_CACHE_LIST: (state, tags) => {
|
||||
state.cacheList = state.cacheList.filter(v => tags.every(tag => tag.name !== v))
|
||||
|
||||
state.cacheList = state.cacheList.filter(v =>
|
||||
tags.every(tag => tag.name !== v)
|
||||
);
|
||||
},
|
||||
|
||||
DEL_ALL_TAG_LIST: state => {
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix)
|
||||
state.tagList = state.tagList.filter(v => !!v.meta.affix);
|
||||
// 保存到localStorage
|
||||
removeItem(TAGLIST);
|
||||
},
|
||||
DEL_ALL_CACHE_LIST: state => {
|
||||
state.cacheList = []
|
||||
|
||||
state.cacheList = [];
|
||||
},
|
||||
|
||||
UPDATE_TAG_LIST: (state, tag) => {
|
||||
const index = state.tagList.findIndex(v => v.path === tag.path);
|
||||
if (index > -1) {
|
||||
state.tagList[index] = Object.assign({}, state.tagList[index], tag)
|
||||
state.tagList[index] = Object.assign({}, state.tagList[index], tag);
|
||||
// 保存到localStorage
|
||||
setItem(TAGLIST, state.tagList);
|
||||
}
|
||||
},
|
||||
|
||||
SAVE_ACTIVE_POSITION: (state, index) => {
|
||||
state.activePosition = index
|
||||
state.activePosition = index;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const actions = {
|
||||
saveActivePosition ({ commit }, index) {
|
||||
commit('SAVE_ACTIVE_POSITION', index)
|
||||
saveActivePosition({ commit }, index) {
|
||||
commit('SAVE_ACTIVE_POSITION', index);
|
||||
},
|
||||
addTag ({ dispatch }, tag) {
|
||||
dispatch('addTagList', tag)
|
||||
dispatch('addCacheList', tag)
|
||||
addTag({ dispatch }, tag) {
|
||||
dispatch('addTagList', tag);
|
||||
dispatch('addCacheList', tag);
|
||||
},
|
||||
addTagList ({ commit }, tag) {
|
||||
commit('ADD_TAG_LIST', tag)
|
||||
addTagList({ commit }, tag) {
|
||||
commit('ADD_TAG_LIST', tag);
|
||||
},
|
||||
addCacheList ({ commit }, tag) {
|
||||
commit('ADD_CACHE_LIST', tag)
|
||||
addCacheList({ commit }, tag) {
|
||||
commit('ADD_CACHE_LIST', tag);
|
||||
},
|
||||
|
||||
delTag ({ dispatch }, tag) {
|
||||
dispatch('delTagList', tag)
|
||||
dispatch('delCacheList', tag)
|
||||
delTag({ dispatch }, tag) {
|
||||
dispatch('delTagList', tag);
|
||||
dispatch('delCacheList', tag);
|
||||
},
|
||||
delTagList ({ commit }, tag) {
|
||||
commit('DEL_TAG_LIST', tag)
|
||||
delTagList({ commit }, tag) {
|
||||
commit('DEL_TAG_LIST', tag);
|
||||
},
|
||||
delCacheList ({ commit }, tag) {
|
||||
commit('DEL_CACHE_LIST', tag)
|
||||
delCacheList({ commit }, tag) {
|
||||
commit('DEL_CACHE_LIST', tag);
|
||||
},
|
||||
|
||||
delOtherTags ({ dispatch }, tag) {
|
||||
dispatch('delOtherTagList', tag)
|
||||
dispatch('delOtherCacheList', tag)
|
||||
delOtherTags({ dispatch }, tag) {
|
||||
dispatch('delOtherTagList', tag);
|
||||
dispatch('delOtherCacheList', tag);
|
||||
},
|
||||
delOtherTagList ({ commit }, tag) {
|
||||
commit('DEL_OTHER_TAG_LIST', tag)
|
||||
delOtherTagList({ commit }, tag) {
|
||||
commit('DEL_OTHER_TAG_LIST', tag);
|
||||
},
|
||||
delOtherCacheList ({ commit }, tag) {
|
||||
commit('DEL_OTHER_CACHE_LIST', tag)
|
||||
delOtherCacheList({ commit }, tag) {
|
||||
commit('DEL_OTHER_CACHE_LIST', tag);
|
||||
},
|
||||
|
||||
delSomeTags ({ commit }, tags) {
|
||||
commit('DEL_SOME_TAG_LIST', tags)
|
||||
commit('DEL_SOME_CACHE_LIST', tags)
|
||||
delSomeTags({ commit }, tags) {
|
||||
commit('DEL_SOME_TAG_LIST', tags);
|
||||
commit('DEL_SOME_CACHE_LIST', tags);
|
||||
},
|
||||
|
||||
delAllTags ({ dispatch }) {
|
||||
dispatch('delAllTagList')
|
||||
dispatch('delAllCacheList')
|
||||
delAllTags({ dispatch }) {
|
||||
dispatch('delAllTagList');
|
||||
dispatch('delAllCacheList');
|
||||
},
|
||||
delAllTagList ({ commit }) {
|
||||
commit('DEL_ALL_TAG_LIST')
|
||||
delAllTagList({ commit }) {
|
||||
commit('DEL_ALL_TAG_LIST');
|
||||
},
|
||||
delAllCacheList ({ commit }) {
|
||||
commit('DEL_ALL_CACHE_LIST')
|
||||
delAllCacheList({ commit }) {
|
||||
commit('DEL_ALL_CACHE_LIST');
|
||||
},
|
||||
|
||||
updateTagList ({ commit }, tag) {
|
||||
commit('UPDATE_TAG_LIST', tag)
|
||||
}
|
||||
}
|
||||
updateTagList({ commit }, tag) {
|
||||
commit('UPDATE_TAG_LIST', tag);
|
||||
},
|
||||
};
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions
|
||||
}
|
||||
actions,
|
||||
};
|
||||
|
||||
@ -1,24 +1,24 @@
|
||||
import axios from "axios";
|
||||
import { ElMessage } from "element-plus";
|
||||
import store from "@/store";
|
||||
import router from "@/router";
|
||||
import axios from 'axios';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import store from '@/store';
|
||||
import router from '@/router';
|
||||
|
||||
const service = axios.create({
|
||||
baseURL: "/",
|
||||
baseURL: '/',
|
||||
timeout: 10000,
|
||||
withCredentials: true,
|
||||
});
|
||||
|
||||
// 拦截请求
|
||||
service.interceptors.request.use(
|
||||
(config) => {
|
||||
config => {
|
||||
const { authorization } = store.state.app;
|
||||
if (authorization) {
|
||||
config.headers.Authorization = `Bearer ${authorization.token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
error => {
|
||||
// console.log(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
@ -27,18 +27,18 @@ service.interceptors.request.use(
|
||||
// 拦截响应
|
||||
service.interceptors.response.use(
|
||||
// 响应成功进入第1个函数,该函数的参数是响应对象
|
||||
(response) => {
|
||||
response => {
|
||||
return response.data;
|
||||
},
|
||||
// 响应失败进入第2个函数,该函数的参数是错误对象
|
||||
async (error) => {
|
||||
async error => {
|
||||
// 如果响应码是 401 ,则请求获取新的 token
|
||||
// 响应拦截器中的 error 就是那个响应的错误对象
|
||||
if (error.response && error.response.status === 401) {
|
||||
// 校验是否有 refresh_token
|
||||
const { authorization } = store.state.app;
|
||||
if (!authorization || !authorization.refresh_token) {
|
||||
router.push("/login");
|
||||
router.push('/login');
|
||||
|
||||
// 代码不要往后执行了
|
||||
return Promise.reject(error);
|
||||
@ -46,8 +46,8 @@ service.interceptors.response.use(
|
||||
// 如果有refresh_token,则请求获取新的 token
|
||||
try {
|
||||
const res = await axios({
|
||||
method: "PUT",
|
||||
url: "/api/authorizations",
|
||||
method: 'PUT',
|
||||
url: '/api/authorizations',
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
Authorization: `Bearer ${authorization.refresh_token}`,
|
||||
@ -55,7 +55,7 @@ service.interceptors.response.use(
|
||||
});
|
||||
// 如果获取成功,则把新的 token 更新到容器中
|
||||
// console.log('刷新 token 成功', res)
|
||||
store.commit("app/setToken", {
|
||||
store.commit('app/setToken', {
|
||||
token: res.data.data.token, // 最新获取的可用 token
|
||||
refresh_token: authorization.refresh_token, // 还是原来的 refresh_token
|
||||
});
|
||||
@ -66,9 +66,9 @@ service.interceptors.response.use(
|
||||
} catch (err) {
|
||||
// 如果获取失败,直接跳转 登录页
|
||||
// console.log('请求刷新 token 失败', err)
|
||||
router.push("/login");
|
||||
router.push('/login');
|
||||
// 清除token
|
||||
store.commit("app/clearToken")
|
||||
store.commit('app/clearToken');
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ export const getItem = name => {
|
||||
};
|
||||
|
||||
export const setItem = (name, value) => {
|
||||
if (typeof value === "object") {
|
||||
if (typeof value === 'object') {
|
||||
value = JSON.stringify(value);
|
||||
}
|
||||
|
||||
@ -17,4 +17,4 @@ export const setItem = (name, value) => {
|
||||
|
||||
export const removeItem = name => {
|
||||
window.localStorage.removeItem(name);
|
||||
};
|
||||
};
|
||||
|
||||
@ -21,14 +21,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
props: ["error"],
|
||||
props: ['error'],
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.error {
|
||||
position: relative;
|
||||
@ -52,4 +51,4 @@ export default defineComponent({
|
||||
margin: 32px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: "home",
|
||||
name: 'home',
|
||||
setup() {},
|
||||
});
|
||||
</script>
|
||||
@ -15,4 +15,4 @@ export default defineComponent({
|
||||
.home {
|
||||
color: $mainColor;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -43,12 +43,12 @@ import {
|
||||
toRefs,
|
||||
ref,
|
||||
computed,
|
||||
} from "vue";
|
||||
import { Login } from "@/api/login";
|
||||
import { useStore } from "vuex";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
} from 'vue';
|
||||
import { Login } from '@/api/login';
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
export default defineComponent({
|
||||
name: "login",
|
||||
name: 'login',
|
||||
setup() {
|
||||
const { ctx } = getCurrentInstance(); // 可以把ctx当成vue2中的this
|
||||
const store = useStore();
|
||||
@ -56,42 +56,42 @@ export default defineComponent({
|
||||
const route = useRoute();
|
||||
const state = reactive({
|
||||
model: {
|
||||
userName: "admin",
|
||||
password: "123456",
|
||||
userName: 'admin',
|
||||
password: '123456',
|
||||
},
|
||||
rules: {
|
||||
userName: [
|
||||
{ required: true, message: "请输入用户名", trigger: "blur" },
|
||||
{ required: true, message: '请输入用户名', trigger: 'blur' },
|
||||
],
|
||||
password: [
|
||||
{ required: true, message: "请输入密码", trigger: "blur" },
|
||||
{ required: true, message: '请输入密码', trigger: 'blur' },
|
||||
{
|
||||
min: 6,
|
||||
max: 12,
|
||||
message: "长度在 6 到 12 个字符",
|
||||
trigger: "blur",
|
||||
message: '长度在 6 到 12 个字符',
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
loading: false,
|
||||
btnText: computed(() => (state.loading ? "登录中..." : "登录")),
|
||||
btnText: computed(() => (state.loading ? '登录中...' : '登录')),
|
||||
loginForm: ref(null),
|
||||
submit: () => {
|
||||
if (state.loading) {
|
||||
return;
|
||||
}
|
||||
state.loginForm.validate(async (valid) => {
|
||||
state.loginForm.validate(async valid => {
|
||||
if (valid) {
|
||||
state.loading = true;
|
||||
const { code, data, message } = await Login(state.model);
|
||||
if (+code === 200) {
|
||||
ctx.$message.success({
|
||||
message: "登录成功",
|
||||
message: '登录成功',
|
||||
duration: 1000,
|
||||
});
|
||||
const targetPath = route.query.redirect;
|
||||
router.push(!!targetPath ? targetPath : "/");
|
||||
store.commit("app/setToken", data);
|
||||
router.push(targetPath ? targetPath : '/');
|
||||
store.commit('app/setToken', data);
|
||||
} else {
|
||||
ctx.$message.error(message);
|
||||
}
|
||||
@ -146,4 +146,4 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
<script>
|
||||
export default {
|
||||
created() {
|
||||
this.$router.replace(this.$route.fullPath.replace(/^\/redirect/, ""));
|
||||
this.$router.replace(this.$route.fullPath.replace(/^\/redirect/, ''));
|
||||
},
|
||||
render(h) {
|
||||
return h();
|
||||
},
|
||||
render() {},
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -4,4 +4,4 @@
|
||||
如果不需要在菜单中显示:<br />
|
||||
需要配置路由增加属性hidden: true,注意不是在meta中增加该属性,而是跟meta同级
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -6,4 +6,4 @@
|
||||
</h2>
|
||||
<h4><mark>刷新页面可切换随机角色</mark></h4>
|
||||
<router-link to="/test/noauth">点击进入只有admin才能访问的页面</router-link>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -6,14 +6,14 @@
|
||||
</dl>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent, onActivated } from "vue";
|
||||
import { defineComponent, onActivated } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: "test-cache", // 该name必须跟路由配置的name一致
|
||||
name: 'test-cache', // 该name必须跟路由配置的name一致
|
||||
setup() {
|
||||
console.log("cache");
|
||||
console.log('cache');
|
||||
onActivated(() => {
|
||||
console.log("onActivated");
|
||||
console.log('onActivated');
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@ -2,4 +2,4 @@
|
||||
<h1>二级菜单</h1>
|
||||
<h3>二级菜单的页面是不会缓存的</h3>
|
||||
<router-view />
|
||||
</template>
|
||||
</template>
|
||||
|
||||
@ -1 +1 @@
|
||||
<template>该页面只有admin能访问</template>
|
||||
<template>该页面只有admin能访问</template>
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
</dl>
|
||||
</template>
|
||||
<script>
|
||||
import { defineComponent } from "vue";
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: "test-no-cache", // 该name必须跟路由配置的name一致,不一致或者不设置name则不缓存
|
||||
name: 'test-no-cache', // 该name必须跟路由配置的name一致,不一致或者不设置name则不缓存
|
||||
setup() {
|
||||
console.log("nocache");
|
||||
console.log('nocache');
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -32,170 +32,170 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, reactive, ref, toRefs } from "vue";
|
||||
import { defineComponent, reactive, ref, toRefs } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: "testList",
|
||||
name: 'testList',
|
||||
setup() {
|
||||
const state = reactive({
|
||||
// 表格列配置,大部分属性跟el-table-column配置一样
|
||||
columns: [
|
||||
{ type: "selection" },
|
||||
{ label: "序号", type: "index" },
|
||||
{ label: "名称", prop: "nickName", sortable: true, width: 180 },
|
||||
{ label: "邮箱", prop: "userEmail" },
|
||||
{ type: 'selection' },
|
||||
{ label: '序号', type: 'index' },
|
||||
{ label: '名称', prop: 'nickName', sortable: true, width: 180 },
|
||||
{ label: '邮箱', prop: 'userEmail' },
|
||||
{
|
||||
label: "操作",
|
||||
fixed: "right",
|
||||
label: '操作',
|
||||
fixed: 'right',
|
||||
width: 180,
|
||||
align: "center",
|
||||
tdSlot: "operate", // 自定义单元格内容的插槽名称
|
||||
align: 'center',
|
||||
tdSlot: 'operate', // 自定义单元格内容的插槽名称
|
||||
},
|
||||
],
|
||||
// 搜索配置
|
||||
searchConfig: {
|
||||
labelWidth: "90px", // 必须带上单位
|
||||
inputWidth: "360px", // 必须带上单位
|
||||
labelWidth: '90px', // 必须带上单位
|
||||
inputWidth: '360px', // 必须带上单位
|
||||
fields: [
|
||||
{
|
||||
type: "text",
|
||||
label: "账户名称",
|
||||
name: "nickName",
|
||||
defaultValue: "abc",
|
||||
type: 'text',
|
||||
label: '账户名称',
|
||||
name: 'nickName',
|
||||
defaultValue: 'abc',
|
||||
},
|
||||
{
|
||||
type: "textarea",
|
||||
label: "描述",
|
||||
name: "description",
|
||||
type: 'textarea',
|
||||
label: '描述',
|
||||
name: 'description',
|
||||
},
|
||||
{
|
||||
label: "状态",
|
||||
name: "status",
|
||||
type: "select",
|
||||
label: '状态',
|
||||
name: 'status',
|
||||
type: 'select',
|
||||
defaultValue: 1,
|
||||
options: [
|
||||
{
|
||||
name: "已发布",
|
||||
name: '已发布',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: "未发布",
|
||||
name: '未发布',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "性别",
|
||||
name: "sex",
|
||||
type: "radio",
|
||||
label: '性别',
|
||||
name: 'sex',
|
||||
type: 'radio',
|
||||
options: [
|
||||
{
|
||||
name: "男",
|
||||
name: '男',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
name: "女",
|
||||
name: '女',
|
||||
value: 0,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "城市",
|
||||
name: "city",
|
||||
type: "radio-button",
|
||||
label: '城市',
|
||||
name: 'city',
|
||||
type: 'radio-button',
|
||||
options: [
|
||||
{
|
||||
name: "北京",
|
||||
value: "bj",
|
||||
name: '北京',
|
||||
value: 'bj',
|
||||
},
|
||||
{
|
||||
name: "上海",
|
||||
value: "sh",
|
||||
name: '上海',
|
||||
value: 'sh',
|
||||
},
|
||||
{
|
||||
name: "广州",
|
||||
value: "gz",
|
||||
name: '广州',
|
||||
value: 'gz',
|
||||
},
|
||||
{
|
||||
name: "深圳",
|
||||
value: "sz",
|
||||
name: '深圳',
|
||||
value: 'sz',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "爱好",
|
||||
name: "hobby",
|
||||
type: "checkbox",
|
||||
defaultValue: ["吃饭"],
|
||||
label: '爱好',
|
||||
name: 'hobby',
|
||||
type: 'checkbox',
|
||||
defaultValue: ['吃饭'],
|
||||
options: [
|
||||
{
|
||||
name: "吃饭",
|
||||
value: "吃饭",
|
||||
name: '吃饭',
|
||||
value: '吃饭',
|
||||
},
|
||||
{
|
||||
name: "睡觉",
|
||||
value: "睡觉",
|
||||
name: '睡觉',
|
||||
value: '睡觉',
|
||||
},
|
||||
{
|
||||
name: "打豆豆",
|
||||
value: "打豆豆",
|
||||
name: '打豆豆',
|
||||
value: '打豆豆',
|
||||
},
|
||||
],
|
||||
// transform: (val) => val.join(","),
|
||||
},
|
||||
{
|
||||
label: "水果",
|
||||
name: "fruit",
|
||||
type: "checkbox-button",
|
||||
label: '水果',
|
||||
name: 'fruit',
|
||||
type: 'checkbox-button',
|
||||
options: [
|
||||
{
|
||||
name: "苹果",
|
||||
value: "苹果",
|
||||
name: '苹果',
|
||||
value: '苹果',
|
||||
},
|
||||
{
|
||||
name: "香蕉",
|
||||
value: "香蕉",
|
||||
name: '香蕉',
|
||||
value: '香蕉',
|
||||
},
|
||||
{
|
||||
name: "橘子",
|
||||
value: "橘子",
|
||||
name: '橘子',
|
||||
value: '橘子',
|
||||
},
|
||||
{
|
||||
name: "葡萄",
|
||||
value: "葡萄",
|
||||
name: '葡萄',
|
||||
value: '葡萄',
|
||||
},
|
||||
],
|
||||
transform: (val) => val.join(","),
|
||||
transform: val => val.join(','),
|
||||
},
|
||||
{
|
||||
label: "日期",
|
||||
name: "date",
|
||||
type: "date",
|
||||
label: '日期',
|
||||
name: 'date',
|
||||
type: 'date',
|
||||
},
|
||||
{
|
||||
label: "时间",
|
||||
name: "datetime",
|
||||
type: "datetime",
|
||||
defaultValue: "2020-10-10 8:00:00",
|
||||
label: '时间',
|
||||
name: 'datetime',
|
||||
type: 'datetime',
|
||||
defaultValue: '2020-10-10 8:00:00',
|
||||
},
|
||||
{
|
||||
label: "日期范围",
|
||||
name: "daterange",
|
||||
type: "daterange",
|
||||
trueNames: ["startDate", "endDate"],
|
||||
label: '日期范围',
|
||||
name: 'daterange',
|
||||
type: 'daterange',
|
||||
trueNames: ['startDate', 'endDate'],
|
||||
},
|
||||
{
|
||||
label: "时间范围",
|
||||
name: "datetimerange",
|
||||
type: "datetimerange",
|
||||
trueNames: ["startTime", "endTime"],
|
||||
style: { width: "360px" },
|
||||
defaultValue: ["2020-10-10 9:00:00", "2020-10-11 18:30:00"],
|
||||
label: '时间范围',
|
||||
name: 'datetimerange',
|
||||
type: 'datetimerange',
|
||||
trueNames: ['startTime', 'endTime'],
|
||||
style: { width: '360px' },
|
||||
defaultValue: ['2020-10-10 9:00:00', '2020-10-11 18:30:00'],
|
||||
},
|
||||
{
|
||||
label: "数量",
|
||||
name: "num",
|
||||
type: "number",
|
||||
label: '数量',
|
||||
name: 'num',
|
||||
type: 'number',
|
||||
min: 0,
|
||||
max: 10,
|
||||
},
|
||||
@ -203,10 +203,10 @@ export default defineComponent({
|
||||
},
|
||||
// 分页配置
|
||||
paginationConfig: {
|
||||
layout: "total, prev, pager, next, sizes", // 分页组件显示哪些功能
|
||||
layout: 'total, prev, pager, next, sizes', // 分页组件显示哪些功能
|
||||
pageSize: 5, // 每页条数
|
||||
pageSizes: [5, 10, 20, 50],
|
||||
style: { textAlign: "left" },
|
||||
style: { textAlign: 'left' },
|
||||
},
|
||||
selectedItems: [],
|
||||
batchDelete() {
|
||||
@ -220,7 +220,7 @@ export default defineComponent({
|
||||
async getList(params) {
|
||||
console.log(params);
|
||||
// params是从组件接收的,包含分页和搜索字段。
|
||||
const { data } = await new Promise((rs) => {
|
||||
const { data } = await new Promise(rs => {
|
||||
setTimeout(() => {
|
||||
rs({
|
||||
code: 200,
|
||||
@ -228,13 +228,13 @@ export default defineComponent({
|
||||
list: [
|
||||
{
|
||||
id: 1,
|
||||
nickName: "zhangsan",
|
||||
userEmail: "zhangsan@xx.com",
|
||||
nickName: 'zhangsan',
|
||||
userEmail: 'zhangsan@xx.com',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
nickName: "lisi",
|
||||
userEmail: "lisi@xx.com",
|
||||
nickName: 'lisi',
|
||||
userEmail: 'lisi@xx.com',
|
||||
},
|
||||
],
|
||||
total: 100,
|
||||
|
||||
@ -1 +1 @@
|
||||
<template>Page2</template>
|
||||
<template>Page2</template>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import path from "path";
|
||||
import { viteMockServe } from "vite-plugin-mock";
|
||||
import viteSvgIcons from "vite-plugin-svg-icons";
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import path from 'path';
|
||||
import { viteMockServe } from 'vite-plugin-mock';
|
||||
import viteSvgIcons from 'vite-plugin-svg-icons';
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default env => {
|
||||
@ -13,11 +13,11 @@ export default env => {
|
||||
plugins: [
|
||||
vue(),
|
||||
viteMockServe({
|
||||
ignore: /^\_/, // 忽略以下划线`_`开头的文件
|
||||
mockPath: "mock", // 指定mock目录中的文件全部是mock接口
|
||||
ignore: /^_/, // 忽略以下划线`_`开头的文件
|
||||
mockPath: 'mock', // 指定mock目录中的文件全部是mock接口
|
||||
supportTs: false, // mockPath目录中的文件是否支持ts文件,现在我们不使用ts,所以设为false
|
||||
localEnabled: env.mode === "mock", // 开发环境是否开启mock功能(可以在package.json的启动命令中指定mode为mock)
|
||||
prodEnabled: env.mode === "mock", // 生产环境是否开启mock功能
|
||||
localEnabled: env.mode === 'mock', // 开发环境是否开启mock功能(可以在package.json的启动命令中指定mode为mock)
|
||||
prodEnabled: env.mode === 'mock', // 生产环境是否开启mock功能
|
||||
injectCode: `
|
||||
import { setupProdMockServer } from '../mock/_createProductionServer';
|
||||
setupProdMockServer();
|
||||
@ -25,9 +25,9 @@ export default env => {
|
||||
}),
|
||||
viteSvgIcons({
|
||||
// 指定需要缓存的图标文件夹
|
||||
iconDirs: [path.resolve(__dirname, "src/assets/svg")],
|
||||
iconDirs: [path.resolve(__dirname, 'src/assets/svg')],
|
||||
// 指定symbolId格式
|
||||
symbolId: "icon-[dir]-[name]",
|
||||
symbolId: 'icon-[dir]-[name]',
|
||||
}),
|
||||
],
|
||||
css: {
|
||||
@ -40,14 +40,14 @@ export default env => {
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "src"),
|
||||
'@': path.resolve(__dirname, 'src'),
|
||||
},
|
||||
},
|
||||
server: {
|
||||
open: true,
|
||||
proxy: {
|
||||
"/api": {
|
||||
target: "http://dev.erp.com", // 后端接口的域名
|
||||
'/api': {
|
||||
target: 'http://dev.erp.com', // 后端接口的域名
|
||||
changeOrigin: true,
|
||||
},
|
||||
},
|
||||
@ -67,8 +67,8 @@ export default env => {
|
||||
output: {
|
||||
// 拆分单独模块
|
||||
manualChunks: {
|
||||
"element-plus": ["element-plus"],
|
||||
mockjs: ["mockjs"],
|
||||
'element-plus': ['element-plus'],
|
||||
mockjs: ['mockjs'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user