diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 541617c..acaafd1 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -22,12 +22,33 @@ android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + - + + + + + + + + ) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 541617c..acaafd1 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -22,12 +22,33 @@ android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 541617c..acaafd1 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -22,12 +22,33 @@ android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 645436a..e1fe112 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,4 +16,15 @@ #FF018786 #FF000000 #FFFFFFFF + + + #96e9b5 + #ff8078 + #80bbff + #916bff + #ffe1ab + #6666FF + #CCFF66 + #37D4AE + #feb5a2 \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 541617c..acaafd1 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -22,12 +22,33 @@ android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 645436a..e1fe112 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,4 +16,15 @@ #FF018786 #FF000000 #FFFFFFFF + + + #96e9b5 + #ff8078 + #80bbff + #916bff + #ffe1ab + #6666FF + #CCFF66 + #37D4AE + #feb5a2 \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6690fd1..3b4876a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -34,4 +34,7 @@ 56dp + + + 230dp \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt new file mode 100644 index 0000000..a2d7bbc --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/BarChart.kt @@ -0,0 +1,50 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.BarChart +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.github.mikephil.charting.formatter.ValueFormatter +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun BarChart.init(context: Context, barLabels: MutableList) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + if (barLabels.isEmpty()) { + this.clearValues() + return + } + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.animateY(1200, Easing.EaseInOutQuad) + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.setScaleEnabled(false) + //去掉描述 + this.description.isEnabled = false + //去掉图例 + this.legend.isEnabled = false + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.labelCount = barLabels.size // 设置x轴上的标签个数 + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return barLabels[value.toInt()] + } + } + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.position = XAxis.XAxisPosition.BOTTOM + xAxis.labelRotationAngle = -45f //X轴标签斜45度 + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + val leftAxis: YAxis = this.axisLeft + leftAxis.axisMinimum = 0f +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt new file mode 100644 index 0000000..ae78052 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/LineChart.kt @@ -0,0 +1,46 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.components.Legend +import com.github.mikephil.charting.components.XAxis +import com.github.mikephil.charting.components.YAxis +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun LineChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setDrawGridBackground(false) + this.setDrawBorders(false) + this.animateY(1200, Easing.EaseInOutQuad) + //设置样式 + val rightAxis: YAxis = this.axisRight + //设置图表右边的y轴禁用 + rightAxis.isEnabled = false + this.isScaleXEnabled = true //X轴可缩放 + this.isScaleYEnabled = false //Y轴不可缩放 + //设置x轴 + val xAxis: XAxis = this.xAxis + xAxis.textColor = R.color.lib_text_color.convertColor(context) + xAxis.textSize = 10f + xAxis.setDrawLabels(true) //绘制标签 指x轴上的对应数值 + xAxis.setDrawAxisLine(true) //是否绘制轴线 + xAxis.setDrawGridLines(false) //设置x轴上每个点对应的线 + xAxis.granularity = 1f //禁止放大后x轴标签重绘 + xAxis.position = XAxis.XAxisPosition.BOTTOM + this.extraBottomOffset = 5f //解决X轴显示不完全问题 + //去掉描述 + this.description.isEnabled = false + //设置图例 + val legend = this.legend + legend.orientation = Legend.LegendOrientation.HORIZONTAL + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt new file mode 100644 index 0000000..1609d16 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/extensions/PieChart.kt @@ -0,0 +1,40 @@ +package com.casic.smart.town.sanxi.extensions + +import android.content.Context +import android.graphics.Color +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.animation.Easing +import com.github.mikephil.charting.charts.Chart +import com.github.mikephil.charting.charts.PieChart +import com.github.mikephil.charting.components.Legend +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.sp2px + +fun PieChart.init(context: Context) { + this.setNoDataText("无数据,无法渲染...") + this.setNoDataTextColor(R.color.red) + this.getPaint(Chart.PAINT_INFO).textSize = 14f.sp2px(context).toFloat() + this.setUsePercentValues(false) //百分比数字显示 + this.description.isEnabled = false + this.dragDecelerationFrictionCoef = 0.95f //图表转动阻力摩擦系数[0,1] + this.setBackgroundColor(Color.WHITE) //设置图表背景色 + this.rotationAngle = 0f + this.isRotationEnabled = false + this.isHighlightPerTapEnabled = true + this.animateY(1200, Easing.EaseInOutQuad) // 设置图表展示动画效果 + this.setDrawEntryLabels(false) //不显示分类标签 + this.isDrawHoleEnabled = false //圆环显示 + this.setDrawCenterText(false) //圆环中心文字 + this.centerText = "占比图" + this.setEntryLabelColor(R.color.blue.convertColor(context)) //图表文本字体颜色 + this.setEntryLabelTextSize(12f) + //设置图表上下左右的偏移,类似于外边距,可以控制饼图大小 + this.setExtraOffsets(7.5f, 2.5f, 7.5f, 2.5f) + //设置图例位置 + val legend = this.legend + legend.verticalAlignment = Legend.LegendVerticalAlignment.BOTTOM + legend.horizontalAlignment = Legend.LegendHorizontalAlignment.CENTER + legend.orientation = Legend.LegendOrientation.HORIZONTAL + //图例是否自动换行 + legend.isWordWrapEnabled = true +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt index 2282b58..1bf928d 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/fragment/StatisticsPageFragment.kt @@ -6,21 +6,32 @@ import com.casic.smart.town.sanxi.adapter.DeviceRecyclerAdapter import com.casic.smart.town.sanxi.adapter.InfrastructureAdapter import com.casic.smart.town.sanxi.model.DeviceModel +import com.casic.smart.town.sanxi.model.LineChartEntryModel +import com.casic.smart.town.sanxi.util.ChartViewHelper +import com.casic.smart.town.sanxi.util.LocaleConstant import com.casic.smart.town.sanxi.view.AllWellActivity import com.casic.smart.town.sanxi.view.BFWellActivity import com.casic.smart.town.sanxi.view.CFWellActivity import com.casic.smart.town.sanxi.vm.DeviceViewModel import com.casic.smart.town.sanxi.vm.InfrastructureViewModel +import com.casic.smart.town.sanxi.vm.PipeViewModel import com.casic.smart.town.sanxi.vm.WellViewModel +import com.github.mikephil.charting.data.Entry import com.pengxh.kt.lite.base.KotlinBaseFragment +import com.pengxh.kt.lite.extensions.convertColor import com.pengxh.kt.lite.extensions.navigatePageTo +import com.pengxh.kt.lite.extensions.timestampToCompleteDate +import com.pengxh.kt.lite.extensions.timestampToLastWeekDate import kotlinx.android.synthetic.main.fragment_statistics.* class StatisticsPageFragment : KotlinBaseFragment() { + private val kTag = "StatisticsPageFragment" + private lateinit var pipeViewModel: PipeViewModel private lateinit var wellViewModel: WellViewModel private lateinit var infrastructureViewModel: InfrastructureViewModel private lateinit var deviceViewModel: DeviceViewModel + private val entryEntries: MutableList> = ArrayList() override fun initLayoutView(): Int = R.layout.fragment_statistics @@ -34,9 +45,43 @@ override fun initData() { //初始化vm + pipeViewModel = ViewModelProvider(this)[PipeViewModel::class.java] wellViewModel = ViewModelProvider(this)[WellViewModel::class.java] infrastructureViewModel = ViewModelProvider(this)[InfrastructureViewModel::class.java] deviceViewModel = ViewModelProvider(this)[DeviceViewModel::class.java] + + pipeViewModel.resultModel.observe(this, { + if (it.code == 200) { + val xAxisLabel: MutableList = ArrayList() + val dataModel = it.data!! + + val firstEntries: ArrayList = ArrayList() + + val secondEntries: ArrayList = ArrayList() + dataModel.forEachIndexed { index, dateModel -> + val split = dateModel.date.toString().split("-") + xAxisLabel.add("${split[1]}/${split[2]}") + + //第一条线 + firstEntries.add( + Entry( + index.toFloat(), dateModel.`_$1`.toFloat(), "管网" + ) + ) + + //第二条线 + secondEntries.add( + Entry( + index.toFloat(), dateModel.`_$2`.toFloat(), "窨井" + ) + ) + } + entryEntries.add(firstEntries) + entryEntries.add(secondEntries) + ChartViewHelper.setLineChartData(healthStatusChart, xAxisLabel, entryEntries) + } + }) + //获取窨井监控数据 wellViewModel.countResultModel.observe(this, { cfWellView.text = it["cfWell"] @@ -44,6 +89,21 @@ allWellDataView.text = it["total"] }) + deviceViewModel.resultModel.observe(this, { + if (it.code == 200) { + val dateRows = ArrayList() + it.data.forEach { data -> + if (data.offLineState != "0" || data.onLineState != "0") { + dateRows.add(data) + } + } + deviceRecyclerView.addItemDecoration( + DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) + ) + deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) + } + }) + infrastructureViewModel.countInfrastructure() infrastructureViewModel.resultModel.observe(this, { if (it.code == 200) { @@ -70,22 +130,13 @@ override fun onResume() { super.onResume() //每次页面切换都需要重新刷新不同状态的闸井数量 + val time = System.currentTimeMillis() + pipeViewModel.getPipeHealthStatus( + time.timestampToLastWeekDate()!!, + time.timestampToCompleteDate(), + "" + ) wellViewModel.countWellByState() - deviceViewModel.countDevice() - deviceViewModel.resultModel.observe(this, { - if (it.code == 200) { - val dateRows = ArrayList() - it.data.forEach { data -> - if (data.offLineState != "0" || data.onLineState != "0") { - dateRows.add(data) - } - } - deviceRecyclerView.addItemDecoration( - DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) - ) - deviceRecyclerView.adapter = DeviceRecyclerAdapter(requireContext(), dateRows) - } - }) } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java new file mode 100644 index 0000000..89333ef --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/HealthStatusModel.java @@ -0,0 +1,77 @@ +package com.casic.smart.town.sanxi.model; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +public class HealthStatusModel { + + private int code; + private List data; + private String message; + private boolean success; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public boolean isSuccess() { + return success; + } + + public void setSuccess(boolean success) { + this.success = success; + } + + public static class DataModel { + private String date; + @SerializedName("1") + private String _$1; + @SerializedName("2") + private String _$2; + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String get_$1() { + return _$1; + } + + public void set_$1(String _$1) { + this._$1 = _$1; + } + + public String get_$2() { + return _$2; + } + + public void set_$2(String _$2) { + this._$2 = _$2; + } + } +} diff --git a/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java new file mode 100644 index 0000000..dcea477 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/model/LineChartEntryModel.java @@ -0,0 +1,29 @@ +package com.casic.smart.town.sanxi.model; + +import com.github.mikephil.charting.data.Entry; + +import java.util.List; + +public class LineChartEntryModel { + //折线数据 + private List entryList; + + //折线颜色 + private Integer lineColor; + + public List getEntryList() { + return entryList; + } + + public void setEntryList(List entryList) { + this.entryList = entryList; + } + + public Integer getLineColor() { + return lineColor; + } + + public void setLineColor(Integer lineColor) { + this.lineColor = lineColor; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt new file mode 100644 index 0000000..4f4a2e2 --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/ChartViewHelper.kt @@ -0,0 +1,171 @@ +package com.casic.smart.town.sanxi.util + +import android.util.Log +import com.casic.smart.town.sanxi.extensions.init +import com.casic.smart.town.sanxi.widgets.LineChartMarkerView +import com.github.mikephil.charting.charts.LineChart +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.data.LineData +import com.github.mikephil.charting.data.LineDataSet +import com.github.mikephil.charting.formatter.ValueFormatter +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.toJson + + +/** + * @author a203 + * @description 各种图初始化配置类 + * @date 2022/2/15 16:24 + * @email 290677893@qq.com + */ +object ChartViewHelper { + private const val kTag = "ChartViewHelper" + + /** + * 多条折线图 + * */ + fun setLineChartData( + chart: LineChart, xAxisDate: MutableList, entries: MutableList> + ) { + //每次加载数据都初始化折线图 + chart.init(chart.context) + //绑定数据 + val lineDataSets: MutableList = ArrayList() + Log.d(kTag, entries.toJson()) + entries.forEachIndexed { index, it -> + //设置数据 + val dataSet = LineDataSet(it, it[index].data.toString()) + dataSet.setDrawCircles(true) + //线条颜色 + dataSet.color = LocaleConstant.COLOR[index].convertColor(chart.context) + //圆点颜色 + dataSet.setCircleColor(LocaleConstant.COLOR[index].convertColor(chart.context)) + dataSet.setDrawFilled(true) + dataSet.fillColor = LocaleConstant.COLOR[index].convertColor(chart.context) + dataSet.mode = LineDataSet.Mode.CUBIC_BEZIER + lineDataSets.add(dataSet) + } + + val lineData = LineData(lineDataSets) + lineData.setDrawValues(false) + //添加自定义Marker + val markerView = LineChartMarkerView(chart.context) + markerView.chartView = chart + markerView.setXAxisDate(xAxisDate) + chart.marker = markerView + //设置X轴坐标 + val xAxis = chart.xAxis + xAxis.valueFormatter = object : ValueFormatter() { + override fun getFormattedValue(value: Float): String { + return xAxisDate[value.toInt()] + } + } + chart.data = lineData + chart.invalidate() + } + + /** + * 竖直柱状图 + * */ +// fun setBarChartData( +// chart: BarChart, +// xAxisLabel: MutableList, +// entries: List, +// dateType: String +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_1.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType(dateType) +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 横向柱状图 + * */ +// fun setBarChartData( +// chart: HorizontalBarChart, +// xAxisLabel: MutableList, +// entries: List +// ) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context, xAxisLabel) +// val barDataSets: MutableList = ArrayList() +// //绑定数据 +// val dataSet = BarDataSet(entries, "") +// dataSet.color = R.color.color_6.convertColor(chart.context) +// dataSet.valueFormatter = object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0").format(value.toDouble()) +// } +// } +// barDataSets.add(dataSet) +// val barData = BarData(barDataSets) +// barData.barWidth = 0.5f +// //添加自定义Marker +// val markerView = BarChartMarkerView(chart.context) +// markerView.chartView = chart +// markerView.setXAxisLabel(xAxisLabel) +// markerView.setBarDataType("") +// chart.marker = markerView +// chart.data = barData +// chart.invalidate() +// } + + /** + * 饼图 + * */ +// fun setPieChartData(chart: PieChart, entries: List) { +// //每次加载数据都初始化饼图 +// chart.init(chart.context) +// if (entries.isEmpty()) { +// return +// } +// //绑定数据 +// val dataSet = PieDataSet(entries, "") +// dataSet.sliceSpace = 1.5f //设置饼状块之间的间隙 +// dataSet.selectionShift = 5f //设置饼状块被选中时突出的距离 +// //设置饼图块颜色 +// val colors: MutableList = ArrayList() +// for (i in entries.indices) { +// colors.add(LocaleConstant.COLORS[i].convertColor(chart.context)) +// } +// dataSet.colors = colors +// //设置标签显示在饼图块外面 +// dataSet.xValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.yValuePosition = PieDataSet.ValuePosition.OUTSIDE_SLICE +// dataSet.valueLineColor = +// R.color.mainThemeColor.convertColor(chart.context) +// dataSet.valueLinePart1Length = 0.55f //标签指示线前半截长度 +// dataSet.valueLinePart2Length = 0.65f //标签指示线后半截长度 +// val data = PieData(dataSet) +// data.setValueFormatter(object : ValueFormatter() { +// override fun getFormattedValue(value: Float): String { +// return DecimalFormat("##0.0").format(value.toDouble()) + "t" +// } +// }) +// data.setValueTextSize(12f) +// data.setValueTextColor(R.color.mainThemeColor.convertColor(chart.context)) //数据值颜色 +// chart.data = data +// chart.highlightValues(null) +// chart.invalidate() +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt index a8eab8e..183c85c 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/LocaleConstant.kt @@ -1,6 +1,7 @@ package com.casic.smart.town.sanxi.util import android.Manifest +import com.casic.smart.town.sanxi.R object LocaleConstant { val USER_PERMISSIONS = arrayOf( @@ -35,4 +36,10 @@ "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/8", "http://111.198.10.15:13002/arcgis/rest/services/sxxz/MapServer/9" ) + //预置颜色 + val COLOR = arrayOf( + R.color.color_1, R.color.color_2, R.color.color_3, + R.color.color_4, R.color.color_5, R.color.color_6, + R.color.color_7, R.color.color_8, R.color.color_9 + ) } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt index 04c0e58..3c09c39 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitService.kt @@ -94,4 +94,12 @@ @GET("/monitor/list") suspend fun queryVideoCameraList(@Header("token") token: String): String + + @GET("/statics/healthStatus") + suspend fun getPipeHealthStatus( + @Header("token") token: String, + @Query("beginTime") beginTime: String, + @Query("endTime") endTime: String, + @Query("alarmType") alarmType: String + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt index 21a194e..6922523 100644 --- a/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/smart/town/sanxi/util/retrofit/RetrofitServiceManager.kt @@ -97,4 +97,13 @@ suspend fun queryVideoCameraList(): String { return smartTownApi.queryVideoCameraList(AuthenticationHelper.token!!) } + + suspend fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String): String { + return smartTownApi.getPipeHealthStatus( + AuthenticationHelper.token!!, + beginTime, + endTime, + alarmType + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt new file mode 100644 index 0000000..d08167c --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/vm/PipeViewModel.kt @@ -0,0 +1,32 @@ +package com.casic.smart.town.sanxi.vm + +import androidx.lifecycle.MutableLiveData +import com.casic.smart.town.sanxi.base.BaseApplication +import com.casic.smart.town.sanxi.extensions.separateResponseCode +import com.casic.smart.town.sanxi.extensions.toErrorMessage +import com.casic.smart.town.sanxi.model.HealthStatusModel +import com.casic.smart.town.sanxi.util.retrofit.RetrofitServiceManager +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import com.pengxh.kt.lite.extensions.launch +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.vm.BaseViewModel + +class PipeViewModel : BaseViewModel() { + private val gson by lazy { Gson() } + val resultModel = MutableLiveData() + + fun getPipeHealthStatus(beginTime: String, endTime: String, alarmType: String) = launch({ + val response = RetrofitServiceManager.getPipeHealthStatus(beginTime, endTime, alarmType) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + resultModel.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + response.toErrorMessage().show(BaseApplication.obtainInstance()) + } + }, { + it.printStackTrace() + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt new file mode 100644 index 0000000..30e7a5d --- /dev/null +++ b/app/src/main/java/com/casic/smart/town/sanxi/widgets/LineChartMarkerView.kt @@ -0,0 +1,45 @@ +package com.casic.smart.town.sanxi.widgets + +import android.content.Context +import android.widget.TextView +import com.casic.smart.town.sanxi.R +import com.github.mikephil.charting.components.MarkerView +import com.github.mikephil.charting.data.Entry +import com.github.mikephil.charting.highlight.Highlight +import com.github.mikephil.charting.utils.MPPointF +import java.text.DecimalFormat +import java.util.* + +class LineChartMarkerView(context: Context?) : + MarkerView(context, R.layout.popu_line_chart_marker) { + + private val decimalFormat = DecimalFormat("##0.0") + private val dayView: TextView = findViewById(R.id.dayView) + private val factoryView: TextView = findViewById(R.id.factoryView) + private val dataView: TextView = findViewById(R.id.dataView) + private var xAxisDate: MutableList = ArrayList() + + fun setXAxisDate(date: MutableList) { + this.xAxisDate = date + } + + //每次重绘,会调用此方法刷新数据 + override fun refreshContent(e: Entry, highlight: Highlight) { + super.refreshContent(e, highlight) + val data = e.data as String + try { + factoryView.text = data + dataView.text = String.format("指数:${decimalFormat.format(e.y.toString().toDouble())}") + val date = xAxisDate[(e.x).toInt()] + val split = date.split("/") + dayView.text = String.format(Locale.CHINA, "${split[0]}月${split[1]}日") + } catch (e1: Exception) { + e1.printStackTrace() + } + super.refreshContent(e, highlight) + } + + override fun getOffset(): MPPointF { + return MPPointF((-(width shr 1)).toFloat(), (-height).toFloat()) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_stroke_layout_blue.xml b/app/src/main/res/drawable/bg_stroke_layout_blue.xml new file mode 100644 index 0000000..26ddc25 --- /dev/null +++ b/app/src/main/res/drawable/bg_stroke_layout_blue.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_text_tag_blue.xml b/app/src/main/res/drawable/bg_text_tag_blue.xml new file mode 100644 index 0000000..6b497b0 --- /dev/null +++ b/app/src/main/res/drawable/bg_text_tag_blue.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_statistics.xml b/app/src/main/res/layout/fragment_statistics.xml index 541617c..acaafd1 100644 --- a/app/src/main/res/layout/fragment_statistics.xml +++ b/app/src/main/res/layout/fragment_statistics.xml @@ -22,12 +22,33 @@ android:layout_height="match_parent"> - + android:layout_height="wrap_content"> + - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 645436a..e1fe112 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -16,4 +16,15 @@ #FF018786 #FF000000 #FFFFFFFF + + + #96e9b5 + #ff8078 + #80bbff + #916bff + #ffe1ab + #6666FF + #CCFF66 + #37D4AE + #feb5a2 \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6690fd1..3b4876a 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -34,4 +34,7 @@ 56dp + + + 230dp \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index bafb7d4..99b48d7 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -102,4 +102,12 @@ @color/hintTextColor @color/mainThemeColor + + \ No newline at end of file