news 2026/6/23 2:02:55

封装ElementPlusIcons图标和系统应用内置图片为应用图标

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
封装ElementPlusIcons图标和系统应用内置图片为应用图标

效果图:

文件放置位置结构

1、定义选择按钮父组件 icon

<template> <div> <iconEdit :mode="'button'" /> </div> </template> <script lang="ts" setup> import iconEdit from "../../components/IconEdit/indev.vue"; </script> <style scoped lang="scss"></style>

2、IconEdit组件

<template> <div> <div v-if="mode === 'button'" class="button-container"> <IconComp v-if="icon" :icon="icon" /> <el-button link type="primary" @click="openIcon"> 选择图片 </el-button> </div> <el-dialog v-model="iconVisible" title="选择图标" width="900" draggable :close-on-click-modal="false"> <el-tabs v-model="activeName" class="icons-tabs"> <el-tab-pane label="内置图标" name="icon"> <div class="button-container"> <el-input v-model="search" :suffix-icon="Search" placeholder="请输入关键字搜索图标" style="width: 240px" @input="searchAction(search)" /> <el-input v-model="colorInput" style="width: 120px" placeholder="颜色"> <template #suffix> <input ref="iconPick" type="color" v-model="colorInput" class="w-[26px]" /> </template> </el-input> </div> <div class="icons-container mt-3 h-[350px] overflow-y-auto"> <el-row :gutter="20"> <el-col v-for="(item, index) in elementPlusIcons" :key="index" :span="2" class="mb-1 cursor-pointer" @click="selectAction(item.name)" > <div :class="{ 'selected-icon': item.name === selected }"> <component :is="item" v-bind="$attrs" :style="{ color: colorInput }" /> <p class="icons-text text-center">{{ item.name }}</p> </div> </el-col> </el-row> </div> </el-tab-pane> <el-tab-pane label="系统内置图片" name="icon-preset"> <el-input v-model="search" :suffix-icon="Search" placeholder="请输入关键字搜索图片" style="width: 240px" @input="searchAction(search)" /> <div class="icons-container mt-3 h-[350px] overflow-y-auto"> <el-row :gutter="20"> <el-col v-for="(item, index) in systemIcons" :key="index" :span="2" class="mb-1 cursor-pointer" @click="selectAction(item.code)" > <div style="display: flex; align-items: center; flex-direction: column" :class="{ 'selected-icon': item.code === selected }" > <img style="width: 50px; height: 50px" :src="item.icon" /> <p class="icons-text text-center">{{ item.name }}</p> </div> </el-col> </el-row> </div> </el-tab-pane> </el-tabs> <template #footer> <div class="dialog-footer"> <el-button @click="reset">重置</el-button> <el-button @click="iconVisible = false">取消</el-button> <el-button type="primary" @click="handleConfirm()"> 确定 </el-button> </div> </template> </el-dialog> </div> </template> <script lang="ts" setup> import { type Component, ref, shallowRef, watch, nextTick } from "vue"; import IconComp from "../../components/IconEdit/iconComp.vue"; import { Icons, AiIcons } from "../../assets/index"; import { Search } from "@element-plus/icons-vue"; import * as ElementPlusIcons from "@element-plus/icons-vue"; const props = defineProps<{ mode?: string; isReadonly?: boolean; }>(); /** 数据源, 父组件不能为空,默认'' */ const icon = defineModel("icon", { type: String, default: "", }); const emit = defineEmits(["confirm", "typeConfirm"]); const activeName = ref("icon"); const iconComp = shallowRef<Component>(); const search = ref(""); const colorInput = ref(""); const selected = ref<string>(""); const systemIcons = ref<any[]>([...Icons, ...AiIcons]); // 打开模态框 const iconVisible = ref(false); const iconPick = ref(); // 打开弹窗 const openIcon = () => { iconVisible.value = true; search.value = ""; const iconArray = icon.value.split("#"); iconComp.value = ElementPlusIcons[iconArray[0] as keyof typeof ElementPlusIcons]; if (iconComp.value) { selected.value = iconArray[0]; colorInput.value = iconArray[1] ? `#${iconArray[1]}` : ""; nextTick(() => { iconPick.value.value = colorInput.value; }); } searchAction(""); }; // 关闭弹窗 const closeIcon = () => { iconVisible.value = false; }; const elementPlusIcons = shallowRef<any>(ElementPlusIcons); const reset = () => { selected.value = ""; iconComp.value = undefined; colorInput.value = ""; iconPick.value.value = ""; }; // 搜索图标 const searchAction = (keyWord: string) => { if (keyWord === "") { elementPlusIcons.value = ElementPlusIcons; return; } const filterIcons = Object.keys(ElementPlusIcons).filter((item) => { return item.toLowerCase().includes(keyWord.toLowerCase()); }); elementPlusIcons.value = {}; filterIcons.forEach((item) => { elementPlusIcons.value[item] = ElementPlusIcons[item as keyof typeof ElementPlusIcons]; }); }; const selectAction = (item: string) => { selected.value = item; }; // 确定图标 const handleConfirm = () => { icon.value = activeName.value === "icon" && colorInput.value ? selected.value + colorInput.value : selected.value; emit("confirm", icon.value); emit("typeConfirm", { type: activeName, value: icon.value, }); iconVisible.value = false; }; watch( () => icon.value, (newValue) => { if (newValue) { const iconArray = newValue.split("#"); iconComp.value = ElementPlusIcons[iconArray[0] as keyof typeof ElementPlusIcons]; if (iconComp.value) { selected.value = iconArray[0]; colorInput.value = iconArray[1]; nextTick(() => { if (iconPick.value) iconPick.value.value = colorInput.value ? `#${colorInput.value}` : ""; }); } } else { selected.value = ""; iconComp.value = undefined; colorInput.value = ""; } }, { immediate: true, } ); // 暴露方法· defineExpose({ closeIcon, openIcon, }); </script> <style scoped lang="scss"> .icons-tabs { .icons-container { padding-right: 15px; margin-right: -10px; } } .selected-icon { background-color: #409eff; border-radius: 6px; } .icons-text { font-size: 12px; } .button-container { display: flex; gap: 0.5rem; /* 2对应大约0.5rem(8px) */ } </style>

3、iconComp组件

<template> <div> <component v-if="iconComp" :is="iconComp" :style="{ color: icon?.split('#')[1], width: size + 'px', height: size + 'px' }" /> <img v-else-if="systemIcons?.find((f: any) => f.code == icon)" :style="{ width: size + 'px', height: size + 'px' }" :src="systemIcons?.find((f: any) => f.code == icon)?.icon" /> <div v-else-if="icon" class="form-icon-item" v-html="icon"></div> </div> </template> <script setup lang="ts"> import { watch, shallowRef, type Component } from "vue"; import * as ElementPlusIcons from "@element-plus/icons-vue"; import { AiIcons, Icons } from "../../assets/index"; const props = defineProps({ icon: { type: String, default: () => {}, }, size: { type: Number, default: 16, }, }); const systemIcons = [...Icons, ...AiIcons]; const iconComp = shallowRef<Component>(); watch( () => props.icon, (newValue) => { if (newValue) { const iconArray = newValue.split("#"); iconComp.value = ElementPlusIcons[iconArray[0] as keyof typeof ElementPlusIcons]; } }, { immediate: true, } ); </script> <style lang="less" scoped></style>

4、系统内置图片路径

index.ts

import bbmbSrc from "../assets/aiToolsIcons/baobiaomoban.png"; import aizy from "../assets/aiToolsIcons/ocr-yinshuawenzishibie.png"; import wbrs from "../assets/aiToolsIcons/wenbenbianjitianchong.png"; import dybgzx from "../assets/aiToolsIcons/baogao.png"; import dyjhzd from "../assets/aiToolsIcons/jihua.png"; import wzsb from "../assets/aiToolsIcons/ocr-yinshuawenzishibie.png"; import wdxxtq from "../assets/aiToolsIcons/wendang.png"; import pzsb from "../assets/aiToolsIcons/chuanpiaozhengfuwu.png"; import wdzh from "../assets/aiToolsIcons/zhuanhuan.png"; import wjcfhb from "../assets/aiToolsIcons/picichaifenhebing.png"; import yywbsc from "../assets/aiToolsIcons/zhihuiyuyinwenben.png"; import hgxjc from "../assets/aiToolsIcons/hefahegui.png"; import bgzdhsc from "../assets/aiToolsIcons/baobiaomoban.png"; import hyjysc from "../assets/aiToolsIcons/huiyi.png"; import wzzyy from "../assets/aiToolsIcons/zhihuiyuyinwenben.png"; import csznzs from "../assets/aiToolsIcons/测试智能助手.png"; import flfg from "../assets/aiToolsIcons/法律法规.png"; import fgk from "../assets/aiToolsIcons/法规库.png"; import flfgk from "../assets/aiToolsIcons/法律法规库@2x.png"; import nbzdk from "../assets/aiToolsIcons/内部制度库.png"; import rdjdzs from "../assets/aiToolsIcons/人大监督助手@2x.png"; import sjfxjmzs from "../assets/aiToolsIcons/审计分析建模助手.png"; import sjjdzs from "../assets/aiToolsIcons/审计监督助手@2x.png"; import sjwtdxzs from "../assets/aiToolsIcons/审计问题定性助手.png"; import sjywtjzs from "../assets/aiToolsIcons/审计业务推荐助手.png"; import sjzgzyzs from "../assets/aiToolsIcons/审计整改指引助手.png"; import xzyszt from "../assets/aiToolsIcons/新增预设主题.png"; import zbdbfxznzs from "../assets/aiToolsIcons/招标对比分析智能助手.png"; import zmzcfxzs from "../assets/aiToolsIcons/中煤招采分析助手.png"; import zdytsc from "../assets/aiToolsIcons/自定义提示词@2x.png"; import aiyyzs from "../assets/aiToolsIcons/AI应用助手@2x.png"; import bijcfxzs from "../assets/aiToolsIcons/BI集成分析助手.png"; export * from './aiIcons/index'; export const Icons = [ { name: '标签模板', code: 'system-bbmbSrc', icon: bbmbSrc }, { name: '文字识别', code: 'system-aizy', icon: aizy }, { name: '文本编辑', code: 'system-wbrs', icon: wbrs }, { name: '报告', code: 'system-dybgzx', icon: dybgzx }, { name: '计划', code: 'system-dyjhzd', icon: dyjhzd }, { name: '识别', code: 'system-wzsb', icon: wzsb }, { name: '文档', code: 'system-wdxxtq', icon: wdxxtq }, { name: '传票', code: 'system-pzsb', icon: pzsb }, { name: '转换', code: 'system-wdzh', icon: wdzh }, { name: '拆分', code: 'system-wjcfhb', icon: wjcfhb }, { name: '语音', code: 'system-yywbsc', icon: yywbsc }, { name: '合法合规', code: 'system-hgxjc', icon: hgxjc }, { name: '报表模板', code: 'system-bgzdhsc', icon: bgzdhsc }, { name: '会议', code: 'system-hyjysc', icon: hyjysc }, { name: '语音文本', code: 'system-wzzyy', icon: wzzyy }, { name: '测试智能助手', code: 'system-csznzs', icon: csznzs }, { name: '法律法规', code: 'system-flfg', icon: flfg }, { name: '法规库', code: 'system-fgk', icon: fgk }, { name: '法律法规库', code: 'system-flfgk', icon: flfgk }, { name: '内部制度库', code: 'system-nbzdk', icon: nbzdk }, { name: '人大监督助手', code: 'system-rdjdzs', icon: rdjdzs }, { name: '审计分析建模助手', code: 'system-sjfxjmzs', icon: sjfxjmzs }, { name: '审计监督助手', code: 'system-sjjdzs', icon: sjjdzs }, { name: '审计问题定性助手', code: 'system-sjwtdxzs', icon: sjwtdxzs }, { name: '审计业务推荐助手', code: 'system-sjywtjzs', icon: sjywtjzs }, { name: '审计整改指引助手', code: 'system-sjzgzyzs', icon: sjzgzyzs }, { name: '新增预设主题', code: 'system-xzyszt', icon: xzyszt }, { name: '招标对比分析智能助手', code: 'system-zbdbfxznzs', icon: zbdbfxznzs }, { name: '中煤招采分析助手', code: 'system-zmzcfxzs', icon: zmzcfxzs }, { name: '自定义提示词', code: 'system-zdytsc', icon: zdytsc }, { name: 'AI应用助手', code: 'system-aiyyzs', icon: aiyyzs }, { name: 'BI集成分析助手', code: 'system-bijcfxzs', icon: bijcfxzs }, ]
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 17:30:26

COMSOL 实现煤体钻孔周围损伤变形:多场耦合下的深度探索

COMSOL实现煤体钻孔周围损伤变形。 该案列考虑温度场和渗流扩散场对损伤影响&#xff0c;介绍钻孔周围损伤分布、损伤后瓦斯压力分布&#xff0c;可分析损伤后渗透率应力等 在煤炭开采等相关领域&#xff0c;理解煤体钻孔周围的损伤变形机制至关重要。借助 COMSOL 这一强大的多…

作者头像 李华
网站建设 2026/6/23 0:37:57

探索电压源型逆变器死区补偿算法:基于电流矢量的创新之路

该模型搭建死区补偿算法&#xff0c;针对电压源型空间矢量脉宽调制逆变器的死区效应,根据电流矢量判断电流极性的死区补偿方法.在静止参考轴系进行补偿电压&#xff0c;进而改善死区效应. 模型附带对应参考文献在电力电子领域&#xff0c;电压源型空间矢量脉宽调制&#xff08…

作者头像 李华
网站建设 2026/6/23 9:11:44

纯电动汽车两档ATM变速箱Simulink模型探索

纯电动汽车两档ATM变速箱simulink模型&#xff0c;模型实现了两档AMT换挡策略和换挡过程仿真&#xff0c;内含详细文档和注释模型&#xff0c;可运行最近在研究纯电动汽车的传动系统&#xff0c;发现了一个超有趣的东西——纯电动汽车两档ATM变速箱Simulink模型。今天就来跟大家…

作者头像 李华
网站建设 2026/6/23 15:40:29

VMD - CNN - BiGRU - Attention实现时间序列预测:风速数据集的探索

VMD-CNN-BiGRU-Attention实现时间序列预测 风速数据集 Matlab语言 你先用&#xff0c;你就是创新程序已调试好&#xff0c;无需更改代码直接替换Excel运行 时间序列单列&#xff0c;也可以加好友换成多变量的回归预测&#xff0c;效果如图1所示&#xff5e; 利用VMD分解将风速数…

作者头像 李华
网站建设 2026/6/23 12:05:13

车辆稳定性相平面MATLAB程序绘制之旅

车辆稳定性相平面MATLAB程序绘制 由魔术公式轮胎模型&#xff0c;建立车辆非线性二自由度动力学模型&#xff0c;并进而对相平面图进行绘制&#xff0c; 包括横摆角速度与质心侧偏角的相平面&#xff0c; 质心侧偏角速度与质心侧偏角的相平面。在车辆动力学研究中&#xff0c;理…

作者头像 李华
网站建设 2026/6/23 19:32:56

别再拿旧的那套忽悠老板了!GEO优化得用这三层指标说话

曝光点击数据再漂亮&#xff0c;也挡不住老板一句灵魂拷问&#xff1a;“所以到底带来了什么&#xff1f;” 当市场预算仍在源源不断流向搜索与内容时&#xff0c;许多市场负责人已感到一种熟悉的无力&#xff1a;报表上的曝光、点击、排名样样好看&#xff0c;直到老板轻飘飘问…

作者头像 李华