XcSelect.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <el-select
  3. v-model="modelObj"
  4. :clearable="props.clearable"
  5. :remote="props.remote"
  6. :id="props.id"
  7. :remote-method="xcMethod"
  8. :style="{ width: props.width + 'px' }"
  9. ref="selectRef"
  10. filterable
  11. @change="el => changeStaff(el)"
  12. @clear="clear"
  13. @focus="getFocus"
  14. >
  15. <el-option
  16. v-for="(item, index) in props.data"
  17. :key="item.index"
  18. :label="item.name"
  19. :value="item.code"
  20. >
  21. <template
  22. v-for="(opitem, index) in optionList"
  23. v-if="optionList.length > 0"
  24. >
  25. <el-divider v-if="index !== 0" direction="vertical"></el-divider>
  26. <span :style="opitem.style">{{ item[opitem.label] }}</span>
  27. </template>
  28. <template v-else>
  29. <span>{{ item.code }}</span>
  30. <el-divider direction="vertical"></el-divider>
  31. <span>{{ item.name }}</span>
  32. </template>
  33. </el-option>
  34. </el-select>
  35. </template>
  36. <script setup>
  37. import { debounce } from "@/utils/debounce";
  38. import { stringNotBlank } from "@/utils/blank-utils";
  39. import { onMounted, watch } from "vue";
  40. import useCompRef from "@/utils/useCompRef";
  41. import { ElSelect } from "element-plus";
  42. const props = defineProps({
  43. modelValue: {
  44. type: Object,
  45. },
  46. name: {
  47. type: Array,
  48. default: ["code", "name"],
  49. },
  50. width: {
  51. type: Number,
  52. default: 120,
  53. },
  54. data: {
  55. type: Array,
  56. default: [],
  57. },
  58. remote: {
  59. type: Boolean,
  60. default: false,
  61. },
  62. clearable: {
  63. type: Boolean,
  64. default: false,
  65. },
  66. id: {
  67. type: String,
  68. },
  69. });
  70. const emit = defineEmits(["method", "change", "focus"]);
  71. const modelObj = ref(null);
  72. const selectRef = useCompRef(ElSelect);
  73. const optionList = ref([]);
  74. const colorList = {
  75. primary: "#409eff",
  76. danger: "#f56c6c",
  77. info: "#8492a6",
  78. success: "#67C23A",
  79. warning: "#E6A23C",
  80. };
  81. const changeStaff = el => {
  82. nextTick(() => {
  83. props.modelValue[props.name[0]] = el;
  84. props.modelValue[props.name[1]] =
  85. selectRef.value?.states.selected?.currentLabel;
  86. });
  87. emit(
  88. "change",
  89. props.data.find(i => i.code === modelObj.value)
  90. );
  91. };
  92. const clear = () => {
  93. modelObj.value = null;
  94. props.modelValue[props.name[0]] = null;
  95. props.modelValue[props.name[1]] = null;
  96. };
  97. const xcMethod = debounce(value => {
  98. if (stringNotBlank(value) && value.length > 1) {
  99. method(value);
  100. }
  101. }, 400);
  102. const getFocus = () => {
  103. emit("focus");
  104. };
  105. /**
  106. * 监听父组件的值是否改变
  107. * 如果改变了那么就,要执行查询动作
  108. * 如果 props.data 里面有值了就不用查询
  109. * props.data 里面没有值对得上那就需要执行查询动作了
  110. *
  111. */
  112. watch(
  113. () => props.modelValue[props.name[0]],
  114. () => {
  115. modelObj.value = props.modelValue[props.name[0]];
  116. let len = props.data.length;
  117. if (len === 0) {
  118. method(modelObj.value);
  119. }
  120. for (let i = 0; i < len; i++) {
  121. if (modelObj.value === props.data[i].code) {
  122. return;
  123. }
  124. }
  125. method(modelObj.value);
  126. }
  127. );
  128. const method = value => {
  129. emit("method", value);
  130. };
  131. const focus = () => {
  132. selectRef.value.focus();
  133. };
  134. const blur = () => {
  135. selectRef.value.blur();
  136. };
  137. defineExpose({ focus, blur });
  138. onMounted(() => {
  139. nextTick(() => {
  140. modelObj.value = props.modelValue[props.name[0]];
  141. });
  142. // 判断组件是否使用了 slot
  143. if (!!useSlots().default) {
  144. // 判断 slot 有没有想要的值
  145. for (let item of useSlots().default()) {
  146. if (item.props !== null) {
  147. let style = {};
  148. if (typeof item.props.style === "undefined") {
  149. if (typeof item.props.type === "undefined") {
  150. style = { color: "#8492a6" };
  151. } else {
  152. style = { color: colorList[item.props.type] };
  153. }
  154. } else {
  155. style = item.props.style;
  156. }
  157. let data = {
  158. label: item.props.label,
  159. style: style,
  160. };
  161. optionList.value.push(data);
  162. }
  163. }
  164. }
  165. });
  166. </script>
  167. <style scoped></style>