重构 scIconSelect 组件

This commit is contained in:
sc 2022-06-06 18:01:31 +08:00 committed by sakuya
parent 0f972114ba
commit 64bca66436
2 changed files with 73 additions and 44 deletions

View File

@ -1,35 +1,47 @@
<!-- <!--
* @Descripttion: 图标选择器组件 * @Descripttion: 图标选择器组件
* @version: 1.4 * @version: 2.0
* @Author: sakuya * @Author: sakuya
* @Date: 2021年7月27日10:02:46 * @Date: 2021年7月27日10:02:46
* @LastEditors: sakuya * @LastEditors: sakuya
* @LastEditTime: 20225月14日19:49:42 * @LastEditTime: 20226月6日13:48:49
--> -->
<template> <template>
<div class="sc-icon-select"> <div class="sc-icon-select">
<el-input v-model="defaultValue" :prefix-icon="defaultValue||'none'" :placeholder="placeholder" :clearable="clearable" :disabled="disabled"> <div class="sc-icon-select__wrapper" :class="{'hasValue':value}" @click="open">
<template #append><el-button icon="el-icon-more-filled" @click="open"></el-button></template> <el-input :prefix-icon="value||'el-icon-plus'" v-model="value" :disabled="disabled" readonly></el-input>
</el-input> </div>
<el-dialog title="图标选择器" v-model="dialogVisible" :width="780" destroy-on-close> <el-dialog title="图标选择器" v-model="dialogVisible" :width="760" destroy-on-close append-to-body>
<el-tabs style="margin-top: -30px;"> <div class="sc-icon-select__dialog" style="margin: -20px 0 -10px 0;">
<el-tab-pane v-for="item in data" :key="item.name" lazy> <el-form :rules="{}">
<template #label> <el-form-item prop="searchText">
{{item.name}} <el-tag size="small" type="info">{{item.icons.length}}</el-tag> <el-input class="sc-icon-select__search-input" prefix-icon="el-icon-search" v-model="searchText" placeholder="搜索" size="large" clearable/>
</template> </el-form-item>
<div class="sc-icon-select__list"> </el-form>
<el-scrollbar> <el-tabs>
<ul @click="selectIcon"> <el-tab-pane v-for="item in data" :key="item.name" lazy>
<li v-for="icon in item.icons" :key="icon"> <template #label>
<span :data-icon="icon"></span> {{item.name}} <el-tag size="small" type="info">{{item.icons.length}}</el-tag>
<el-icon><component :is="icon" /></el-icon> </template>
</li> <div class="sc-icon-select__list">
</ul> <el-scrollbar>
</el-scrollbar> <ul @click="selectIcon">
</div> <el-empty v-if="item.icons.length==0" :image-size="100" description="未查询到相关图标" />
</el-tab-pane> <li v-for="icon in item.icons" :key="icon">
</el-tabs> <span :data-icon="icon"></span>
<el-icon><component :is="icon" /></el-icon>
</li>
</ul>
</el-scrollbar>
</div>
</el-tab-pane>
</el-tabs>
</div>
<template #footer>
<el-button @click="clear" text>清除</el-button>
<el-button @click="dialogVisible=false">取消</el-button>
</template>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
@ -40,27 +52,28 @@
export default { export default {
props: { props: {
modelValue: { type: String, default: "" }, modelValue: { type: String, default: "" },
placeholder: { type: String, default: "请输入或者选择图标" },
clearable: { type: Boolean, default: false },
disabled: { type: Boolean, default: false }, disabled: { type: Boolean, default: false },
}, },
data() { data() {
return { return {
defaultValue: '', value: "",
dialogVisible: false, dialogVisible: false,
data: [] data: [],
searchText: ""
} }
}, },
watch:{ watch:{
modelValue(val){ modelValue(val){
this.defaultValue = val this.value = val
}, },
defaultValue(val){ value(val){
this.$emit('update:modelValue', val) this.$emit('update:modelValue', val)
},
searchText(val){
this.search(val)
} }
}, },
mounted() { mounted() {
this.defaultValue = this.modelValue
this.data.push(...config.icons) this.data.push(...config.icons)
}, },
methods: { methods: {
@ -74,25 +87,41 @@
if(e.target.tagName != 'SPAN'){ if(e.target.tagName != 'SPAN'){
return false return false
} }
this.defaultValue = e.target.dataset.icon this.value = e.target.dataset.icon
this.dialogVisible = false this.dialogVisible = false
this.$emit('update:modelValue', this.defaultValue); },
clear(){
this.value = ""
this.dialogVisible = false
},
search(text){
if(text){
const filterData = JSON.parse(JSON.stringify(config.icons))
filterData.forEach(t => {
t.icons = t.icons.filter(n => n.includes(text))
})
this.data = filterData
}else{
this.data = JSON.parse(JSON.stringify(config.icons))
}
} }
} }
} }
</script> </script>
<style scoped> <style scoped>
.sc-icon-select {display: inline-block;} .sc-icon-select {display: inline-flex;}
.sc-icon-select__list {height:360px;overflow: auto;} .sc-icon-select__wrapper {cursor: pointer;display: inline-flex;}
.sc-icon-select__list ul {} .sc-icon-select__wrapper:deep(.el-input__wrapper).is-focus {box-shadow: 0 0 0 1px var(--el-input-hover-border-color) inset;}
.sc-icon-select__list li {display: inline-block;width:80px;height:80px;margin:5px;vertical-align: top;box-shadow: 0 0 0 1px #eee;transition: all 0.1s;border-radius: 4px;position: relative;} .sc-icon-select__wrapper:deep(.el-input__inner) {flex-grow:0;width: 0;}
.sc-icon-select__list li span {position: absolute;top:0;left:0;right:0;bottom:0;z-index: 1;cursor: pointer;} .sc-icon-select__wrapper:deep(.el-input__icon) {margin: 0;font-size: 16px;}
.sc-icon-select__list li i {display: inline-block;width: 100%;height:100%;font-size: 26px;color: #6d7882;background: #fff;display: flex;justify-content: center;align-items: center;border-radius: 4px;} .sc-icon-select__wrapper.hasValue:deep(.el-input__icon) {color: var(--el-text-color-regular);}
.sc-icon-select__list li:hover {box-shadow: 0 0 1px 4px rgba(64,158,255,1);}
.sc-icon-select__list li:hover i {color: #409EFF;}
.dark .sc-icon-select__list li {box-shadow: 0 0 0 1px #333;;} .sc-icon-select__list {height:270px;overflow: auto;}
.dark .sc-icon-select__list li:hover {box-shadow: 0 0 1px 4px rgba(64,158,255,1);} .sc-icon-select__list ul {}
.dark .sc-icon-select__list li i {background: var(--el-bg-color);} .sc-icon-select__list li {display: inline-block;width:80px;height:80px;margin:5px;vertical-align: top;transition: all 0.1s;border-radius: 4px;position: relative;}
.sc-icon-select__list li span {position: absolute;top:0;left:0;right:0;bottom:0;z-index: 1;cursor: pointer;}
.sc-icon-select__list li i {display: inline-block;width: 100%;height:100%;font-size: 26px;color: #6d7882;display: flex;justify-content: center;align-items: center;border-radius: 4px;}
.sc-icon-select__list li:hover {box-shadow: 0 0 1px 4px var(--el-color-primary);background: var(--el-color-primary-light-9);}
.sc-icon-select__list li:hover i {color: var(--el-color-primary);}
</style> </style>

View File

@ -13,7 +13,7 @@
<el-card shadow="never"> <el-card shadow="never">
<el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px"> <el-form ref="ruleForm" :model="form" :rules="rules" label-width="100px">
<el-form-item label="图标" prop="icon"> <el-form-item label="图标" prop="icon">
<sc-icon-select v-model="form.icon" clearable :disabled="disabled"></sc-icon-select> <sc-icon-select v-model="form.icon" :disabled="disabled"></sc-icon-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" @click="submitForm">保存</el-button> <el-button type="primary" @click="submitForm">保存</el-button>