diff --git a/src/views/device/apdevice/index.vue b/src/views/device/apdevice/index.vue index 193d0f4..f8dc096 100644 --- a/src/views/device/apdevice/index.vue +++ b/src/views/device/apdevice/index.vue @@ -14,13 +14,32 @@ class="flex-col-stretch sm:flex-1-hidden card-wrapper" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {{ t('page.apdevice.useSiteSettings') }} + {{ t('page.apdevice.on') }} + {{ t('page.apdevice.off') }} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -63,10 +229,12 @@ import { useTable } from '@/hooks/common/table'; import { SimpleScrollbar } from '~/packages/materials/src'; import { computed, shallowRef } from 'vue'; import { useElementSize } from '@vueuse/core'; -import { fetchApDeviceList } from '@/service/api/auth'; -import { Card as ACard, Table as ATable, Tag as ATag } from 'ant-design-vue'; +import { fetchApDeviceList,forgetApDevice, addApDevice } from '@/service/api/auth'; +import {Card as ACard, Table as ATable, Tag as ATag, Modal, message } from 'ant-design-vue'; import DeviceSearch from './modules/device-search.vue'; import { useI18n } from 'vue-i18n'; +import { SettingOutlined, DeleteOutlined, ReloadOutlined,PlusOutlined } from '@ant-design/icons-vue'; +import {Rule} from "ant-design-vue/es/form"; const { t } = useI18n(); const wrapperEl = shallowRef(null); @@ -77,6 +245,42 @@ const scrollConfig = computed(() => ({ x: 800 })); +// 添加站点相关的状态 +const siteList = ref([]); +const selectedSiteId = ref(''); +const siteLoading = ref(false); + +// 获取站点列表 +const getSiteList = async () => { + try { + siteLoading.value = true; + const response = await fetchSiteList({ + pageNum: 1, + pageSize: 100 + }); + + // 适配新的响应格式 + siteList.value = response.data.rows || []; + + // 如果有站点数据,默认选择第一个 + if (siteList.value.length > 0) { + selectedSiteId.value = siteList.value[0].siteId; // 使用 siteId 而不是 id + await getData(); + } + } catch (error) { + console.error('Get site list error:', error); + message.error(t('page.apdevice.getSiteError')); + } finally { + siteLoading.value = false; + } +}; + +// 处理站点变更 +const handleSiteChange = async (value: string) => { + selectedSiteId.value = value; + await getData(); +}; + const { columns, columnChecks, @@ -86,15 +290,22 @@ const { mobilePagination, searchParams, } = useTable({ - apiFn: async (params: Api.Device.ApDeviceParams) => { - try { - console.log('Fetching with params:', JSON.stringify(params, null, 2)); - const response = await fetchApDeviceList(params); - console.log('API Response:', response); + apiFn: async (params: { searchKey?: string; pageNum: number; pageSize: number }) => { + if (!selectedSiteId.value) { return { data: { - rows: response.data || [], - total: Array.isArray(response.data) ? response.data.length : 0 + rows: [], + total: 0 + } + }; + } + + try { + const response = await fetchApDeviceList(selectedSiteId.value, params); + return { + data: { + rows: response.data.rows, + total: response.data.total } }; } catch (error) { @@ -108,7 +319,7 @@ const { }; } }, - immediate: true, + immediate: false, apiParams: { pageNum: 1, pageSize: 10, @@ -159,6 +370,13 @@ const { title: t('page.apdevice.status'), align: 'center', width: 100 + }, + { + key: 'operate', + title: t('common.operate'), + align: 'center', + width: 100, + fixed: 'right' } ] }); @@ -184,14 +402,312 @@ const handleReset = () => { const currentPageSize = searchParams.pageSize; // 重置搜索参数 - searchParams.name = ''; - searchParams.mac = ''; + searchParams.searchKey = ''; searchParams.pageNum = 1; searchParams.pageSize = currentPageSize; // 重新获取数据 getData(); }; + + +// 添加相关的处理函数 +// 处理打开配置对话框 +const handleEditConfig = async (record: Api.Device.ApDevice) => { + try { + if (!selectedSiteId.value) { + throw new Error('No site selected'); + } + + const hide = message.loading(t('common.loading'), 0); + + // 先获取设备当前的配置 + const response = await getApDeviceConfig(selectedSiteId.value, record.mac); + + hide(); + + // 保存当前编辑的设备信息 + currentDevice.value = record; + + // 使用获取到的配置更新表单,处理 null 和嵌套对象 + configForm.value = { + name: response.data?.name || record.name, + ledSetting: response.data?.ledSetting ?? 2, // 如果没有设置,默认使用站点设置 + // tagIds: response.data?.tagIds || [], // 暂时注释掉 + longitude: response.data?.location?.longitude, + latitude: response.data?.location?.latitude, + address: response.data?.location?.address || '' + }; + + // 显示配置对话框 + configVisible.value = true; + } catch (error) { + console.error('Get device config error:', error); + message.error(t('page.apdevice.getConfigError')); + } +}; + +const handleForgetDevice = (record: Api.Device.ApDevice) => { + Modal.confirm({ + title: t('common.confirm'), + content: t('page.apdevice.forgetConfirm'), + onOk: async () => { + try { + const hide = message.loading(t('common.loading'), 0); + console.log('Forgetting device:', record); + + if (!selectedSiteId.value || !record.mac) { + throw new Error('Missing required parameters: siteId or mac'); + } + + // 使用当前选中的 siteId + const response = await forgetApDevice(selectedSiteId.value, record.mac); + console.log('Forget device response:', response); + + hide(); + message.success(t('page.apdevice.forgetSuccess')); + + // 重新获取列表数据 + getData(); + } catch (error) { + console.error('Forget device error:', error); + message.error(t('page.apdevice.forgetError')); + throw error; + } + } + }); +}; + +const handleRestart = (record: Api.Device.ApDevice) => { + // 处理重启设备 + Modal.confirm({ + title: t('common.confirm'), + content: t('page.apdevice.restartConfirm'), + onOk: async () => { + // 调用重启设备 API + console.log('Restart device:', record); + } + }); +}; + +// 纳管表单数据 +const adoptForm = ref({ + username: '', + password: '' +}); + +// 纳管对话框可见性 +const adoptVisible = ref(false); + +// 当前要纳管的设备 +const adoptingDevice = ref(null); + +// 处理纳管按钮点击 +const handleAdopt = (record: Api.Device.ApDevice) => { + adoptingDevice.value = record; + adoptForm.value = { + username: '', + password: '' + }; + adoptVisible.value = true; +}; + +// 处理纳管确认 +const handleAdoptConfirm = async () => { + try { + if (!adoptingDevice.value || !selectedSiteId.value) { + throw new Error('Missing device or site information'); + } + + const hide = message.loading(t('common.loading'), 0); + + // 构造请求参数,只有在有值时才包含 + const params: { username?: string; password?: string } = {}; + if (adoptForm.value.username) { + params.username = adoptForm.value.username; + } + if (adoptForm.value.password) { + params.password = adoptForm.value.password; + } + + await adoptApDevice(selectedSiteId.value, adoptingDevice.value.mac, params); + + hide(); + message.success(t('page.apdevice.adoptSuccess')); + adoptVisible.value = false; + + // 重新获取列表数据 + getData(); + } catch (error) { + console.error('Adopt device error:', error); + message.error(t('page.apdevice.adoptError')); + } +}; + + +// 修改表单验证规则的定义 +const addDeviceRules = { + sn: [ + { required: true, message: t('page.apdevice.snRequired'), trigger: 'blur' }, + { + pattern: /^[A-Z0-9]{13}$/, + message: t('page.apdevice.snFormatError'), + trigger: 'blur' + } + ] as Rule[], + name: [ + { + pattern: /^[^ \+\-\@\=]$|^[^ \+\-\@\=].{0,126}[^ ]$/, + message: t('page.apdevice.nameFormatError'), + trigger: 'blur' + } + ] as Rule[] +}; + +// 添加设备的表单数据 +const addDeviceForm = ref({ + sn: '', + name: '', + username: '', + password: '' +}); + +// 添加设备对话框的可见性 +const addDeviceVisible = ref(false); + +// 处理添加设备 +const handleAdd = () => { + addDeviceVisible.value = true; +}; + +// 处理添加设备的确认 +const handleAddConfirm = async () => { + try { + // 先验证表单 + await formRef.value?.validate(); + + const hide = message.loading(t('common.loading'), 0); + + // 构造请求参数,即使所有字段都为空也要发送一个空对象 + // 构造请求参数,确保 sn 字段存在 + const deviceParams: Api.Device.AddApDeviceItem = { + sn: addDeviceForm.value.sn // sn 是必填的 + }; + + // 只添加其他有值的字段 + if (addDeviceForm.value.name) { + deviceParams.name = addDeviceForm.value.name; + } + if (addDeviceForm.value.username) { + deviceParams.username = addDeviceForm.value.username; + } + if (addDeviceForm.value.password) { + deviceParams.password = addDeviceForm.value.password; + } + + await addApDevice(selectedSiteId.value, deviceParams); + + hide(); + message.success(t('page.apdevice.addSuccess')); + addDeviceVisible.value = false; + + // 清空表单 + addDeviceForm.value = { + sn: '', + name: '', + username: '', + password: '' + }; + + // 重新获取列表数据 + getData(); + } catch (error) { + console.error('Add device error:', error); + message.error(t('page.apdevice.addError')); + } +}; +// 添加表单引用 +const formRef = ref(); +// 配置表单的数据 +const configForm = ref({ + name: '', + ledSetting: 2, + // tagIds: [], + longitude: undefined, + latitude: undefined, + address: '' +}); + +// 配置对话框的可见性 +const configVisible = ref(false); + +// 配置表单的验证规则 +const configRules = { + name: [ + { + pattern: /^[^ \+\-\@\=]$|^[^ \+\-\@\=].{0,126}[^ ]$/, + message: t('page.apdevice.nameFormatError'), + trigger: 'blur' + } + ] as Rule[], + longitude: [ + { + type: 'number', + min: -180, + max: 180, + message: t('page.apdevice.longitudeError'), + trigger: 'change' + } + ] as Rule[], + latitude: [ + { + type: 'number', + min: -90, + max: 90, + message: t('page.apdevice.latitudeError'), + trigger: 'change' + } + ] as Rule[] +}; + +// 当前编辑的设备 +const currentDevice = ref(null); + +// 处理配置确认 +const handleConfigConfirm = async () => { + try { + await configFormRef.value?.validate(); + + if (!currentDevice.value || !selectedSiteId.value) { + throw new Error('Missing device or site information'); + } + + const hide = message.loading(t('common.loading'), 0); + + await updateApDeviceConfig( + selectedSiteId.value, + currentDevice.value.mac, + configForm.value + ); + + hide(); + message.success(t('page.apdevice.configSuccess')); + configVisible.value = false; + + // 重新获取列表数据 + getData(); + } catch (error) { + console.error('Update config error:', error); + message.error(t('page.apdevice.configError')); + } +}; + +// 配置表单引用 +const configFormRef = ref(); +// 在组件挂载时获取站点列表 +onMounted(() => { + getSiteList(); +});