feat(system): 菜单增加图标选择功能

- 在菜单查询中添加 icon 字段
- 在菜单对话框中添加图标选择功能
- 在侧边栏中根据路由图标进行分类显示
- 添加知识库相关图标
This commit is contained in:
du.meimei
2025-04-25 14:30:15 +08:00
parent 19024c50d4
commit a7a5260a78
5 changed files with 109 additions and 28 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -13,10 +13,21 @@
@click="selectParentMenu(route)" @click="selectParentMenu(route)"
> >
<i <i
v-if="route.meta && route.meta.icon" v-if="route.icon"
class="iconfont fs22" :class="[
:class="route.meta.icon" route.icon,
{ iconfont: !route.icon.includes('el-icon') },
{ mb5: route.icon.includes('el-icon') }
]"
class=" fs22"
></i> ></i>
<img
v-else
:src="activeParent === route.url ? knowledgeActive : knowledge"
alt=""
class="mb5"
style="width: 20px"
/>
<span class="menu-title">{{ route.menuName }}</span> <span class="menu-title">{{ route.menuName }}</span>
</div> </div>
</div> </div>
@@ -43,9 +54,12 @@
@click="navigateTo(subItem.url)" @click="navigateTo(subItem.url)"
> >
<i <i
v-if="subItem.meta && subItem.meta.icon" v-if="subItem.icon"
class="iconfont mr10" class="mr10"
:class="subItem.meta.icon" :class="[
subItem.icon,
{ iconfont: !subItem.icon.includes('el-icon') }
]"
/> />
<span>{{ subItem.menuName }}</span> <span>{{ subItem.menuName }}</span>
</div> </div>
@@ -57,15 +71,22 @@
</template> </template>
<script> <script>
import Cookies from 'js-cookie'
import { mapGetters, mapActions } from 'vuex' import { mapGetters, mapActions } from 'vuex'
import Logo from './Logo' import Logo from './Logo'
import variables from '@/assets/sass/variables.scss' import variables from '@/assets/sass/variables.scss'
import Personal from '@/views/app/layout/components/Sidebar/personal.vue' import Personal from '@/views/app/layout/components/Sidebar/personal.vue'
import knowledge from '@/assets/images/knowledge.png'
import knowledgeActive from '@/assets/images/knowledgeActive.png'
export default { export default {
components: { Personal, Logo }, components: { Personal, Logo },
computed: { computed: {
knowledge() {
return knowledge
},
knowledgeActive() {
return knowledgeActive
},
...mapGetters(['sidebar', 'sidebarList']), ...mapGetters(['sidebar', 'sidebarList']),
routes() { routes() {
return this.$router.options.routes return this.$router.options.routes
@@ -91,8 +112,6 @@ export default {
currentSubmenu() { currentSubmenu() {
if (!this.activeParent) return [] if (!this.activeParent) return []
const parent = this.menuList.find(item => item.url === this.activeParent) const parent = this.menuList.find(item => item.url === this.activeParent)
console.log('Parent found:', parent)
console.log('Children:', parent ? parent.children : 'No children')
return parent ? parent.children || [] : [] return parent ? parent.children || [] : []
}, },
currentParentTitle() { currentParentTitle() {
@@ -115,8 +134,6 @@ export default {
menu.map(item => { menu.map(item => {
if (parentPath) { if (parentPath) {
item.url = '/' + parentPath + '/' + item.url item.url = '/' + parentPath + '/' + item.url
} else {
item.url = item.url
} }
if (item.otherInfo1 == 0) { if (item.otherInfo1 == 0) {
item.name = item.menuName item.name = item.menuName
@@ -138,7 +155,6 @@ export default {
}, },
selectParentMenu(route) { selectParentMenu(route) {
this.activeParent = route.url this.activeParent = route.url
console.log(Cookies.get('sidebarStatus'))
// this.$store.dispatch('app/toggleSideBar') // this.$store.dispatch('app/toggleSideBar')
// If this parent has children, don't navigate // If this parent has children, don't navigate
if (route.children && route.children.length > 0) { if (route.children && route.children.length > 0) {
@@ -189,24 +205,14 @@ export default {
created() { created() {
if (sessionStorage.token !== 'MockToken') { if (sessionStorage.token !== 'MockToken') {
// 获取路由数据 // 获取路由数据
let data = this.$store.state.app.sidebarList
console.log('sidebarList')
console.log(data)
// 通过检查路由结构来确定顶级菜单
const topLevelRoutes = data.filter(route => {
// 如果路由有 meta 和 children则认为它是顶级菜单
return route.meta && route.children && !route.hidden
})
this.menuList = data this.menuList = this.$store.state.app.sidebarList
} else { } else {
// 从路由配置中获取顶级路由 // 从路由配置中获取顶级路由
const topLevelRoutes = this.routes.filter(route => { this.menuList = this.routes.filter(route => {
// 只显示有 meta 和 children 的路由,并且不是隐藏的 // 只显示有 meta 和 children 的路由,并且不是隐藏的
return route.meta && route.children && !route.hidden return route.meta && route.children && !route.hidden
}) })
this.menuList = topLevelRoutes
} }
// 根据当前路由设置活动的父菜单 // 根据当前路由设置活动的父菜单
@@ -246,7 +252,6 @@ export default {
border-right: 1px solid #ebeef2; border-right: 1px solid #ebeef2;
overflow-y: auto; overflow-y: auto;
background-color: #fff; background-color: #fff;
padding: 0 10px;
text-align: center; text-align: center;
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -81,6 +81,32 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12">
<el-form-item label="菜单icon" prop="icon">
<el-select
v-model="form.icon"
size="medium"
filterable
placeholder="请选择图标"
>
<el-option label="全部" value=""></el-option>
<el-option
v-for="icon in iconList"
:key="icon"
:label="icon"
:value="icon"
>
<div class="flex align-items-c">
<i
:class="[icon, { iconfont: !icon.includes('el-icon') }]"
class="mr10"
></i>
<span>{{ icon }}</span>
</div>
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row> </el-row>
</el-form> </el-form>
<div slot="footer" class="dialog-footer" v-if="!isView"> <div slot="footer" class="dialog-footer" v-if="!isView">
@@ -147,7 +173,55 @@ export default {
type: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }] type: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }]
}, },
typeOptions: [{ value: 0, label: '菜单' }, { value: 1, label: '接口' }], typeOptions: [{ value: 0, label: '菜单' }, { value: 1, label: '接口' }],
loading: false loading: false,
iconList: [
'el-icon-user-solid',
'el-icon-bangzhu',
'el-icon-orange',
'el-icon-lock',
'el-icon-setting',
'el-icon-camera-solid',
'el-icon-video-camera-solid',
'el-icon-bell',
'el-icon-map-location',
'el-icon-picture-outline',
'el-icon-picture',
'el-icon-document',
'el-icon-document-add',
'el-icon-printer',
'el-icon-share',
'el-icon-delete-solid',
'el-icon-delete',
'el-icon-search',
'el-icon-edit',
'el-icon-edit-outline',
'el-icon-refresh',
'el-icon-refresh-left',
'el-icon-refresh-right',
'el-icon-circle-plus',
'el-icon-circle-plus-outline',
'el-icon-remove',
'el-icon-remove-outline',
'el-icon-circle-check',
'el-icon-circle-check-solid',
'el-icon-circle-close',
'el-icon-circle-close-solid',
'el-icon-top',
'el-icon-bottom',
'el-icon-right',
'el-icon-back',
'el-icon-d-arrow-left',
'el-icon-d-arrow-right',
'el-icon-sort',
'el-icon-sort-up',
'el-icon-sort-down',
'icon-zhuye',
'icon-dingwei',
'icon-notebook',
'el-icon-s-custom',
'icon-dengpao1',
'icon-guizeshezhi'
]
} }
}, },
watch: { watch: {
@@ -220,7 +294,7 @@ export default {
this.form = {} this.form = {}
} }
}) })
.catch(error => { .catch(() => {
this.$message.error(this.isEdit ? '修改菜单出错' : '添加菜单出错') this.$message.error(this.isEdit ? '修改菜单出错' : '添加菜单出错')
}) })
.finally(() => { .finally(() => {

View File

@@ -85,7 +85,8 @@ export default {
queryParams: { queryParams: {
menuCodeLike: '', menuCodeLike: '',
menuNameLike: '', menuNameLike: '',
type: null type: null,
icon: ''
}, },
typeOptions: [{ value: 0, label: '菜单' }, { value: 1, label: '接口' }], typeOptions: [{ value: 0, label: '菜单' }, { value: 1, label: '接口' }],
// 表格配置项 // 表格配置项
@@ -188,6 +189,7 @@ export default {
this.queryParams.menuNameLike = '' this.queryParams.menuNameLike = ''
this.queryParams.menuCodeLike = '' this.queryParams.menuCodeLike = ''
this.queryParams.type = null this.queryParams.type = null
this.queryParams.icon = ''
this.handleQuery() this.handleQuery()
}, },
handleSubmit() { handleSubmit() {