diff --git a/src/api/record/index.ts b/src/api/record/index.ts
index cfe927eab..9423c484f 100644
--- a/src/api/record/index.ts
+++ b/src/api/record/index.ts
@@ -54,4 +54,8 @@ export const RecordApi = {
getRecordStatistics: async (params: any) => {
return await request.get({ url: `/system/record/statistics`, params })
},
+ //获取会员回访记录统计
+ getStatistics: async (orgid: number,startDate:string,endDate:string) => {
+ return await request.get({ url: `/system/record/getstatistics?orgid=` + orgid + `&startDate=` + startDate + `&endDate=` + endDate })
+ },
}
diff --git a/src/views/stat/Members.vue b/src/views/stat/Members.vue
index 022ea751d..4ff1700fd 100644
--- a/src/views/stat/Members.vue
+++ b/src/views/stat/Members.vue
@@ -27,13 +27,22 @@
-
+
+
+
+
+
+
@@ -145,4 +173,23 @@ onMounted(() => {
.stat-card {
min-height: 320px; /* 统计图卡片主内容区高度,可根据实际需求调整 */
}
+
+/* 无数据提示样式 */
+.no-data-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 580px; /* 与图表容器保持一致的高度 */
+ width: 100%;
+}
+
+.no-data-empty {
+ text-align: center;
+}
+
+.no-data-empty :deep(.el-empty__description) {
+ color: #909399;
+ font-size: 16px;
+ margin-top: 16px;
+}
diff --git a/src/views/stat/Returnvisit.vue b/src/views/stat/Returnvisit.vue
index dcc011697..6e2b29303 100644
--- a/src/views/stat/Returnvisit.vue
+++ b/src/views/stat/Returnvisit.vue
@@ -13,6 +13,7 @@
value-format="YYYY-MM-DD HH:mm:ss"
@change="onDateChange"
style="width: 300px;"
+ clearable
/>
@@ -22,6 +23,9 @@
柱状图
+
+ 堆叠图
+
@@ -43,10 +47,18 @@ import { RecordApi } from '@/api/record'
import dayjs from 'dayjs'
import { getUserProfile } from '@/api/system/user/profile'
-// 图表类型:'line' 折线图,'bar' 柱状图
-const chartType = ref<'line' | 'bar'>('line')
-// 预警统计数据
-const chartData = ref<{ date: string; totalCount: number; readCount: number; unreadCount: number }[]>([])
+// 图表类型:'line' 折线图,'bar' 柱状图,'stack' 堆叠图
+const chartType = ref<'line' | 'bar' | 'stack'>('bar')
+// 回访统计数据
+const chartData = ref<{
+ date: string;
+ totalCount: number;
+ visitedCount: number;
+ unvisitedCount: number;
+ satisfiedCount: number;
+ normalCount: number;
+ unsatisfiedCount: number;
+}[]>([])
// 时间范围,默认一周
const dateRange = ref<[string, string]>([
dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD 00:00:00'),
@@ -58,17 +70,55 @@ const renderChart = () => {
const dom = document.getElementById('main')
if (!dom) return
const myChart = echarts.init(dom)
- myChart.setOption({
+
+ // 当没有数据时显示提示
+ if (!chartData.value || chartData.value.length === 0) {
+ myChart.setOption(
+ {
+ title: {
+ text: '当前时间段无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: { color: '#909399', fontSize: 16 }
+ },
+ // 清空系列的和轴线,避免旧内容残留
+ xAxis: { show: false },
+ yAxis: { show: false },
+ series: []
+ },
+ true
+ ) // true表示不跟之前的option合并
+ return
+ }
+
+ const option: any = {
+ title: {
+ text: '电话回访统计',
+ left: 'center',
+ top: 0,
+ textStyle: {
+ fontSize: 18,
+ fontWeight: 'bold'
+ }
+ },
tooltip: {
trigger: 'axis',
formatter: function(params: any) {
- const data = params[0]
- const date = data.name
- const value = data.value
- return `${date}
预警信息数量: ${value}`
+ const date = params[0].name
+ let result = `${date}
`
+
+ params.forEach((param: any) => {
+ result += `${param.seriesName}: ${param.value}
`
+ })
+
+ return result
}
},
- grid: { left: 40, right: 20, top: 60, bottom: 40 },
+ legend: {
+ data: ['总回访数', '已回访', '未回访', '满意', '一般', '不满意'],
+ top: 30
+ },
+ grid: { left: 40, right: 20, top: 80, bottom: 40 },
xAxis: {
type: 'category',
data: chartData.value.map(item => item.date),
@@ -81,15 +131,59 @@ const renderChart = () => {
axisLine: { lineStyle: { color: '#dcdfe6' } },
axisLabel: { color: '#666', fontSize: 14 }
},
- series: [
+ series: []
+ }
+
+ if (chartType.value === 'stack') {
+ // 堆叠图:显示回访状态和满意度
+ option.series = [
{
- name: '预警信息数量',
+ name: '已回访',
+ type: 'bar',
+ stack: 'status',
+ data: chartData.value.map(item => item.visitedCount),
+ itemStyle: { color: '#67C23A' }
+ },
+ {
+ name: '未回访',
+ type: 'bar',
+ stack: 'status',
+ data: chartData.value.map(item => item.unvisitedCount),
+ itemStyle: { color: '#909399' }
+ },
+ {
+ name: '满意',
+ type: 'bar',
+ stack: 'result',
+ data: chartData.value.map(item => item.satisfiedCount),
+ itemStyle: { color: '#409EFF' }
+ },
+ {
+ name: '一般',
+ type: 'bar',
+ stack: 'result',
+ data: chartData.value.map(item => item.normalCount),
+ itemStyle: { color: '#E6A23C' }
+ },
+ {
+ name: '不满意',
+ type: 'bar',
+ stack: 'result',
+ data: chartData.value.map(item => item.unsatisfiedCount),
+ itemStyle: { color: '#F56C6C' }
+ }
+ ]
+ } else {
+ // 普通柱状图或折线图
+ option.series = [
+ {
+ name: '总回访数',
type: chartType.value,
data: chartData.value.map(item => item.totalCount),
smooth: chartType.value === 'line',
barWidth: chartType.value === 'bar' ? '40%' : undefined,
itemStyle: {
- color: chartType.value === 'line' ? '#409EFF' : '#67C23A',
+ color: '#409EFF',
borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
},
lineStyle: {
@@ -97,22 +191,83 @@ const renderChart = () => {
color: '#409EFF'
},
areaStyle: chartType.value === 'line' ? { color: 'rgba(64,158,255,0.15)' } : undefined
+ },
+ {
+ name: '已回访',
+ type: chartType.value,
+ data: chartData.value.map(item => item.visitedCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#67C23A',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#67C23A'
+ }
+ },
+ {
+ name: '未回访',
+ type: chartType.value,
+ data: chartData.value.map(item => item.unvisitedCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#909399',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#909399'
+ }
}
]
- })
+ }
+
+ myChart.setOption(option)
}
// 渲染饼图
const renderPieChart = () => {
const dom = document.getElementById('pieChart')
if (!dom) return
-
- // 计算已读数量、未读数量
- const readCount = chartData.value.reduce((sum, item) => sum + item.readCount, 0)
- const unreadCount = chartData.value.reduce((sum, item) => sum + item.unreadCount, 0)
-
const pieChart = echarts.init(dom)
+
+ // 当没有数据时显示提示
+ if (!chartData.value || chartData.value.length === 0) {
+ pieChart.setOption(
+ {
+ title: {
+ text: '当前时间段无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: { color: '#909399', fontSize: 16 }
+ },
+ series: []
+ },
+ true
+ )
+ return
+ }
+
+ // 计算总数
+ const totalVisited = chartData.value.reduce((sum, item) => sum + item.visitedCount, 0)
+ const totalUnvisited = chartData.value.reduce((sum, item) => sum + item.unvisitedCount, 0)
+ const totalSatisfied = chartData.value.reduce((sum, item) => sum + item.satisfiedCount, 0)
+ const totalNormal = chartData.value.reduce((sum, item) => sum + item.normalCount, 0)
+ const totalUnsatisfied = chartData.value.reduce((sum, item) => sum + item.unsatisfiedCount, 0)
+
pieChart.setOption({
+ title: {
+ text: '回访状态分布',
+ left: 'center',
+ top: 0,
+ textStyle: {
+ fontSize: 16,
+ fontWeight: 'bold'
+ }
+ },
tooltip: {
trigger: 'item',
formatter: '{a}
{b}: {c} ({d}%)'
@@ -124,10 +279,10 @@ const renderPieChart = () => {
},
series: [
{
- name: '预警信息',
+ name: '回访状态',
type: 'pie',
radius: ['40%', '70%'],
- center: ['60%', '60%'],
+ center: ['65%', '50%'],
avoidLabelOverlap: false,
label: {
show: false,
@@ -144,8 +299,8 @@ const renderPieChart = () => {
show: false
},
data: [
- { value: readCount, name: '已读', itemStyle: { color: '#67C23A' } },
- { value: unreadCount, name: '未读', itemStyle: { color: '#E6A23C' } }
+ { value: totalVisited, name: '已回访', itemStyle: { color: '#67C23A' } },
+ { value: totalUnvisited, name: '未回访', itemStyle: { color: '#909399' } }
]
}
]
@@ -158,30 +313,46 @@ const params = ref({
orgid: 0,
})
-// 获取预警统计数据
+// 获取回访统计数据
const fetchData = async () => {
try {
const userProfile = await getUserProfile()
params.value.orgid = userProfile.dept.id
- const res = await RecordApi.getRecordStatistics(params.value)
+ // 调用回访统计的API
+ const res = await RecordApi.getStatistics(
+ params.value.orgid,
+ params.value.startTime,
+ params.value.endTime
+ )
+ console.log(res)
// 处理返回的数据格式
- if (res && res.dailyData && Array.isArray(res.dailyData)) {
- chartData.value = res.dailyData.map((item: any) => {
- // 处理date字段,如果是数组格式 [year, month, day],转换为日期字符串
- let dateStr = item.date
- if (Array.isArray(item.date) && item.date.length >= 3) {
+ if (res && Array.isArray(res)) {
+ chartData.value = res.map((item: any) => {
+ // 处理date字段
+ let dateStr = ''
+ if (typeof item.date === 'number') {
+ // 时间戳格式
+ dateStr = dayjs(item.date).format('YYYY-MM-DD')
+ } else if (Array.isArray(item.date) && item.date.length >= 3) {
+ // 数组格式 [year, month, day]
const [year, month, day] = item.date
// 月份需要减1,因为JavaScript的Date构造函数中月份是从0开始的
const date = new Date(year, month - 1, day)
dateStr = dayjs(date).format('YYYY-MM-DD')
+ } else {
+ // 默认是字符串格式
+ dateStr = item.date
}
-
+
return {
date: dateStr,
totalCount: item.totalCount || 0,
- readCount: item.readCount || 0,
- unreadCount: item.unreadCount || 0
+ visitedCount: item.visitedCount || 0,
+ unvisitedCount: item.unvisitedCount || 0,
+ satisfiedCount: item.satisfiedCount || 0,
+ normalCount: item.normalCount || 0,
+ unsatisfiedCount: item.unsatisfiedCount || 0
}
})
} else {
@@ -190,15 +361,23 @@ const fetchData = async () => {
console.log('处理后的图表数据:', chartData.value)
} catch (error) {
- console.error('获取预警统计数据失败:', error)
+ console.error('获取回访统计数据失败:', error)
chartData.value = []
}
}
// 时间范围变化时
-const onDateChange = (range: [string, string]) => {
- dateRange.value = range
- fetchData()
+const onDateChange = (range: [string, string] | null) => {
+ // 当range不为空时,更新参数并获取数据
+ if (range && range.length === 2) {
+ dateRange.value = range
+ params.value.startTime = range[0]
+ params.value.endTime = range[1]
+ fetchData()
+ } else {
+ // 当日期被清空时,清空图表数据
+ chartData.value = []
+ }
}
// 监听数据和图表类型变化,自动渲染图表
diff --git a/src/views/stat/Warnings.vue b/src/views/stat/Warnings.vue
index 4301dd4e0..a5d4b1037 100644
--- a/src/views/stat/Warnings.vue
+++ b/src/views/stat/Warnings.vue
@@ -13,6 +13,7 @@
value-format="YYYY-MM-DD HH:mm:ss"
@change="onDateChange"
style="width: 300px;"
+ clearable
/>
@@ -22,6 +23,9 @@
柱状图
+
+ 堆叠图
+
@@ -43,10 +47,18 @@ import { AlertMessageApi } from '@/api/alertmessage'
import dayjs from 'dayjs'
import { getUserProfile } from '@/api/system/user/profile'
-// 图表类型:'line' 折线图,'bar' 柱状图
-const chartType = ref<'line' | 'bar'>('line')
+// 图表类型:'line' 折线图,'bar' 柱状图,'stack' 堆叠图
+const chartType = ref<'line' | 'bar' | 'stack'>('bar')
// 预警统计数据
-const chartData = ref<{ date: string; totalCount: number; readCount: number; unreadCount: number }[]>([])
+const chartData = ref<{
+ date: string;
+ sosCount: number;
+ analysisCount: number;
+ sosReadCount: number;
+ analysisReadCount: number;
+ sosUnreadCount: number;
+ analysisUnreadCount: number;
+}[]>([])
// 时间范围,默认一周
const dateRange = ref<[string, string]>([
dayjs().subtract(6, 'day').startOf('day').format('YYYY-MM-DD 00:00:00'),
@@ -58,17 +70,55 @@ const renderChart = () => {
const dom = document.getElementById('main')
if (!dom) return
const myChart = echarts.init(dom)
- myChart.setOption({
+
+ // 当没有数据时显示提示
+ if (!chartData.value || chartData.value.length === 0) {
+ myChart.setOption(
+ {
+ title: {
+ text: '当前时间段无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: { color: '#909399', fontSize: 16 }
+ },
+ // 清空系列的和轴线,避免旧内容残留
+ xAxis: { show: false },
+ yAxis: { show: false },
+ series: []
+ },
+ true
+ ) // true表示不跟之前的option合并
+ return
+ }
+
+ const option: any = {
+ title: {
+ text: '预警信息统计',
+ left: 'center',
+ top: 0,
+ textStyle: {
+ fontSize: 18,
+ fontWeight: 'bold'
+ }
+ },
tooltip: {
trigger: 'axis',
formatter: function(params: any) {
- const data = params[0]
- const date = data.name
- const value = data.value
- return `${date}
预警信息数量: ${value}`
+ const date = params[0].name
+ let result = `${date}
`
+
+ params.forEach((param: any) => {
+ result += `${param.seriesName}: ${param.value}
`
+ })
+
+ return result
}
},
- grid: { left: 40, right: 20, top: 60, bottom: 40 },
+ legend: {
+ data: ['总预警数', 'SOS预警', '分析预警', '已读', '未读'],
+ top: 30
+ },
+ grid: { left: 40, right: 20, top: 80, bottom: 40 },
xAxis: {
type: 'category',
data: chartData.value.map(item => item.date),
@@ -81,15 +131,52 @@ const renderChart = () => {
axisLine: { lineStyle: { color: '#dcdfe6' } },
axisLabel: { color: '#666', fontSize: 14 }
},
- series: [
+ series: []
+ }
+
+ if (chartType.value === 'stack') {
+ // 堆叠图:显示预警类型和状态
+ option.series = [
{
- name: '预警信息数量',
+ name: 'SOS预警',
+ type: 'bar',
+ stack: 'type',
+ data: chartData.value.map(item => item.sosCount),
+ itemStyle: { color: '#F56C6C' }
+ },
+ {
+ name: '分析预警',
+ type: 'bar',
+ stack: 'type',
+ data: chartData.value.map(item => item.analysisCount),
+ itemStyle: { color: '#E6A23C' }
+ },
+ {
+ name: '已读',
+ type: 'bar',
+ stack: 'status',
+ data: chartData.value.map(item => item.sosReadCount + item.analysisReadCount),
+ itemStyle: { color: '#67C23A' }
+ },
+ {
+ name: '未读',
+ type: 'bar',
+ stack: 'status',
+ data: chartData.value.map(item => item.sosUnreadCount + item.analysisUnreadCount),
+ itemStyle: { color: '#909399' }
+ }
+ ]
+ } else {
+ // 普通柱状图或折线图
+ option.series = [
+ {
+ name: '总预警数',
type: chartType.value,
- data: chartData.value.map(item => item.totalCount),
+ data: chartData.value.map(item => item.sosCount + item.analysisCount),
smooth: chartType.value === 'line',
barWidth: chartType.value === 'bar' ? '40%' : undefined,
itemStyle: {
- color: chartType.value === 'line' ? '#409EFF' : '#67C23A',
+ color: '#409EFF',
borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
},
lineStyle: {
@@ -97,22 +184,112 @@ const renderChart = () => {
color: '#409EFF'
},
areaStyle: chartType.value === 'line' ? { color: 'rgba(64,158,255,0.15)' } : undefined
+ },
+ {
+ name: 'SOS预警',
+ type: chartType.value,
+ data: chartData.value.map(item => item.sosCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#F56C6C',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#F56C6C'
+ }
+ },
+ {
+ name: '分析预警',
+ type: chartType.value,
+ data: chartData.value.map(item => item.analysisCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#E6A23C',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#E6A23C'
+ }
+ },
+ {
+ name: '已读',
+ type: chartType.value,
+ data: chartData.value.map(item => item.sosReadCount + item.analysisReadCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#67C23A',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#67C23A'
+ }
+ },
+ {
+ name: '未读',
+ type: chartType.value,
+ data: chartData.value.map(item => item.sosUnreadCount + item.analysisUnreadCount),
+ smooth: chartType.value === 'line',
+ barWidth: chartType.value === 'bar' ? '40%' : undefined,
+ itemStyle: {
+ color: '#909399',
+ borderRadius: chartType.value === 'bar' ? [6, 6, 0, 0] : 0
+ },
+ lineStyle: {
+ width: 3,
+ color: '#909399'
+ }
}
]
- })
+ }
+
+ myChart.setOption(option)
}
// 渲染饼图
const renderPieChart = () => {
const dom = document.getElementById('pieChart')
if (!dom) return
-
- // 计算已读数量、未读数量
- const readCount = chartData.value.reduce((sum, item) => sum + item.readCount, 0)
- const unreadCount = chartData.value.reduce((sum, item) => sum + item.unreadCount, 0)
-
const pieChart = echarts.init(dom)
+
+ // 当没有数据时显示提示
+ if (!chartData.value || chartData.value.length === 0) {
+ pieChart.setOption(
+ {
+ title: {
+ text: '当前时间段无数据',
+ left: 'center',
+ top: 'center',
+ textStyle: { color: '#909399', fontSize: 16 }
+ },
+ series: []
+ },
+ true
+ )
+ return
+ }
+
+ // 计算总数
+ const totalSos = chartData.value.reduce((sum, item) => sum + item.sosCount, 0)
+ const totalAnalysis = chartData.value.reduce((sum, item) => sum + item.analysisCount, 0)
+ const totalRead = chartData.value.reduce((sum, item) => sum + item.sosReadCount + item.analysisReadCount, 0)
+ const totalUnread = chartData.value.reduce((sum, item) => sum + item.sosUnreadCount + item.analysisUnreadCount, 0)
+
pieChart.setOption({
+ title: {
+ text: '预警状态分布',
+ left: 'center',
+ top: 0,
+ textStyle: {
+ fontSize: 16,
+ fontWeight: 'bold'
+ }
+ },
tooltip: {
trigger: 'item',
formatter: '{a}
{b}: {c} ({d}%)'
@@ -124,10 +301,10 @@ const renderPieChart = () => {
},
series: [
{
- name: '预警信息',
+ name: '预警状态',
type: 'pie',
radius: ['40%', '70%'],
- center: ['60%', '60%'],
+ center: ['65%', '50%'],
avoidLabelOverlap: false,
label: {
show: false,
@@ -144,8 +321,8 @@ const renderPieChart = () => {
show: false
},
data: [
- { value: readCount, name: '已读', itemStyle: { color: '#67C23A' } },
- { value: unreadCount, name: '未读', itemStyle: { color: '#E6A23C' } }
+ { value: totalRead, name: '已读', itemStyle: { color: '#67C23A' } },
+ { value: totalUnread, name: '未读', itemStyle: { color: '#909399' } }
]
}
]
@@ -160,10 +337,12 @@ const params = ref({
// 获取预警统计数据
const fetchData = async () => {
+ try {
const userProfile = await getUserProfile()
params.value.orgid = userProfile.dept.id
- try {
+
const res = await AlertMessageApi.getAlertMessageStatistics(params.value)
+ console.log(res)
// 处理返回的数据格式
if (res && res.dailyData && Array.isArray(res.dailyData)) {
chartData.value = res.dailyData.map((item: any) => {
@@ -178,14 +357,19 @@ const fetchData = async () => {
return {
date: dateStr,
- totalCount: item.totalCount || 0,
- readCount: item.readCount || 0,
- unreadCount: item.unreadCount || 0
+ sosCount: item.sosCount || 0,
+ analysisCount: item.analysisCount || 0,
+ sosReadCount: item.sosReadCount || 0,
+ analysisReadCount: item.analysisReadCount || 0,
+ sosUnreadCount: item.sosUnreadCount || 0,
+ analysisUnreadCount: item.analysisUnreadCount || 0
}
})
} else {
chartData.value = []
}
+
+ console.log('处理后的图表数据:', chartData.value)
} catch (error) {
console.error('获取预警统计数据失败:', error)
chartData.value = []
@@ -193,9 +377,17 @@ const fetchData = async () => {
}
// 时间范围变化时
-const onDateChange = (range: [string, string]) => {
- dateRange.value = range
- fetchData()
+const onDateChange = (range: [string, string] | null) => {
+ // 当range不为空时,更新参数并获取数据
+ if (range && range.length === 2) {
+ dateRange.value = range
+ params.value.startTime = range[0]
+ params.value.endTime = range[1]
+ fetchData()
+ } else {
+ // 当日期被清空时,清空图表数据
+ chartData.value = []
+ }
}
// 监听数据和图表类型变化,自动渲染图表