index.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. <template>
  2. <div class="kSelectPopIdx">
  3. <van-popup v-model:show="selPopShow" round position="bottom">
  4. <div class="o-ptb-10 l-re">
  5. <div class="o-plr-20 o-mb-20 l-flex-between">
  6. <div @click="selPopShow = false" class="c-text-16 c-color">{{ $t('kSelectPop.cancel') }}</div>
  7. <div class="c-text-16 c-text-b">{{ $t('kSelectPop.selectTitle') }}</div>
  8. <div @click="confirmClk" class="c-text-16 c-text-color">{{ $t('kSelectPop.confirm') }}</div>
  9. </div>
  10. <van-search v-model="searchValue" :placeholder="$t('kSelectPop.searchKey')" shape="round" background="#4d6add"
  11. @update:model-value="valueChange" />
  12. <div style="height: 50vh;overflow:hidden;overflow-y:auto;">
  13. <!-- 全选 -->
  14. <van-checkbox-group v-model="allChecked" ref="allCheckRef">
  15. <van-cell-group inset>
  16. <van-cell :title="$t('kSelectPop.allCheck')" @click="checkAll">
  17. <template #right-icon>
  18. <van-checkbox name="all" @click="checkAll" />
  19. </template>
  20. </van-cell>
  21. </van-cell-group>
  22. </van-checkbox-group>
  23. <div class="content">
  24. <van-checkbox-group v-model="checked" ref="checkboxGroup">
  25. <van-cell-group inset>
  26. <div v-for="(item, index) in props.selOptions" :key="index" class="kBordBott">
  27. <van-cell :border="false" :title="item[selTitleAndName[0]]" @click="toggle(index)">
  28. <template #right-icon>
  29. <van-checkbox @click.stop="toggle(index)" :name="item[selTitleAndName[0]]"
  30. :ref="(el) => (checkboxRefs[index] = el)" />
  31. </template>
  32. </van-cell>
  33. </div>
  34. </van-cell-group>
  35. </van-checkbox-group>
  36. </div>
  37. </div>
  38. </div>
  39. </van-popup>
  40. </div>
  41. </template>
  42. <script>
  43. /**
  44. * kSelectPop 选择弹窗组件
  45. * @description 本组件主要是用于单选或多选的组件。
  46. *
  47. */
  48. import { ref, onBeforeUpdate } from "vue";
  49. export default {
  50. props: {
  51. selOptions: {
  52. type: Array,
  53. default: () => {
  54. return [];
  55. },
  56. },
  57. selTitleAndName: {
  58. type: Array,
  59. default: () => {
  60. return ["name", "id"];
  61. },
  62. },
  63. },
  64. setup(props, { emit }) {
  65. // 点击确定按钮
  66. const confirmClk = () => {
  67. // console.log("选中", checked.value);
  68. let checkedOptions = [];
  69. props.selOptions.forEach((item) => {
  70. if (checked.value.includes(item.name) || (item.username != null && checked.value.includes(item.username)) || (item.clientId != null && checked.value.includes(item.clientId))) {
  71. checkedOptions.push(item.id);
  72. }
  73. })
  74. // console.log("checkedOptions", checkedOptions);
  75. emit("selconfirm", checked.value, checkedOptions);
  76. };
  77. // 搜索关键词
  78. const searchValue = ref('');
  79. const tempOptions = ref([]);
  80. const valueChange = () => {
  81. if (tempOptions.value.length == 0) {
  82. tempOptions.value = props.selOptions;
  83. }
  84. let newOptions = [];
  85. tempOptions.value.forEach((item) => {
  86. if (item.name.includes(searchValue.value) || (item.username != null && item.username.includes(searchValue.value)) || (item.clientId != null && item.clientId.includes(searchValue.value))) {
  87. newOptions.push(item);
  88. }
  89. })
  90. emit("searchData", newOptions);
  91. if (checked.value.length === tempOptions.value.length) {
  92. allCheckRef.value.toggleAll(true);
  93. checkboxGroup.value.toggleAll(true);
  94. } else {
  95. allCheckRef.value.toggleAll(false);
  96. }
  97. }
  98. // 全选
  99. const allCheckRef = ref(null);
  100. const allChecked = ref([]);
  101. // 点击全选
  102. const checkAll = () => {
  103. // 如果已存在全选,那么是取消
  104. if (allChecked.value.length > 0) {
  105. allCheckRef.value.toggleAll(false);
  106. checkboxGroup.value.toggleAll(false);
  107. } else {
  108. allCheckRef.value.toggleAll(true);
  109. checkboxGroup.value.toggleAll(true);
  110. }
  111. };
  112. // 弹窗是否显示
  113. const selPopShow = ref(false);
  114. const selPopOpen = (selectedOpt) => {
  115. if (selectedOpt) {
  116. // 找到选中的值在所有值里面的下标,做切换状态
  117. if (props.selOptions.length > 0) {
  118. console.log('selectedOpt', selectedOpt)
  119. checked.value = selectedOpt;
  120. }
  121. } else {
  122. // 请空选中的值
  123. checked.value = [];
  124. allChecked.value = [];
  125. }
  126. selPopShow.value = true;
  127. };
  128. // 关闭弹窗
  129. const selPopClose = () => {
  130. selPopShow.value = false;
  131. };
  132. // 单选
  133. const checkboxGroup = ref(null);
  134. const checked = ref([]);
  135. const checkboxRefs = ref([]);
  136. const toggle = (index) => {
  137. // 单个选中状态切换
  138. checkboxRefs.value[index].toggle();
  139. console.log("tempOptions.value.length", tempOptions.value.length)
  140. // 如果选中的长度和选项的长度相等,那么全选要选中状态
  141. if (checked.value.length === tempOptions.value.length) {
  142. allCheckRef.value.toggleAll(true);
  143. } else {
  144. allCheckRef.value.toggleAll(false);
  145. }
  146. };
  147. // 每次更新前恢复单个ref
  148. onBeforeUpdate(() => {
  149. checkboxRefs.value = [];
  150. });
  151. return {
  152. props,
  153. selPopShow,
  154. selPopOpen,
  155. toggle,
  156. checked,
  157. checkboxRefs,
  158. checkAll,
  159. checkboxGroup,
  160. allChecked,
  161. allCheckRef,
  162. confirmClk,
  163. selPopClose,
  164. searchValue,
  165. valueChange
  166. };
  167. },
  168. };
  169. </script>
  170. <style lang="less" scoped>
  171. .kSelectPopIdx {
  172. .content {
  173. .kBordBott {
  174. &:last-child {
  175. border-bottom: none;
  176. }
  177. }
  178. }
  179. }
  180. </style>