local-search.vue 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. <template>
  2. <uni-popup
  3. class="local-search-popup"
  4. ref="localSearchPopRef"
  5. type="bottom"
  6. :is-mask-click="false"
  7. borderRadius="10px 10px 0 0 "
  8. background-color="#fff"
  9. >
  10. <view class="popup-content">
  11. <uni-row class="head-row align-center">
  12. <uni-col
  13. :span="6"
  14. class="head-cancel align-center justify-start"
  15. @click="oncancel"
  16. >
  17. {{ $t("operation.cancel") }}
  18. </uni-col>
  19. <uni-col :span="12" class="head-title justify-center">
  20. {{ title }}
  21. </uni-col>
  22. <uni-col :span="6" class="head-add align-center justify-end"> </uni-col>
  23. </uni-row>
  24. <uni-row class="search-row flex-row justify-between">
  25. <uni-col :span="24">
  26. <uni-easyinput
  27. v-model="searchValue"
  28. :styles="inputStyles"
  29. :placeholderStyle="placeholderStyle"
  30. :placeholder="`${$t('operation.PleaseInput')}`"
  31. :clearable="false"
  32. @input="searchList"
  33. >
  34. </uni-easyinput>
  35. </uni-col>
  36. </uni-row>
  37. <scroll-view scroll-y="true" class="page-table">
  38. <uni-row
  39. class="item-row align-center"
  40. :class="{ choosed: chooseIds.includes(item.value) }"
  41. v-for="(item, index) in dataList"
  42. :key="index"
  43. @click="onChoose(item)"
  44. >
  45. <uni-col :span="24" class="flex-row align-center">
  46. <text>{{ item.text }}</text>
  47. </uni-col>
  48. </uni-row>
  49. </scroll-view>
  50. </view>
  51. </uni-popup>
  52. </template>
  53. <script setup>
  54. import dayjs from "dayjs";
  55. import { computed, ref, reactive, watch, onMounted } from "vue";
  56. import { useI18n } from "vue-i18n";
  57. const { t, locale } = useI18n({
  58. useScope: "global",
  59. });
  60. const chooseIds = ref([]);
  61. const placeholderStyle = ref('color:#ADADAD;font-weight:400;font-size:12px')
  62. const inputStyles = reactive({
  63. backgroundColor: '#F5F5F5',
  64. color: '#797979',
  65. })
  66. // 接收父组件传递的参数
  67. const props = defineProps({});
  68. const oncancel = () => {
  69. // 清空搜索值
  70. searchValue.value = "";
  71. // 关闭弹窗
  72. close();
  73. };
  74. onMounted(() => {});
  75. // 本地搜索弹窗
  76. const localSearchPopRef = ref(null);
  77. // 搜索值
  78. const searchValue = ref("");
  79. // 弹窗标题
  80. const title = ref("");
  81. // 展示的列表数据的参数名
  82. const propKey = ref("");
  83. // 搜索列表数据
  84. const dataList = ref([]);
  85. // 原始数据列表
  86. const dataListOrigin = ref([]);
  87. // 搜索列表
  88. const searchList = (event) => {
  89. console.log("🚀 ~ searchList ~ event:", event)
  90. console.log("🚀 ~ searchList ~ searchValue.value:", searchValue.value)
  91. if (event) {
  92. dataList.value = dataList.value.filter((item) => {
  93. return item.text.includes(event);
  94. });
  95. } else {
  96. dataList.value = dataListOrigin.value;
  97. }
  98. };
  99. // 选择列表项
  100. const onChoose = (item) => {
  101. // 选择列表项时,判断是否已选择,已选择则取消选择,否则添加选择
  102. if (chooseIds.value.includes(item.value)) {
  103. // 已选择则取消选择
  104. chooseIds.value.splice(chooseIds.value.indexOf(item.value), 1);
  105. } else {
  106. // 未选择则添加选择
  107. chooseIds.value = [item.value];
  108. }
  109. emit("choosed", propKey.value, item);
  110. close();
  111. };
  112. // 打开弹窗
  113. const open = (props) => {
  114. if (props.propKey !== propKey.value) {
  115. // 清空已选择的值
  116. chooseIds.value = [];
  117. }
  118. if (props.choosed) {
  119. // 已选择的值添加到已选择列表
  120. chooseIds.value = [props.choosed];
  121. }
  122. propKey.value = props.propKey;
  123. title.value = props.title;
  124. dataListOrigin.value = props.list;
  125. dataList.value = props.list;
  126. localSearchPopRef.value.open();
  127. };
  128. // 关闭弹窗
  129. const close = () => {
  130. // 清空搜索值
  131. searchValue.value = "";
  132. localSearchPopRef.value.close();
  133. };
  134. const emit = defineEmits(["choosed"]);
  135. // 提供外部方法
  136. const expose = {
  137. open,
  138. };
  139. defineExpose(expose);
  140. </script>
  141. <style lang="scss" scoped>
  142. @import "@/style/choose-device.scss";
  143. .local-search-popup {
  144. position: relative;
  145. width: 100%;
  146. height: 100%;
  147. border: 1px solid #cacccf;
  148. background-color: #fff;
  149. padding: 20px;
  150. }
  151. .popup-content {
  152. position: relative;
  153. width: 100%;
  154. height: calc(100% - 280px);
  155. max-height: 500px;
  156. }
  157. :deep(.uni-popup__wrapper) {
  158. padding: 20px;
  159. box-sizing: border-box;
  160. position: relative;
  161. }
  162. .head-row {
  163. margin-bottom: 10px;
  164. font-size: 16px;
  165. line-height: 21px;
  166. color: #a3a3a3;
  167. height: 40px;
  168. border-bottom: 1px dashed #cacccf;
  169. }
  170. .head-title {
  171. color: #333333;
  172. font-weight: bold;
  173. }
  174. .head-add {
  175. color: #004098;
  176. }
  177. .search-row {
  178. margin-bottom: 10px;
  179. }
  180. .page-table {
  181. width: 100%;
  182. position: relative;
  183. padding: 0;
  184. height: 500px;
  185. }
  186. .choosed {
  187. color: #004098;
  188. }
  189. </style>