BleConfig.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <script setup lang="ts">
  2. import { ref, reactive, onMounted, onUnmounted } from 'vue'
  3. import { message, Modal } from 'ant-design-vue'
  4. import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons-vue'
  5. import { getBleList, createBle, updateBle, deleteBle } from '@/api/ble'
  6. import type { BleConfig, BleConfigForm } from '@/types'
  7. const loading = ref(false)
  8. const list = ref<BleConfig[]>([])
  9. const modalVisible = ref(false)
  10. const editingId = ref<number | null>(null)
  11. const isMobile = ref(window.innerWidth < 768)
  12. const form = reactive<BleConfigForm>({
  13. device_name: 'AI-Light',
  14. service_uuid: 'b8b7e001-7a6b-4f4f-9a8b-11c0ffee0001',
  15. char_uuid: 'b8b7e002-7a6b-4f4f-9a8b-11c0ffee0001',
  16. enabled: true,
  17. })
  18. const columns = [
  19. { title: 'ID', dataIndex: 'id', width: 60 },
  20. { title: '设备名称', dataIndex: 'device_name', width: 120 },
  21. { title: 'Service UUID', dataIndex: 'service_uuid', ellipsis: true },
  22. { title: 'Characteristic UUID', dataIndex: 'char_uuid', ellipsis: true },
  23. { title: '启用', dataIndex: 'enabled', width: 80, key: 'enabled' },
  24. { title: '操作', key: 'actions', width: 140 },
  25. ]
  26. async function fetchList() {
  27. loading.value = true
  28. try {
  29. const res = await getBleList()
  30. list.value = res.data.data || []
  31. } catch {
  32. } finally {
  33. loading.value = false
  34. }
  35. }
  36. function openModal(record?: BleConfig) {
  37. if (record) {
  38. editingId.value = record.id
  39. form.device_name = record.device_name
  40. form.service_uuid = record.service_uuid
  41. form.char_uuid = record.char_uuid
  42. form.enabled = record.enabled
  43. } else {
  44. editingId.value = null
  45. form.device_name = 'AI-Light'
  46. form.service_uuid = 'b8b7e001-7a6b-4f4f-9a8b-11c0ffee0001'
  47. form.char_uuid = 'b8b7e002-7a6b-4f4f-9a8b-11c0ffee0001'
  48. form.enabled = true
  49. }
  50. modalVisible.value = true
  51. }
  52. async function onSubmit() {
  53. if (!form.device_name) {
  54. message.warning('请填写设备名称')
  55. return
  56. }
  57. if (!form.service_uuid) {
  58. message.warning('请填写 Service UUID')
  59. return
  60. }
  61. if (!form.char_uuid) {
  62. message.warning('请填写 Characteristic UUID')
  63. return
  64. }
  65. try {
  66. if (editingId.value !== null) {
  67. await updateBle(editingId.value, { ...form })
  68. message.success('更新成功')
  69. } else {
  70. await createBle({ ...form })
  71. message.success('创建成功')
  72. }
  73. modalVisible.value = false
  74. fetchList()
  75. } catch {}
  76. }
  77. function onDelete(record: BleConfig) {
  78. Modal.confirm({
  79. title: '确认删除',
  80. content: `确定删除 BLE 配置 #${record.id}(${record.device_name})?`,
  81. okType: 'danger',
  82. async onOk() {
  83. try {
  84. await deleteBle(record.id)
  85. message.success('删除成功')
  86. fetchList()
  87. } catch {}
  88. },
  89. })
  90. }
  91. function onResize() {
  92. isMobile.value = window.innerWidth < 768
  93. }
  94. onMounted(() => {
  95. fetchList()
  96. window.addEventListener('resize', onResize)
  97. })
  98. onUnmounted(() => window.removeEventListener('resize', onResize))
  99. </script>
  100. <template>
  101. <div class="ble-page">
  102. <div class="page-header">
  103. <span>BLE 配置管理</span>
  104. <a-button type="primary" @click="openModal()">
  105. <PlusOutlined /> 新建配置
  106. </a-button>
  107. </div>
  108. <a-table
  109. :columns="columns"
  110. :data-source="list"
  111. :loading="loading"
  112. row-key="id"
  113. :pagination="false"
  114. :scroll="isMobile ? { x: 600 } : undefined"
  115. >
  116. <template #bodyCell="{ column, record }">
  117. <template v-if="column.key === 'enabled'">
  118. <a-badge :status="record.enabled ? 'success' : 'default'" :text="record.enabled ? '启用' : '禁用'" />
  119. </template>
  120. <template v-if="column.key === 'actions'">
  121. <a-space>
  122. <a-button type="link" size="small" @click="openModal(record)">
  123. <EditOutlined /> 编辑
  124. </a-button>
  125. <a-button type="link" size="small" danger @click="onDelete(record)">
  126. <DeleteOutlined /> 删除
  127. </a-button>
  128. </a-space>
  129. </template>
  130. </template>
  131. </a-table>
  132. <a-modal
  133. :title="editingId !== null ? '编辑 BLE 配置' : '新建 BLE 配置'"
  134. :open="modalVisible"
  135. @cancel="modalVisible = false"
  136. :width="480"
  137. @ok="onSubmit"
  138. :ok-text="editingId !== null ? '更新' : '创建'"
  139. cancel-text="取消"
  140. >
  141. <a-form layout="vertical">
  142. <a-form-item label="设备名称" required>
  143. <a-input v-model:value="form.device_name" placeholder="AI-Light" />
  144. </a-form-item>
  145. <a-form-item label="Service UUID" required>
  146. <a-input v-model:value="form.service_uuid" placeholder="b8b7e001-7a6b-4f4f-9a8b-11c0ffee0001" />
  147. </a-form-item>
  148. <a-form-item label="Characteristic UUID" required>
  149. <a-input v-model:value="form.char_uuid" placeholder="b8b7e002-7a6b-4f4f-9a8b-11c0ffee0001" />
  150. </a-form-item>
  151. <a-form-item label="启用">
  152. <a-switch v-model:checked="form.enabled" />
  153. </a-form-item>
  154. </a-form>
  155. </a-modal>
  156. </div>
  157. </template>
  158. <style scoped>
  159. .ble-page {
  160. color: var(--text-color);
  161. }
  162. .page-header {
  163. display: flex;
  164. justify-content: space-between;
  165. align-items: center;
  166. margin-bottom: 24px;
  167. font-size: 16px;
  168. font-weight: 500;
  169. }
  170. @media (max-width: 767px) {
  171. .page-header {
  172. margin-bottom: 16px;
  173. font-size: 14px;
  174. }
  175. }
  176. </style>