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 02eae45..b2cc693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ 🎉🎉🔥 `vue-next-admin` 基于 vue3.x 、Typescript、vite、Element plus 等,适配手机、平板、pc 的后台开源免费模板库(vue2.x 请切换 vue-prev-admin 分支) +## 1.2.0 + +`2021.11.28` + +- 🌟 更新 依赖更新最新版本 +- 🎯 优化 深色模式 +- 🎯 优化 `/@/utils` 文件夹,合并删除单一内容 +- 🎯 优化 系统设置:菜单管理(新增、修改)、角色管理(新增菜单权限)、用户管理、部门管理、字典管理 +- 🎯 优化 登录界面逻辑、权限管理逻辑 +- 🎯 优化 同步 [vue-next-admin-images](https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu) 后端控制菜单模拟数据 +- 🎉 新增 适配 Font Icon 向 SVG Icon 迁移(改动大,"element-plus": "^1.2.0-beta.4" 谨慎更新) +- 🐞 修复 热更新问题,感谢@甜蜜蜜 +- 🐞 修复 页面/element 字体图标演示 +- 🐞 修复 功能/图标选择器演示,新增高级功能 [issues #I4GJXQ](https://gitee.com/lyt-top/vue-next-admin/issues/I4GJXQ) + ## 1.1.2 `2021.10.17` diff --git a/package.json b/package.json index 4c4dc91..e4271de 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "vue-next-admin", - "version": "1.1.2", + "version": "1.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/" }, @@ -13,16 +13,16 @@ "axios": "^0.24.0", "countup.js": "^2.0.8", "cropperjs": "^1.5.12", - "echarts": "^5.2.1", + "echarts": "^5.2.2", "echarts-gl": "^2.0.8", "echarts-wordcloud": "^2.0.0", - "element-plus": "^1.1.0-beta.24", + "element-plus": "^1.2.0-beta.5", "jsplumb": "^2.15.6", "mitt": "^3.0.0", "nprogress": "^0.2.0", "print-js": "^1.6.0", "qrcodejs2-fixes": "^0.0.2", - "screenfull": "^5.1.0", + "screenfull": "^6.0.0", "sortablejs": "^1.14.0", "splitpanes": "^3.0.4", "vue": "^3.2.20", @@ -30,28 +30,28 @@ "vue-grid-layout": "^3.0.0-beta1", "vue-i18n": "^9.1.9", "vue-router": "^4.0.12", - "vue-web-screen-shot": "^1.2.0", + "vue-web-screen-shot": "^1.3.0", "vuex": "^4.0.2", - "wangeditor": "^4.7.9" + "wangeditor": "^4.7.10" }, "devDependencies": { "@types/axios": "^0.14.0", "@types/clipboard": "^2.0.1", - "@types/node": "^16.11.6", + "@types/node": "^16.11.11", "@types/nprogress": "^0.2.0", "@types/sortablejs": "^1.10.7", - "@typescript-eslint/eslint-plugin": "^5.2.0", - "@typescript-eslint/parser": "^5.2.0", - "@vitejs/plugin-vue": "^1.9.4", - "@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.1.0", - "eslint-plugin-vue": "^8.0.3", - "prettier": "^2.4.1", - "sass": "^1.43.4", + "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.4.4", - "vite": "^2.6.13", + "typescript": "^4.5.2", + "vite": "^2.6.14", "vue-eslint-parser": "^8.0.1" }, "browserslist": [ diff --git a/src/App.vue b/src/App.vue index 0d51873..d9a308c 100644 --- a/src/App.vue +++ b/src/App.vue @@ -11,7 +11,7 @@ import { computed, ref, getCurrentInstance, onBeforeMount, onMounted, onUnmounted, nextTick, defineComponent, watch, reactive, toRefs } 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'; @@ -25,7 +25,6 @@ export default defineComponent({ const setingsRef = ref(); const route = useRoute(); const store = useStore(); - const title = useTitle(); const state = reactive({ i18nLocale: null, }); @@ -75,7 +74,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" >
-
{{ 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/noticeBar/index.vue b/src/components/noticeBar/index.vue index c0671ad..44e560b 100644 --- a/src/components/noticeBar/index.vue +++ b/src/components/noticeBar/index.vue @@ -6,7 +6,7 @@
{{ text }}
- +
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/i18n/lang/en.ts b/src/i18n/lang/en.ts index 152de08..1164a73 100644 --- a/src/i18n/lang/en.ts +++ b/src/i18n/lang/en.ts @@ -4,7 +4,10 @@ export default { home: 'home', system: 'system', systemMenu: 'systemMenu', + systemRole: 'systemRole', systemUser: 'systemUser', + systemDept: 'systemDept', + systemDic: 'systemDic', limits: 'limits', limitsFrontEnd: 'FrontEnd', limitsFrontEndPage: 'FrontEndPage', diff --git a/src/i18n/lang/zh-cn.ts b/src/i18n/lang/zh-cn.ts index a3a7946..deb2c4f 100644 --- a/src/i18n/lang/zh-cn.ts +++ b/src/i18n/lang/zh-cn.ts @@ -4,7 +4,10 @@ export default { home: '首页', system: '系统设置', systemMenu: '菜单管理', + systemRole: '角色管理', systemUser: '用户管理', + systemDept: '部门管理', + systemDic: '字典管理', limits: '权限管理', limitsFrontEnd: '前端控制', limitsFrontEndPage: '页面权限', diff --git a/src/i18n/lang/zh-tw.ts b/src/i18n/lang/zh-tw.ts index 1bd381d..cf3378f 100644 --- a/src/i18n/lang/zh-tw.ts +++ b/src/i18n/lang/zh-tw.ts @@ -4,7 +4,10 @@ export default { home: '首頁', system: '系統設置', systemMenu: '選單管理', + systemRole: '角色管理', systemUser: '用戶管理', + systemDept: '部門管理', + systemDic: '字典管理', limits: '許可權管理', limitsFrontEnd: '前端控制', limitsFrontEndPage: '頁面許可權', diff --git a/src/layout/component/columnsAside.vue b/src/layout/component/columnsAside.vue index 37e3513..61bcde9 100644 --- a/src/layout/component/columnsAside.vue +++ b/src/layout/component/columnsAside.vue @@ -16,7 +16,7 @@ :title="$t(v.meta.title)" >
- +
{{ $t(v.meta.title) && $t(v.meta.title).length >= 4 @@ -27,7 +27,7 @@
- +
{{ $t(v.meta.title) && $t(v.meta.title).length >= 4 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 057ded3..b8d4cb9 100644 --- a/src/layout/navBars/breadcrumb/breadcrumb.vue +++ b/src/layout/navBars/breadcrumb/breadcrumb.vue @@ -1,18 +1,18 @@
- + + +
@@ -35,7 +37,9 @@ @@ -54,7 +58,9 @@ {{ getUserInfos.userName === '' ? 'test' : getUserInfos.userName }} - + + + @@ -42,10 +42,10 @@ export default defineComponent({ const state = reactive({ isShow: false, dropdownList: [ - { contextMenuClickId: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'el-icon-refresh-right' }, - { contextMenuClickId: 1, txt: 'message.tagsView.close', affix: false, icon: 'el-icon-close' }, - { contextMenuClickId: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'el-icon-circle-close' }, - { contextMenuClickId: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'el-icon-folder-delete' }, + { contextMenuClickId: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'elementRefreshRight' }, + { contextMenuClickId: 1, txt: 'message.tagsView.close', affix: false, icon: 'elementClose' }, + { contextMenuClickId: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'elementCircleClose' }, + { contextMenuClickId: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'elementFolderDelete' }, { contextMenuClickId: 4, txt: 'message.tagsView.fullscreen', diff --git a/src/layout/navBars/tagsView/tagsView.vue b/src/layout/navBars/tagsView/tagsView.vue index a3243a6..d33466e 100644 --- a/src/layout/navBars/tagsView/tagsView.vue +++ b/src/layout/navBars/tagsView/tagsView.vue @@ -17,21 +17,23 @@ " > - + {{ $t(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; // 当前滚动条偏移宽度 @@ -507,6 +509,8 @@ export default { .layout-navbars-tagsview { background-color: var(--el-color-white); border-bottom: 1px solid #f1f2f3; + position: relative; + z-index: 4; ::v-deep(.el-scrollbar__wrap) { overflow-x: auto !important; } diff --git a/src/layout/navMenu/horizontal.vue b/src/layout/navMenu/horizontal.vue index 1fcb694..b387445 100644 --- a/src/layout/navMenu/horizontal.vue +++ b/src/layout/navMenu/horizontal.vue @@ -5,19 +5,19 @@ diff --git a/src/views/fun/qrcode/index.vue b/src/views/fun/qrcode/index.vue index 2536aed..85b4b7f 100644 --- a/src/views/fun/qrcode/index.vue +++ b/src/views/fun/qrcode/index.vue @@ -11,7 +11,12 @@
- 重新生成 + + + + + 重新生成 +
diff --git a/src/views/fun/screenShort/index.vue b/src/views/fun/screenShort/index.vue index 2306dc0..d476dcf 100644 --- a/src/views/fun/screenShort/index.vue +++ b/src/views/fun/screenShort/index.vue @@ -8,7 +8,10 @@ class="mb15" > - 点击截屏 + + + 点击截屏 +
diff --git a/src/views/fun/selector/index.vue b/src/views/fun/selector/index.vue index fb9d8b8..dbdce9f 100644 --- a/src/views/fun/selector/index.vue +++ b/src/views/fun/selector/index.vue @@ -1,6 +1,6 @@ diff --git a/src/views/limits/frontEnd/btn/index.vue b/src/views/limits/frontEnd/btn/index.vue index 3acafbc..f0184dc 100644 --- a/src/views/limits/frontEnd/btn/index.vue +++ b/src/views/limits/frontEnd/btn/index.vue @@ -8,28 +8,48 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -40,28 +60,48 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -72,28 +112,48 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -106,22 +166,42 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -130,22 +210,42 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -154,22 +254,42 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
- 跳转 + + + + + 跳转 +
@@ -181,17 +301,32 @@
- 新增 + + + + + 新增 +
- 编辑 + + + + + 编辑 +
- 删除 + + + + + 删除 +
diff --git a/src/views/limits/frontEnd/page/index.vue b/src/views/limits/frontEnd/page/index.vue index 08ea1d7..0df9540 100644 --- a/src/views/limits/frontEnd/page/index.vue +++ b/src/views/limits/frontEnd/page/index.vue @@ -8,7 +8,7 @@ :closable="false" > { - return store.state.userInfos.userInfos.authPageList; + const getRoles = computed(() => { + return store.state.userInfos.userInfos.roles; }); // 获取用户按钮权限信息 const getAuthBtnList = computed(() => { @@ -45,27 +45,28 @@ export default { }); // 初始化用户权限 const initUserAuth = () => { - state.userAuth = store.state.userInfos.userInfos.authPageList[0]; + state.userAuth = store.state.userInfos.userInfos.roles[0]; }; // 用户权限改变时 const onRadioChange = async () => { + // 模拟数据 resetRoute(); - 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 testRoles: Array = ['common']; // test 按钮权限标识 let testAuthBtnList: Array = ['btn.add', 'btn.link']; // 不同用户模拟不同的用户权限 if (state.userAuth === 'admin') { - defaultAuthPageList = adminAuthPageList; + defaultRoles = adminRoles; defaultAuthBtnList = adminAuthBtnList; } else { - defaultAuthPageList = testAuthPageList; + defaultRoles = testRoles; defaultAuthBtnList = testAuthBtnList; } const userInfos = { @@ -75,7 +76,7 @@ export default { ? '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, }; Session.set('userInfo', userInfos); @@ -88,7 +89,7 @@ export default { initUserAuth(); }); return { - getAuthPageList, + getRoles, getAuthBtnList, onRadioChange, ...toRefs(state), diff --git a/src/views/login/component/account.vue b/src/views/login/component/account.vue index ee6aab4..b0f00b7 100644 --- a/src/views/login/component/account.vue +++ b/src/views/login/component/account.vue @@ -1,24 +1,22 @@