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

news2024/11/16 5:08:05

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

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

一、添加视图

        在根目录下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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2241279.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构Python版

2.3.3 双链表 双链表和链表一样&#xff0c;只不过每个节点有两个链接——一个指向后一个节点&#xff0c;一个指向前一个节点。此外&#xff0c;除了第一个节点&#xff0c;双链表还需要记录最后一个节点。 每个结点为DLinkNode类对象&#xff0c;包括存储元素的列表data、…

【HarmonyOS学习日志(8)】UIAbility,HAP,AbilityStage组件及其生命周期

基本概念 UIAbility组件是一种包含UI的应用组件&#xff0c;主要用于和用户交互。 在项目创建时&#xff0c;系统默认生成的EntryAbility类继承了UIAbility类。 ExtensionAbility组件&#xff1a;是基于特定场景&#xff08;例如服务卡片、输入法等&#xff09;提供的应用组件…

【Linux】多线程(中)

目录 一、线程互斥 1.1 互斥概念 1.2 互斥量mutex 1.3 互斥量相关API &#xff08;1&#xff09;初始化互斥量 &#xff08;2&#xff09;销毁互斥量 &#xff08;3&#xff09;互斥量加锁和解锁 1.4 互斥量原理 1.5 重入和线程安全 二、死锁 2.1 概念 2.2 造成死锁…

【数字图像处理+MATLAB】基于 Sobel 算子计算图像梯度并进行边缘增强:使用 imgradientxy 函数

引言 在图像处理中&#xff0c;边缘通常是图像中像素强度变化最大的地方&#xff0c;这种变化可以通过计算图像的梯度来量化。梯度是一个向量&#xff0c;它的方向指向像素强度增加最快的方向&#xff0c;它的大小&#xff08;或者说幅度&#xff09;表示像素强度增加的速度。…

Nuxt.js 应用中的 schema:beforeWrite 事件钩子详解

title: Nuxt.js 应用中的 schema:beforeWrite 事件钩子详解 date: 2024/11/14 updated: 2024/11/14 author: cmdragon excerpt: schema:beforeWrite 钩子是 Vite 提供的一个功能强大的生命周期钩子,允许开发者在 JSON Schema 被写入之前执行自定义操作。利用这个钩子,您可以…

k8s服务内容滚动升级以及常用命令介绍

查看K8S集群所有的节点信息 kubectl get nodes 删除K8S集群中某个特定节点 kubectl delete nodes/10.0.0.123 获取K8S集群命名空间 kubectl get namespace 获取K8S所有命名空间的那些部署 kubectl get deployment --all-namespaces 创建命名空间 web界面上看到的效果,但是…

MinIo在Ubantu和Java中的整合

1.MinIo在Ubantu中的部署 首先准备好一台已经安装好Ubantu系统的服务器 MinIO是一个开源的对象存储服务器&#xff0c;兼容Amazon S3&#xff0c;性能卓越&#xff0c;适合存储非结构化数据&#xff0c;例如照片、视频、日志文件、备份和容器镜像等。 1&#xff1a;更新系统…

设计模式-参考的雷丰阳老师直播课

一般开发中使用的模式为模版模式策略模式组合&#xff0c;模版用来定义骨架&#xff0c;策略用来实现细节。 模版模式 策略模式 与模版模式特别像&#xff0c;模版模式会定义好步骤定义好框架&#xff0c;策略模式定义小细节 入口类 使用模版模式策略模式开发支付 以上使用…

【LeetCode】【算法】53. 最大子数组和

LeetCode 53. 最大子数组和 题目描述 给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。子数组是数组中的一个连续部分。 思路 思路&#xff1a;动态规划秒了 具体递推式如…

供应SW6301V单C口多协议升降压移动电源IC

1. 概述 SW6301V 是一款高集成度的单 C 口多协议升降压移动电源 SOC。集成双向升降压控制器&#xff0c;支持 2~6 节 电池串联&#xff0c;提供 100W 功 率 输 入 输 出 &#xff1b; 支 持 C 口 快 充 输入输出 &#xff1b; 支 持UFCS/PPS/PD/SVOOC/VOOC/SCP/FCP/QC/AFC/BC…

C++常用的新特性-->day06

时间间隔duration duration表示一段时间间隔&#xff0c;用来记录时间长度&#xff0c;可以表示几秒、几分钟、几个小时的时间间隔。duration的原型如下 // 定义于头文件 <chrono> template<class Rep,class Period std::ratio<1> > class duration;Rep&…

Cyberchef配合Wireshark提取并解析TCP/FTP流量数据包中的文件

前一篇文章中讲述了如何使用cyberchef提取HTTP/TLS数据包中的文件,详见《Cyberchef配合Wireshark提取并解析HTTP/TLS流量数据包中的文件》,链接这里,本文讲述下如何使用cyberchef提取FTP/TCP数据包中的文件。 FTP 是最为常见的文件传输协议,和HTTP协议不同的是FTP协议传输…

性能面向下一代PCIe Gen 5,G991B322HR、G99L12312HR 安费诺ExtremePort™ Swift连接器支持内部I/O应用

前言 为了在网络设备和服务器上提供更高速度和更小尺寸的解决方案&#xff0c;Amphenol开发了ExtremePort™ Swift连接器&#xff0c;适用于PCIe Gen5 NRZ 32GT/s、UPI 2.0 24GT/s、24Gb/s SAS信号。 G991B322HR G9912312HR G9912322HR G9914312HR G991B312HR G991C312HR G99…

IDEA调整警告级别【IntelliJ IDEA 2024.2.0.1】

文章目录 目前现状鼠标悬停&#xff0c;选择配置筛选 > 取消选择OK效果 目前现状 需要把提示改成只要显示error的5个 鼠标悬停&#xff0c;选择配置 筛选 > 取消选择 OK 效果

【二叉搜素树】——LeetCode二叉树问题集锦:6个实用题目和解题思路

文章目录 计算布尔二叉树的值求根节点到叶节点的数字之和二叉树剪枝验证二叉搜索树二叉搜索树中第K小的元素二叉树的所有路径 计算布尔二叉树的值 解题思路&#xff1a; 这是一个二叉树的布尔评估问题。树的每个节点包含一个值&#xff0c;其中叶子节点值为 0 或 1&#xff0…

windows下QT5.12.11使用MSVC编译器编译mysql驱动并使用详解

1、下载mysql开发库,后面驱动编译的时候需要引用到,下载地址:mysql开发库下载 2、使用everything搜索:msvc-version.conf,用记事本打开,添加:QMAKE_MSC_VER=1909。不然msvc下的mysql源码加载不上。

Isaac Sim+SKRL机器人并行强化学习

目录 Isaac Sim介绍 OmniIssacGymEnvs安装 SKRL安装与测试 基于UR5的机械臂Reach强化学习测评 机器人控制 OMNI GYM环境编写 SKRL运行文件 训练结果与速度对比 结果分析 运行体验与建议 Isaac Sim介绍 Isaac Sim是英伟达出的一款机器人仿真平台&#xff0c;适用于做机…

删库跑路,启动!

起因&#xff1a;这是一个悲伤的故事&#xff0c;在抓logcat时 device待机自动回根目录了&#xff0c;而题主对当前路径的印象还停留在文件夹下&#xff0c;不小心在根目录执行了rm -rf * … 所以&#xff0c;这是个悲伤的故事&#xff0c;东西全没了…device也黑屏了&#xff…

CSS的综合应用例子(网页制作)

这是html的一些最基本内容的代码&#xff1a; <!DOCTYPE html> <html lang"zh"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <t…

SobarQube实现PDF报告导出

文章目录 前言一、插件配置二、使用步骤1.新生成一个Token2.将拷贝的Token加到上文中执行的命令中3.查看报告 三、友情提示总结 前言 这篇博文是承接此文 .Net项目在Windows中使用sonarqube进行代码质量扫描的详细操作配置 描述如何导出PDF报告 众所周知&#xff0c;导出PDF功…