pullDownSelector.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <template>
  2. <div class="w-full h-full flex flex-col">
  3. <div class="w-full pt-2 searchKeywords">
  4. <van-search v-model.trim="searchForValue" shape="round" placeholder="请输入搜索关键词"
  5. @update:model-value="debouncedSearchOptions" input-align="left" />
  6. </div>
  7. <div class="flex-1 my-2 overflow-y-auto">
  8. <template v-if="renderingOptions.length == 1 && renderingOptions[0] && !renderingOptions[0].label">
  9. <van-empty />
  10. </template>
  11. <template v-else>
  12. <!-- 加载 -->
  13. <template v-if="listLoading">
  14. <van-skeleton :row="10" />
  15. </template>
  16. <template v-else>
  17. <template v-if="!multipleChoice">
  18. <!-- 单选 -->
  19. <van-radio-group v-model="selectChecked">
  20. <template v-for="item in renderingOptions">
  21. <van-cell-group inset>
  22. <van-cell clickable @click="selectChecked = item.value">
  23. <template #right-icon>
  24. <van-radio :name="item.value" />
  25. </template>
  26. <template #title>
  27. <TranslationComponent :openId="item.label" />
  28. </template>
  29. </van-cell>
  30. </van-cell-group>
  31. </template>
  32. </van-radio-group>
  33. </template>
  34. <!-- 多选 -->
  35. <template v-if="multipleChoice">
  36. <van-checkbox-group v-model="selectChecked">
  37. <van-cell-group inset>
  38. <van-cell v-for="(item, index) in renderingOptions" clickable :key="index" @click="toggle(index)">
  39. <template #right-icon>
  40. <van-checkbox :name="item.value" :ref="(el) => (checkboxRefs[index] = el)" @click.stop />
  41. </template>
  42. <template #title>
  43. <TranslationComponent :openId="item.label" />
  44. </template>
  45. </van-cell>
  46. </van-cell-group>
  47. </van-checkbox-group>
  48. </template>
  49. </template>
  50. </template>
  51. </div>
  52. <div class="w-full pb-2 px-4">
  53. <van-button type="primary" round class="w-full" :disabled="multipleChoice ? !selectChecked.length : (!selectChecked && selectChecked != 0)" @click="confirmClick">确定</van-button>
  54. </div>
  55. </div>
  56. </template>
  57. <script setup>
  58. import { ref, onBeforeUpdate, reactive, watch, onMounted, onActivated } from "vue";
  59. import { manualCopying, useDebounce } from "@hooks/useCommon";
  60. import requests from "@common/requests";
  61. import { GET_ALL_PERSONNEL } from "@hooks/useApi";
  62. import useFixedData from "@store/useFixedData";
  63. const props = defineProps({
  64. options: {
  65. type: Array,
  66. default: () => [],
  67. },
  68. showElement: {
  69. type: Boolean,
  70. default: () => false,
  71. },
  72. value: {
  73. type: [String, Array],
  74. default: () => [],
  75. },
  76. doYouNeedTranslation: {
  77. type: Boolean,
  78. default: () => true,
  79. },
  80. multipleChoice: {
  81. type: Boolean,
  82. default: () => false,
  83. },
  84. });
  85. const emit = defineEmits(["change"]);
  86. const fixedData = useFixedData();
  87. const listLoading = ref(false);
  88. const selectChecked = ref([]);
  89. const checkboxRefs = ref([]);
  90. const searchForValue = ref("");
  91. const allOptions = ref([]);
  92. const renderingOptions = ref([]);
  93. const debouncedSearchOptions = useDebounce(searchOptions, 500);
  94. watch(() => props.options, (newValue) => {
  95. selectChecked.value = props.multipleChoice ? [] : null;
  96. const isItAnArray = Array.isArray(newValue);
  97. if (isItAnArray && newValue.length > 0) {
  98. renderingOptions.value = manualCopying(newValue);
  99. allOptions.value = manualCopying(newValue);
  100. } else {
  101. obtainPersonnelData();
  102. }
  103. })
  104. watch(() => props.value, (newValue) => {
  105. if(!newValue) {
  106. selectChecked.value = []
  107. }
  108. selectChecked.value = Array.isArray(newValue) ? newValue : [newValue]
  109. })
  110. watch(() => props.showElement, (newValue) => {
  111. if(!newValue) {
  112. setTimeout(() => {
  113. searchForValue.value = ''
  114. searchOptions('')
  115. const val = (props.value && Array.isArray(props.value) && props.value.length > 0)
  116. selectChecked.value = val ? selectChecked.value : []
  117. }, 500)
  118. }
  119. })
  120. function searchOptions(val) {
  121. listLoading.value = true
  122. if (!props.doYouNeedTranslation) {
  123. setTimeout(() => {
  124. listLoading.value = false
  125. }, 200)
  126. if (!val) {
  127. renderingOptions.value = manualCopying(allOptions.value);
  128. return;
  129. }
  130. const list = manualCopying(allOptions.value);
  131. renderingOptions.value = list.filter((item) => (item.label || '').indexOf(val) > -1);
  132. return
  133. }
  134. // 转译人员搜索
  135. requests.post(GET_ALL_PERSONNEL, { keyword: val }).then((res) => {
  136. const { data } = res
  137. renderingOptions.value = [ ...data ]
  138. }).finally(() => {
  139. listLoading.value = false
  140. })
  141. }
  142. function toggle(index) {
  143. checkboxRefs.value[index].toggle();
  144. }
  145. function valueTaking(val) {
  146. if (Array.isArray(val)) {
  147. return allOptions.value
  148. .filter((item) => val.includes(item.value))
  149. .map((item) => item.label);
  150. } else {
  151. return allOptions.value.find((item) => item.value === val)?.label;
  152. }
  153. }
  154. function obtainPersonnelData() {
  155. if (fixedData.allUserData && fixedData.allUserData.length) {
  156. renderingOptions.value = [...fixedData.allUserData];
  157. allOptions.value = [...fixedData.allUserData];
  158. return;
  159. }
  160. listLoading.value = true;
  161. requests.post(GET_ALL_PERSONNEL, {}).then(({ data = [] }) => {
  162. renderingOptions.value = [...data];
  163. allOptions.value = [...data];
  164. fixedData.updateState({
  165. allUserData: [...data]
  166. })
  167. }).finally(() => {
  168. listLoading.value = false;
  169. })
  170. }
  171. function confirmClick() {
  172. emit("change", selectChecked.value, valueTaking(selectChecked.value));
  173. }
  174. onBeforeUpdate(() => {
  175. checkboxRefs.value = [];
  176. });
  177. onMounted(() => {
  178. selectChecked.value = props.multipleChoice ? [] : null;
  179. const isItAnArray = Array.isArray(props.options);
  180. if (isItAnArray && props.options.length > 0) {
  181. renderingOptions.value = manualCopying(props.options);
  182. allOptions.value = manualCopying(props.options);
  183. } else {
  184. obtainPersonnelData();
  185. }
  186. if(props.value) {
  187. selectChecked.value = props.multipleChoice ? Array.isArray(props.value) ? props.value : props.value.split(',') : props.value
  188. }
  189. });
  190. </script>
  191. <style lang="scss" scoped>
  192. </style>