<template> <div class="app-icon-picker"> <el-input :placeholder="placeholder" :disabled="disabled ? true : false" :readonly="readonly" v-model="itemValue" clearable @focus="focus" @input="change" > </el-input> <el-dialog :title="$t('components.iconpicker.title')" :visible.sync="iconSelectorState" :before-close="handleCancel" :modal="false" width="80%"> <div class="app-icon-picker__box"> <el-input v-model="searchIconKey" :placeholder="$t('components.iconpicker.placeholder')" @input="handleSearchIconChange"></el-input> <el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect"> <el-menu-item v-for="(item, index) in iconCategories" :title="item" :key="index" :index="String(index)">{{ computedIconCategories(item) }}</el-menu-item> </el-menu> <div class="selector-content__icon-list"> <div class="selector-content__icon-item" v-for="(item, index) in iconData" :key="index" > <div :class="{ 'icon-item__box': true, 'is-active': currentIconKey === (`fa fa-${item.id}`) }" :title="`fa fa-${item.id}`" @click.prevent="handleIconChange((`fa fa-${item.id}`))" > <p class="item-icon" > <i :class="['fa', `fa-${item.id}`]"></i> </p> <p class="icon-tip">{{ item.id }}</p> </div> </div> </div> </div> <span slot="footer" class="dialog-footer"> <el-button @click="handleCancel()">{{$t('app.commonwords.cancel')}}</el-button> <el-button type="primary" @click="handleConfirm">{{ $t('app.commonwords.ok') }}</el-button> </span> </el-dialog> </div> </template> <script lang="ts"> import { Vue, Component, Prop, Watch, Model, Emit } from 'vue-property-decorator'; @Component({}) export default class AppIconPicker extends Vue { /** * 双向绑定值 * * @type {any} * @memberof AppIconPicker */ @Model("change") readonly itemValue?: any; /** * placeholder值 * * @type {String} * @memberof AppIconPicker */ @Prop() public placeholder?: string; /** * 是否禁用 * * @type {boolean} * @memberof AppIconPicker */ @Prop() public disabled?: boolean; /** * 只读模式 * * @type {boolean} */ @Prop({ default: false }) public readonly?: boolean; /** * 当前渲染的icon数据 * * @memberof AppIconPicker */ public iconData:any = []; /** * 所有icon数据集合 * * @memberof AppIconPicker */ public iconDataSet: any = require(`@/assets/json/icon/awesome.json`); /** * 图标分类数据 * * @memberof AppIconPicker */ public iconCategories: any[] = []; /** * 图标选择弹框状态 * * @type {boolean} * @memberof AppIconPicker */ public iconSelectorState: boolean = false; /** * 菜单选中下标 * * @type {string} * @memberof AppIconPicker */ public activeIndex: string = '0'; /** * 当前选中的icon * * @type {string} * @memberof AppIconPicker */ public currentIconKey: string = ''; /** * 搜索关键字过滤icon * * @memberof AppIconPicker */ public searchIconKey: string = ''; @Watch('iconSelectorState') public onIconSelectorStateChange(val: boolean, oldVal: boolean) { if (val) { this.loadData(); this.handleSelect(Number(this.activeIndex)) } } /** * 关闭弹框 * * @memberof AppIconPicker */ public handleCancel() { this.searchIconKey = ''; this.currentIconKey = ''; this.iconSelectorState = false; } /** * 确认选择 * * @memberof AppIconPicker */ public handleConfirm() { if (this.currentIconKey) { this.$emit('change', this.currentIconKey); } this.handleCancel(); } /** * 处理选择图标改变 * * @param {string} value * @memberof AppIconPicker */ public handleIconChange(value: string) { this.currentIconKey = value; } /** * 选择需要渲染的分类数据 * * @param {number} key * @memberof AppIconPicker */ public handleSelect(key: number, keyPath?: string[0]) { this.searchIconKey = ''; this.activeIndex = String(key); this.computedIconData(this.iconCategories[key]); } /** * 处理icon搜索框change事件 * * @param {string} data * @memberof AppIconPicker */ public handleSearchIconChange(data: string) { const categories = String(this.iconCategories[Number(this.activeIndex)]); this.computedIconData(categories, data); } /** * 处理需要渲染的icon分类数据国际化 * * @memberof AppIconPicker */ public computedIconCategories(categoriesItem: string) { if (!categoriesItem) { return ''; } const value = categoriesItem.replace(/\s/g, '').replace(/Icons/g, '').toLowerCase(); return this.$t(`components.iconpicker.${value}`); } /** * 处理需要需要渲染的的icon数据 * * @type {string} * @memberof AppIconPicker */ public computedIconData(categories: string, data?: string) { let iconData: any[] = this.iconDataSet.icons.filter((item: any) => { return item.categories[0] === categories; }); if (data) { this.iconData = iconData.filter((item: any) => { return item.id.indexOf(data) !== -1; }); } else { this.iconData = iconData; } } /** * 初始化渲染内容 * * @memberof AppIconPicker */ public loadData() { this.currentIconKey = this.itemValue; let categoriesData: any[] = []; this.iconDataSet.icons.forEach((item: any) => { if (categoriesData.indexOf(item.categories[0]) === -1) { categoriesData.push(item.categories[0]); } }); this.iconCategories = categoriesData; } /** * 获取焦点事件 * * @memberof AppIconPicker */ @Emit() public focus(value: string) { if (!this.disabled && !this.readonly) { this.iconSelectorState = true; } return this.itemValue; } /** * change事件 * * @memberof AppIconPicker */ @Emit() public change(value: string) { return this.itemValue; } } </script>