DeviceSelector.vue 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. <script setup lang="ts">
  2. import { ref, onMounted } from "vue";
  3. import { getDeviceList } from "@/api/device";
  4. defineOptions({
  5. name: "DeviceSelector"
  6. });
  7. interface Device {
  8. id: number;
  9. deviceId: string;
  10. storeName: string;
  11. status: number;
  12. }
  13. const props = defineProps({
  14. modelValue: {
  15. type: Array as () => number[],
  16. default: () => []
  17. },
  18. multiple: {
  19. type: Boolean,
  20. default: true
  21. },
  22. placeholder: {
  23. type: String,
  24. default: "请选择设备"
  25. }
  26. });
  27. const emit = defineEmits(["update:modelValue", "change"]);
  28. const devices = ref<Device[]>([]);
  29. const filteredDevices = ref<Device[]>([]);
  30. const loading = ref(false);
  31. async function fetchDevices() {
  32. loading.value = true;
  33. try {
  34. const { data } = await getDeviceList({ page: 1, pageSize: 1000 });
  35. devices.value = data?.list || [];
  36. filteredDevices.value = devices.value;
  37. } catch (error) {
  38. console.error("获取设备列表失败:", error);
  39. devices.value = [];
  40. filteredDevices.value = [];
  41. } finally {
  42. loading.value = false;
  43. }
  44. }
  45. function handleFilter(query: string) {
  46. if (!query) {
  47. filteredDevices.value = devices.value;
  48. return;
  49. }
  50. filteredDevices.value = devices.value.filter(device =>
  51. device.deviceId.toLowerCase().includes(query.toLowerCase()) ||
  52. device.storeName.toLowerCase().includes(query.toLowerCase())
  53. );
  54. }
  55. function handleChange(value: number[]) {
  56. emit("update:modelValue", value);
  57. emit("change", value);
  58. }
  59. onMounted(() => {
  60. fetchDevices();
  61. });
  62. </script>
  63. <template>
  64. <el-select
  65. :model-value="modelValue"
  66. :multiple="multiple"
  67. :placeholder="placeholder"
  68. :loading="loading"
  69. :filterable="true"
  70. :filter-method="handleFilter"
  71. @change="handleChange"
  72. class="w-full"
  73. >
  74. <el-option
  75. v-for="device in filteredDevices"
  76. :key="device.id"
  77. :label="device.storeName"
  78. :value="device.id"
  79. >
  80. <span>{{ device.storeName }}</span>
  81. <span class="text-gray-400 text-sm ml-2">{{ device.deviceId }}</span>
  82. </el-option>
  83. </el-select>
  84. </template>
  85. <style lang="scss" scoped>
  86. :deep(.el-select-dropdown__item) {
  87. display: flex;
  88. justify-content: space-between;
  89. align-items: center;
  90. }
  91. </style>