群控系统服务端开发模式-应用开发-前端菜单功能开发

今天优先开发菜单及角色,明天将开发岗位配置、级别配置等功能。具体看下图

而前端的路由不需要手动添加,是依据数据库里面存储的路径。

一、添加视图

在根目录下src文件夹下views文件夹下permission文件夹下menu文件夹下,新建index.vue,代码如下

<template>
    <div class="app-container">
        <div class="filter-container" style="float:right;">
            <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexAdd')" class="filter-item" style="margin-left: 10px;" @click="handleAdd" type="primary">添加</el-button>
            <el-button class="filter-item" style="margin-left: 10px;" @click="getAll">刷新</el-button>
            <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexTostatus')" class="filter-item" style="margin-left: 10px;" @click="handleStatus(1)" type="success">启用</el-button>
            <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexTostatus')" class="filter-item" style="margin-left: 10px;" @click="handleStatus(0)" type="warning">禁用</el-button>
            <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexDelete')" class="filter-item" @click="handleDelete" type="danger">删除</el-button>
        </div>
        <el-table
                ref="resTable"
                :key="tableKey"
                v-loading="listLoading"
                :data="list"
                row-key="id"
                border
                highlight-current-row
                style="width:100%;margin-top:10px;height:100%;"
                lazy
                :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
                :default-sort="{prop: 'id', order: 'descending'}"
        >
            <el-table-column type="selection" width="50" align="center" />
            <el-table-column label="ID" sortable prop="id" align="center" width="100">
                <template slot-scope="{row}">
                    <span>{{ row.id }}</span>
                </template>
            </el-table-column>
            <el-table-column label="标识" prop="menuname" align="center">
                <template slot-scope="{row}">
                    <span>{{ row.menuname }}</span>
                </template>
            </el-table-column>
            <el-table-column label="名称" prop="title" align="center">
                <template slot-scope="{row}">
                    <span>{{ row.title }}</span>
                </template>
            </el-table-column>
            <el-table-column label="图标" prop="icon" align="center" width="80">
                <template slot-scope="{row}">
                    <span><svg-icon :icon-class="row.icon" /></span>
                </template>
            </el-table-column>
            <el-table-column label="路由" prop="path" align="center">
                <template slot-scope="{row}">
                    <span>{{ row.path }}</span>
                </template>
            </el-table-column>
            <el-table-column label="组件" prop="component" align="center">
                <template slot-scope="{row}">
                    <span>{{ row.component }}</span>
                </template>
            </el-table-column>
            <el-table-column label="重定向" prop="redirect" align="center">
                <template slot-scope="{row}">
                    <span>{{ row.redirect }}</span>
                </template>
            </el-table-column>
            <el-table-column label="缓存" prop="is_cache" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag v-if="row.is_cache == 1" type="success">是</el-tag>
                    <el-tag v-if="row.is_cache == 0" type="danger">否</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="隐藏" prop="is_hidden" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag v-if="row.is_hidden == 1" type="success">是</el-tag>
                    <el-tag v-if="row.is_hidden == 0" type="danger">否</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="显示" prop="always_show" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag v-if="row.always_show == 1" type="success">是</el-tag>
                    <el-tag v-if="row.always_show == 0" type="danger">否</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="图标" prop="is_icon" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag>{{ row.is_icon === 1 ? '是' : '否' }}</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="菜单" prop="is_menu" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag>{{ row.is_menu === 1 ? '是' : '否' }}</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="状态" prop="status" align="center" width="70">
                <template slot-scope="{row}">
                    <el-tag>{{ row.status === 1 ? '启用' : '禁用' }}</el-tag>
                </template>
            </el-table-column>
            <el-table-column label="操作" prop="action" align="center" width="210">
                <template slot-scope="{row}">
                    <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexDetails')" size="mini" @click="handleDetails(row.id)" type="info">详情</el-button>
                    <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexEdit')" size="mini" @click="handleEdit(row.id)" type="primary">编辑</el-button>
                    <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexDelete')" size="mini" @click="handleDelete(row.id)" type="danger">删除</el-button>
                </template>
            </el-table-column>
        </el-table>
        <!-- 添加或修改路由菜单 -->
        <el-dialog :visible.sync="dialogVisible" :title="resTemp.id === 0 ? '添加' : '编辑'" :close-on-click-modal="false" :close-on-press-escape="false">
            <el-form ref="resForm" :rules="formRules" :model="resTemp" label-position="right" label-width="100px">
                <el-row :gutter="20">
                    <el-col :span="24">
                        <el-form-item label="父级菜单" prop="pid">
                            <el-cascader
                                    v-model="resTemp.pid"
                                    :options="options"
                                    :show-all-levels="false"
                                    change-on-select
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="是否为菜单" prop="is_menu">
                            <el-switch v-model="resTemp.is_menu" :active-value="1" :inactive-value="0" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="24">
                        <el-form-item label="唯一标识" prop="menuname">
                            <el-input v-model="resTemp.menuname" style="width:300px" />
                        </el-form-item>
                    </el-col>
                    <el-col :span="24">
                        <el-form-item v-if="resTemp.is_menu === 1" label="菜单名称" prop="title">
                            <el-input v-model="resTemp.title" style="width:300px" />
                        </el-form-item>
                        <el-form-item v-if="resTemp.is_menu === 0" label="按钮名称" prop="title">
                            <el-input v-model="resTemp.title" style="width:300px" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="路由地址" prop="path">
                            <el-input v-model="resTemp.path" style="width:300px" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="组件路径" prop="component">
                            <el-input v-model="resTemp.component" style="width:300px" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item v-if="resTemp.pid === '' || resTemp.pid[0] === 0" label="重定向" prop="redirect">
                            <el-input v-model="resTemp.redirect" style="width:300px" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="菜单图标" prop="icon">
                            <el-popover
                                    placement="bottom-start"
                                    width="460"
                                    trigger="click"
                            >
                                <IconPicker ref="iconPicker" @selected="selected" @show="$refs['iconPicker'].reset()" />
                                <el-input slot="reference" v-model="resTemp.icon" placeholder="点击选择图标" readonly style="width:300px">
                                    <svg-icon v-if="resTemp.icon" slot="prefix" :icon-class="resTemp.icon" class="el-input__icon" style="height: 32px;width: 16px;" />
                                    <i v-else slot="prefix" class="el-icon-search el-input__icon" />
                                </el-input>
                            </el-popover>
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="排序" prop="sort">
                            <el-input-number v-model="resTemp.sort" size="small" :min="0" :max="99" label="描述文字" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="缓存" prop="is_cache">
                            <el-switch v-model="resTemp.is_cache" :active-value="1" :inactive-value="0" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="隐藏" prop="is_hidden">
                            <el-switch v-model="resTemp.is_hidden" :active-value="1" :inactive-value="0" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="总是显示" prop="always_show">
                            <el-switch v-model="resTemp.always_show" :active-value="1" :inactive-value="0" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="是否显示图标" prop="is_icon">
                            <el-switch v-model="resTemp.is_icon" :active-value="1" :inactive-value="0" />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 0" :span="24">
                        <el-form-item label="按钮类型" prop="button_type">
                            <el-radio-group v-model="resTemp.button_type">
                                <el-radio label="0">无效</el-radio>
                                <el-radio label="1">列表</el-radio>
                                <el-radio label="2">所有</el-radio>
                                <el-radio label="3">添加</el-radio>
                                <el-radio label="4">编辑</el-radio>
                                <el-radio label="5">保存</el-radio>
                                <el-radio label="6">删除</el-radio>
                                <el-radio label="7">详情</el-radio>
                                <el-radio label="8">信息</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogVisible=false">取消</el-button>
                <el-button v-if="$store.getters.butts.includes('PermissionMenuIndexSave')" type="primary" @click="saveInfo()">提交</el-button>
            </div>
        </el-dialog>
        <!-- 详情路由菜单 -->
        <el-dialog :visible.sync="dialogDetails" title="详情" :close-on-click-modal="false" :close-on-press-escape="false">
            <el-form ref="resForm" :rules="formRules" :model="resTemp" label-position="right" label-width="100px">
                <el-row :gutter="20">
                    <el-col :span="24">
                        <el-form-item label="父级菜单" prop="pid">
                            <el-cascader
                                    v-model="resTemp.pid"
                                    :options="options"
                                    :show-all-levels="false"
                                    change-on-select
                                    disabled
                            />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="是否为菜单" prop="is_menu">
                            <el-switch v-model="resTemp.is_menu" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col :span="24">
                        <el-form-item label="唯一标识" prop="menuname">
                            <el-input v-model="resTemp.menuname" style="width:300px" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col :span="24">
                        <el-form-item v-if="resTemp.is_menu === 1" label="菜单名称" prop="title">
                            <el-input v-model="resTemp.title" style="width:300px" disabled />
                        </el-form-item>
                        <el-form-item v-if="resTemp.is_menu === 0" label="按钮名称" prop="title">
                            <el-input v-model="resTemp.title" style="width:300px" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="路由地址" prop="path">
                            <el-input v-model="resTemp.path" style="width:300px" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="组件路径" prop="component">
                            <el-input v-model="resTemp.component" style="width:300px" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item v-if="resTemp.pid === '' || resTemp.pid[0] === 0" label="重定向" prop="redirect">
                            <el-input v-model="resTemp.redirect" style="width:300px" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="菜单图标" prop="icon">
                            <el-popover
                                    placement="bottom-start"
                                    width="460"
                                    trigger="click"
                            >
                                <IconPicker ref="iconPicker" @selected="selected" @show="$refs['iconPicker'].reset()" />
                                <el-input slot="reference" v-model="resTemp.icon" placeholder="点击选择图标" disabled style="width:300px" >
                                    <svg-icon v-if="resTemp.icon" slot="prefix" :icon-class="resTemp.icon" class="el-input__icon" style="height: 32px;width: 16px;" />
                                    <i v-else slot="prefix" class="el-icon-search el-input__icon" />
                                </el-input>
                            </el-popover>
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="24">
                        <el-form-item label="排序" prop="sort">
                            <el-input-number v-model="resTemp.sort" size="small" :min="0" :max="99" label="描述文字" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="缓存" prop="is_cache">
                            <el-switch v-model="resTemp.is_cache" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="隐藏" prop="is_hidden">
                            <el-switch v-model="resTemp.is_hidden" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="总是显示" prop="always_show">
                            <el-switch v-model="resTemp.always_show" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 1" :span="12">
                        <el-form-item label="是否显示图标" prop="is_icon">
                            <el-switch v-model="resTemp.is_icon" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col :span="12">
                        <el-form-item label="状态" prop="status">
                            <el-switch v-model="resTemp.status" :active-value="1" :inactive-value="0" disabled />
                        </el-form-item>
                    </el-col>
                    <el-col v-if="resTemp.is_menu === 0" :span="24">
                        <el-form-item label="按钮类型" prop="button_type">
                            <el-radio-group v-model="resTemp.button_type" disabled>
                                <el-radio label="1">列表</el-radio>
                                <el-radio label="2">所有</el-radio>
                                <el-radio label="3">添加</el-radio>
                                <el-radio label="4">编辑</el-radio>
                                <el-radio label="5">保存</el-radio>
                                <el-radio label="6">删除</el-radio>
                                <el-radio label="7">详情</el-radio>
                                <el-radio label="8">信息</el-radio>
                            </el-radio-group>
                        </el-form-item>
                    </el-col>
                </el-row>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogDetails=false">取消</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
    import { succ, warn, err } from '@/utils/message'
    import { getInfo, getAll, saveInfo, deleteInfo, statusInfo } from '@/api/permission/menu'
    import IconPicker from '@/components/iconPicker'
    export default {
        name: 'PermissionMenuIndex', // 名空间
        components: { IconPicker },
        data() {
            const validateButtonType = (rule, value, callback) => {
                const myArr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
                if (myArr.findIndex(item => item === (value * 1 + 1)) === 0) {
                    callback(new Error('请选择正确的按钮类型'))
                } else {
                    callback()
                }
            }
            return {
                list: [],
                options: [],
                tableKey: 0,
                listLoading: true,
                dialogVisible: false,
                dialogDetails: false,
                resTemp: {
                    id: 0,
                    pid: '',
                    menuname: '',
                    title: '',
                    path: '',
                    component: '',
                    redirect: '',
                    icon: '',
                    sort: 0,
                    is_cache: 1,
                    is_hidden: 0,
                    always_show: 0,
                    is_icon: 1,
                    is_menu: 1,
                    button_type: 0,
                    status: 1
                },
                formRules: {
                    menuname: [{ required: true, message: '请输入唯一标识', trigger: 'blur' }],
                    title: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
                    path: [{ required: true, message: '请输入路由地址', trigger: 'blur' }],
                    component: [{ required: true, message: '请输入组件路径', trigger: 'blur' }],
                    icon: [{ required: true, message: '请输入菜单图标', trigger: 'blur' }],
                    redirect: [
                        { required: true, message: '请填写重定向', trigger: 'blur' },
                        { min: 2, max: 100, message: '长度在 2 到 100 个字符', trigger: 'blur' }
                    ],
                    button_type: [
                        { required: true, message: '请选择按钮类型', trigger: 'blur' },
                        { trigger: 'blur', validator: validateButtonType }
                    ]
                }
            }
        },
        created() {
            this.getAll()
        },
        methods: {
            // 图标选择器
            selected(name) {
                this.resTemp.icon = name
            },
            // 所有
            getAll() {
                this.listLoading = true
                getAll().then(res => {
                    this.list = res.data
                    this.options = this.getParent(res.data)
                    // 延时
                    setTimeout(() => {
                        this.listLoading = false
                    }, 0.5 * 1000)
                })
            },
            // 递归
            getParent(arr) {
                const roles = []
                roles.push({ label: '无(一级菜单)', value: 0 })
                arr.forEach(function(val) {
                    const chil = []
                    if (val.children !== undefined) {
                        val.children.forEach(function(v) {
                            chil.push({ label: v.title, value: v.id })
                        })
                    }
                    if (val.children !== undefined) {
                        roles.push({ label: val.title, value: val.id, children: chil })
                    } else {
                        roles.push({ label: val.title, value: val.id })
                    }
                })
                return roles
            },
            // 重置表单数据 ---添加时候需要使用
            resetTemp() {
                this.resTemp = {
                    id: 0,
                    pid: '',
                    menuname: '',
                    title: '',
                    path: '',
                    component: '',
                    redirect: '',
                    icon: '',
                    sort: 0,
                    is_cache: 1,
                    is_hidden: 0,
                    always_show: 0,
                    is_icon: 1,
                    is_menu: 1,
                    button_type: 0,
                    status: 1
                }
            },
            // 添加
            handleAdd() {
                this.resetTemp()
                this.dialogVisible = true
                this.$nextTick(() => {
                    this.$refs['resForm'].clearValidate()
                })
            },
            // 编辑
            handleEdit(id) {
                getInfo({ id: id }).then(res => {
                    const row = res.data
                    this.resTemp = Object.assign({}, row)
                    if (row.pid === 0) {
                        this.resTemp.pid = [0]
                    }
                    this.resTemp.button_type = row.button_type + ''
                    this.dialogVisible = true
                    this.$nextTick(() => {
                        this.$refs['resForm'].clearValidate()
                    })
                })
            },
            // 详情
            handleDetails(id){
                getInfo({ id: id }).then(res => {
                    const row = res.data
                    this.resTemp = Object.assign({}, row)
                    if (row.pid === 0) {
                        this.resTemp.pid = [0]
                    }
                    this.resTemp.button_type = row.button_type + ''
                    this.dialogDetails = true
                    this.$nextTick(() => {
                        this.$refs['resForm'].clearValidate()
                    })
                })
            },
            // 保存
            async saveInfo() {
                this.$refs['resForm'].validate((valid) => {
                    if (valid) {
                        this.loading = true
                        saveInfo(this.resTemp).then(res => {
                            this.loading = false
                            succ(res.message)
                            this.getAll()
                            this.dialogVisible = false
                        })
                    } else {
                        return false
                    }
                })
            },
            // 删除
            handleDelete(id) {
                this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning',
                    center: true
                }).then(async() => {
                    const ids = []
                    if (id > 0) { // 单个删除
                        ids.push(id)
                    } else { // 批量删除
                        const select = this.$refs.resTable.selection
                        if (select.length === 0) {
                            warn('批量删除必须选择指定产品')
                            return false
                        }
                        // 组合数据
                        select.forEach(item => {
                            ids.push(item.id)
                        })
                    }
                    // 删除
                    deleteInfo({ id: ids }).then(res => {
                        this.getAll()// 更新列表
                        succ(res.message)// 提示结果
                    })
                }).catch(err => {
                    err(err.message)
                    return false
                })
            },
            // 启禁用
            handleStatus(status){
                let statusText = status == 1 ? '启用' : '禁用';
                this.$confirm('此操作将永久'+ statusText +'该产品, 是否继续?', '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning',
                    center: true
                }).then(async() => {
                    const ids = []
                    const select = this.$refs.resTable.selection
                    if (select.length === 0) {
                        warn('批量'+ statusText +'必须选择指定产品')
                        return false
                    }
                    // 组合数据
                    select.forEach(item => {
                        ids.push(item.id)
                    })
                    // 删除
                    statusInfo({ id: ids, status:status }).then(res => {
                        this.getAll()// 更新列表
                        succ(res.message)// 提示结果
                    })
                }).catch(err => {
                    err(err.message)
                    return false
                })
            }
        }
    }
</script>
<style lang="scss" scoped>
    .app-container {
        padding:10px;
        ::v-deep {
            .el-dialog {
                .el-dialog__header {
                    border-bottom: 1px solid #ebebeb;
                }
                .el-dialog__footer {
                    border-top: 1px solid #ebebeb;
                }
            }
        }
    }
</style>

二、添加ajax请求

在根目录下src文件夹下api文件夹下permission文件夹下menu.js,代码如下

import request from '@/utils/request'
// 所有
export function getAll() {
    return request({
        url: '/permission/menu/get_all',
        method: 'post'
    })
}
// 获取
export function getInfo(data) {
    return request({
        url: '/permission/menu/get_info',
        method: 'post',
        data
    })
}
// 保存
export function saveInfo(data) {
    return request({
        url: '/permission/menu/save_info',
        method: 'post',
        data
    })
}
// 删除
export function deleteInfo(data) {
    return request({
        url: '/permission/menu/delete_info',
        method: 'post',
        data
    })
}
// 启禁用
export function statusInfo(data) {
    return request({
        url: '/permission/menu/status_info',
        method: 'post',
        data
    })
}

三、添加图标文件

在根目录下src文件夹下components文件夹下创建文件夹iconPicker,在iconPicker文件夹下新建index.vue,代码如下

<template>
    <div class="icon-picker">
        <el-input v-model="name" class="icon-search" clearable placeholder="输入图标名称" @clear="filterIcons"
                  @input.native="filterIcons">
            <i slot="suffix" class="el-icon-search el-input__icon"/>
        </el-input>
        <div class="icon-list">
            <el-row>
                <el-col v-for="(item, index) in iconList" :key="index" class="svg-box">
                    <el-tooltip effect="dark" :content="item" placement="top-start">
                        <svg-icon :icon-class="item" @click="iconPicker(item)"/>
                    </el-tooltip>
                </el-col>
            </el-row>
        </div>
    </div>
</template>

<script>
    import svgIcons from '../../icons/svg-icon'

    export default {
        name: 'IconPicker',
        data() {
            return {
                name: '',
                iconList: svgIcons
            }
        },
        methods: {
            filterIcons() {
                if (this.name) {
                    this.iconList = this.iconList.filter(item => item.includes(this.name))
                } else {
                    this.iconList = svgIcons
                }
            },
            iconPicker(name) {
                this.$emit('selected', name)
                document.body.click()
            },
            reset() {
                this.name = ''
                this.iconList = svgIcons
            }
        }
    }
</script>

<style lang="scss" scoped>
    .icon-picker {
        width: 100%;
        padding: 5px 0 5px 0;
        .icon-search {
            position: relative;
        }
        .icon-list {
            height: 230px;
            overflow-y: auto;
            .svg-box {
                height: 40px;
                width: 40px;
                padding: 7px;
                border: 1px solid #ddd;
                border-radius: 5px;
                margin: 6px;
                .svg-icon {
                    width: 24px;
                    height: 24px;
                }
            }
            .svg-box :hover {
                color: #409EFF;
            }
        }
    }
</style>

在根目录下src文件夹下icons文件夹下新建js文件并命名为svg-icon.js,代码如下

const req = require.context('./svg', false, /\.svg$/)
const requireAll = requireContext => requireContext.keys()

const re = /\.\/(.*)\.svg/

const svgIcons = requireAll(req).map(i => {
    return i.match(re)[1]
})

export default svgIcons
相关推荐
Java程序之猿1 小时前
微服务分布式(一、项目初始化)
分布式·微服务·架构
落魄实习生2 小时前
AI应用-本地模型实现AI生成PPT(简易版)
python·ai·vue·ppt
来一杯龙舌兰2 小时前
【RabbitMQ】RabbitMQ保证消息不丢失的N种策略的思想总结
分布式·rabbitmq·ruby·持久化·ack·消息确认
节点。csn4 小时前
Hadoop yarn安装
大数据·hadoop·分布式
bpmf_fff4 小时前
二九(vue2-05)、父子通信v-model、sync、ref、¥nextTick、自定义指令、具名插槽、作用域插槽、综合案例 - 商品列表
vue
NiNg_1_2345 小时前
基于Hadoop的数据清洗
大数据·hadoop·分布式
隔着天花板看星星6 小时前
Spark-Streaming集成Kafka
大数据·分布式·中间件·spark·kafka
java_heartLake10 小时前
Vue3之状态管理Vuex
vue·vuex·前端状态管理
技术路上的苦行僧11 小时前
分布式专题(8)之MongoDB存储原理&多文档事务详解
数据库·分布式·mongodb
龙哥·三年风水11 小时前
workman服务端开发模式-应用开发-后端api推送修改二
分布式·gateway·php