From d1bbf7ce31c473977a1126bd22b1442159655956 Mon Sep 17 00:00:00 2001 From: ZHW <1941286652@qq.com> Date: Mon, 29 Dec 2025 13:36:54 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E6=A0=A1=E5=8C=BA=E7=9A=84=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/web/src/views/area/Campus.vue | 53 ++- .../web/src/views/equipment/Terminal.vue | 350 +++++++++++++++++- .../web/src/views/personnel/Maintenance.vue | 4 +- 3 files changed, 379 insertions(+), 28 deletions(-) diff --git a/src/main/resources/web/src/views/area/Campus.vue b/src/main/resources/web/src/views/area/Campus.vue index b929fbf..b6ac21f 100644 --- a/src/main/resources/web/src/views/area/Campus.vue +++ b/src/main/resources/web/src/views/area/Campus.vue @@ -497,6 +497,7 @@ const confirmDelete = async () => { } } +// 保存校区信息 // 保存校区信息 const handleSave = async () => { saving.value = true @@ -508,12 +509,6 @@ const handleSave = async () => { return } - // 校园类型必须有父级区域ID - if (!isEdit.value && (!formData.value.parentAreaId || formData.value.parentAreaId.trim() === '')) { - alert('新增校区时必须选择所属市区') - return - } - // 必须选择负责人 if (!selectedManager.value) { alert('请选择负责人') @@ -530,7 +525,19 @@ const handleSave = async () => { data: Area }>('/api/web/area/update', { method: 'PUT', - body: JSON.stringify(formData.value) + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authStore.token}` + }, + body: JSON.stringify({ + areaId: formData.value.areaId, + areaName: formData.value.areaName, + areaType: 'campus', + parentAreaId: formData.value.parentAreaId, + address: formData.value.address, + manager: formData.value.manager, + managerPhone: formData.value.managerPhone + }) }) if (response?.code === 200 && response?.data) { @@ -539,25 +546,47 @@ const handleSave = async () => { } else { const errorMsg = response?.msg || `更新失败(错误码:${response?.code || '未知'})` console.error('更新校区失败:', errorMsg) - alert(`更新校区失败:${errorMsg}`) + alert(`更新校区失败:${ errorMsg}`) } } else { + // 新增模式 - 添加更严格的验证 + if (!formData.value.parentAreaId || formData.value.parentAreaId.trim() === '') { + alert('新增校区时必须选择所属市区') + return + } + + // 验证选择的市区是否真实存在且类型为市区 + const selectedCity = cityList.value.find(city => + city.areaId === formData.value.parentAreaId && city.areaType === 'zone' + ) + + if (!selectedCity) { + alert('选择的市区不存在或类型错误,请重新选择') + return + } + // 新增模式 const newCampus = { areaName: formData.value.areaName, - areaType: 'campus' as const, - parentAreaId: formData.value.parentAreaId, // 必须包含父级区域ID + areaType: 'campus', + parentAreaId: formData.value.parentAreaId, address: formData.value.address, manager: formData.value.manager, managerPhone: formData.value.managerPhone } + console.log('发送的校区数据:', newCampus) // 调试日志 + response = await request<{ code: number msg: string data: Area }>('/api/web/area/add', { method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${authStore.token}` + }, body: JSON.stringify(newCampus) }) @@ -567,7 +596,7 @@ const handleSave = async () => { } else { const errorMsg = response?.msg || `新增失败(错误码:${response?.code || '未知'})` console.error('新增校区失败:', errorMsg) - alert(`新增校区失败:${errorMsg}`) + alert(`新增校区失败:${ errorMsg}`) } } } catch (error: any) { @@ -577,7 +606,7 @@ const handleSave = async () => { : error.message.includes('Network') ? '网络连接失败,请检查网络' : error.message || '保存失败,请稍后重试' - alert(`保存校区失败:${errorMsg}`) + alert(`保存校区失败:${ errorMsg}`) } finally { saving.value = false } diff --git a/src/main/resources/web/src/views/equipment/Terminal.vue b/src/main/resources/web/src/views/equipment/Terminal.vue index 08260a7..de89ae2 100644 --- a/src/main/resources/web/src/views/equipment/Terminal.vue +++ b/src/main/resources/web/src/views/equipment/Terminal.vue @@ -143,10 +143,70 @@ + + +
+ + +
+ + +
+ + +

+ 该市区暂无校区 +

+
+
- + +

+ 该校区暂无可用的供水机 +

+
@@ -175,7 +235,6 @@ const isTerminalManageVO = (obj: any): obj is TerminalManageVO => { ['active', 'inactive', 'warning', 'fault'].includes(obj.terminalStatus) } - // 终端状态类型定义 type TerminalStatus = 'active' | 'inactive' | 'fault' | 'warning' @@ -190,6 +249,27 @@ interface TerminalManageVO { deviceId?: string } +// 设备类型定义 +interface Device { + deviceId: string + deviceName: string + installLocation: string + deviceType: string + status: string + areaId: string // 设备所属片区ID +} + +// 区域类型定义 +interface Area { + areaId: string + areaName: string + areaType: string + parentAreaId: string | null + address: string + manager: string + managerPhone: string +} + // 响应式数据 const terminals = ref([]) const searchKeyword = ref('') @@ -209,10 +289,19 @@ const currentTerminal = ref({ terminalName: '', longitude: 0, latitude: 0, - terminalStatus: 'active' + terminalStatus: 'active', + deviceId: undefined }) -// 加载终端数据 +// 可用供水机设备列表 +const availableSupplyDevices = ref([]) + +// 片区相关数据 +const cityList = ref([]) // 市区列表 +const campusList = ref([]) // 校区列表 +const selectedCityId = ref('') // 选择的市区ID +const selectedCampusId = ref('') // 选择的校区ID + // 加载终端数据 const loadTerminals = async (): Promise => { try { @@ -227,10 +316,7 @@ const loadTerminals = async (): Promise => { console.log('开始加载终端机数据...') // 获取所有终端 - const result = await request>( - `/api/web/terminal/list`, - { method: 'GET' } - ) + const result = await request>(`/api/web/terminal/list`, { method: 'GET' }) console.log('终端机请求结果:', result) @@ -285,8 +371,183 @@ const loadTerminals = async (): Promise => { } } +// 加载市区列表 +const loadCityList = async (): Promise => { + try { + const token = authStore.token + if (!token) { + console.warn('未获取到 Token,跳转到登录页') + router.push('/login') + return + } + + console.log('开始加载市区列表...') + const result = await request('/api/web/area/cities', { method: 'GET' }) + if (result && typeof result === 'object' && 'code' in result) { + if (result.code === 200 && result.data && Array.isArray(result.data)) { + cityList.value = result.data + console.log(`获取到${cityList.value.length}个市区`) + } else { + console.warn('API响应非成功状态或数据格式错误:', result) + cityList.value = [] + } + } else if (Array.isArray(result)) { + cityList.value = result + } else { + console.warn('API响应数据格式错误:', result) + cityList.value = [] + } + } catch (error) { + console.error('加载市区列表失败:', error) + cityList.value = [] + if ((error as Error).message.includes('401')) { + authStore.logout() + router.push('/login') + } + } +} + +// 根据市区ID加载校区列表 +const loadCampusListByCity = async (cityId: string): Promise => { + try { + const token = authStore.token + if (!token) { + console.warn('未获取到 Token,跳转到登录页') + router.push('/login') + return + } + + console.log(`开始加载市区 ${cityId} 的校区列表...`) + + const result = await request(`/api/web/area/campuses/${cityId}`, { method: 'GET' }) + + if (result && typeof result === 'object' && 'code' in result) { + if (result.code === 200 && result.data && Array.isArray(result.data)) { + campusList.value = result.data + console.log(`获取到${campusList.value.length}个校区`) + } else { + console.warn('API响应非成功状态或数据格式错误:', result) + campusList.value = [] + } + } else if (Array.isArray(result)) { + campusList.value = result + } else { + console.warn('API响应数据格式错误:', result) + campusList.value = [] + } + } catch (error) { + console.error('加载校区列表失败:', error) + campusList.value = [] + if ((error as Error).message.includes('401')) { + authStore.logout() + router.push('/login') + } + } +} + +// 加载可用供水机设备列表 +const loadAvailableSupplyDevices = async (): Promise => { + try { + const token = authStore.token + if (!token) { + console.warn('未获取到 Token,跳转到登录页') + router.push('/login') + return + } + + console.log('开始加载设备列表...') + + // 使用与供水机页面相同的接口获取供水机 + const params = new URLSearchParams(); + params.append('deviceType', 'water_supply'); // 只获取供水机 + params.append('status', 'online'); // 只获取在线设备 + + const queryString = params.toString(); + const url = `/api/web/device-status/by-type${queryString ? `?${queryString}` : ''}`; + + const result = await request(url, { method: 'GET' }) + + if (result && typeof result === 'object' && 'code' in result) { + if (result.code === 200 && result.data && Array.isArray(result.data)) { + // 直接使用返回的供水机设备数据 + // 在 loadAvailableSupplyDevices 方法中添加数据转换 +availableSupplyDevices.value = result.data.map((device: any) => ({ + deviceId: device.deviceId, + deviceName: device.deviceName, + installLocation: device.installLocation, + deviceType: device.deviceType, + status: device.status, + areaId: device.areaId ? device.areaId.split('-')[0] : '' // 提取简单的片区标识符 +})) + + console.log(`获取到${availableSupplyDevices.value.length}个可用供水机`) + } else { + console.warn('API响应非成功状态或数据格式错误:', result) + availableSupplyDevices.value = [] + } + } else if (Array.isArray(result)) { + // 直接返回数组的情况 + availableSupplyDevices.value = (result as any[]).map((device: any) => ({ + deviceId: device.deviceId, + deviceName: device.deviceName, + installLocation: device.installLocation, + deviceType: device.deviceType, + status: device.status, + areaId: device.areaId // 设备所属片区ID + })) + } else { + console.warn('API响应数据格式错误:', result) + availableSupplyDevices.value = [] + } + } catch (error) { + console.error('加载可用供水机列表失败:', error) + availableSupplyDevices.value = [] + if ((error as Error).message.includes('401')) { + authStore.logout() + router.push('/login') + } + } +} + +// 根据选择的校区过滤供水机 +const filteredSupplyDevices = computed(() => { + if (!selectedCampusId.value) { + return availableSupplyDevices.value + } + + // 获取选中校区的 area_name + const selectedCampus = campusList.value.find(campus => campus.areaId === selectedCampusId.value) + if (!selectedCampus) { + return availableSupplyDevices.value + } + + // 使用校区的 area_name 来匹配设备的 areaId + return availableSupplyDevices.value.filter(device => { + // 假设设备的 areaId 字段实际上存储的是区域的 area_name + return device.areaId === selectedCampus.areaName + }) +}) + + +// 市区选择变化时的处理 +const onCityChange = async () => { + // 清空校区选择和设备ID + selectedCampusId.value = '' + currentTerminal.value.deviceId = undefined + campusList.value = [] + + if (selectedCityId.value) { + await loadCampusListByCity(selectedCityId.value) + } +} + +// 校区选择变化时的处理 +const onCampusChange = () => { + // 当选择校区时,清空当前选择的设备ID + currentTerminal.value.deviceId = undefined +} // 多条件过滤终端数据 const filteredTerminals = computed(() => { @@ -345,9 +606,18 @@ const editTerminal = (terminal: TerminalManageVO) => { currentTerminal.value = { ...terminal } isEditing.value = true showAddModal.value = true + + // 确保设备列表已加载 + if (availableSupplyDevices.value.length === 0) { + loadAvailableSupplyDevices() + } + + // 确保市区列表已加载 + if (cityList.value.length === 0) { + loadCityList() + } } -// 删除终端 // 删除终端 const deleteTerminal = async (terminalId: string) => { if (!confirm(`确定要删除终端 ${terminalId} 吗?`)) { @@ -392,7 +662,6 @@ const deleteTerminal = async (terminalId: string) => { } } - // 保存终端(新增或更新) const saveTerminal = async () => { try { @@ -413,6 +682,18 @@ const saveTerminal = async () => { }) } else { // 添加终端 + // 验证是否选择了校区(新增终端时) + if (!selectedCampusId.value) { + alert('请选择校区') + return + } + + // 验证是否选择了关联设备 + if (!currentTerminal.value.deviceId) { + alert('请选择关联的供水机') + return + } + result = await request | TerminalManageVO>('/api/web/terminal/add', { method: 'POST', body: JSON.stringify(currentTerminal.value) @@ -434,8 +715,12 @@ const saveTerminal = async () => { terminalName: '', longitude: 0, latitude: 0, - terminalStatus: 'active' + terminalStatus: 'active', + deviceId: undefined } + selectedCityId.value = '' + selectedCampusId.value = '' + campusList.value = [] alert(isEditing.value ? '终端更新成功' : '终端添加成功') } else if (result.code === 200) { @@ -451,8 +736,12 @@ const saveTerminal = async () => { terminalName: '', longitude: 0, latitude: 0, - terminalStatus: 'active' + terminalStatus: 'active', + deviceId: undefined } + selectedCityId.value = '' + selectedCampusId.value = '' + campusList.value = [] alert(isEditing.value ? '终端更新成功' : '终端添加成功') } else { @@ -472,8 +761,12 @@ const saveTerminal = async () => { terminalName: '', longitude: 0, latitude: 0, - terminalStatus: 'active' + terminalStatus: 'active', + deviceId: undefined } + selectedCityId.value = '' + selectedCampusId.value = '' + campusList.value = [] alert(isEditing.value ? '终端更新成功' : '终端添加成功') } @@ -490,8 +783,12 @@ const saveTerminal = async () => { terminalName: '', longitude: 0, latitude: 0, - terminalStatus: 'active' + terminalStatus: 'active', + deviceId: undefined } + selectedCityId.value = '' + selectedCampusId.value = '' + campusList.value = [] alert(isEditing.value ? '终端更新成功' : '终端添加成功') } @@ -509,6 +806,8 @@ const saveTerminal = async () => { onMounted(async () => { console.log('🚀 开始加载终端数据...') await loadTerminals() + await loadAvailableSupplyDevices() + await loadCityList() }) @@ -788,6 +1087,29 @@ onMounted(async () => { border: none; } +/* 新增:下拉框样式 */ +.select-input { + width: 100%; + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + box-sizing: border-box; + background: white; + cursor: pointer; +} + +.select-input:focus { + outline: none; + border-color: #42b983; +} + +/* 新增:无数据提示样式 */ +.no-data-message { + margin-top: 8px; + color: #8c8c8c; + font-size: 12px; +} + /* 响应式调整 */ @media (max-width: 768px) { .filters { diff --git a/src/main/resources/web/src/views/personnel/Maintenance.vue b/src/main/resources/web/src/views/personnel/Maintenance.vue index 92201b0..9436397 100644 --- a/src/main/resources/web/src/views/personnel/Maintenance.vue +++ b/src/main/resources/web/src/views/personnel/Maintenance.vue @@ -160,8 +160,8 @@
-- 2.34.1 From 14b779ee5eb455297d9af2f9f25c4892286d01a6 Mon Sep 17 00:00:00 2001 From: ZHW <1941286652@qq.com> Date: Mon, 29 Dec 2025 14:51:08 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E8=AE=BE=E5=A4=87=E7=9A=84=E7=89=87?= =?UTF-8?q?=E5=8C=BA=E5=85=B3=E8=81=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/web/src/api/types/auth.ts | 46 ++-- .../web/src/views/equipment/Terminal.vue | 28 +++ .../web/src/views/equipment/WaterMaker.vue | 202 +++++++++++++++++- 3 files changed, 248 insertions(+), 28 deletions(-) diff --git a/src/main/resources/web/src/api/types/auth.ts b/src/main/resources/web/src/api/types/auth.ts index 92b8e1a..97d1329 100644 --- a/src/main/resources/web/src/api/types/auth.ts +++ b/src/main/resources/web/src/api/types/auth.ts @@ -1,29 +1,31 @@ -// src/api/types/auth.ts - -// 登录请求参数 - 匹配后端的 LoginRequest +// src/main/resources/web/src/api/types/auth.ts export interface LoginRequest { + username: string + password: string +} + +export interface LoginVO { + token: string + userInfo: { + id: number username: string - password: string - userType: string // 添加这个属性 - rememberMe?: boolean + realName: string + role: string + avatar: string + } } -// 通用响应结构 +// 在 '@/api/types/auth.ts' 文件中添加 export interface ResultVO { - code: number - message: string - data: T + code: number; + message: string; + data?: T; + [key: string]: any; } -// 登录响应数据 - 匹配后端的 LoginVO -export interface LoginVO { - token: string - userInfo: { - id: number - username: string - realName?: string // 根据后端字段调整 - role?: string // 根据后端字段调整 - userType?: string // 添加这个字段 - avatar?: string - } -} \ No newline at end of file + +export interface LoginResponse { + code: number + message: string + data: LoginVO +} diff --git a/src/main/resources/web/src/views/equipment/Terminal.vue b/src/main/resources/web/src/views/equipment/Terminal.vue index de89ae2..3e6d27c 100644 --- a/src/main/resources/web/src/views/equipment/Terminal.vue +++ b/src/main/resources/web/src/views/equipment/Terminal.vue @@ -247,6 +247,7 @@ interface TerminalManageVO { terminalStatus: TerminalStatus installDate?: string deviceId?: string + areaId?: string } // 设备类型定义 @@ -547,8 +548,17 @@ const onCityChange = async () => { const onCampusChange = () => { // 当选择校区时,清空当前选择的设备ID currentTerminal.value.deviceId = undefined + + // 设置areaId为选中校区的areaName(不是areaId) + const selectedCampus = campusList.value.find(campus => campus.areaId === selectedCampusId.value) + if (selectedCampus) { + currentTerminal.value.areaId = selectedCampus.areaName // 使用areaName作为areaId + } else { + currentTerminal.value.areaId = undefined + } } + // 多条件过滤终端数据 const filteredTerminals = computed(() => { return terminals.value.filter(terminal => { @@ -673,6 +683,24 @@ const saveTerminal = async () => { return } + // 验证是否选择了校区(新增终端时) + if (!isEditing.value && !selectedCampusId.value) { + alert('请选择校区') + return + } + + // 验证areaId是否已设置 + if (!currentTerminal.value.areaId) { + alert('请先选择校区以确定所属片区') + return + } + + // 验证是否选择了关联设备 + if (!currentTerminal.value.deviceId) { + alert('请选择关联的供水机') + return + } + let result: ResultVO | TerminalManageVO if (isEditing.value) { // 更新终端 diff --git a/src/main/resources/web/src/views/equipment/WaterMaker.vue b/src/main/resources/web/src/views/equipment/WaterMaker.vue index e2f0167..927c53f 100644 --- a/src/main/resources/web/src/views/equipment/WaterMaker.vue +++ b/src/main/resources/web/src/views/equipment/WaterMaker.vue @@ -150,13 +150,49 @@
+ +
- - + + + +
+ + +
+ + +

+ 该市区暂无校区 +

+
@@ -231,6 +267,17 @@ interface WaterMakerDevice { createTime?: string } +// 区域类型定义 +interface Area { + areaId: string + areaName: string + areaType: string + parentAreaId: string | null + address: string + manager: string + managerPhone: string +} + // 响应式数据 const devices = ref([]) const searchKeyword = ref('') @@ -253,11 +300,17 @@ const currentDeviceId = ref('') const newDevice = ref({ deviceId: '', deviceName: '', - areaId: '市区', + areaId: '', installLocation: '', deviceType: 'water_maker' }) +// 片区相关数据 +const cityList = ref([]) // 市区列表 +const campusList = ref([]) // 校区列表 +const selectedCityId = ref('') // 选择的市区ID +const selectedCampusId = ref('') // 选择的校区ID + const offlineReason = ref('') const faultInfo = ref({ faultType: '', @@ -310,6 +363,104 @@ const loadDevices = async (): Promise => { } } +// 加载市区列表 +const loadCityList = async (): Promise => { + try { + const token = authStore.token + if (!token) { + console.warn('未获取到 Token,跳转到登录页') + router.push('/login') + return + } + + console.log('开始加载市区列表...') + + const result = await request('/api/web/area/cities', { method: 'GET' }) + + if (result && typeof result === 'object' && 'code' in result) { + if (result.code === 200 && result.data && Array.isArray(result.data)) { + cityList.value = result.data + console.log(`获取到${cityList.value.length}个市区`) + } else { + console.warn('API响应非成功状态或数据格式错误:', result) + cityList.value = [] + } + } else if (Array.isArray(result)) { + cityList.value = result + } else { + console.warn('API响应数据格式错误:', result) + cityList.value = [] + } + } catch (error) { + console.error('加载市区列表失败:', error) + cityList.value = [] + if ((error as Error).message.includes('401')) { + authStore.logout() + router.push('/login') + } + } +} + +// 根据市区ID加载校区列表 +const loadCampusListByCity = async (cityId: string): Promise => { + try { + const token = authStore.token + if (!token) { + console.warn('未获取到 Token,跳转到登录页') + router.push('/login') + return + } + + console.log(`开始加载市区 ${cityId} 的校区列表...`) + + const result = await request(`/api/web/area/campuses/${cityId}`, { method: 'GET' }) + + if (result && typeof result === 'object' && 'code' in result) { + if (result.code === 200 && result.data && Array.isArray(result.data)) { + campusList.value = result.data + console.log(`获取到${campusList.value.length}个校区`) + } else { + console.warn('API响应非成功状态或数据格式错误:', result) + campusList.value = [] + } + } else if (Array.isArray(result)) { + campusList.value = result + } else { + console.warn('API响应数据格式错误:', result) + campusList.value = [] + } + } catch (error) { + console.error('加载校区列表失败:', error) + campusList.value = [] + if ((error as Error).message.includes('401')) { + authStore.logout() + router.push('/login') + } + } +} + +// 市区选择变化时的处理 +const onCityChange = async () => { + // 清空校区选择和设备ID + selectedCampusId.value = '' + campusList.value = [] + + if (selectedCityId.value) { + await loadCampusListByCity(selectedCityId.value) + } +} + +// 校区选择变化时的处理 +const onCampusChange = () => { + // 设置areaId为选中校区的areaName(不是areaId) + const selectedCampus = campusList.value.find(campus => campus.areaId === selectedCampusId.value) + if (selectedCampus) { + newDevice.value.areaId = selectedCampus.areaName // 使用areaName作为areaId + } else { + newDevice.value.areaId = '' + } +} + // 多条件过滤设备数据 const filteredDevices = computed(() => { return devices.value.filter(device => { @@ -549,6 +700,18 @@ const addDevice = async () => { return } + // 验证是否选择了校区 + if (!selectedCampusId.value) { + alert('请选择校区') + return + } + + // 验证areaId是否已设置 + if (!newDevice.value.areaId) { + alert('请先选择校区以确定所属片区') + return + } + // 构造设备对象 const deviceToAdd = { deviceId: newDevice.value.deviceId, @@ -573,10 +736,13 @@ const addDevice = async () => { newDevice.value = { deviceId: '', deviceName: '', - areaId: '市区', + areaId: '', installLocation: '', deviceType: 'water_maker' } + selectedCityId.value = '' + selectedCampusId.value = '' + campusList.value = [] alert('设备添加成功') } else { @@ -596,6 +762,7 @@ const addDevice = async () => { onMounted(async () => { console.log('🚀 开始加载设备数据...') await loadDevices() + await loadCityList() }) @@ -880,6 +1047,29 @@ onMounted(async () => { border: none; } +/* 新增:下拉框样式 */ +.select-input { + width: 100%; + padding: 8px 12px; + border: 1px solid #ddd; + border-radius: 4px; + box-sizing: border-box; + background: white; + cursor: pointer; +} + +.select-input:focus { + outline: none; + border-color: #42b983; +} + +/* 新增:无数据提示样式 */ +.no-data-message { + margin-top: 8px; + color: #8c8c8c; + font-size: 12px; +} + /* 响应式调整 */ @media (max-width: 768px) { .filters { -- 2.34.1 From 8638bfcacf892915823d301d494f9c9f19275d77 Mon Sep 17 00:00:00 2001 From: ZHW <1941286652@qq.com> Date: Mon, 29 Dec 2025 16:20:55 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E6=B7=BB=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/web/package-lock.json | 34 +++ src/main/resources/web/package.json | 2 + .../web/src/views/equipment/WaterMaker.vue | 20 -- .../src/views/equipment/WaterMakerDetail.vue | 179 +++++++++++++- .../views/equipment/WaterSupplierDetail.vue | 233 ++++++++++++++---- 5 files changed, 397 insertions(+), 71 deletions(-) diff --git a/src/main/resources/web/package-lock.json b/src/main/resources/web/package-lock.json index 23ec651..c4c011f 100644 --- a/src/main/resources/web/package-lock.json +++ b/src/main/resources/web/package-lock.json @@ -8,11 +8,13 @@ "name": "web", "version": "0.0.0", "dependencies": { + "echarts": "^6.0.0", "pinia": "^2.1.7", "vue": "^3.4.21", "vue-router": "^4.3.0" }, "devDependencies": { + "@tsconfig/node24": "^24.0.3", "@vitejs/plugin-vue": "^5.0.4", "typescript": "^5.2.2", "vite": "^5.1.6", @@ -770,6 +772,13 @@ "win32" ] }, + "node_modules/@tsconfig/node24": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.3.tgz", + "integrity": "sha512-vcERKtKQKHgzt/vfS3Gjasd8SUI2a0WZXpgJURdJsMySpS5+ctgbPfuLj2z/W+w4lAfTWxoN4upKfu2WzIRYnw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -991,6 +1000,16 @@ "dev": true, "license": "MIT" }, + "node_modules/echarts": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-6.0.0.tgz", + "integrity": "sha512-Tte/grDQRiETQP4xz3iZWSvoHrkCQtwqd6hs+mifXcjrCuo2iKWbajFObuLJVBlDIJlOzgQPd1hsaKt/3+OMkQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "6.0.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -1250,6 +1269,12 @@ "node": ">=0.10.0" } }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -1417,6 +1442,15 @@ "peerDependencies": { "typescript": "*" } + }, + "node_modules/zrender": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-6.0.0.tgz", + "integrity": "sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } } } } diff --git a/src/main/resources/web/package.json b/src/main/resources/web/package.json index 9d08c5e..4e2ae2a 100644 --- a/src/main/resources/web/package.json +++ b/src/main/resources/web/package.json @@ -9,11 +9,13 @@ "preview": "vite preview" }, "dependencies": { + "echarts": "^6.0.0", "pinia": "^2.1.7", "vue": "^3.4.21", "vue-router": "^4.3.0" }, "devDependencies": { + "@tsconfig/node24": "^24.0.3", "@vitejs/plugin-vue": "^5.0.4", "typescript": "^5.2.2", "vite": "^5.1.6", diff --git a/src/main/resources/web/src/views/equipment/WaterMaker.vue b/src/main/resources/web/src/views/equipment/WaterMaker.vue index 927c53f..c794784 100644 --- a/src/main/resources/web/src/views/equipment/WaterMaker.vue +++ b/src/main/resources/web/src/views/equipment/WaterMaker.vue @@ -84,27 +84,7 @@ @click="updateDeviceStatus(device.deviceId, 'online')" :disabled="device.status === 'online'" > - 设为在线 - - - - diff --git a/src/main/resources/web/src/views/equipment/WaterMakerDetail.vue b/src/main/resources/web/src/views/equipment/WaterMakerDetail.vue index 9e66e0f..88d7bd9 100644 --- a/src/main/resources/web/src/views/equipment/WaterMakerDetail.vue +++ b/src/main/resources/web/src/views/equipment/WaterMakerDetail.vue @@ -47,10 +47,7 @@ 创建时间: {{ formatDate(deviceDetail.deviceInfo?.createTime) }}
-
- 最后心跳时间: - {{ formatDate(deviceDetail.deviceInfo?.lastHeartbeatTime) }} -
+ @@ -111,6 +108,26 @@ {{ formatDate(deviceDetail.realtimeData?.recordTime) }} + + +
+

TDS值对比

+
+
+ + +
+

滤芯寿命

+
+
+
+
+
{{ deviceDetail.realtimeData?.filterLife || 0 }}%
+
+
@@ -169,11 +186,12 @@ + diff --git a/src/main/resources/web/src/views/equipment/WaterSupplierDetail.vue b/src/main/resources/web/src/views/equipment/WaterSupplierDetail.vue index 0a6bd5a..f817881 100644 --- a/src/main/resources/web/src/views/equipment/WaterSupplierDetail.vue +++ b/src/main/resources/web/src/views/equipment/WaterSupplierDetail.vue @@ -115,6 +115,25 @@ {{ formatDate(deviceDetail.realtimeData?.timestamp) }} + + +
+

实时监控数据

+
+
+
水压监控
+
+
+
+
流量监控
+
+
+
+
温度监控
+
+
+
+
@@ -130,11 +149,12 @@ -- 2.34.1