diff --git a/.eslintrc.js b/.eslintrc.js
index 6824bb0..7b28cb7 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -44,6 +44,7 @@ module.exports = {
'vue/comment-directive': 'off',
'vue/no-parsing-error': 'off',
'vue/no-deprecated-v-on-native-modifier': 'off',
+ 'vue/multi-word-component-names': 'off',
'no-useless-escape': 'off',
'no-sparse-arrays': 'off',
'no-prototype-builtins': 'off',
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d4a70e..661b2b7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
🎉🎉🔥 `vue-next-admin-template` 基于 (vue-next-admin-v1.1.2 版本) vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支)
+## 0.2.0
+
+`2021.12.04`
+
+- 🎉 同步 master 分支 v1.2.0 版本内容,具体查看 master CHANGELOG.md
+
## 0.1.0
`2021.10.17`
diff --git a/README.md b/README.md
index 5c6c96c..2490c31 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@
-#### 🌈 介绍(基础版 ts(不带国际化))
+#### 🌈 介绍 基础版 ts(不带国际化)
基于 vue3.x + CompositionAPI + typescript + vite + element plus + vue-router-next + next.vuex,适配手机、平板、pc 的后台开源免费模板,希望减少工作量,帮助大家实现快速开发。
diff --git a/package.json b/package.json
index ab1a3a9..a054c0b 100644
--- a/package.json
+++ b/package.json
@@ -1,22 +1,22 @@
{
"name": "vue-next-admin-template",
- "version": "0.1.0",
+ "version": "0.2.0",
"description": "vue3 vite next admin template",
"author": "lyt_20201208",
"license": "MIT",
"scripts": {
- "dev": "vite",
+ "dev": "vite --force",
"build": "vite build",
"lint-fix": "eslint --fix --ext .js --ext .jsx --ext .vue src/"
},
"dependencies": {
- "axios": "^0.23.0",
- "echarts": "^5.2.1",
- "element-plus": "^1.1.0-beta.20",
+ "axios": "^0.24.0",
+ "echarts": "^5.2.2",
+ "element-plus": "^1.2.0-beta.5",
"qrcodejs2-fixes": "^0.0.2",
"mitt": "^3.0.0",
"nprogress": "^0.2.0",
- "screenfull": "^5.1.0",
+ "screenfull": "^6.0.0",
"sortablejs": "^1.14.0",
"vue": "^3.2.20",
"vue-clipboard3": "^1.0.1",
@@ -26,21 +26,21 @@
"devDependencies": {
"@types/axios": "^0.14.0",
"@types/clipboard": "^2.0.1",
- "@types/node": "^16.11.0",
+ "@types/node": "^16.11.11",
"@types/nprogress": "^0.2.0",
- "@typescript-eslint/eslint-plugin": "^5.0.0",
- "@typescript-eslint/parser": "^5.0.0",
- "@vitejs/plugin-vue": "^1.9.3",
- "@vue/compiler-sfc": "^3.2.20",
+ "@typescript-eslint/eslint-plugin": "^5.5.0",
+ "@typescript-eslint/parser": "^5.5.0",
+ "@vitejs/plugin-vue": "^1.10.1",
+ "@vue/compiler-sfc": "^3.2.23",
"dotenv": "^10.0.0",
- "eslint": "^8.0.1",
- "eslint-plugin-vue": "^7.19.1",
- "prettier": "^2.4.1",
- "sass": "^1.43.2",
- "sass-loader": "^12.2.0",
- "typescript": "^4.4.4",
- "vite": "^2.6.7",
- "vue-eslint-parser": "^7.11.0"
+ "eslint": "^8.4.0",
+ "eslint-plugin-vue": "^8.1.1",
+ "prettier": "^2.5.0",
+ "sass": "^1.44.0",
+ "sass-loader": "^12.3.0",
+ "typescript": "^4.5.2",
+ "vite": "^2.6.14",
+ "vue-eslint-parser": "^8.0.1"
},
"browserslist": [
"> 1%",
diff --git a/src/App.vue b/src/App.vue
index 11202ad..f840c80 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -9,7 +9,7 @@
import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, nextTick, defineComponent, watch } from 'vue';
import { useRoute } from 'vue-router';
import { useStore } from '/@/store/index';
-import { useTitle } from '/@/utils/setWebTitle';
+import other from '/@/utils/other';
import { Local, Session } from '/@/utils/storage';
import setIntroduction from '/@/utils/setIconfont';
import LockScreen from '/@/layout/lockScreen/index.vue';
@@ -23,7 +23,6 @@ export default defineComponent({
const setingsRef = ref();
const route = useRoute();
const store = useStore();
- const title = useTitle();
// 获取布局配置信息
const getThemeConfig = computed(() => {
return store.state.themeConfig.themeConfig;
@@ -61,7 +60,7 @@ export default defineComponent({
watch(
() => route.path,
() => {
- title();
+ other.useTitle();
}
);
return {
diff --git a/src/components/iconSelector/index.vue b/src/components/iconSelector/index.vue
index 68feae0..90fab43 100644
--- a/src/components/iconSelector/index.vue
+++ b/src/components/iconSelector/index.vue
@@ -14,29 +14,33 @@
@blur="onIconBlur"
>
-
+ v-if="fontIconPrefix === '' ? prepend?.indexOf('element') > -1 : fontIconPrefix?.indexOf('element') > -1"
+ />
+
-
{{ title }}
+
+
{{ title }}
+
+ ali
+ ele
+ awe
+
+
-
+
@@ -61,7 +65,7 @@ export default {
// 输入框前置内容
prepend: {
type: String,
- default: () => 'el-icon-thumb',
+ default: () => 'elementPointer',
},
// 输入框占位文本
placeholder: {
@@ -104,6 +108,7 @@ export default {
},
setup(props, { emit }) {
const inputWidthRef = ref();
+ const selectorScrollbarRef = ref();
const state: any = reactive({
fontIconPrefix: '',
fontIconVisible: false,
@@ -112,6 +117,8 @@ export default {
fontIconTabsIndex: 0,
fontIconSheetsList: [],
fontIconPlaceholder: '',
+ fontIconType: 'ali',
+ fontIconShow: true,
});
// 处理 input 获取焦点时,modelValue 有值时,改变 input 的 placeholder 值
const onIconFocus = () => {
@@ -153,21 +160,19 @@ export default {
});
};
// 初始化数据
- const initFontIconData = async () => {
- if (props.type === 'ali') {
+ const initFontIconData = async (type: string) => {
+ state.fontIconSheetsList = [];
+ if (type === 'ali') {
await initIconfont.ali().then((res: any) => {
- state.fontIconTabsIndex = 0;
// 阿里字体图标使用 `iconfont xxx`
state.fontIconSheetsList = res.map((i) => `iconfont ${i}`);
});
- } else if (props.type === 'ele') {
+ } else if (type === 'ele') {
await initIconfont.ele().then((res: any) => {
- state.fontIconTabsIndex = 1;
state.fontIconSheetsList = res;
});
- } else if (props.type === 'awe') {
+ } else if (type === 'awe') {
await initIconfont.awe().then((res: any) => {
- state.fontIconTabsIndex = 2;
// fontawesome字体图标使用 `fa xxx`
state.fontIconSheetsList = res.map((i) => `fa ${i}`);
});
@@ -177,14 +182,19 @@ export default {
state.fontIconPlaceholder = props.placeholder;
// 初始化双向绑定回显
initModeValueEcho();
+ // 切换时,滚动条置顶。感兴趣可以使用 keep-alive 进行缓存
+ selectorScrollbarRef.value.wrap$.scrollTop = 0;
+ };
+ // 图标点击切换
+ const onIconChange = (type: string) => {
+ state.fontIconType = type;
+ initFontIconData(type);
};
// 获取当前点击的 icon 图标
const onColClick = (v: any) => {
state.fontIconPlaceholder = v;
state.fontIconVisible = false;
- if (state.fontIconTabsIndex === 0) state.fontIconPrefix = `${v}`;
- else if (state.fontIconTabsIndex === 1) state.fontIconPrefix = `${v}`;
- else if (state.fontIconTabsIndex === 2) state.fontIconPrefix = `${v}`;
+ state.fontIconPrefix = v;
emit('get', state.fontIconPrefix);
emit('update:modelValue', state.fontIconPrefix);
};
@@ -196,7 +206,15 @@ export default {
};
// 页面加载时
onMounted(() => {
- initFontIconData();
+ // 判断默认进来是什么类型图标,进行 tab 回显
+ if (props.type === 'all') {
+ if (props.modelValue?.indexOf('iconfont') > -1) onIconChange('ali');
+ else if (props.modelValue?.indexOf('element') > -1) onIconChange('ele');
+ else if (props.modelValue?.indexOf('fa') > -1) onIconChange('awe');
+ else onIconChange('ali');
+ } else {
+ onIconChange(props.type);
+ }
initResize();
getInputWidth();
});
@@ -209,8 +227,10 @@ export default {
);
return {
inputWidthRef,
+ selectorScrollbarRef,
fontIconSheetsFilterList,
onColClick,
+ onIconChange,
onClearFontIcon,
onIconFocus,
onIconBlur,
diff --git a/src/components/svgIcon/index.vue b/src/components/svgIcon/index.vue
new file mode 100644
index 0000000..b3b6304
--- /dev/null
+++ b/src/components/svgIcon/index.vue
@@ -0,0 +1,28 @@
+
diff --git a/src/layout/component/columnsAside.vue b/src/layout/component/columnsAside.vue
index 3542646..bdd02d0 100644
--- a/src/layout/component/columnsAside.vue
+++ b/src/layout/component/columnsAside.vue
@@ -16,7 +16,7 @@
:title="v.meta.title"
>
-
+
{{
v.meta.title && v.meta.title.length >= 4 ? v.meta.title.substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3) : v.meta.title
@@ -25,7 +25,7 @@
@@ -39,15 +39,19 @@
@keyup.enter.native.stop="onLockScreenSubmit()"
>
-
+
+
+
+
+
-
-
-
+
+
+
diff --git a/src/layout/main/defaults.vue b/src/layout/main/defaults.vue
index f609ccc..3dade0a 100644
--- a/src/layout/main/defaults.vue
+++ b/src/layout/main/defaults.vue
@@ -33,7 +33,7 @@ export default {
watch(
() => route.path,
() => {
- proxy.$refs.layoutDefaultsScrollbarRef.wrap.scrollTop = 0;
+ proxy.$refs.layoutDefaultsScrollbarRef.wrap$.scrollTop = 0;
}
);
return {
diff --git a/src/layout/navBars/breadcrumb/breadcrumb.vue b/src/layout/navBars/breadcrumb/breadcrumb.vue
index 7ab7aee..016e8e3 100644
--- a/src/layout/navBars/breadcrumb/breadcrumb.vue
+++ b/src/layout/navBars/breadcrumb/breadcrumb.vue
@@ -9,10 +9,10 @@
- {{ v.meta.title }}
+ {{ v.meta.title }}
- {{ v.meta.title }}
+ {{ v.meta.title }}
diff --git a/src/layout/navBars/breadcrumb/closeFull.vue b/src/layout/navBars/breadcrumb/closeFull.vue
index 8970dd6..6599e4f 100644
--- a/src/layout/navBars/breadcrumb/closeFull.vue
+++ b/src/layout/navBars/breadcrumb/closeFull.vue
@@ -1,7 +1,7 @@
diff --git a/src/layout/navBars/breadcrumb/search.vue b/src/layout/navBars/breadcrumb/search.vue
index 879126f..bfd92b4 100644
--- a/src/layout/navBars/breadcrumb/search.vue
+++ b/src/layout/navBars/breadcrumb/search.vue
@@ -5,11 +5,15 @@
v-model="menuQuery"
:fetch-suggestions="menuSearch"
placeholder="菜单搜索:支持中文、路由路径"
- prefix-icon="el-icon-search"
ref="layoutMenuAutocompleteRef"
@select="onHandleSelect"
@blur="onSearchBlur"
>
+
+
+
+
+
{{ item.meta.title }}
diff --git a/src/layout/navBars/breadcrumb/setings.vue b/src/layout/navBars/breadcrumb/setings.vue
index 301c38e..c35557c 100644
--- a/src/layout/navBars/breadcrumb/setings.vue
+++ b/src/layout/navBars/breadcrumb/setings.vue
@@ -38,7 +38,7 @@
菜单 / 顶栏
-
{{ 顶栏背景 }}
+
顶栏背景
@@ -355,17 +355,16 @@
-
+
+
+
+
一键复制配置
-
+
+
+
+
一键恢复默认
diff --git a/src/layout/navBars/breadcrumb/user.vue b/src/layout/navBars/breadcrumb/user.vue
index f4a53d9..4c0d4b0 100644
--- a/src/layout/navBars/breadcrumb/user.vue
+++ b/src/layout/navBars/breadcrumb/user.vue
@@ -14,7 +14,9 @@
-
+
+
+
@@ -23,7 +25,9 @@
-
+
+
+
@@ -38,7 +42,9 @@
{{ getUserInfos.userName === '' ? 'test' : getUserInfos.userName }}
-
+
+
+
diff --git a/src/layout/navBars/tagsView/contextmenu.vue b/src/layout/navBars/tagsView/contextmenu.vue
index 31e5e2b..4dce3ea 100644
--- a/src/layout/navBars/tagsView/contextmenu.vue
+++ b/src/layout/navBars/tagsView/contextmenu.vue
@@ -19,7 +19,7 @@
v-if="!v.affix"
@click="onCurrentContextmenuClick(v.contextMenuClickId)"
>
-
+
{{ v.txt }}
@@ -42,10 +42,10 @@ export default defineComponent({
const state = reactive({
isShow: false,
dropdownList: [
- { contextMenuClickId: 0, txt: '刷新', affix: false, icon: 'el-icon-refresh-right' },
- { contextMenuClickId: 1, txt: '关闭', affix: false, icon: 'el-icon-close' },
- { contextMenuClickId: 2, txt: '关闭其它', affix: false, icon: 'el-icon-circle-close' },
- { contextMenuClickId: 3, txt: '全部关闭', affix: false, icon: 'el-icon-folder-delete' },
+ { contextMenuClickId: 0, txt: '刷新', affix: false, icon: 'elementRefreshRight' },
+ { contextMenuClickId: 1, txt: '关闭', affix: false, icon: 'elementClose' },
+ { contextMenuClickId: 2, txt: '关闭其它', affix: false, icon: 'elementCircleClose' },
+ { contextMenuClickId: 3, txt: '全部关闭', affix: false, icon: 'elementFolderDelete' },
{ contextMenuClickId: 4, txt: '当前页全屏', affix: false, icon: 'iconfont icon-fullscreen' },
],
item: {},
diff --git a/src/layout/navBars/tagsView/tagsView.vue b/src/layout/navBars/tagsView/tagsView.vue
index 61e8e36..e6c9a6b 100644
--- a/src/layout/navBars/tagsView/tagsView.vue
+++ b/src/layout/navBars/tagsView/tagsView.vue
@@ -6,7 +6,7 @@
v-for="(v, k) in tagsViewList"
:key="k"
class="layout-navbars-tagsview-ul-li"
- :data-name="v.name"
+ :data-name="v.url"
:class="{ 'is-active': isActive(v) }"
@contextmenu.prevent="onContextmenu(v, $event)"
@click="onTagsClick(v, k)"
@@ -20,18 +20,20 @@
{{ v.meta.title }}
-
-
+
+ />
-
+ />
@@ -324,7 +326,7 @@ export default {
};
// 鼠标滚轮滚动
const onHandleScroll = (e: any) => {
- proxy.$refs.scrollbarRef.$refs.wrap.scrollLeft += e.wheelDelta / 4;
+ proxy.$refs.scrollbarRef.$refs.wrap$.scrollLeft += e.wheelDelta / 4;
};
// tagsView 横向滚动
const tagsViewmoveToCurrentTag = () => {
@@ -341,7 +343,7 @@ export default {
// 最后 li
let liLast: any = tagsRefs.value[tagsRefs.value.length - 1];
// 当前滚动条的值
- let scrollRefs = proxy.$refs.scrollbarRef.$refs.wrap;
+ let scrollRefs = proxy.$refs.scrollbarRef.$refs.wrap$;
// 当前滚动条滚动宽度
let scrollS = scrollRefs.scrollWidth;
// 当前滚动条偏移宽度
@@ -401,7 +403,7 @@ export default {
state.sortable && state.sortable.destroy();
state.sortable = Sortable.create(el, {
animation: 300,
- dataIdAttr: 'data-name',
+ dataIdAttr: 'data-url',
disabled: getThemeConfig.value.isSortableTagsView ? false : true,
onEnd: () => {
const sortEndList: any = [];
diff --git a/src/layout/navMenu/horizontal.vue b/src/layout/navMenu/horizontal.vue
index 9d17c1a..e323df1 100644
--- a/src/layout/navMenu/horizontal.vue
+++ b/src/layout/navMenu/horizontal.vue
@@ -5,19 +5,19 @@
-
+
{{ val.meta.title }}
-
+
{{ val.meta.title }}
-
+
{{ val.meta.title }}
diff --git a/src/layout/navMenu/subItem.vue b/src/layout/navMenu/subItem.vue
index 5e9437b..2799a49 100644
--- a/src/layout/navMenu/subItem.vue
+++ b/src/layout/navMenu/subItem.vue
@@ -2,19 +2,19 @@
-
+
{{ val.meta.title }}
-
+
{{ val.meta.title }}
-
+
{{ val.meta.title }}
diff --git a/src/layout/navMenu/vertical.vue b/src/layout/navMenu/vertical.vue
index 2deeb9e..7c06405 100644
--- a/src/layout/navMenu/vertical.vue
+++ b/src/layout/navMenu/vertical.vue
@@ -10,13 +10,13 @@
-
+
{{ val.meta.title }}
-
+
{{ val.meta.title }}
diff --git a/src/main.ts b/src/main.ts
index acfa54c..05dc208 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -3,7 +3,7 @@ import App from './App.vue';
import router from './router';
import { store, key } from './store';
import { directive } from '/@/utils/directive';
-import { globalComponentSize } from '/@/utils/componentSize';
+import other from '/@/utils/other';
import ElementPlus from 'element-plus';
import 'element-plus/dist/index.css';
@@ -11,8 +11,10 @@ import '/@/theme/index.scss';
import mitt from 'mitt';
const app = createApp(App);
-app.use(router).use(store, key).use(ElementPlus, { size: globalComponentSize }).mount('#app');
-
-app.config.globalProperties.mittBus = mitt();
directive(app);
+other.elSvg(app);
+
+app.use(router).use(store, key).use(ElementPlus, { size: other.globalComponentSize }).mount('#app');
+
+app.config.globalProperties.mittBus = mitt();
diff --git a/src/router/backEnd.ts b/src/router/backEnd.ts
index aa064c8..f6d0a0c 100644
--- a/src/router/backEnd.ts
+++ b/src/router/backEnd.ts
@@ -48,7 +48,7 @@ export async function initBackEndControlRoutes() {
*/
export function getBackEndControlRoutes() {
// 模拟 admin 与 test
- const auth = store.state.userInfos.userInfos.authPageList[0];
+ const auth = store.state.userInfos.userInfos.roles[0];
// 管理员 admin
if (auth === 'admin') return getMenuAdmin();
// 其它用户 test
diff --git a/src/router/index.ts b/src/router/index.ts
index 80d05ca..c7ad392 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -81,34 +81,34 @@ export function formatTwoStageRoutes(arr: any) {
*/
export function setCacheTagsViewRoutes() {
// 获取有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
- let authsRoutes = setFilterHasAuthMenu(dynamicRoutes, store.state.userInfos.userInfos.authPageList);
+ let rolesRoutes = setFilterHasRolesMenu(dynamicRoutes, store.state.userInfos.userInfos.roles);
// 添加到 vuex setTagsViewRoutes 中
- store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(authsRoutes))[0].children);
+ store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes))[0].children);
}
/**
- * 判断路由 `meta.auth` 中是否包含当前登录用户权限字段
- * @param auths 用户权限标识,在 userInfos(用户信息)的 authPageList(登录页登录时缓存到浏览器)数组
+ * 判断路由 `meta.roles` 中是否包含当前登录用户权限字段
+ * @param roles 用户权限标识,在 userInfos(用户信息)的 roles(登录页登录时缓存到浏览器)数组
* @param route 当前循环时的路由项
* @returns 返回对比后有权限的路由项
*/
-export function hasAuth(auths: any, route: any) {
- if (route.meta && route.meta.auth) return auths.some((auth: any) => route.meta.auth.includes(auth));
+export function hasRoles(roles: any, route: any) {
+ if (route.meta && route.meta.auth) return roles.some((role: any) => route.meta.roles.includes(role));
else return true;
}
/**
* 获取当前用户权限标识去比对路由表,设置递归过滤有权限的路由
* @param routes 当前路由 children
- * @param auth 用户权限标识,在 userInfos(用户信息)的 authPageList(登录页登录时缓存到浏览器)数组
- * @returns 返回有权限的路由数组 `meta.auth` 中控制
+ * @param roles 用户权限标识,在 userInfos(用户信息)的 roles(登录页登录时缓存到浏览器)数组
+ * @returns 返回有权限的路由数组 `meta.roles` 中控制
*/
-export function setFilterHasAuthMenu(routes: any, auth: any) {
+export function setFilterHasRolesMenu(routes: any, roles: any) {
const menu: any = [];
routes.forEach((route: any) => {
const item = { ...route };
- if (hasAuth(auth, item)) {
- if (item.children) item.children = setFilterHasAuthMenu(item.children, auth);
+ if (hasRoles(roles, item)) {
+ if (item.children) item.children = setFilterHasRolesMenu(item.children, roles);
menu.push(item);
}
});
@@ -121,7 +121,7 @@ export function setFilterHasAuthMenu(routes: any, auth: any) {
* @description 用于 tagsView、菜单搜索中:未过滤隐藏的(isHide)
*/
export function setFilterMenuAndCacheTagsViewRoutes() {
- store.dispatch('routesList/setRoutesList', setFilterHasAuthMenu(dynamicRoutes[0].children, store.state.userInfos.userInfos.authPageList));
+ store.dispatch('routesList/setRoutesList', setFilterHasRolesMenu(dynamicRoutes[0].children, store.state.userInfos.userInfos.roles));
setCacheTagsViewRoutes();
}
@@ -135,10 +135,10 @@ export function setFilterMenuAndCacheTagsViewRoutes() {
export function setFilterRoute(chil: any) {
let filterRoute: any = [];
chil.forEach((route: any) => {
- if (route.meta.auth) {
- route.meta.auth.forEach((metaAuth: any) => {
- store.state.userInfos.userInfos.authPageList.forEach((auth: any) => {
- if (metaAuth === auth) filterRoute.push({ ...route });
+ if (route.meta.roles) {
+ route.meta.roles.forEach((metaRoles: any) => {
+ store.state.userInfos.userInfos.roles.forEach((roles: any) => {
+ if (metaRoles === roles) filterRoute.push({ ...route });
});
});
}
diff --git a/src/router/route.ts b/src/router/route.ts
index 7ab93fb..f954c0b 100644
--- a/src/router/route.ts
+++ b/src/router/route.ts
@@ -9,7 +9,7 @@ import { RouteRecordRaw } from 'vue-router';
* isKeepAlive: 是否缓存组件状态
* isAffix: 是否固定在 tagsView 栏上
* isIframe: 是否内嵌窗口,,开启条件,`1、isIframe:true 2、链接地址不为空`
- * auth: 当前路由权限标识(多个请用逗号隔开),最后转成数组格式,用于与当前用户权限进行对比,控制路由显示、隐藏
+ * roles: 当前路由权限标识,取角色管理。控制路由显示、隐藏。超级管理员:admin 普通角色:common
* icon: 菜单、tagsView 图标,阿里:加 `iconfont xxx`,fontawesome:加 `fa xxx`
* }
*/
@@ -41,7 +41,7 @@ export const dynamicRoutes: Array = [
isKeepAlive: true,
isAffix: true,
isIframe: false,
- auth: ['admin', 'test'],
+ roles: ['admin', 'common'],
icon: 'iconfont icon-shouye',
},
},
@@ -57,7 +57,7 @@ export const dynamicRoutes: Array = [
isKeepAlive: true,
isAffix: false,
isIframe: false,
- auth: ['admin'],
+ roles: ['admin'],
icon: 'iconfont icon-xitongshezhi',
},
children: [
@@ -72,10 +72,25 @@ export const dynamicRoutes: Array = [
isKeepAlive: true,
isAffix: false,
isIframe: false,
- auth: ['admin'],
+ roles: ['admin'],
icon: 'iconfont icon-caidan',
},
},
+ {
+ path: '/system/role',
+ name: 'systemRole',
+ component: () => import('/@/views/system/role/index.vue'),
+ meta: {
+ title: '角色管理',
+ isLink: '',
+ isHide: false,
+ isKeepAlive: true,
+ isAffix: false,
+ isIframe: false,
+ roles: ['admin'],
+ icon: 'elementColdDrink',
+ },
+ },
{
path: '/system/user',
name: 'systemUser',
@@ -87,10 +102,40 @@ export const dynamicRoutes: Array = [
isKeepAlive: true,
isAffix: false,
isIframe: false,
- auth: ['admin'],
+ roles: ['admin'],
icon: 'iconfont icon-icon-',
},
},
+ {
+ path: '/system/dept',
+ name: 'systemDept',
+ component: () => import('/@/views/system/dept/index.vue'),
+ meta: {
+ title: '部门管理',
+ isLink: '',
+ isHide: false,
+ isKeepAlive: true,
+ isAffix: false,
+ isIframe: false,
+ roles: ['admin'],
+ icon: 'elementOfficeBuilding',
+ },
+ },
+ {
+ path: '/system/dic',
+ name: 'systemDic',
+ component: () => import('/@/views/system/dic/index.vue'),
+ meta: {
+ title: '字典管理',
+ isLink: '',
+ isHide: false,
+ isKeepAlive: true,
+ isAffix: false,
+ isIframe: false,
+ roles: ['admin'],
+ icon: 'elementSetUp',
+ },
+ },
],
},
],
diff --git a/src/theme/app.scss b/src/theme/app.scss
index e92be9e..b027a5b 100644
--- a/src/theme/app.scss
+++ b/src/theme/app.scss
@@ -169,6 +169,25 @@ body,
}
}
+/* cursor 鼠标形状
+------------------------------- */
+// 默认
+.cursor-default {
+ cursor: default !important;
+}
+// 帮助
+.cursor-help {
+ cursor: help !important;
+}
+// 手指
+.cursor-pointer {
+ cursor: pointer !important;
+}
+// 移动
+.cursor-move {
+ cursor: move !important;
+}
+
/* 宽高 100%
------------------------------- */
.w100 {
diff --git a/src/theme/dark.scss b/src/theme/dark.scss
index 2fe72d3..e2b03e6 100644
--- a/src/theme/dark.scss
+++ b/src/theme/dark.scss
@@ -12,6 +12,7 @@
.error img {
filter: unset;
}
+
// element plus
.el-radio-button__original-radio:checked + .el-radio-button__inner,
.el-image-viewer__close,
@@ -20,6 +21,13 @@
.el-image-viewer__prev {
color: #000000 !important;
}
+ .el-overlay {
+ background-color: rgba(0, 0, 0, 0.05) !important;
+ }
+ .el-drawer {
+ box-shadow: 0 8px 10px -5px rgb(0 0 0 / 1%), 0 16px 24px 2px rgb(0 0 0 / 2%), 0 6px 30px 5px rgb(0 0 0 / 1%);
+ }
+
// 数据可视化演示
.visualizing-container-head {
background: linear-gradient(to bottom, rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.02)) !important;
@@ -39,6 +47,7 @@
.cropper-modal {
background-color: #ffffff;
}
+
// 其它菜单等
--bg-menuBar: #ffffff !important;
--bg-menuBarColor: #303133 !important;
diff --git a/src/theme/element.scss b/src/theme/element.scss
index eb1be71..538a771 100644
--- a/src/theme/element.scss
+++ b/src/theme/element.scss
@@ -853,7 +853,7 @@
@include generalIcon;
}
// element plus 本身字体图标
-.el-sub-menu [class^='el-icon-'] {
+.el-sub-menu .el-icon {
font-size: 14px !important;
}
// 去掉离开浏览器时,菜单的默认高亮
@@ -1015,6 +1015,9 @@
/* scrollbar
------------------------------- */
+.el-scrollbar__bar {
+ z-index: 4;
+}
.el-scrollbar__wrap {
overflow-x: hidden !important;
max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/
diff --git a/src/theme/iconSelector.scss b/src/theme/iconSelector.scss
index c9af770..6e599e6 100644
--- a/src/theme/iconSelector.scss
+++ b/src/theme/iconSelector.scss
@@ -9,6 +9,19 @@
height: 40px;
line-height: 40px;
padding: 0 15px;
+ .icon-selector-warp-title-tab {
+ span {
+ cursor: pointer;
+ &:hover {
+ color: var(--color-primary);
+ text-decoration: underline;
+ }
+ }
+ .span-active {
+ color: var(--color-primary);
+ text-decoration: underline;
+ }
+ }
}
.icon-selector-warp-row {
height: 230px;
diff --git a/src/theme/index.scss b/src/theme/index.scss
index 3907840..7ed25d2 100644
--- a/src/theme/index.scss
+++ b/src/theme/index.scss
@@ -1,5 +1,8 @@
@import './app.scss';
@import './base.scss';
+@import './other.scss';
@import './element.scss';
+@import './iconSelector.scss';
@import './media/media.scss';
+@import './waves.scss';
@import './dark.scss';
diff --git a/src/theme/media/chart.scss b/src/theme/media/chart.scss
new file mode 100644
index 0000000..8485e39
--- /dev/null
+++ b/src/theme/media/chart.scss
@@ -0,0 +1,94 @@
+@import './index.scss';
+
+/* 页面宽度小于768px
+------------------------------- */
+@media screen and (max-width: $sm) {
+ .big-data-down-left {
+ width: 100% !important;
+ flex-direction: unset !important;
+ flex-wrap: wrap;
+ .flex-warp-item {
+ min-height: 196.24px;
+ padding: 0 7.5px 15px 15px !important;
+ .flex-warp-item-box {
+ border: none !important;
+ border-bottom: 1px solid #ebeef5 !important;
+ }
+ }
+ }
+ .big-data-down-center {
+ width: 100% !important;
+ .big-data-down-center-one,
+ .big-data-down-center-two {
+ min-height: 196.24px;
+ padding-left: 15px !important;
+ .big-data-down-center-one-content {
+ border: none !important;
+ border-bottom: 1px solid #ebeef5 !important;
+ }
+ .flex-warp-item-box {
+ @extend .big-data-down-center-one-content;
+ }
+ }
+ }
+ .big-data-down-right {
+ .flex-warp-item {
+ .flex-warp-item-box {
+ border: none !important;
+ border-bottom: 1px solid #ebeef5 !important;
+ }
+ &:nth-of-type(2) {
+ padding-left: 15px !important;
+ }
+ &:last-of-type {
+ .flex-warp-item-box {
+ border: none !important;
+ }
+ }
+ }
+ }
+}
+
+/* 页面宽度大于768px小于1200px
+------------------------------- */
+@media screen and (min-width: $sm) and (max-width: $lg) {
+ .chart-warp-bottom {
+ .big-data-down-left {
+ width: 50% !important;
+ }
+ .big-data-down-center {
+ width: 50% !important;
+ }
+ .big-data-down-right {
+ .flex-warp-item {
+ width: 50% !important;
+ &:nth-of-type(2) {
+ padding-left: 7.5px !important;
+ }
+ }
+ }
+ }
+}
+
+/* 页面宽度小于1200px
+------------------------------- */
+@media screen and (max-width: $lg) {
+ .chart-warp-top {
+ .up-left {
+ display: none;
+ }
+ }
+ .chart-warp-bottom {
+ overflow-y: auto !important;
+ flex-wrap: wrap;
+ .big-data-down-right {
+ width: 100% !important;
+ flex-direction: unset !important;
+ flex-wrap: wrap;
+ .flex-warp-item {
+ min-height: 196.24px;
+ padding: 0 7.5px 15px 15px !important;
+ }
+ }
+ }
+}
diff --git a/src/theme/media/media.scss b/src/theme/media/media.scss
index 9b49e2f..c470d5c 100644
--- a/src/theme/media/media.scss
+++ b/src/theme/media/media.scss
@@ -1,8 +1,10 @@
@import './login.scss';
@import './error.scss';
@import './layout.scss';
+@import './personal.scss';
@import './tagsView.scss';
@import './home.scss';
+@import './chart.scss';
@import './form.scss';
@import './scrollbar.scss';
@import './pagination.scss';
diff --git a/src/theme/media/personal.scss b/src/theme/media/personal.scss
new file mode 100644
index 0000000..7ec0d4a
--- /dev/null
+++ b/src/theme/media/personal.scss
@@ -0,0 +1,16 @@
+@import './index.scss';
+
+/* 页面宽度小于768px
+------------------------------- */
+@media screen and (max-width: $sm) {
+ .personal-info {
+ padding-left: 0 !important;
+ margin-top: 15px;
+ }
+ .personal-recommend-col {
+ margin-bottom: 15px;
+ &:last-of-type {
+ margin-bottom: 0;
+ }
+ }
+}
diff --git a/src/theme/other.scss b/src/theme/other.scss
new file mode 100644
index 0000000..9e8e950
--- /dev/null
+++ b/src/theme/other.scss
@@ -0,0 +1,28 @@
+/* wangeditor富文本编辑器
+------------------------------- */
+.w-e-toolbar {
+ border: 1px solid #ebeef5 !important;
+ border-bottom: 1px solid #ebeef5 !important;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+ z-index: 2 !important;
+}
+.w-e-text-container {
+ border: 1px solid #ebeef5 !important;
+ border-top: none !important;
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+ z-index: 1 !important;
+}
+
+/* web端自定义截屏
+------------------------------- */
+#screenShotContainer {
+ z-index: 9998 !important;
+}
+#toolPanel {
+ height: 42px !important;
+}
+#optionPanel {
+ height: 37px !important;
+}
diff --git a/src/theme/waves.scss b/src/theme/waves.scss
new file mode 100644
index 0000000..23add2c
--- /dev/null
+++ b/src/theme/waves.scss
@@ -0,0 +1,101 @@
+/* Waves v0.6.0
+* http://fian.my.id/Waves
+*
+* Copyright 2014 Alfiana E. Sibuea and other contributors
+* Released under the MIT license
+* https://github.com/fians/Waves/blob/master/LICENSE
+*/
+.waves-effect {
+ position: relative;
+ cursor: pointer;
+ display: inline-block;
+ overflow: hidden;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-tap-highlight-color: transparent;
+ vertical-align: middle;
+ z-index: 1;
+ will-change: opacity, transform;
+ transition: all 0.3s ease-out;
+}
+.waves-effect .waves-ripple {
+ position: absolute;
+ border-radius: 50%;
+ width: 20px;
+ height: 20px;
+ margin-top: -10px;
+ margin-left: -10px;
+ opacity: 0;
+ background: rgba(0, 0, 0, 0.2);
+ transition: all 0.7s ease-out;
+ transition-property: opacity, -webkit-transform;
+ transition-property: transform, opacity;
+ transition-property: transform, opacity, -webkit-transform;
+ -webkit-transform: scale(0);
+ transform: scale(0);
+ pointer-events: none;
+}
+.waves-effect.waves-light .waves-ripple {
+ background-color: rgba(255, 255, 255, 0.45);
+}
+.waves-effect.waves-red .waves-ripple {
+ background-color: rgba(244, 67, 54, 0.7);
+}
+.waves-effect.waves-yellow .waves-ripple {
+ background-color: rgba(255, 235, 59, 0.7);
+}
+.waves-effect.waves-orange .waves-ripple {
+ background-color: rgba(255, 152, 0, 0.7);
+}
+.waves-effect.waves-purple .waves-ripple {
+ background-color: rgba(156, 39, 176, 0.7);
+}
+.waves-effect.waves-green .waves-ripple {
+ background-color: rgba(76, 175, 80, 0.7);
+}
+.waves-effect.waves-teal .waves-ripple {
+ background-color: rgba(0, 150, 136, 0.7);
+}
+.waves-effect input[type='button'],
+.waves-effect input[type='reset'],
+.waves-effect input[type='submit'] {
+ border: 0;
+ font-style: normal;
+ font-size: inherit;
+ text-transform: inherit;
+ background: none;
+}
+.waves-notransition {
+ transition: none !important;
+}
+.waves-circle {
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ -webkit-mask-image: -webkit-radial-gradient(circle, #fff 100%, #000 100%);
+}
+.waves-input-wrapper {
+ border-radius: 0.2em;
+ vertical-align: bottom;
+}
+.waves-input-wrapper .waves-button-input {
+ position: relative;
+ top: 0;
+ left: 0;
+ z-index: 1;
+}
+.waves-circle {
+ text-align: center;
+ width: 2.5em;
+ height: 2.5em;
+ line-height: 2.5em;
+ border-radius: 50%;
+ -webkit-mask-image: none;
+}
+.waves-block {
+ display: block;
+}
+a.waves-effect .waves-ripple {
+ z-index: -1;
+}
diff --git a/src/utils/componentSize.ts b/src/utils/componentSize.ts
deleted file mode 100644
index d747aa0..0000000
--- a/src/utils/componentSize.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { Local } from '/@/utils/storage';
-
-/**
- * 全局组件大小
- * @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize`
- */
-export const globalComponentSize: string = Local.get('themeConfig')?.globalComponentSize;
diff --git a/src/utils/deepClone.ts b/src/utils/deepClone.ts
deleted file mode 100644
index 819f744..0000000
--- a/src/utils/deepClone.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * 对象深克隆
- * @param obj 源对象
- * @returns 克隆后的对象
- */
-export function deepClone(obj: any) {
- let newObj: any;
- try {
- newObj = obj.push ? [] : {};
- } catch (error) {
- newObj = {};
- }
- for (let attr in obj) {
- if (typeof obj[attr] === 'object') {
- newObj[attr] = deepClone(obj[attr]);
- } else {
- newObj[attr] = obj[attr];
- }
- }
- return newObj;
-}
diff --git a/src/utils/getStyleSheets.ts b/src/utils/getStyleSheets.ts
index 73406a0..0401c68 100644
--- a/src/utils/getStyleSheets.ts
+++ b/src/utils/getStyleSheets.ts
@@ -1,4 +1,5 @@
import { nextTick } from 'vue';
+import * as svg from '@element-plus/icons';
// 获取阿里字体图标
const getAlicdnIconfont = () => {
@@ -27,24 +28,16 @@ const getAlicdnIconfont = () => {
});
};
-// 初始化获取 css 样式,获取 element plus 自带图标
+// 初始化获取 css 样式,获取 element plus 自带 svg 图标,增加了 element 前缀,使用时:elementAim
const getElementPlusIconfont = () => {
return new Promise((resolve, reject) => {
nextTick(() => {
- const styles: any = document.styleSheets;
- let sheetsIconList = [];
- for (let i = 0; i < styles.length; i++) {
- for (let j = 0; j < styles[i].cssRules.length; j++) {
- if (styles[i].cssRules[j].selectorText && styles[i].cssRules[j].selectorText.indexOf('.el-icon-') === 0) {
- if (/::before/.test(styles[i].cssRules[j].selectorText)) {
- sheetsIconList.push(
- `${styles[i].cssRules[j].selectorText.substring(1, styles[i].cssRules[j].selectorText.length).replace(/\:\:before/gi, '')}`
- );
- }
- }
- }
+ const icons = svg as any;
+ const sheetsIconList = [];
+ for (const i in icons) {
+ sheetsIconList.push(`element${icons[i].name}`);
}
- if (sheetsIconList.length > 0) resolve(sheetsIconList.reverse());
+ if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
diff --git a/src/utils/lazyImgLoading.ts b/src/utils/lazyImgLoading.ts
deleted file mode 100644
index 4506269..0000000
--- a/src/utils/lazyImgLoading.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { nextTick } from 'vue';
-
-/**
- * 图片懒加载
- * @param el dom 目标元素
- * @param arr 列表数据
- * @description data-xxx 属性用于存储页面或应用程序的私有自定义数据
- */
-export const lazyImgLoading = (el: any, arr: any) => {
- const io = new IntersectionObserver((res) => {
- res.forEach((v: any) => {
- if (v.isIntersecting) {
- const { img, key } = v.target.dataset;
- v.target.src = img;
- v.target.onload = () => {
- io.unobserve(v.target);
- arr[key]['loading'] = false;
- };
- }
- });
- });
- nextTick(() => {
- document.querySelectorAll(el).forEach((img) => io.observe(img));
- });
-};
diff --git a/src/utils/other.ts b/src/utils/other.ts
new file mode 100644
index 0000000..a2be193
--- /dev/null
+++ b/src/utils/other.ts
@@ -0,0 +1,118 @@
+import { nextTick } from 'vue';
+import type { App } from 'vue';
+import * as svg from '@element-plus/icons';
+import router from '/@/router/index';
+import { store } from '/@/store/index';
+import { Local } from '/@/utils/storage';
+import SvgIcon from '/@/components/svgIcon/index.vue';
+
+/**
+ * 导出全局注册 element plus svg 图标
+ * @param app vue 实例
+ * @description 使用:https://element-plus.gitee.io/zh-CN/component/icon.html
+ */
+export function elSvg(app: App) {
+ const icons = svg as any;
+ for (const i in icons) {
+ app.component(`element${icons[i].name}`, icons[i]);
+ }
+ app.component('SvgIcon', SvgIcon);
+}
+
+/**
+ * 设置浏览器标题
+ * @method const title = useTitle(); ==> title()
+ */
+export function useTitle() {
+ return () => {
+ nextTick(() => {
+ let webTitle = '';
+ let globalTitle: string = store.state.themeConfig.themeConfig.globalTitle;
+ webTitle = router.currentRoute.value.meta.title as any;
+ document.title = `${webTitle} - ${globalTitle}` || globalTitle;
+ });
+ };
+}
+
+/**
+ * 图片懒加载
+ * @param el dom 目标元素
+ * @param arr 列表数据
+ * @description data-xxx 属性用于存储页面或应用程序的私有自定义数据
+ */
+export const lazyImg = (el: any, arr: any) => {
+ const io = new IntersectionObserver((res) => {
+ res.forEach((v: any) => {
+ if (v.isIntersecting) {
+ const { img, key } = v.target.dataset;
+ v.target.src = img;
+ v.target.onload = () => {
+ io.unobserve(v.target);
+ arr[key]['loading'] = false;
+ };
+ }
+ });
+ });
+ nextTick(() => {
+ document.querySelectorAll(el).forEach((img) => io.observe(img));
+ });
+};
+
+/**
+ * 全局组件大小
+ * @returns 返回 `window.localStorage` 中读取的缓存值 `globalComponentSize`
+ */
+export function globalComponentSize() {
+ return Local.get('themeConfig')?.globalComponentSize;
+}
+
+/**
+ * 对象深克隆
+ * @param obj 源对象
+ * @returns 克隆后的对象
+ */
+export function deepClone(obj: any) {
+ let newObj: any;
+ try {
+ newObj = obj.push ? [] : {};
+ } catch (error) {
+ newObj = {};
+ }
+ for (let attr in obj) {
+ if (typeof obj[attr] === 'object') {
+ newObj[attr] = deepClone(obj[attr]);
+ } else {
+ newObj[attr] = obj[attr];
+ }
+ }
+ return newObj;
+}
+
+/**
+ * 统一批量导出
+ * @method elSvg 导出全局注册 element plus svg 图标
+ * @method useTitle 设置浏览器标题国际化
+ * @method lazyImg 图片懒加载
+ * @method globalComponentSize element plus 全局组件大小
+ * @method deepClone 对象深克隆
+ */
+const other = {
+ elSvg: (app: App) => {
+ elSvg(app);
+ },
+ useTitle: () => {
+ useTitle();
+ },
+ lazyImg: (el: any, arr: any) => {
+ lazyImg(el, arr);
+ },
+ globalComponentSize: () => {
+ globalComponentSize();
+ },
+ deepClone: (obj: any) => {
+ deepClone(obj);
+ },
+};
+
+// 统一批量导出
+export default other;
diff --git a/src/utils/setWebTitle.ts b/src/utils/setWebTitle.ts
deleted file mode 100644
index 8c6a901..0000000
--- a/src/utils/setWebTitle.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { nextTick } from 'vue';
-import router from '/@/router/index';
-import { store } from '/@/store/index';
-
-/**
- * 设置浏览器标题
- */
-export function useTitle() {
- return () => {
- nextTick(() => {
- let webTitle = '';
- let globalTitle: string = store.state.themeConfig.themeConfig.globalTitle;
- webTitle = router.currentRoute.value.meta.title as any;
- document.title = `${webTitle} - ${globalTitle}` || globalTitle;
- });
- };
-}
diff --git a/src/utils/wartermark.ts b/src/utils/wartermark.ts
index 1fb0af2..2e5d5e3 100644
--- a/src/utils/wartermark.ts
+++ b/src/utils/wartermark.ts
@@ -9,7 +9,6 @@ const setWatermark = (str: string) => {
cans.rotate((-20 * Math.PI) / 180);
cans.font = '12px Vedana';
cans.fillStyle = 'rgba(200, 200, 200, 0.30)';
- cans.textAlign = 'center';
cans.textBaseline = 'Middle';
cans.fillText(str, can.width / 10, can.height / 2);
const div = document.createElement('div');
diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index 6e3adeb..64f6f8f 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -20,9 +20,9 @@
{{ v.title }}
-
{{v.titleNum}}
+
{{ v.titleNum }}
{{ v.tip }}
-
{{v.tipNum}}
+
{{ v.tipNum }}
@@ -74,7 +74,7 @@
-
+
{{ v.title }}
{{ v.label }}
diff --git a/src/views/login/component/account.vue b/src/views/login/component/account.vue
index dcbdabc..8093a10 100644
--- a/src/views/login/component/account.vue
+++ b/src/views/login/component/account.vue
@@ -1,24 +1,17 @@
-
+
+
+
+
-
+
+
+
+
-
+
+
+
+
+
@@ -90,23 +79,24 @@ export default defineComponent({
});
// 登录
const onSignIn = async () => {
+ // 模拟数据
state.loading.signIn = true;
- let defaultAuthPageList: Array = [];
+ let defaultRoles: Array = [];
let defaultAuthBtnList: Array = [];
- // admin 页面权限标识,对应路由 meta.auth,用于控制路由的显示/隐藏
- let adminAuthPageList: Array = ['admin'];
+ // admin 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
+ let adminRoles: Array = ['admin'];
// admin 按钮权限标识
let adminAuthBtnList: Array = ['btn.add', 'btn.del', 'btn.edit', 'btn.link'];
- // test 页面权限标识,对应路由 meta.auth,用于控制路由的显示/隐藏
- let testAuthPageList: Array = ['test'];
+ // test 页面权限标识,对应路由 meta.roles,用于控制路由的显示/隐藏
+ let testAuthPageList: Array = ['common'];
// test 按钮权限标识
let testAuthBtnList: Array = ['btn.add', 'btn.link'];
// 不同用户模拟不同的用户权限
if (state.ruleForm.userName === 'admin') {
- defaultAuthPageList = adminAuthPageList;
+ defaultRoles = adminRoles;
defaultAuthBtnList = adminAuthBtnList;
} else {
- defaultAuthPageList = testAuthPageList;
+ defaultRoles = testAuthPageList;
defaultAuthBtnList = testAuthBtnList;
}
// 用户信息模拟数据
@@ -117,7 +107,7 @@ export default defineComponent({
? 'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg'
: 'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg',
time: new Date().getTime(),
- authPageList: defaultAuthPageList,
+ roles: defaultRoles,
authBtnList: defaultAuthBtnList,
};
// 存储 token 到浏览器缓存
diff --git a/src/views/login/component/mobile.vue b/src/views/login/component/mobile.vue
index 271d167..699ce37 100644
--- a/src/views/login/component/mobile.vue
+++ b/src/views/login/component/mobile.vue
@@ -1,21 +1,20 @@
-
+
+
+
+
-
+
+
+
+
+
获取验证码
@@ -51,9 +50,6 @@ export default defineComponent({
diff --git a/src/views/system/menu/component/addMenu.vue b/src/views/system/menu/component/addMenu.vue
index ceb2d22..01ac32e 100644
--- a/src/views/system/menu/component/addMenu.vue
+++ b/src/views/system/menu/component/addMenu.vue
@@ -1,89 +1,138 @@
-