This commit is contained in:
zsen hu 2021-09-26 12:16:46 +08:00
parent 21febfbaa5
commit b683825beb
23 changed files with 831 additions and 76 deletions

39
package-lock.json generated
View File

@ -553,6 +553,12 @@
} }
} }
}, },
"@element-plus/icons": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/@element-plus/icons/-/icons-0.0.11.tgz",
"integrity": "sha512-iKQXSxXu131Ai+I9Ymtcof9WId7kaXvB1+WRfAfpQCW7UiAMYgdNDqb/u0hgTo2Yq3MwC4MWJnNuTBEpG8r7+A==",
"dev": true
},
"@eslint/eslintrc": { "@eslint/eslintrc": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz",
@ -610,9 +616,9 @@
} }
}, },
"@popperjs/core": { "@popperjs/core": {
"version": "2.9.1", "version": "2.10.1",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.9.1.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz",
"integrity": "sha512-DvJbbn3dUgMxDnJLH+RZQPnXak1h4ZVYQ7CWiFWjQwBFkVajT4rfw2PdpHLTSTwxrYfnoEXkuBiwkDm6tPMQeA==", "integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw==",
"dev": true "dev": true
}, },
"@rollup/plugin-node-resolve": { "@rollup/plugin-node-resolve": {
@ -954,9 +960,9 @@
"dev": true "dev": true
}, },
"async-validator": { "async-validator": {
"version": "3.5.1", "version": "3.5.2",
"resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.5.1.tgz", "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-3.5.2.tgz",
"integrity": "sha512-DDmKA7sdSAJtTVeNZHrnr2yojfFaoeW8MfQN8CeuXg8DDQHTqKk9Fdv38dSvnesHoO8MUwMI2HphOeSyIF+wmQ==", "integrity": "sha512-8eLCg00W9pIRZSB781UUX/H6Oskmm8xloZfr09lz5bikRpBVDlJ3hRVuxxP1SxcwsEYfJ4IU8Q19Y8/893r3rQ==",
"dev": true "dev": true
}, },
"at-least-node": { "at-least-node": {
@ -1540,9 +1546,9 @@
"dev": true "dev": true
}, },
"dayjs": { "dayjs": {
"version": "1.10.4", "version": "1.10.7",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.4.tgz", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz",
"integrity": "sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw==", "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==",
"dev": true "dev": true
}, },
"debug": { "debug": {
@ -1751,11 +1757,12 @@
"dev": true "dev": true
}, },
"element-plus": { "element-plus": {
"version": "1.0.2-beta.35", "version": "1.0.2-beta.71",
"resolved": "https://registry.npmjs.org/element-plus/-/element-plus-1.0.2-beta.35.tgz", "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-1.0.2-beta.71.tgz",
"integrity": "sha512-T12EfxbWoNOrWE2bzXFPJdOU3cl4YWuLwxE5QKM40oPw1VYPMRrRB8Uy5TwF8h3itxzsJQ5iFj2rdDO+q3Jcdg==", "integrity": "sha512-tlfbRORIav8gJcIpjZI5F6aJIVHIaDuGO6/vKu43lgYq4JS2JPNRTjvrSE2p4f5xLfaFNfOWjCS3sybXLfMg8g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@element-plus/icons": "^0.0.11",
"@popperjs/core": "^2.4.4", "@popperjs/core": "^2.4.4",
"async-validator": "^3.4.0", "async-validator": "^3.4.0",
"dayjs": "1.x", "dayjs": "1.x",
@ -4773,12 +4780,12 @@
"dev": true "dev": true
}, },
"sass": { "sass": {
"version": "1.32.8", "version": "1.41.1",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.32.8.tgz", "resolved": "https://registry.npmjs.org/sass/-/sass-1.41.1.tgz",
"integrity": "sha512-Sl6mIeGpzjIUZqvKnKETfMf0iDAswD9TNlv13A7aAF3XZlRPMq4VvJWBC2N2DXbp94MQVdNSFG6LfF/iOXrPHQ==", "integrity": "sha512-vIjX7izRxw3Wsiez7SX7D+j76v7tenfO18P59nonjr/nzCkZuoHuF7I/Fo0ZRZPKr88v29ivIdE9BqGDgQD/Nw==",
"dev": true, "dev": true,
"requires": { "requires": {
"chokidar": ">=2.0.0 <4.0.0" "chokidar": ">=3.0.0 <4.0.0"
} }
}, },
"semver": { "semver": {

View File

@ -33,7 +33,7 @@
"autoprefixer": "^10.2.5", "autoprefixer": "^10.2.5",
"babel-eslint": "^10.1.0", "babel-eslint": "^10.1.0",
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"element-plus": "^1.0.2-beta.35", "element-plus": "^1.0.2-beta.71",
"eslint": "^6.7.2", "eslint": "^6.7.2",
"eslint-plugin-prettier": "^3.1.3", "eslint-plugin-prettier": "^3.1.3",
"eslint-plugin-vue": "^7.0.0-0", "eslint-plugin-vue": "^7.0.0-0",
@ -41,7 +41,7 @@
"lint-staged": "^9.5.0", "lint-staged": "^9.5.0",
"mockjs": "^1.1.0", "mockjs": "^1.1.0",
"prettier": "^1.19.1", "prettier": "^1.19.1",
"sass": "^1.32.8", "sass": "^1.41.1",
"vite": "^2.1.0", "vite": "^2.1.0",
"vite-plugin-mock": "^2.3.0", "vite-plugin-mock": "^2.3.0",
"vite-plugin-svg-icons": "^0.4.0" "vite-plugin-svg-icons": "^0.4.0"

View File

@ -24,7 +24,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-23 17:26:35 * @LastEditTime: 2021-09-18 13:17:44
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -32,9 +32,29 @@
--> -->
<template> <template>
<el-config-provider :locale="locale">
<router-view /> <router-view />
</el-config-provider>
</template> </template>
<script>
import { defineComponent } from 'vue'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/lib/locale/lang/zh-cn'
export default defineComponent({
components: {
[ElConfigProvider.name]: ElConfigProvider,
},
data() {
return {
locale: zhCn,
}
},
})
</script>
<style lang="scss"> <style lang="scss">
html, html,
body, body,

View File

@ -1,7 +1,11 @@
/* 改变主题色变量 */ /* 改变主题色变量 */
$--color-primary: $mainColor; $--colors: (
'primary': (
'base': $mainColor,
),
);
/* 改变 icon 字体路径变量,必需 */ /* 改变 icon 字体路径变量,必需 */
$--font-path: "element-plus/lib/theme-chalk/fonts"; $--font-path: 'element-plus/lib/theme-chalk/fonts';
@import 'element-plus/packages/theme-chalk/src/reset';
@import "element-plus/packages/theme-chalk/src/index"; @import 'element-plus/packages/theme-chalk/src/index';

View File

@ -0,0 +1,202 @@
<!--
* ......................................&&.........................
* ....................................&&&..........................
* .................................&&&&............................
* ...............................&&&&..............................
* .............................&&&&&&..............................
* ...........................&&&&&&....&&&..&&&&&&&&&&&&&&&........
* ..................&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&..............
* ................&...&&&&&&&&&&&&&&&&&&&&&&&&&&&&.................
* .......................&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.........
* ...................&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&...............
* ..................&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&............
* ...............&&&&&@ &&&&&&&&&&..&&&&&&&&&&&&&&&&&&&...........
* ..............&&&&&&&&&&&&&&&.&&....&&&&&&&&&&&&&..&&&&&.........
* ..........&&&&&&&&&&&&&&&&&&...&.....&&&&&&&&&&&&&...&&&&........
* ........&&&&&&&&&&&&&&&&&&&.........&&&&&&&&&&&&&&&....&&&.......
* .......&&&&&&&&.....................&&&&&&&&&&&&&&&&.....&&......
* ........&&&&&.....................&&&&&&&&&&&&&&&&&&.............
* ..........&...................&&&&&&&&&&&&&&&&&&&&&&&............
* ................&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&............
* ..................&&&&&&&&&&&&&&&&&&&&&&&&&&&&..&&&&&............
* ..............&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&....&&&&&............
* ...........&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&......&&&&............
* .........&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.........&&&&............
* .......&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&...........&&&&............
* ......&&&&&&&&&&&&&&&&&&&...&&&&&&...............&&&.............
* .....&&&&&&&&&&&&&&&&............................&&..............
* ....&&&&&&&&&&&&&&&.................&&...........................
* ...&&&&&&&&&&&&&&&.....................&&&&......................
* ...&&&&&&&&&&.&&&........................&&&&&...................
* ..&&&&&&&&&&&..&&..........................&&&&&&&...............
* ..&&&&&&&&&&&&...&............&&&.....&&&&...&&&&&&&.............
* ..&&&&&&&&&&&&&.................&&&.....&&&&&&&&&&&&&&...........
* ..&&&&&&&&&&&&&&&&..............&&&&&&&&&&&&&&&&&&&&&&&&.........
* ..&&.&&&&&&&&&&&&&&&&&.........&&&&&&&&&&&&&&&&&&&&&&&&&&&.......
* ...&&..&&&&&&&&&&&&.........&&&&&&&&&&&&&&&&...&&&&&&&&&&&&......
* ....&..&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&...........&&&&&&&&.....
* .......&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&..............&&&&&&&....
* .......&&&&&.&&&&&&&&&&&&&&&&&&..&&&&&&&&...&..........&&&&&&....
* ........&&&.....&&&&&&&&&&&&&.....&&&&&&&&&&...........&..&&&&...
* .......&&&........&&&.&&&&&&&&&.....&&&&&.................&&&&...
* .......&&&...............&&&&&&&.......&&&&&&&&............&&&...
* ........&&...................&&&&&&.........................&&&..
* .........&.....................&&&&........................&&....
* ...............................&&&.......................&&......
* ................................&&......................&&.......
* .................................&&..............................
* ..................................&..............................
*
* @Descripttion:
* @version:
* @Date: 2021-08-30 14:19:46
* @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-09-18 18:18:35
* @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
-->
<template>
<el-select
ref="select"
class="select"
style="width:100%"
clearable
:multiple="multiple"
v-model="selectValue"
:value-key="treeProps.label"
@remove-tag="handleRemove"
@clear="handleClear"
popper-class="select-popover"
:popper-append-to-body="false"
collapse-tags
:placeholder="placeholder"
>
<el-option
v-for="(item, index) in selectOptions"
:key="index"
:label="item[treeProps.label]"
:value="item"
/>
</el-select>
</template>
<script>
import {
defineComponent,
onBeforeMount,
reactive,
ref,
watch,
toRefs,
inject,
} from 'vue'
export default defineComponent({
props: {
value: {},
data: {
type: Array,
default() {
return []
},
},
multiple: {
type: Boolean,
default() {
return false
},
},
treeProps: {
type: Object,
default() {
return {}
},
},
},
setup(props, { emit }) {
const {
multiple,
treeProps: { label, children, nodeKey },
} = props
const state = reactive({
select: ref(null),
newValue: null,
selectValue: '',
selectOptions: [],
placeholder: inject('placeholder'),
updateSelectValue(values) {
if (!values || state.selectOptions.length <= 0) {
return
}
state.selectValue = multiple
? state.selectOptions.filter(item => values.includes(item[nodeKey]))
: state.selectOptions.find(item => values === item[nodeKey]) || {}
},
updateSelectOptions(data) {
state.selectOptions = state.flatTree(data)
},
flatTree(tree) {
const res = []
tree.forEach(item => {
res.push({
[nodeKey]: item[nodeKey],
[label]: item[label],
})
if (item[children] && item[children].length > 0) {
res.push(...state.flatTree(item[children]))
}
})
return res
},
handleRemove() {
emit(
'select-change',
multiple
? state.selectValue.map(item => item[nodeKey])
: state.selectValue[nodeKey]
)
},
handleClear() {
emit('select-change', multiple ? [] : '')
},
})
watch(
() => props.data,
v => {
state.updateSelectOptions(v)
state.updateSelectValue(state.newValue)
},
{
immediate: true,
}
)
watch(
() => props.value,
v => {
state.newValue = v
state.updateSelectValue(state.newValue)
},
{
immediate: true,
}
)
onBeforeMount(() => {
state.updateSelectOptions(props.data)
})
return toRefs(state)
},
})
</script>
<style lang="scss" scoped>
.select {
:deep(.select-popover) {
display: none;
}
}
</style>

View File

@ -0,0 +1,130 @@
<!--
* 江城子 . 程序员之歌
*
* 十年生死两茫茫写程序到天亮
* 千行代码Bug何处藏
* 纵使上线又怎样朝令改夕断肠
*
* 领导每天新想法天天改日日忙
* 相顾无言惟有泪千行
* 每晚灯火阑珊处夜难寐加班狂
*
*
* @Descripttion:
* @version:
* @Date: 2021-09-18 17:17:46
* @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-09-18 18:20:15
* @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
-->
<template>
<div v-if="data.length <= 0" style="text-align:center;padding: 16px">
暂无数据
</div>
<el-tree
v-else
class="common-tree"
ref="tree"
:data="data"
:node-key="nodeKey"
:show-checkbox="multiple"
:check-strictly="treeProps['check-strictly'] || true"
:expand-on-click-node="false"
:check-on-click-node="true"
:default-expanded-keys="treeProps['default-expanded-keys'] || value"
:default-checked-keys="value"
@node-click="handleNodeClick"
@check-change="handleCheckChange"
v-bind="treeProps"
></el-tree>
</template>
<script>
import { defineComponent, reactive, ref, toRefs, watch } from 'vue'
export default defineComponent({
props: {
value: {
type: Array,
default: () => [],
},
data: {
type: Array,
default() {
return []
},
},
multiple: {
type: Boolean,
default() {
return false
},
},
treeProps: {
type: Object,
default() {
return {}
},
},
},
setup(props, { emit }) {
const { multiple, treeProps } = props
const state = reactive({
nodeKey: treeProps['node-key'] || 'id',
tree: ref(null),
handleNodeClick(node) {
if (!multiple) {
state.tree.setCheckedKeys([node[state.nodeKey]])
state.hanelEmit()
emit('close')
}
},
handleCheckChange() {
if (!multiple) {
return
}
state.hanelEmit()
},
hanelEmit() {
const res = state.tree.getCheckedKeys()
emit('tree-change', multiple ? res : res[0] || '')
},
updateValue(value) {
if (state.tree) {
state.tree.setCheckedKeys(value)
// state.hanelEmit()
}
},
})
watch(
() => props.value,
v => {
state.updateValue(v)
},
{
immediate: true,
}
)
return toRefs(state)
},
})
</script>
<style lang="scss" scoped>
.common-tree {
overflow: auto;
:deep {
.el-tree-node {
&.is-checked {
> .el-tree-node__content {
color: $mainColor;
}
}
}
}
}
</style>

View File

@ -0,0 +1,145 @@
<!--
*
* Esc F1 F2 F3 F4 F5 F6 F7 F8 F9F10F11F12 P/SS LP/B
*
*
* ~ `│! 1│@ 2│# 3│$ 4│% 5│^ 6│& 7│* 8│( 9│) 0│_ -│+ =│ BacSp │ │Ins│Hom│PUp│ │N L│ / │ * │ - │
*
* Tab Q W E R T Y U I O P { [} ] | \ DelEndPDn 7 8 9
* +
* Caps A S D F G H J K L : ;" ' Enter 4 5 6
*
* Shift Z X C V B N M < ,> .? / Shift 1 2 3
* E
* Ctrl Alt Space Alt Ctrl 0 .
*
*
* @Descripttion:
* @version:
* @Date: 2021-09-18 17:17:46
* @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-09-18 17:17:59
* @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
-->
<template>
<el-popover
ref="popover"
placement="bottom-start"
trigger="click"
:popper-options="{ boundariesElement: 'viewport' }"
v-model:visible="visible"
:disabled="disabled"
>
<tree
ref="tree"
:value="is_multiple ? modelValue : modelValue ? [modelValue] : []"
:data="data || treeProps.data"
:multiple="is_multiple"
:tree-props="treeProps"
@tree-change="handleTreeChange"
@close="visible = false"
/>
<template #reference>
<custom-select
ref="select"
:value="modelValue"
:data="data || treeProps.data"
:multiple="is_multiple"
:tree-props="{ children, label, nodeKey }"
@select-change="handleSelectChange"
/>
</template>
</el-popover>
</template>
<script>
import { defineComponent, reactive, ref, toRefs, onMounted, provide } from 'vue'
import Tree from './Tree.vue'
import CustomSelect from './Select.vue'
export default defineComponent({
name: 'el-select-tree',
components: {
Tree,
CustomSelect,
},
props: {
modelValue: {},
disabled: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '请选择',
},
data: {
type: Array,
default() {
return []
},
},
multiple: {
type: Boolean,
default() {
return false
},
},
treeProps: {
type: Object,
default() {
return {}
},
},
},
setup(props, { emit }) {
provide('placeholder', props.placeholder)
const { treeProps, multiple } = props
const state = reactive({
popover: ref(null),
visible: false,
select: ref(null),
tree: ref(null),
is_multiple: multiple || treeProps['show-checkbox'],
label:
treeProps.props && treeProps.props.label
? treeProps.props.label
: 'label',
children:
treeProps.props && treeProps.props.children
? treeProps.props.children
: 'children',
nodeKey: treeProps['node-key'] || 'id',
handleTreeChange(value) {
emit('update:modelValue', value)
emit('change', value)
},
handleSelectChange(value) {
// state.tree.updateValue(value)
emit('update:modelValue', value)
emit('change', value)
},
initPopoverStyle(width) {
state.popover.popperRef.style.minWidth = width
state.popover.popperRef.style.boxSizing = 'border-box'
state.popover.popperRef.style.maxHeight = '400px'
state.popover.popperRef.style.overflow = 'auto'
},
})
onMounted(() => {
state.initPopoverStyle(
state.select.select.selectWrapper.offsetWidth + 'px'
)
})
return toRefs(state)
},
})
</script>

View File

@ -44,7 +44,7 @@
* @version: * @version:
* @Date: 2021-07-22 17:22:14 * @Date: 2021-07-22 17:22:14
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-23 14:44:42 * @LastEditTime: 2021-09-18 15:02:01
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -53,6 +53,8 @@
export default { export default {
menus: { menus: {
// 菜单栏是否显示
isShow: true,
// 菜单栏排列方式 // 菜单栏排列方式
mode: 'vertical', // horizontal: 水平排列 vertical: 垂直排列 mode: 'vertical', // horizontal: 水平排列 vertical: 垂直排列
}, },

View File

@ -1,33 +1,20 @@
/* /*
* _______________#########_______________________ * 江城子 . 程序员之歌
* ______________############_____________________ *
* ______________#############____________________ * 十年生死两茫茫写程序到天亮
* _____________##__###########___________________ * 千行代码Bug何处藏
* ____________###__######_#####__________________ * 纵使上线又怎样朝令改夕断肠
* ____________###_#######___####_________________ *
* ___________###__##########_####________________ * 领导每天新想法天天改日日忙
* __________####__###########_####_______________ * 相顾无言惟有泪千行
* ________#####___###########__#####_____________ * 每晚灯火阑珊处夜难寐加班狂
* _______######___###_########___#####___________ *
* _______#####___###___########___######_________
* ______######___###__###########___######_______
* _____######___####_##############__######______
* ____#######__#####################_#######_____
* ____#######__##############################____
* ___#######__######_#################_#######___
* ___#######__######_######_#########___######___
* ___#######____##__######___######_____######___
* ___#######________######____#####_____#####____
* ____######________#####_____#####_____####_____
* _____#####________####______#####_____###______
* ______#####______;###________###______#________
* ________##_______####________####______________
* *
* @Descripttion: * @Descripttion:
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-09-18 09:32:01
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-21 12:48:53 * @LastEditTime: 2021-09-18 17:54:29
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -36,3 +23,4 @@
export { default as SvgIcon } from '@/components/SvgIcon/index.vue' export { default as SvgIcon } from '@/components/SvgIcon/index.vue'
export { default as ProTable } from '@/components/ProTable/index.vue' export { default as ProTable } from '@/components/ProTable/index.vue'
export { default as ElSelectTree } from '@/components/SelectTree/index.vue'

69
src/hooks/useCloseTag.js Normal file
View File

@ -0,0 +1,69 @@
/*
*
*      + +
*   + +
*         
*         ++ + + +
* +
*          +
*        
*          + +
*     
*       
*        + + + +
*       
*        + 神兽保佑
*        代码无bug
*         +
*         + +
*            
*            
*     + + + +
*      
*      + + + +
*
*
* @Descripttion:
* @version:
* @Date: 2021-08-20 11:15:27
* @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-09-18 17:25:32
* @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
*/
import { reactive, toRefs, getCurrentInstance } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useStore } from 'vuex'
// 关闭当前标签
export default () => {
const instance = getCurrentInstance()
const store = useStore()
const router = useRouter()
const route = useRoute()
const state = reactive({
/**
* @param {String} fullPath 要跳转到那个页面的地址
* @param {Boolean} reload 是否在跳转后重新渲染页面组件
* @param {Boolean} f5 是否在跳转后刷新页面
* @return {*}
*/
closeTag({ fullPath, reload, f5 } = {}) {
store.dispatch('tags/delTag', route)
fullPath ? router.push(fullPath) : router.back()
reload &&
setTimeout(() => {
instance.appContext.config.globalProperties.$tagsbar.refreshSelectedTag(
route
)
}, 500)
f5 && setTimeout(() => window.location.reload(), 500)
},
})
return toRefs(state)
}

View File

@ -13,7 +13,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-23 16:48:37 * @LastEditTime: 2021-09-18 17:50:46
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -68,13 +68,17 @@
</template> </template>
<script> <script>
import { defineComponent, computed } from 'vue' import { defineComponent, computed, getCurrentInstance } from 'vue'
import { useTags } from './hooks/useTags' import { useTags } from './hooks/useTags'
import { useContextMenu } from './hooks/useContextMenu' import { useContextMenu } from './hooks/useContextMenu'
import { useStore } from 'vuex' import { useStore } from 'vuex'
export default defineComponent({ export default defineComponent({
name: 'Tagsbar', name: 'Tagsbar',
mounted() {
const instance = getCurrentInstance()
instance.appContext.config.globalProperties.$tagsbar = this
},
setup() { setup() {
const store = useStore() const store = useStore()
const defaultSettings = computed(() => store.state.layoutSettings) const defaultSettings = computed(() => store.state.layoutSettings)

View File

@ -37,7 +37,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-23 15:01:18 * @LastEditTime: 2021-09-18 15:39:30
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -87,8 +87,6 @@ export default defineComponent({
const logout = () => { const logout = () => {
// token // token
store.dispatch('app/clearToken') store.dispatch('app/clearToken')
//
store.dispatch('tags/delAllTags')
router.push('/login') router.push('/login')
} }

View File

@ -27,7 +27,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-23 17:19:35 * @LastEditTime: 2021-09-18 14:58:53
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -36,11 +36,11 @@
<template> <template>
<div class="wrapper" :class="{ fluid: isFluid }"> <div class="wrapper" :class="{ fluid: isFluid }">
<sidebar v-if="!isHorizontalMenu" /> <sidebar v-if="isMenusShow && !isHorizontalMenu" />
<div class="right" :class="{ flex: isTopbarFixed }"> <div class="right" :class="{ flex: isTopbarFixed }">
<div class="top"> <div class="top">
<topbar /> <topbar />
<menus mode="horizontal" v-if="isHorizontalMenu" /> <menus mode="horizontal" v-if="isMenusShow && isHorizontalMenu" />
<tagsbar /> <tagsbar />
<breadcrumbs <breadcrumbs
v-if="isBreadcrumbsShow" v-if="isBreadcrumbsShow"
@ -80,6 +80,7 @@ export default defineComponent({
const defaultSettings = computed(() => store.state.layoutSettings) const defaultSettings = computed(() => store.state.layoutSettings)
const isFluid = computed(() => defaultSettings.value.layout.isFluid) const isFluid = computed(() => defaultSettings.value.layout.isFluid)
const isTopbarFixed = computed(() => defaultSettings.value.topbar.isFixed) const isTopbarFixed = computed(() => defaultSettings.value.topbar.isFixed)
const isMenusShow = computed(() => defaultSettings.value.menus.isShow)
const isHorizontalMenu = computed( const isHorizontalMenu = computed(
() => defaultSettings.value.menus.mode === 'horizontal' () => defaultSettings.value.menus.mode === 'horizontal'
) )
@ -94,6 +95,7 @@ export default defineComponent({
return { return {
isFluid, isFluid,
isTopbarFixed, isTopbarFixed,
isMenusShow,
isHorizontalMenu, isHorizontalMenu,
isBreadcrumbsShow, isBreadcrumbsShow,
paddingFlag, paddingFlag,

View File

@ -26,14 +26,15 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-26 18:28:31 * @LastEditTime: 2021-09-18 17:43:01
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
* @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/ * @Donate: https://huzhushan.gitee.io/vue3-element-admin/donate/
*/ */
import router from '@/router' import { ElLoading } from 'element-plus'
import router, { asyncRoutes } from '@/router'
import store from '@/store' import store from '@/store'
import { TOKEN } from '@/store/modules/app' // TOKEN变量名 import { TOKEN } from '@/store/modules/app' // TOKEN变量名
@ -68,17 +69,35 @@ router.beforeEach(async to => {
let userinfo = store.state.account.userinfo let userinfo = store.state.account.userinfo
if (!userinfo) { if (!userinfo) {
try { try {
const loadingInstance = ElLoading.service({
lock: true,
text: '正在加载数据,请稍候~',
background: 'rgba(0, 0, 0, 0.7)',
})
// 获取用户信息 // 获取用户信息
userinfo = await store.dispatch('account/getUserinfo') userinfo = await store.dispatch('account/getUserinfo')
loadingInstance.close()
} catch (err) { } catch (err) {
return false return false
} }
// 删除所有动态路由
asyncRoutes.forEach(item => {
router.removeRoute(item.name)
})
return to.fullPath
} }
// 生成菜单(如果你的项目有动态菜单,在此处会添加动态路由) // 生成菜单(如果你的项目有动态菜单,在此处会添加动态路由)
if (store.state.menu.menus.length <= 0) { if (store.state.menu.menus.length <= 0) {
try { try {
const loadingInstance = ElLoading.service({
lock: true,
text: '正在加载数据,请稍候~',
background: 'rgba(0, 0, 0, 0.7)',
})
await store.dispatch('menu/generateMenus', userinfo) await store.dispatch('menu/generateMenus', userinfo)
loadingInstance.close()
return to.fullPath // 添加动态路由后必须加这一句触发重定向否则会404 return to.fullPath // 添加动态路由后必须加这一句触发重定向否则会404
} catch (err) { } catch (err) {
return false return false

View File

@ -3,7 +3,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-21 09:34:31 * @LastEditTime: 2021-09-18 16:23:58
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -11,10 +11,10 @@
*/ */
import store from '@/store' import store from '@/store'
const checkUserinfo = code => { const checkUserinfo = (code, fullPath) => {
const userinfo = store.state.account.userinfo const userinfo = store.state.account.userinfo
if (userinfo) { if (userinfo) {
return `/error/${code}` return `/error/${code === '404' ? fullPath : code}`
} }
return true return true
} }
@ -46,7 +46,7 @@ export default [
}, },
}, },
{ {
path: '404', path: ':pathMatch(.*)',
name: 'error-not-found', name: 'error-not-found',
component: Error, component: Error,
meta: { title: '404' }, meta: { title: '404' },
@ -85,8 +85,8 @@ export default [
props: { props: {
error: '404', error: '404',
}, },
beforeEnter() { beforeEnter(to) {
return checkUserinfo('404') return checkUserinfo('404', to.fullPath.replace('/', ''))
}, },
}, },
] ]

View File

@ -3,7 +3,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-28 09:38:35 * @LastEditTime: 2021-09-18 15:40:50
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -56,6 +56,10 @@ export default {
commit('clearToken') commit('clearToken')
// 清除用户信息 // 清除用户信息
commit('account/clearUserinfo', '', { root: true }) commit('account/clearUserinfo', '', { root: true })
// 清除标签栏
commit('tags/CLEAR_ALL_TAGS', '', { root: true })
// 清空menus
commit('menu/SET_MENUS', [], { root: true })
}, },
setScreenCode({ commit, state }, password) { setScreenCode({ commit, state }, password) {
const authorization = toRaw(state.authorization) const authorization = toRaw(state.authorization)

View File

@ -27,7 +27,7 @@
* @version: * @version:
* @Date: 2021-07-23 16:10:49 * @Date: 2021-07-23 16:10:49
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-07-23 16:19:35 * @LastEditTime: 2021-09-18 15:03:26
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -35,7 +35,7 @@
*/ */
import { getItem, setItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法 import { getItem, setItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
import defaultSettings from '@/defaultSettings' import defaultSettings from '@/default-settings'
export default { export default {
namespaced: true, namespaced: true,
state: getItem('defaultSettings') || defaultSettings, state: getItem('defaultSettings') || defaultSettings,

View File

@ -3,7 +3,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-29 11:19:20 * @LastEditTime: 2021-09-18 15:36:04
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -93,7 +93,12 @@ const mutations = {
DEL_ALL_CACHE_LIST: state => { DEL_ALL_CACHE_LIST: state => {
state.cacheList = [] state.cacheList = []
}, },
CLEAR_ALL_TAGS: state => {
state.cacheList = []
state.tagList = []
// 保存到localStorage
removeItem(TAGLIST)
},
UPDATE_TAG_LIST: (state, tag) => { UPDATE_TAG_LIST: (state, tag) => {
const index = state.tagList.findIndex(v => v.path === tag.path) const index = state.tagList.findIndex(v => v.path === tag.path)
if (index > -1) { if (index > -1) {

View File

@ -22,7 +22,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-21 12:48:30 * @LastEditTime: 2021-09-18 15:44:39
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -69,10 +69,21 @@ service.interceptors.response.use(
// 校验是否有 refresh_token // 校验是否有 refresh_token
const { authorization } = store.state.app const { authorization } = store.state.app
if (!authorization || !authorization.refresh_token) { if (!authorization || !authorization.refresh_token) {
if (router.currentRoute.value.name === 'login') {
return Promise.reject(error)
}
const redirect = encodeURIComponent(window.location.href) const redirect = encodeURIComponent(window.location.href)
router.push(`/login?redirect=${redirect}`) router.push(`/login?redirect=${redirect}`)
// 清除token // 清除token
store.dispatch('app/clearToken') store.dispatch('app/clearToken')
setTimeout(() => {
ElMessage.closeAll()
try {
ElMessage.error(error.response.data.msg)
} catch (err) {
ElMessage.error(error.message)
}
})
// 代码不要往后执行了 // 代码不要往后执行了
return Promise.reject(error) return Promise.reject(error)
} }
@ -108,7 +119,12 @@ service.interceptors.response.use(
} }
// console.dir(error) // 可在此进行错误上报 // console.dir(error) // 可在此进行错误上报
ElMessage.closeAll()
try {
ElMessage.error(error.response.data.msg)
} catch (err) {
ElMessage.error(error.message) ElMessage.error(error.message)
}
return Promise.reject(error) return Promise.reject(error)
} }

View File

@ -3,7 +3,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-21 09:33:38 * @LastEditTime: 2021-09-18 18:10:39
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -16,4 +16,111 @@
<br /> <br />
需要配置路由增加属性hidden: true注意不是在meta中增加该属性而是跟meta同级 需要配置路由增加属性hidden: true注意不是在meta中增加该属性而是跟meta同级
</div> </div>
<hr />
<div style="width: 400px">
<el-select-tree
placeholder="请选择角色"
v-model="roles"
:multiple="true"
:data="treeData"
:tree-props="treeProps"
@change="handleChange"
/>
</div>
</template> </template>
<script>
import { defineComponent, reactive, toRefs } from 'vue'
export default defineComponent({
setup() {
const state = reactive({
roles: ['11', '311'],
treeData: [
{
id: '1',
label: '一级 1',
children: [
{
id: '11',
label: '二级 1-1',
children: [
{
id: '111',
label: '三级 1-1-1',
},
],
},
],
},
{
id: '2',
label: '一级 2',
children: [
{
id: '21',
label: '二级 2-1',
children: [
{
id: '211',
label: '三级 2-1-1',
},
],
},
{
id: '22',
label: '二级 2-2',
children: [
{
id: '221',
label: '三级 2-2-1',
},
],
},
],
},
{
id: '3',
label: '一级 3',
children: [
{
id: '31',
label: '二级 3-1',
children: [
{
id: '311',
label: '三级 3-1-1',
},
],
},
{
id: '32',
label: '二级 3-2',
children: [
{
id: '321',
label: '三级 3-2-1',
},
],
},
],
},
],
treeProps: {
props: {
children: 'children',
label: 'label',
},
},
handleChange(v) {
console.log('你选择了:', v)
},
})
return {
...toRefs(state),
}
},
})
</script>

View File

@ -27,7 +27,7 @@
* @version: * @version:
* @Date: 2021-04-28 16:50:05 * @Date: 2021-04-28 16:50:05
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-28 16:50:41 * @LastEditTime: 2021-09-18 17:51:25
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -36,4 +36,24 @@
<template> <template>
<h2>编辑页面 id:{{ $route.params.id }}</h2> <h2>编辑页面 id:{{ $route.params.id }}</h2>
<el-button type="primary" @click="closeTag">关闭</el-button>
<el-button type="success" @click="closeTag({ reload: true })">
关闭当前页面更新上级页面组件重新渲染
</el-button>
<el-button type="warning" @click="closeTag({ f5: true })">
关闭当前页面刷新上级页面浏览器刷新
</el-button>
</template> </template>
<script>
import { defineComponent } from 'vue'
import useCloseTag from '@/hooks/useCloseTag'
export default defineComponent({
setup() {
const { closeTag } = useCloseTag()
return {
closeTag,
}
},
})
</script>

View File

@ -14,7 +14,7 @@
* @version: * @version:
* @Date: 2021-04-20 11:06:21 * @Date: 2021-04-20 11:06:21
* @LastEditors: huzhushan@126.com * @LastEditors: huzhushan@126.com
* @LastEditTime: 2021-04-22 09:28:15 * @LastEditTime: 2021-09-18 15:09:15
* @Author: huzhushan@126.com * @Author: huzhushan@126.com
* @HomePage: https://huzhushan.gitee.io/vue3-element-admin * @HomePage: https://huzhushan.gitee.io/vue3-element-admin
* @Github: https://github.com/huzhushan/vue3-element-admin * @Github: https://github.com/huzhushan/vue3-element-admin
@ -76,6 +76,7 @@ export default env => {
'/api': { '/api': {
target: 'http://dev.api.xxx.com', // 后端接口的域名 target: 'http://dev.api.xxx.com', // 后端接口的域名
changeOrigin: true, changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
}, },
}, },
}, },

12
升级.txt Normal file
View File

@ -0,0 +1,12 @@
升级element-plus
升级sass
更新App.vue国际化配置
defaultSettings重命名、增加menus.isShow
permission.js增加loading
permission.js增加404页面白名单
permission.js删除所有动态路由
退出的时候清空标签栏和menus
tags增加清空标签栏的mutations
404页面路由修改
增加公共hooks
增加树形下拉组件