index.vue 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. <template>
  2. <span>
  3. <el-popover
  4. ref="pop"
  5. v-model="pop"
  6. :placement="placement"
  7. width="300"
  8. trigger="click"
  9. >
  10. <el-row v-if="clearable" type="flex" justify="end" class="ibps-mb-10">
  11. <el-button
  12. type="danger"
  13. icon="el-icon-delete"
  14. size="mini"
  15. class="ibps-fr"
  16. @click="selectIcon()"
  17. >
  18. 清空
  19. </el-button>
  20. </el-row>
  21. <el-input
  22. v-model="searchText"
  23. :clearable="true"
  24. placeholder="搜索 比如 'logo'"
  25. prefix-icon="el-icon-search"
  26. />
  27. <el-collapse v-if="!searchMode" v-model="collapseActive" class="ibps-iconselect--group">
  28. <el-collapse-item v-for="(item, index) in fontIcon" :key="index" :title="item.title" :name="index" class="ibps-iconselect--class">
  29. <el-row class="ibps-iconselect--class-row">
  30. <el-col v-for="(iconName, iconIndex) in item.icon" :key="iconIndex" class="ibps-iconselect--class-col" :span="4" @click.native="selectIcon(iconName)">
  31. <i :class="'ibps-icon ibps-icon-' + iconName" />
  32. </el-col>
  33. </el-row>
  34. </el-collapse-item>
  35. </el-collapse>
  36. <div v-if="searchMode" class="ibps-iconselect--group">
  37. <div v-for="(item, index) in iconFilted" :key="index" class="ibps-iconselect--class">
  38. <div class="ibps-iconselect--class-title">{{ item.title }}</div>
  39. <el-row class="ibps-iconselect--class-row">
  40. <el-col v-for="(iconName, iconIndex) in item.icon" :key="iconIndex" class="ibps-iconselect--class-col" :span="4" @click.native="selectIcon(iconName)">
  41. <i :class="'ibps-icon ibps-icon-' + iconName" />
  42. </el-col>
  43. </el-row>
  44. </div>
  45. </div>
  46. </el-popover>
  47. <!-- 允许用户输入 -->
  48. <el-input
  49. v-if="userInput"
  50. v-model="currentValue"
  51. v-bind="bind"
  52. style="max-width: 240px;"
  53. >
  54. <template v-if="value" slot="prepend">
  55. <i :class="'ibps-icon ibps-icon-' + value" />
  56. </template>
  57. <el-button slot="append" v-popover:pop>
  58. <i class="ibps-icon ibps-icon-list" />
  59. </el-button>
  60. </el-input>
  61. <!-- 不允许用户输入 -->
  62. <el-button v-if="!userInput" v-popover:pop>
  63. <template v-if="value">
  64. <i :class="'ibps-icon ibps-icon-' + value" />
  65. </template>
  66. {{ value ? (showLabel?value:'') : placeholder }}
  67. </el-button>
  68. </span>
  69. </template>
  70. <script>
  71. import fontIcon from './data/index'
  72. import Emitter from '@/plugins/element-ui/src/mixins/emitter'
  73. import { valueEquals } from '@/plugins/element-ui/src/utils/util'
  74. export default {
  75. name: 'ibps-icon-select',
  76. mixins: [Emitter],
  77. props: {
  78. // 值
  79. value: {
  80. type: String,
  81. required: false,
  82. default: ''
  83. },
  84. // 占位符
  85. placeholder: {
  86. type: String,
  87. required: false,
  88. default: '请选择'
  89. },
  90. icon: {
  91. type: String,
  92. default: 'el-icon-search"'
  93. },
  94. // 弹出界面的方向
  95. placement: {
  96. type: String,
  97. required: false,
  98. default: 'right'
  99. },
  100. // 是否可清空
  101. clearable: {
  102. type: Boolean,
  103. required: false,
  104. default: true
  105. },
  106. // 是否允许用户输入
  107. userInput: {
  108. type: Boolean,
  109. required: false,
  110. default: false
  111. },
  112. // 是否在选择后自动关闭
  113. autoClose: {
  114. type: Boolean,
  115. required: false,
  116. default: true
  117. },
  118. showLabel: {
  119. type: Boolean,
  120. default: true
  121. }
  122. },
  123. data() {
  124. return {
  125. // 绑定弹出框
  126. pop: false,
  127. // 所有图标
  128. fontIcon: fontIcon,
  129. // 组件内输入框的值
  130. currentValue: '',
  131. // 搜索的文字
  132. searchText: '',
  133. // 不是搜索的时候显示的折叠面板绑定的展开数据
  134. collapseActive: []
  135. // collapseActive: [...Array(icon.length)].map((e, i) => i)
  136. }
  137. },
  138. computed: {
  139. // 输入框上绑定的设置
  140. bind() {
  141. return {
  142. placeholder: this.placeholder,
  143. clearable: this.clearable,
  144. ...this.$attrs
  145. }
  146. },
  147. // 是否在搜索
  148. searchMode() {
  149. return !!this.searchText
  150. },
  151. // 过滤后的图标
  152. iconFilted() {
  153. return this.fontIcon.map(iconClass => ({
  154. title: iconClass.title,
  155. icon: iconClass.icon.filter(icon => icon.indexOf(this.searchText) >= 0)
  156. })).filter(iconClass => iconClass.icon.length > 0)
  157. }
  158. },
  159. watch: {
  160. value(value, oldVal) {
  161. this.currentValue = value
  162. if (!valueEquals(value, oldVal)) {
  163. this.dispatch('ElFormItem', 'el.form.change', value)
  164. }
  165. }
  166. },
  167. created() {
  168. this.currentValue = this.value
  169. },
  170. methods: {
  171. selectIcon(iconName = '') {
  172. this.$emit('input', iconName)
  173. if (iconName && this.autoClose) {
  174. this.pop = false
  175. }
  176. }
  177. }
  178. }
  179. </script>
  180. <style lang="scss" scoped>
  181. .ibps-iconselect--group {
  182. max-height: 400px;
  183. overflow-x: hidden;
  184. overflow-y: scroll;
  185. border-top: none;
  186. border-bottom: none;
  187. .ibps-iconselect--class {
  188. .ibps-iconselect--class-title {
  189. line-height: 30px;
  190. text-align: center;
  191. background-color: $color-bg;
  192. border-radius: 4px;
  193. margin: 10px 0px;
  194. }
  195. .ibps-iconselect--class-row {
  196. .ibps-iconselect--class-col {
  197. line-height: 40px;
  198. text-align: center;
  199. color: $color-text-sub;
  200. &:hover {
  201. color: $color-text-main;
  202. background-color: $color-bg;
  203. border-radius: 4px;
  204. font-size: 26px;
  205. box-shadow: inset 0px 0px 0px 1px $color-border-1;
  206. }
  207. }
  208. }
  209. }
  210. }
  211. </style>