完善保险端前后端和养殖端小程序

This commit is contained in:
xuqiuyun
2025-09-22 19:09:45 +08:00
parent 02a25515a9
commit 325c114c38
256 changed files with 48348 additions and 4444 deletions

View File

@@ -404,25 +404,167 @@ export const smartAlertService = {
const response = await api.get('/smart-alerts/public/stats');
return response && response.success ? response.data : response;
},
/**
* 获取智能耳标预警统计
* @returns {Promise<Object>} 耳标预警统计
*/
async getEartagAlertStats() {
const response = await api.get('/smart-alerts/public/eartag/stats');
return response && response.success ? response.data : response;
},
/**
* 获取智能耳标预警列表
* @param {Object} params - 查询参数
* @param {number} params.page - 页码
* @param {number} params.limit - 每页数量
* @param {string} params.search - 搜索关键词
* @param {string} params.alertType - 预警类型筛选
* @param {string} params.alertLevel - 预警级别筛选
* @param {string} params.status - 设备状态筛选
* @param {string} params.startDate - 开始日期
* @param {string} params.endDate - 结束日期
* @returns {Promise<Object>} 智能耳标预警列表响应
*/
async getEartagAlerts(params = {}) {
const response = await api.get('/smart-alerts/public/eartag', { params });
return response;
},
/**
* 获取单个智能耳标预警详情
* @param {string} id - 预警ID
* @returns {Promise<Object>} 预警详情
*/
async getEartagAlertById(id) {
const response = await api.get(`/smart-alerts/public/eartag/${id}`);
return response && response.success ? response.data : response;
},
/**
* 处理智能耳标预警
* @param {string} id - 预警ID
* @param {Object} data - 处理数据
* @param {string} data.action - 处理动作
* @param {string} data.notes - 处理备注
* @param {string} data.handler - 处理人
* @returns {Promise<Object>} 处理结果
*/
async handleEartagAlert(id, data = {}) {
const response = await api.post(`/smart-alerts/public/eartag/${id}/handle`, data);
return response;
},
/**
* 批量处理智能耳标预警
* @param {Object} data - 批量处理数据
* @param {Array} data.alertIds - 预警ID列表
* @param {string} data.action - 处理动作
* @param {string} data.notes - 处理备注
* @param {string} data.handler - 处理人
* @returns {Promise<Object>} 处理结果
*/
async batchHandleEartagAlerts(data) {
const response = await api.post('/smart-alerts/public/eartag/batch-handle', data);
return response;
},
/**
* 导出智能耳标预警数据
* @param {Object} params - 导出参数
* @param {string} params.search - 搜索关键词
* @param {string} params.alertType - 预警类型筛选
* @param {string} params.alertLevel - 预警级别筛选
* @param {string} params.startDate - 开始日期
* @param {string} params.endDate - 结束日期
* @param {string} params.format - 导出格式 (json/csv)
* @returns {Promise<Object>} 导出结果
*/
async exportEartagAlerts(params = {}) {
const response = await api.get('/smart-alerts/public/eartag/export', { params });
return response;
},
/**
* 获取智能项圈预警统计
* @returns {Promise<Object>} 项圈预警统计
*/
async getCollarAlertStats() {
const response = await api.get('/smart-alerts/public/collar/stats');
return response && response.success ? response.data : response;
},
/**
* 获取智能项圈预警列表
* @param {Object} params - 查询参数
* @param {number} params.page - 页码
* @param {number} params.limit - 每页数量
* @param {string} params.search - 搜索关键词
* @param {string} params.alertType - 预警类型筛选
* @param {string} params.alertLevel - 预警级别筛选
* @param {string} params.status - 设备状态筛选
* @param {string} params.startDate - 开始日期
* @param {string} params.endDate - 结束日期
* @returns {Promise<Object>} 智能项圈预警列表响应
*/
async getCollarAlerts(params = {}) {
const response = await api.get('/smart-alerts/public/collar', { params });
return response;
},
/**
* 获取单个智能项圈预警详情
* @param {string} id - 预警ID
* @returns {Promise<Object>} 预警详情
*/
async getCollarAlertById(id) {
const response = await api.get(`/smart-alerts/public/collar/${id}`);
return response && response.success ? response.data : response;
},
/**
* 处理智能项圈预警
* @param {string} id - 预警ID
* @param {Object} data - 处理数据
* @param {string} data.action - 处理动作
* @param {string} data.notes - 处理备注
* @param {string} data.handler - 处理人
* @returns {Promise<Object>} 处理结果
*/
async handleCollarAlert(id, data = {}) {
const response = await api.post(`/smart-alerts/public/collar/${id}/handle`, data);
return response;
},
/**
* 批量处理智能项圈预警
* @param {Object} data - 批量处理数据
* @param {Array} data.alertIds - 预警ID列表
* @param {string} data.action - 处理动作
* @param {string} data.notes - 处理备注
* @param {string} data.handler - 处理人
* @returns {Promise<Object>} 处理结果
*/
async batchHandleCollarAlerts(data) {
const response = await api.post('/smart-alerts/public/collar/batch-handle', data);
return response;
},
/**
* 导出智能项圈预警数据
* @param {Object} params - 导出参数
* @param {string} params.search - 搜索关键词
* @param {string} params.alertType - 预警类型筛选
* @param {string} params.alertLevel - 预警级别筛选
* @param {string} params.startDate - 开始日期
* @param {string} params.endDate - 结束日期
* @param {string} params.format - 导出格式 (json/csv)
* @returns {Promise<Object>} 导出结果
*/
async exportCollarAlerts(params = {}) {
const response = await api.get('/smart-alerts/public/collar/export', { params });
return response;
}
};

View File

@@ -64,7 +64,8 @@
<a-select-option value="">全部预警</a-select-option>
<a-select-option value="battery">低电量预警</a-select-option>
<a-select-option value="offline">离线预警</a-select-option>
<a-select-option value="temperature">温度预警</a-select-option>
<a-select-option value="temperature_low">温度过低预警</a-select-option>
<a-select-option value="temperature_high">温度过高预警</a-select-option>
<a-select-option value="movement">异常运动预警</a-select-option>
<a-select-option value="wear">佩戴异常预警</a-select-option>
</a-select>
@@ -340,12 +341,54 @@ const columns = [
}
]
// 判断预警类型
const determineAlertType = (record) => {
const alerts = []
// 检查电量预警
if (record.battery !== undefined && record.battery !== null && record.battery < 20) {
alerts.push('battery')
}
// 检查脱落预警 (bandge_status为0)
if (record.bandge_status !== undefined && record.bandge_status !== null && record.bandge_status === 0) {
alerts.push('wear')
}
// 检查离线预警 (is_connect为0)
if (record.is_connect !== undefined && record.is_connect !== null && record.is_connect === 0) {
alerts.push('offline')
}
// 检查温度预警
if (record.temperature !== undefined && record.temperature !== null) {
if (record.temperature < 20) {
alerts.push('temperature_low')
} else if (record.temperature > 40) {
alerts.push('temperature_high')
}
}
// 检查运动异常预警 (steps - y_steps为0)
if (record.steps !== undefined && record.y_steps !== undefined &&
record.steps !== null && record.y_steps !== null) {
const movementDiff = record.steps - record.y_steps
if (movementDiff === 0) {
alerts.push('movement')
}
}
// 返回第一个预警类型如果没有预警则返回null
return alerts.length > 0 ? alerts[0] : null
}
// 获取预警类型文本
const getAlertTypeText = (type) => {
const typeMap = {
'battery': '低电量预警',
'offline': '离线预警',
'temperature': '温度预警',
'temperature_low': '温度过低预警',
'temperature_high': '温度过高预警',
'movement': '异常运动预警',
'wear': '佩戴异常预警'
}
@@ -357,7 +400,8 @@ const getAlertTypeColor = (type) => {
const colorMap = {
'battery': 'orange',
'offline': 'red',
'temperature': 'red',
'temperature_low': 'blue',
'temperature_high': 'red',
'movement': 'purple',
'wear': 'blue'
}
@@ -384,6 +428,56 @@ const getAlertLevelColor = (level) => {
return colorMap[level] || 'default'
}
// 计算统计数据
const calculateStats = (data) => {
const newStats = {
lowBattery: 0,
offline: 0,
highTemperature: 0,
abnormalMovement: 0,
wearOff: 0
}
data.forEach(item => {
const alertType = determineAlertType(item)
if (alertType === 'battery') {
newStats.lowBattery++
} else if (alertType === 'offline') {
newStats.offline++
} else if (alertType === 'temperature_high') {
newStats.highTemperature++
} else if (alertType === 'movement') {
newStats.abnormalMovement++
} else if (alertType === 'wear') {
newStats.wearOff++
}
})
return newStats
}
// 获取统计数据
const fetchStats = async () => {
try {
const { smartAlertService } = await import('../utils/dataService')
const statsResult = await smartAlertService.getCollarAlertStats()
if (statsResult && statsResult.success) {
const statsData = statsResult.data || {}
stats.lowBattery = statsData.lowBattery || 0
stats.offline = statsData.offline || 0
stats.highTemperature = statsData.highTemperature || 0
stats.abnormalMovement = statsData.abnormalMovement || 0
stats.wearOff = statsData.wearOff || 0
console.log('统计数据更新:', stats)
} else {
console.warn('获取统计数据失败:', statsResult)
}
} catch (error) {
console.error('获取统计数据失败:', error)
}
}
// 获取数据
const fetchData = async (showMessage = false, customAlertType = null) => {
try {
@@ -437,15 +531,6 @@ const fetchData = async (showMessage = false, customAlertType = null) => {
const rawData = result.data || []
console.log('原始API数据:', rawData)
// 预警类型中文映射
const alertTypeMap = {
'battery': '低电量预警',
'offline': '离线预警',
'temperature': '温度预警',
'movement': '异常运动预警',
'wear': '佩戴异常预警'
}
// 预警级别中文映射
const alertLevelMap = {
'high': '高级',
@@ -471,11 +556,51 @@ const fetchData = async (showMessage = false, customAlertType = null) => {
}
}
// 使用API返回的预警类型如果没有则使用判断函数
let alertTypeText = '正常'
let alertLevel = 'low'
let determinedAlertType = null
if (item.alertType) {
// 使用API返回的预警类型
const alertTypeMap = {
'battery': '低电量预警',
'offline': '离线预警',
'temperature': '温度预警',
'temperature_low': '温度过低预警',
'temperature_high': '温度过高预警',
'movement': '异常运动预警',
'wear': '佩戴异常预警'
}
alertTypeText = alertTypeMap[item.alertType] || item.alertType
determinedAlertType = item.alertType
// 使用API返回的预警级别
const alertLevelMap = {
'high': '高级',
'medium': '中级',
'low': '低级',
'critical': '紧急'
}
alertLevel = alertLevelMap[item.alertLevel] || item.alertLevel
} else {
// 如果没有预警类型,使用判断函数
determinedAlertType = determineAlertType(item)
alertTypeText = determinedAlertType ? getAlertTypeText(determinedAlertType) : '正常'
// 根据预警类型确定预警级别
if (determinedAlertType === 'battery' || determinedAlertType === 'offline' || determinedAlertType === 'temperature_high') {
alertLevel = 'high'
} else if (determinedAlertType === 'movement' || determinedAlertType === 'wear' || determinedAlertType === 'temperature_low') {
alertLevel = 'medium'
}
}
return {
id: item.id || `${item.deviceId || item.sn}_${item.alertType || 'unknown'}`,
id: item.id || `${item.deviceId || item.sn}_${item.alertType || 'normal'}`,
collarNumber: item.collarNumber || item.sn || item.deviceId || '',
alertType: alertTypeMap[item.alertType] || item.alertType || '',
alertLevel: alertLevelMap[item.alertLevel] || item.alertLevel || '高级',
alertType: alertTypeText,
alertLevel: alertLevel,
alertTime: alertTime,
battery: item.battery || item.batteryLevel || '',
temperature: item.temperature || item.temp || '',
@@ -483,7 +608,9 @@ const fetchData = async (showMessage = false, customAlertType = null) => {
longitude: item.longitude || 0,
latitude: item.latitude || 0,
// 保留原始数据用于其他功能
...item
...item,
// 添加判断结果
determinedAlertType: determinedAlertType
}
})
@@ -491,15 +618,27 @@ const fetchData = async (showMessage = false, customAlertType = null) => {
alerts.value = transformedData
pagination.total = result.total || 0
// 更新统计数据
// 使用API返回的统计数据
if (result.stats) {
stats.lowBattery = result.stats.lowBattery || 0
stats.offline = result.stats.offline || 0
stats.highTemperature = result.stats.highTemperature || 0
stats.abnormalMovement = result.stats.abnormalMovement || 0
stats.wearOff = result.stats.wearOff || 0
console.log('使用API返回的统计数据:', result.stats)
} else {
// 如果没有统计数据,使用计算的方式
const calculatedStats = calculateStats(rawData)
stats.lowBattery = calculatedStats.lowBattery
stats.offline = calculatedStats.offline
stats.highTemperature = calculatedStats.highTemperature
stats.abnormalMovement = calculatedStats.abnormalMovement
stats.wearOff = calculatedStats.wearOff
console.log('计算统计数据:', calculatedStats)
}
console.log('更新后的统计数据:', stats)
console.log('转换后的预警列表:', alerts.value)
console.log('总数:', pagination.total)
console.log('统计数据:', result.stats)
@@ -621,13 +760,13 @@ const updateSearchValue = (e) => {
}
// 搜索处理
const handleSearch = () => {
const handleSearch = async () => {
pagination.current = 1
fetchData(true)
await fetchData(true)
}
// 筛选变化处理
const handleFilterChange = (value) => {
const handleFilterChange = async (value) => {
console.log('=== 智能项圈预警类型筛选变化 ===')
console.log('传入的 value 参数:', value)
console.log('传入的 value 参数类型:', typeof value)
@@ -649,16 +788,16 @@ const handleFilterChange = (value) => {
limit: pagination.pageSize
})
// 直接调用 fetchData 并传递 alertType 参数
fetchData(true, alertType)
// 更新列表数据,统计数据会在数据转换时计算
await fetchData(true, alertType)
}
// 清除搜索
const handleClearSearch = () => {
const handleClearSearch = async () => {
searchValue.value = ''
alertTypeFilter.value = ''
pagination.current = 1
fetchData(true)
await fetchData(true)
}
// 查看详情
@@ -683,9 +822,29 @@ const viewLocation = (record) => {
}
// 处理预警
const handleAlert = (record) => {
message.success(`正在处理预警: ${record.collarNumber}`)
// 这里可以添加处理预警的逻辑
const handleAlert = async (record) => {
try {
console.log('处理预警:', record)
// 调用API处理预警
const { smartAlertService } = await import('../utils/dataService')
const result = await smartAlertService.handleCollarAlert(record.id, {
action: 'acknowledged',
notes: '通过管理界面处理',
handler: 'admin'
})
if (result.success) {
message.success(`预警处理成功: ${record.collarNumber}`)
// 刷新数据
await fetchData()
} else {
message.error(`预警处理失败: ${result.message}`)
}
} catch (error) {
console.error('处理预警失败:', error)
message.error('处理预警失败: ' + error.message)
}
}
// 取消详情
@@ -789,59 +948,72 @@ const initBaiduMap = async () => {
}
// 表格变化处理
const handleTableChange = (pag) => {
const handleTableChange = async (pag) => {
pagination.current = pag.current
pagination.pageSize = pag.pageSize
fetchData()
await fetchData()
}
// 导出数据
const exportData = async () => {
try {
if (!alerts.value || alerts.value.length === 0) {
message.warning('没有数据可导出')
return
}
console.log('🔄 开始导出智能项圈预警数据 - 版本: 2025-01-18-v3')
console.log('🔄 开始导出智能项圈预警数据')
message.loading('正在导出数据...', 0)
// 数据已经在fetchData中转换过了直接使用
const exportData = alerts.value.map(item => ({
collarNumber: item.collarNumber || '',
alertType: item.alertType || '',
alertLevel: item.alertLevel || '',
alertTime: item.alertTime || '',
battery: item.battery || '',
temperature: item.temperature || '',
dailySteps: item.dailySteps || ''
}))
// 调用API导出数据
const { smartAlertService } = await import('../utils/dataService')
const exportParams = {
search: searchValue.value.trim(),
alertType: alertTypeFilter.value,
format: 'json'
}
console.log('导出数据示例:', exportData[0])
console.log('导出数据总数:', exportData.length)
// 新的列配置
const newColumns = [
{ title: '耳标编号', dataIndex: 'collarNumber', key: 'collarNumber' },
{ title: '预警类型', dataIndex: 'alertType', key: 'alertType' },
{ title: '预警级别', dataIndex: 'alertLevel', key: 'alertLevel' },
{ title: '预警时间', dataIndex: 'alertTime', key: 'alertTime', dataType: 'datetime' },
{ title: '设备电量', dataIndex: 'battery', key: 'battery' },
{ title: '设备温度', dataIndex: 'temperature', key: 'temperature' },
{ title: '当日步数', dataIndex: 'dailySteps', key: 'dailySteps' }
]
console.log('使用新的列配置:', newColumns)
// 直接调用导出方法,使用新的列配置
const result = ExportUtils.exportToExcel(exportData, newColumns, '智能项圈预警数据')
const result = await smartAlertService.exportCollarAlerts(exportParams)
if (result.success) {
message.destroy()
message.success(`导出成功!文件:${result.filename}`)
const exportData = result.data || []
if (exportData.length === 0) {
message.destroy()
message.warning('没有数据可导出')
return
}
// 转换数据格式用于Excel导出
const transformedData = exportData.map(item => ({
collarNumber: item.collarNumber || item.sn || '',
alertType: item.alertType || '',
alertLevel: item.alertLevel || '',
alertTime: item.alertTime || '',
battery: item.battery || item.batteryLevel || '',
temperature: item.temperature || item.temp || '',
dailySteps: item.dailySteps || item.steps || ''
}))
// 列配置
const columns = [
{ title: '项圈编号', dataIndex: 'collarNumber', key: 'collarNumber' },
{ title: '预警类型', dataIndex: 'alertType', key: 'alertType' },
{ title: '预警级别', dataIndex: 'alertLevel', key: 'alertLevel' },
{ title: '预警时间', dataIndex: 'alertTime', key: 'alertTime', dataType: 'datetime' },
{ title: '设备电量', dataIndex: 'battery', key: 'battery' },
{ title: '设备温度', dataIndex: 'temperature', key: 'temperature' },
{ title: '当日步数', dataIndex: 'dailySteps', key: 'dailySteps' }
]
// 调用导出方法
const exportResult = ExportUtils.exportToExcel(transformedData, columns, '智能项圈预警数据')
if (exportResult.success) {
message.destroy()
message.success(`导出成功!文件:${exportResult.filename}`)
} else {
message.destroy()
message.error(exportResult.message)
}
} else {
message.destroy()
message.error(result.message)
message.error(`导出失败: ${result.message}`)
}
} catch (error) {
message.destroy()
@@ -851,8 +1023,9 @@ const exportData = async () => {
}
// 组件挂载时获取数据
onMounted(() => {
fetchData(true)
onMounted(async () => {
// 获取列表数据,统计数据会在数据转换时计算
await fetchData(true)
})
</script>

View File

@@ -554,9 +554,29 @@ const viewDetails = (record) => {
}
// 处理预警
const handleAlert = (record) => {
message.success(`正在处理预警: ${record.eartagNumber}`)
// 这里可以添加处理预警的逻辑
const handleAlert = async (record) => {
try {
console.log('处理预警:', record)
// 调用API处理预警
const { smartAlertService } = await import('../utils/dataService')
const result = await smartAlertService.handleEartagAlert(record.id, {
action: 'acknowledged',
notes: '通过管理界面处理',
handler: 'admin'
})
if (result.success) {
message.success(`预警处理成功: ${record.eartagNumber}`)
// 刷新数据
fetchData()
} else {
message.error(`预警处理失败: ${result.message}`)
}
} catch (error) {
console.error('处理预警失败:', error)
message.error('处理预警失败: ' + error.message)
}
}
// 取消详情