personnelSearch.vue 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <script lang="ts" setup>
  2. import { ref, reactive, onMounted, inject, watchEffect, computed } from 'vue';
  3. import { debounce } from 'lodash';
  4. import { storeToRefs } from 'pinia';
  5. import { Emits, optionsType } from '../type';
  6. import { useStore } from '@/store/index'
  7. import { generateUniqueId } from '@/utils/tools'
  8. import { post, get, uploadFile } from "@/utils/request";
  9. const props = defineProps({
  10. modelValue: { type: [String, Number, Array, Object, Boolean], required: true },
  11. multiple: { type: Boolean, required: false, default: false },
  12. size: { type: String as () => assemblySize, required: true, default: () => 'small' },
  13. placeholder: { type: String, required: false, default: () => '请选择' },
  14. disabled: { type: Boolean, required: false, default: false },
  15. options: { type: Array as () => optionsType, required: false, default: () => [] },
  16. clearable: { type: Boolean, required: false, default: true },
  17. width: { type: String, required: false, default: () => '100%' },
  18. });
  19. const emit = defineEmits<Emits>();
  20. const personnelArray = ref<optionsType>([]);
  21. const { userInfo, personnelList } = storeToRefs(useStore());
  22. const { setValue } = useStore()
  23. const timeRef = generateUniqueId()
  24. const selectLoading = ref(false);
  25. const controlTranslation = reactive({
  26. visibleFlag: false // 下拉框出现隐藏
  27. })
  28. const selectedValue = ref(props.modelValue); // 响应式绑定 v-model 的值
  29. const getSelectedLabel = computed(() => {
  30. if (!props.multiple) {
  31. const item = getPersonnelListItems(selectedValue.value);
  32. return item ? item.label : props.placeholder
  33. }
  34. if (props.multiple) {
  35. if (Array.isArray(selectedValue.value)) {
  36. if (selectedValue.value.length <= 0) {
  37. return props.placeholder
  38. }
  39. const item = getPersonnelListItems(selectedValue.value);
  40. return item ? item.label : props.placeholder
  41. } else {
  42. return props.placeholder
  43. }
  44. }
  45. return props.placeholder
  46. })
  47. function tagClose(_evt: MouseEvent) {
  48. if (Array.isArray(selectedValue.value)) {
  49. selectedValue.value.shift()
  50. updateValue(selectedValue.value)
  51. }
  52. }
  53. function getPersonnelListItems(val: any) {
  54. let value = val;
  55. if (Array.isArray(val) && val.length > 0) {
  56. value = val[0]
  57. }
  58. return personnelList.value.find((item: any) => item.value == value)
  59. }
  60. function getUserList(keyword: string = '') {
  61. post(`/user/getSimpleActiveUserListNew`, { keyword }).then(res => {
  62. personnelArray.value = res.data
  63. if (!keyword) {
  64. setValue((res.data || []), 'personnelList')
  65. }
  66. }).finally(() => {
  67. selectLoading.value = false
  68. })
  69. }
  70. function visibleChange(visible: boolean) { // 下拉框出现/隐藏时触发
  71. controlTranslation.visibleFlag = visible
  72. }
  73. const filterMethod = debounce(filterMethods, 500)
  74. function filterMethods(val: string) {
  75. if (val == '') {
  76. personnelArray.value = personnelList.value
  77. selectLoading.value = false
  78. return personnelArray.value
  79. }
  80. getUserList(val)
  81. }
  82. function updateValue(val: any) { // 值改变的时候触发
  83. emit('update:modelValue', selectedValue.value)
  84. emit('change', val)
  85. }
  86. onMounted(() => {
  87. if (personnelList.value.length == 0) {
  88. if (props.options.length > 0) {
  89. personnelArray.value = props.options
  90. } else {
  91. getUserList()
  92. }
  93. } else {
  94. personnelArray.value = personnelList.value
  95. }
  96. })
  97. </script>
  98. <template>
  99. <!-- <el-select v-model="selectedValue" :ref="`selectRef${timeRef}`" :multiple="multiple" :size="size"
  100. :loading="selectLoading" :placeholder="placeholder" :disabled="disabled" clearable filterable collapse-tags
  101. :style="`width: ${width}`"
  102. :class="`custom-select ${userInfo.userNameNeedTranslate != 1 && !controlTranslation.visibleFlag ? 'setUpInput' : ''}`"
  103. @change="updateValue" @visible-change="visibleChange"
  104. :filter-method="(val: string) => { selectLoading = true, filterMethod(val) }">
  105. 搜索内容显示
  106. <template #prefix v-if="!multiple">
  107. <div style="height: 100%;display: flex;align-items: center;">
  108. 单选
  109. <div v-if="!controlTranslation.visibleFlag" class="selectSingleChoice">
  110. <template v-if="getSelectedLabel == placeholder">
  111. {{ placeholder }}
  112. </template>
  113. <template v-else>
  114. <span style="color: #303133;">
  115. <TextTranslation translationTypes="userName" :translationValue="getSelectedLabel"></TextTranslation>
  116. </span>
  117. </template>
  118. </div>
  119. </div>
  120. </template>
  121. <template #tag v-if="multiple">
  122. 多选
  123. <template v-if="Array.isArray(selectedValue) && selectedValue.length > 0">
  124. <el-tag type="info" :size="size" closable @close="tagClose">
  125. <TextTranslation translationTypes="userName" :translationValue="getSelectedLabel"></TextTranslation>
  126. </el-tag>
  127. <el-tag type="info" :size="size" v-if="selectedValue.length > 1">+{{ selectedValue.length }}</el-tag>
  128. </template>
  129. <template v-else>
  130. <span style="color: #A8ABB2">{{ placeholder }}</span>
  131. </template>
  132. </template>
  133. 主题内容显示
  134. <el-option v-for="item in personnelArray" :key="item.value" :label="item.label" :value="item.value"></el-option>
  135. </el-select> -->
  136. <el-select-v2 v-model="selectedValue" :ref="`selectRef${timeRef}`" :multiple="multiple" :size="size"
  137. :loading="selectLoading" :placeholder="placeholder" :disabled="disabled" :clearable="clearable" filterable collapse-tags
  138. :style="`width: ${width}`" :options="personnelArray"
  139. :class="`custom-select ${!controlTranslation.visibleFlag ? 'setUpInput' : ''}`" @change="updateValue"
  140. @visible-change="visibleChange" :filter-method="filterMethod">
  141. <!-- 搜索内容显示 -->
  142. <template #prefix v-if="!multiple">
  143. <div style="height: 100%;display: flex;align-items: center;">
  144. <!-- 单选 -->
  145. <div v-if="!controlTranslation.visibleFlag" class="selectSingleChoice">
  146. <template v-if="getSelectedLabel == placeholder">
  147. {{ placeholder }}
  148. </template>
  149. <template v-else>
  150. <span style="color: #606266;">
  151. <TextTranslation translationTypes="userName" :translationValue="getSelectedLabel"></TextTranslation>
  152. </span>
  153. </template>
  154. </div>
  155. </div>
  156. </template>
  157. <template #tag v-if="multiple">
  158. <!-- 多选 -->
  159. <template v-if="Array.isArray(selectedValue) && selectedValue.length > 0">
  160. <el-tag type="info" :size="size" closable @close="tagClose">
  161. <TextTranslation translationTypes="userName" :translationValue="getSelectedLabel"></TextTranslation>
  162. </el-tag>
  163. <el-tag type="info" :size="size" v-if="selectedValue.length > 1">+{{ selectedValue.length }}</el-tag>
  164. </template>
  165. <template v-else>
  166. <span style="color: #A8ABB2">{{ placeholder }}</span>
  167. </template>
  168. </template>
  169. <!-- 基础 -->
  170. <template #default="{ item }">
  171. <div class="flex items-center">
  172. <TextTranslation translationTypes="userName" :translationValue="item.label"></TextTranslation>
  173. </div>
  174. </template>
  175. </el-select-v2>
  176. </template>
  177. <style lang="scss" scoped>
  178. .custom-select {
  179. :deep(.el-select__placeholder.is-transparent) {
  180. color: transparent !important;
  181. }
  182. :deep(.el-select__placeholder) {
  183. span {
  184. display: none;
  185. }
  186. }
  187. :deep(.el-select__input) {
  188. margin-left: 0;
  189. }
  190. }
  191. .setUpInput :deep(.el-input__inner) {
  192. color: #fff !important;
  193. }
  194. </style>