diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_alarm.xml b/app/src/main/res/layout/fragment_alarm.xml index c218ab3..018c7f4 100644 --- a/app/src/main/res/layout/fragment_alarm.xml +++ b/app/src/main/res/layout/fragment_alarm.xml @@ -71,24 +71,6 @@ app:cardElevation="@dimen/dp_2" app:cardUseCompatPadding="true"> - - - - - + + - - @@ -130,7 +119,7 @@ android:layout_height="wrap_content" /> @@ -139,6 +128,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_alarm.xml b/app/src/main/res/layout/fragment_alarm.xml index c218ab3..018c7f4 100644 --- a/app/src/main/res/layout/fragment_alarm.xml +++ b/app/src/main/res/layout/fragment_alarm.xml @@ -71,24 +71,6 @@ app:cardElevation="@dimen/dp_2" app:cardUseCompatPadding="true"> - - - - - + + - - @@ -130,7 +119,7 @@ android:layout_height="wrap_content" /> @@ -139,6 +128,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l.xml b/app/src/main/res/layout/item_alarm_rv_l.xml new file mode 100644 index 0000000..dcfca23 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_alarm.xml b/app/src/main/res/layout/fragment_alarm.xml index c218ab3..018c7f4 100644 --- a/app/src/main/res/layout/fragment_alarm.xml +++ b/app/src/main/res/layout/fragment_alarm.xml @@ -71,24 +71,6 @@ app:cardElevation="@dimen/dp_2" app:cardUseCompatPadding="true"> - - - - - + + - - @@ -130,7 +119,7 @@ android:layout_height="wrap_content" /> @@ -139,6 +128,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l.xml b/app/src/main/res/layout/item_alarm_rv_l.xml new file mode 100644 index 0000000..dcfca23 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l_title.xml b/app/src/main/res/layout/item_alarm_rv_l_title.xml new file mode 100644 index 0000000..2381e19 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l_title.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_alarm.xml b/app/src/main/res/layout/fragment_alarm.xml index c218ab3..018c7f4 100644 --- a/app/src/main/res/layout/fragment_alarm.xml +++ b/app/src/main/res/layout/fragment_alarm.xml @@ -71,24 +71,6 @@ app:cardElevation="@dimen/dp_2" app:cardUseCompatPadding="true"> - - - - - + + - - @@ -130,7 +119,7 @@ android:layout_height="wrap_content" /> @@ -139,6 +128,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l.xml b/app/src/main/res/layout/item_alarm_rv_l.xml new file mode 100644 index 0000000..dcfca23 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l_title.xml b/app/src/main/res/layout/item_alarm_rv_l_title.xml new file mode 100644 index 0000000..2381e19 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l_title.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_task_rv_l.xml b/app/src/main/res/layout/item_task_rv_l.xml index 346fc84..1eafe30 100644 --- a/app/src/main/res/layout/item_task_rv_l.xml +++ b/app/src/main/res/layout/item_task_rv_l.xml @@ -9,7 +9,7 @@ android:paddingHorizontal="@dimen/dp_15"> diff --git a/app/build.gradle b/app/build.gradle index a644fbe..dfbeb5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -105,6 +105,8 @@ implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' //高德地图 implementation 'com.amap.api:3dmap:latest.integration' + //经纬度逆编码检索 + implementation 'com.amap.api:search:8.1.0' //日期范围选择 implementation project(path: ':cosmocalendar') //腾讯Android UI框架 diff --git a/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt new file mode 100644 index 0000000..097bfa9 --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/AlarmAdapter.kt @@ -0,0 +1,147 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.recyclerview.widget.RecyclerView +import com.amap.api.services.core.LatLonPoint +import com.amap.api.services.geocoder.GeocodeResult +import com.amap.api.services.geocoder.GeocodeSearch +import com.amap.api.services.geocoder.RegeocodeQuery +import com.amap.api.services.geocoder.RegeocodeResult +import com.casic.br.ktd.R +import com.casic.br.ktd.extensions.toChineseType +import com.casic.br.ktd.model.AlarmListModel +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor + +class AlarmAdapter( + private val ctx: Context, private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private val geoSearch by lazy { GeocodeSearch(ctx) } + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l_title, parent, false)) + } else { + return ViewHolder(inflater.inflate(R.layout.item_alarm_rv_l, parent, false)) + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + if (holder.itemViewType == TYPE_ITEM_DATA) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val item = dataRows[position - 1] + val alarmTime = if (item.alarmTime.isNullOrBlank()) { + "时间未知" + } else { + item.alarmTime + } + + val alarmState: String + if (item.alarmStatus == "0") { + alarmState = "正在报警" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.red.convertColor(ctx) + ) + } else { + alarmState = "已处置" + holder.setBackgroundColor( + R.id.alarmStateView, + R.color.green.convertColor(ctx) + ) + } + + if (item.alarmLatitude.isNotEmpty() && item.alarmLongitude.isNotEmpty()) { + val queryParam = RegeocodeQuery( + LatLonPoint(item.alarmLatitude.toDouble(), item.alarmLongitude.toDouble()), + 200f, GeocodeSearch.AMAP + ) + geoSearch.getFromLocationAsyn(queryParam) + geoSearch.setOnGeocodeSearchListener(object : + GeocodeSearch.OnGeocodeSearchListener { + override fun onRegeocodeSearched(regeocodeResult: RegeocodeResult, code: Int) { + if (code == 1000) { + val address = regeocodeResult.regeocodeAddress.formatAddress + holder.setText(R.id.alarmAddressView, address) + } + } + + override fun onGeocodeSearched(geocodeResult: GeocodeResult?, i: Int) {} + }) + } + + val alarmValue = if (item.alarmType == "1") { + "${item.alarmValue}ppm" + } else { + "${item.alarmValue * 100}%" + } + holder.setText(R.id.alarmCodeView, item.alarmCode) + .setText(R.id.alarmTimeView, alarmTime) + .setText(R.id.alarmTypeView, item.alarmType.toChineseType()) + .setText(R.id.alarmValueView, alarmValue) + .setText(R.id.alarmStateView, alarmState) + .setOnClickListener(R.id.handleAlarmButton) { + itemClickedListener?.onHandleButtonClicked(item) + } + + holder.itemView.setOnClickListener { itemClickedListener?.onItemClicked(item) } + } else { + holder.setText(R.id.alarmCodeView, "报警编号") + .setText(R.id.alarmTimeView, "报警时间") + .setText(R.id.alarmTypeView, "报警类型") + .setText(R.id.alarmValueView, "报警值") + .setText(R.id.alarmAddressView, "详细地址") + .setText(R.id.alarmStateView, "处置情况") + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + private var itemClickedListener: OnItemClickedListener? = null + + interface OnItemClickedListener { + fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) + + fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) + } + + fun setOnItemCheckedListener(listener: OnItemClickedListener) { + itemClickedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt new file mode 100644 index 0000000..ffc2d6d --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/adapter/SwipeActionAdapter.kt @@ -0,0 +1,131 @@ +package com.casic.br.ktd.adapter + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.Color +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.CheckBox +import android.widget.LinearLayout +import androidx.annotation.LayoutRes +import androidx.recyclerview.widget.RecyclerView +import com.casic.br.ktd.R +import com.casic.br.ktd.holder.SwipeViewHolder +import com.pengxh.kt.lite.adapter.ViewHolder +import com.pengxh.kt.lite.extensions.convertColor +import com.pengxh.kt.lite.extensions.convertDrawable +import com.pengxh.kt.lite.extensions.dp2px +import com.qmuiteam.qmui.recyclerView.QMUISwipeAction + +abstract class SwipeActionAdapter( + ctx: Context, + @LayoutRes private val titleXmlRes: Int, @LayoutRes private val itemXmlRes: Int, + private val dataRows: MutableList +) : RecyclerView.Adapter() { + + private val kTag = "TaskAdapter" + private val TYPE_TOP_TITLE = 0 + private val TYPE_ITEM_DATA = 1 + private var inflater: LayoutInflater = LayoutInflater.from(ctx) + private var multipleSelected = mutableSetOf() + private var selectedItems = ArrayList() + + private var deleteAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.delete_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("删除") + .backgroundColor(Color.RED) + .build() + + private var handleAction = QMUISwipeAction.ActionBuilder() + .icon(R.mipmap.handle_task.convertDrawable(ctx)) + .textSize(16f.dp2px(ctx)) + .textColor(Color.WHITE) + .paddingStartEnd(16f.dp2px(ctx)).text("编辑") + .backgroundColor(R.color.themeColor.convertColor(ctx)) + .build() + + //标题行,需要+1 + override fun getItemCount(): Int = dataRows.size + 1 + + override fun getItemViewType(position: Int): Int { + return if (position == 0) { + TYPE_TOP_TITLE + } else { + TYPE_ITEM_DATA + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + if (viewType == TYPE_TOP_TITLE) { + return ViewHolder(inflater.inflate(titleXmlRes, parent, false)) + } else { + val view = inflater.inflate(itemXmlRes, parent, false) + val swipeViewHolder = SwipeViewHolder(view) + swipeViewHolder.addSwipeAction(deleteAction) + swipeViewHolder.addSwipeAction(handleAction) + return swipeViewHolder + } + } + + @SuppressLint("NotifyDataSetChanged") + fun setRefreshData(dataRows: MutableList) { + this.dataRows.clear() + this.dataRows.addAll(dataRows) + notifyDataSetChanged() + } + + fun setLoadMoreData(dataRows: MutableList) { + this.dataRows.addAll(dataRows) + notifyItemRangeInserted(this.dataRows.size, dataRows.size) + } + + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is SwipeViewHolder) { + //绑定数据。标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val index = position - 1 + + convertView(holder, index, dataRows[index]) + + //多选 + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) + + multiCheckBox.isSelected = multipleSelected.contains(index) + multiCheckBox.setOnClickListener { + if (multipleSelected.contains(index)) { + multipleSelected.remove(index) + selectedItems.remove(dataRows[index]) + holder.itemView.isSelected = false + } else { + multipleSelected.add(index) + selectedItems.add(dataRows[index]) + holder.itemView.isSelected = true + } + + itemCheckedListener?.onItemChecked(selectedItems) + } + } else { + convertTitleView(holder as ViewHolder) + } + //item背景色 + if (position % 2 == 0) { + val linearLayout = holder.itemView.findViewById(R.id.rootView) + linearLayout.setBackgroundColor(Color.parseColor("#EEF1F6")) + } + } + + abstract fun convertView(viewHolder: SwipeViewHolder, position: Int, item: T) + + abstract fun convertTitleView(viewHolder: ViewHolder) + + private var itemCheckedListener: OnItemCheckedListener? = null + + interface OnItemCheckedListener { + fun onItemChecked(items: ArrayList) + } + + fun setOnItemCheckedListener(listener: OnItemCheckedListener) { + itemCheckedListener = listener + } +} \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt index 68260b2..983719f 100644 --- a/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt +++ b/app/src/main/java/com/casic/br/ktd/adapter/TaskAdapter.kt @@ -116,9 +116,10 @@ .setText(R.id.endTimeView, endDate) .setText(R.id.pathLengthView, km) .setText(R.id.taskStateView, taskState) + holder.itemView.setOnClickListener { itemCheckedListener?.onItemClicked(item) } //多选 - val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiSelectCheckBox) + val multiCheckBox: CheckBox = holder.itemView.findViewById(R.id.multiCheckBox) multiCheckBox.isSelected = multipleSelected.contains(position) multiCheckBox.setOnClickListener { @@ -152,6 +153,8 @@ private var itemCheckedListener: OnItemCheckedListener? = null interface OnItemCheckedListener { + fun onItemClicked(item: TaskListModel.DataModel.RowsModel) + fun onItemChecked(items: ArrayList) } diff --git a/app/src/main/java/com/casic/br/ktd/extensions/String.kt b/app/src/main/java/com/casic/br/ktd/extensions/String.kt index ee2db04..36af820 100644 --- a/app/src/main/java/com/casic/br/ktd/extensions/String.kt +++ b/app/src/main/java/com/casic/br/ktd/extensions/String.kt @@ -52,6 +52,17 @@ return dateFormat.format(Date(timestamp)) } +fun String.toChineseType(): String { + if (this.isEmpty()) { + return this + } + return if (this == "1") { + "浓度超限报警" + } else { + "第三方施工识别报警" + } +} + //拼接图片地址 fun String.combineImagePath(): String { if (this.isEmpty()) return this diff --git a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt index 9418169..ce2fa9f 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/AlarmPageFragment.kt @@ -1,15 +1,61 @@ package com.casic.br.ktd.fragment import android.os.Bundle +import android.os.Handler +import android.os.Message +import android.view.View +import androidx.lifecycle.ViewModelProvider import com.casic.br.ktd.R +import com.casic.br.ktd.adapter.AlarmAdapter import com.casic.br.ktd.base.KotlinBaseFragment +import com.casic.br.ktd.model.AlarmListModel +import com.casic.br.ktd.vm.AlarmViewModel import com.casic.br.ktd.widgets.DateRangeActionSheet +import com.pengxh.kt.lite.extensions.show +import com.pengxh.kt.lite.utils.WeakReferenceHandler import kotlinx.android.synthetic.main.fragment_alarm.view.* -class AlarmPageFragment : KotlinBaseFragment() { +class AlarmPageFragment : KotlinBaseFragment(), Handler.Callback { + + private val kTag = "TaskPageFragment" + private lateinit var weakReferenceHandler: WeakReferenceHandler + private lateinit var alarmViewModel: AlarmViewModel + private lateinit var alarmAdapter: AlarmAdapter + private var dataBeans: MutableList = ArrayList() + private var page = 1 + private var isRefresh = false + private var isLoadMore = false + private var startTime = "" + private var endTime = "" override fun initView(savedInstanceState: Bundle?) { + weakReferenceHandler = WeakReferenceHandler(this) + alarmViewModel = ViewModelProvider(this)[AlarmViewModel::class.java] + alarmViewModel.alarmList.observe(this) { + if (it.code == 200) { + val dataRows = it.data?.rows!! + when { + isRefresh -> { + alarmAdapter.setRefreshData(dataRows) + bv.alarmLayout.finishRefresh() + isRefresh = false + } + isLoadMore -> { + if (dataRows.size == 0) { + "到底了,别拉了".show(requireContext()) + } + alarmAdapter.setLoadMoreData(dataRows) + bv.alarmLayout.finishLoadMore() + isLoadMore = false + } + else -> { + dataBeans = dataRows + weakReferenceHandler.sendEmptyMessage(2023072901) + } + } + } + } } override fun initEvent() { @@ -18,10 +64,78 @@ .setOnActionSheetListener(object : DateRangeActionSheet.OnDateRangeSelectedListener { override fun onDateRangeSelected(startDate: String, endDate: String) { + startTime = startDate + endTime = endDate + //条件查询 + getAlarmsByPage(true) + bv.selectedDateView.text = "$startDate ~ $endDate" } }).build().show() } + + bv.resetParamView.setOnClickListener { + bv.selectedDateView.text = "" + + startTime = "" + endTime = "" + + //显示所有 + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnRefreshListener { + isRefresh = true + getAlarmsByPage(true) + } + + bv.alarmLayout.setOnLoadMoreListener { + isLoadMore = true + getAlarmsByPage(false) + } + } + + override fun onResume() { + super.onResume() + getAlarmsByPage(true) + } + + private fun getAlarmsByPage(isRefresh: Boolean) { + if (isRefresh) { + page = 1 + } else { + page++ + } + alarmViewModel.getAlarmsByPage( + startTime, "", "", endTime, page + ) + } + + override fun handleMessage(msg: Message): Boolean { + when (msg.what) { + 2023072901 -> { + if (dataBeans.size == 0) { + bv.alarmLayout.visibility = View.GONE + bv.emptyLayout.visibility = View.VISIBLE + } else { + bv.alarmLayout.visibility = View.VISIBLE + bv.emptyLayout.visibility = View.GONE + alarmAdapter = AlarmAdapter(requireContext(), dataBeans) + bv.alarmRecyclerView.adapter = alarmAdapter + alarmAdapter.setOnItemCheckedListener(object : + AlarmAdapter.OnItemClickedListener { + override fun onItemClicked(item: AlarmListModel.DataModel.RowsModel) { + "点击${item.alarmCode}".show(requireContext()) + } + + override fun onHandleButtonClicked(item: AlarmListModel.DataModel.RowsModel) { + "处理${item.alarmCode}".show(requireContext()) + } + }) + } + } + } + return true } override fun initLayoutRes(): Int = R.layout.fragment_alarm diff --git a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt index e965fd5..dc46490 100644 --- a/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt +++ b/app/src/main/java/com/casic/br/ktd/fragment/TaskPageFragment.kt @@ -100,6 +100,10 @@ bv.taskRecyclerView.adapter = taskAdapter taskAdapter.setOnItemCheckedListener(object : TaskAdapter.OnItemCheckedListener { + override fun onItemClicked(item: TaskListModel.DataModel.RowsModel) { + "点击${item.taskCode}".show(requireContext()) + } + override fun onItemChecked(items: ArrayList) { selectedItems = items } @@ -128,23 +132,25 @@ action: QMUISwipeAction? ) { super.onClickAction(swipeAction, selected, action) - val adapterPosition = selected!!.bindingAdapterPosition + //标题已经把position=0占用,但是size+1,所以需要数据绑定实际position-1 + val adapterPosition = selected!!.bindingAdapterPosition - 1 + val rowsModel = dataBeans[adapterPosition] if (action?.text == "删除") { - deleteItem(adapterPosition) + deleteItem(rowsModel) } else { AlertInputDialog.Builder() .setContext(requireContext()) .setTitle("编辑") .setSubLayoutVisibility(true) .setSubTitle("原任务名称") - .setOldValue(dataBeans[adapterPosition].taskName) + .setOldValue(rowsModel.taskName) .setHintMessage("请输入新的巡检任务名称") .setNegativeButton("取消") .setPositiveButton("确定") .setOnDialogButtonClickListener(object : AlertInputDialog.OnDialogButtonClickListener { override fun onConfirmClick(value: String) { - + "编辑${rowsModel.taskCode}".show(requireContext()) } override fun onCancelClick() {} @@ -153,7 +159,7 @@ } }) - private fun deleteItem(adapterPosition: Int) { + private fun deleteItem(rowsModel: TaskListModel.DataModel.RowsModel) { AlertControlDialog.Builder() .setContext(requireContext()) .setTitle("提示") @@ -167,7 +173,7 @@ } override fun onConfirmClick() { - + "删除${rowsModel.taskCode}".show(requireContext()) } }).build().show() } diff --git a/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java new file mode 100644 index 0000000..8e0519a --- /dev/null +++ b/app/src/main/java/com/casic/br/ktd/model/AlarmListModel.java @@ -0,0 +1,220 @@ +package com.casic.br.ktd.model; + +import java.util.List; + +public class AlarmListModel { + + private int code; + private DataModel data; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public DataModel getData() { + return data; + } + + public void setData(DataModel data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public static class DataModel { + private List rows; + private int total; + + public List getRows() { + return rows; + } + + public void setRows(List rows) { + this.rows = rows; + } + + public int getTotal() { + return total; + } + + public void setTotal(int total) { + this.total = total; + } + + public static class RowsModel { + private String alarmCode; + private String alarmContent; + private String alarmLatitude; + private String alarmLongitude; + private String alarmPicture; + private String alarmStatus; + private int alarmThresh; + private String alarmTime; + private String alarmType; + private int alarmValue; + private String alarmVideo; + private String cancelResult; + private String cancelTime; + private String cancelUser; + private String deviceId; + private String id; + private String taskId; + private String ts; + + public String getAlarmCode() { + return alarmCode; + } + + public void setAlarmCode(String alarmCode) { + this.alarmCode = alarmCode; + } + + public String getAlarmContent() { + return alarmContent; + } + + public void setAlarmContent(String alarmContent) { + this.alarmContent = alarmContent; + } + + public String getAlarmLatitude() { + return alarmLatitude; + } + + public void setAlarmLatitude(String alarmLatitude) { + this.alarmLatitude = alarmLatitude; + } + + public String getAlarmLongitude() { + return alarmLongitude; + } + + public void setAlarmLongitude(String alarmLongitude) { + this.alarmLongitude = alarmLongitude; + } + + public String getAlarmPicture() { + return alarmPicture; + } + + public void setAlarmPicture(String alarmPicture) { + this.alarmPicture = alarmPicture; + } + + public String getAlarmStatus() { + return alarmStatus; + } + + public void setAlarmStatus(String alarmStatus) { + this.alarmStatus = alarmStatus; + } + + public int getAlarmThresh() { + return alarmThresh; + } + + public void setAlarmThresh(int alarmThresh) { + this.alarmThresh = alarmThresh; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public int getAlarmValue() { + return alarmValue; + } + + public void setAlarmValue(int alarmValue) { + this.alarmValue = alarmValue; + } + + public String getAlarmVideo() { + return alarmVideo; + } + + public void setAlarmVideo(String alarmVideo) { + this.alarmVideo = alarmVideo; + } + + public String getCancelResult() { + return cancelResult; + } + + public void setCancelResult(String cancelResult) { + this.cancelResult = cancelResult; + } + + public String getCancelTime() { + return cancelTime; + } + + public void setCancelTime(String cancelTime) { + this.cancelTime = cancelTime; + } + + public String getCancelUser() { + return cancelUser; + } + + public void setCancelUser(String cancelUser) { + this.cancelUser = cancelUser; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTaskId() { + return taskId; + } + + public void setTaskId(String taskId) { + this.taskId = taskId; + } + + public String getTs() { + return ts; + } + + public void setTs(String ts) { + this.ts = ts; + } + } + } +} diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt index 222fce6..25c0b4e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitService.kt @@ -127,4 +127,15 @@ @Header("token") token: String, @Body requestBody: RequestBody ): String + + /** + * 获取报警列表 + */ + @POST("/alarm/listPage") + suspend fun getAlarmsByPage( + @Header("token") token: String, + @Body requestBody: RequestBody, + @QueryMap limit: Map, + @QueryMap offset: Map, + ): String } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt index ce36a66..416d99e 100644 --- a/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt +++ b/app/src/main/java/com/casic/br/ktd/retrofit/RetrofitServiceManager.kt @@ -233,4 +233,34 @@ ) return api.addAlarm(AuthenticationHelper.token, requestBody) } + + /** + * 获取报警列表 + */ + suspend fun getAlarmsByPage( + beginDate: String, + alarmStatus: String, + alarmType: String, + endDate: String, + offset: Int + ): String { + val param = JsonObject() + param.addProperty("beginDate", beginDate) + param.addProperty("alarmStatus", alarmStatus) + param.addProperty("alarmType", alarmType) + param.addProperty("endDate", endDate) + + val requestBody = param.toString().toRequestBody( + "application/json;charset=UTF-8".toMediaType() + ) + + val limitMap = HashMap() + limitMap["limit"] = LocaleConstant.PAGE_LIMIT + + val offsetMap = HashMap() + offsetMap["offset"] = offset + return api.getAlarmsByPage( + AuthenticationHelper.token, requestBody, limitMap, offsetMap + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt index dc834ea..2aed5f5 100644 --- a/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt +++ b/app/src/main/java/com/casic/br/ktd/vm/AlarmViewModel.kt @@ -4,6 +4,7 @@ import com.casic.br.ktd.base.BaseApplication import com.casic.br.ktd.extensions.separateResponseCode import com.casic.br.ktd.extensions.toErrorMessage +import com.casic.br.ktd.model.AlarmListModel import com.casic.br.ktd.model.AlarmParam import com.casic.br.ktd.model.AlarmRuleListModel import com.casic.br.ktd.retrofit.RetrofitServiceManager @@ -21,6 +22,7 @@ private val gson by lazy { Gson() } val alarmRuleList = MutableLiveData() + val alarmList = MutableLiveData() fun addAlarmRule(high: String, deviceId: String, ts: String) = launch({ loadState.value = LoadState.Loading @@ -54,4 +56,25 @@ }, { it.printStackTrace() }) + + fun getAlarmsByPage( + beginDate: String, alarmStatus: String, alarmType: String, endDate: String, offset: Int + ) = launch({ + loadState.value = LoadState.Loading + val response = RetrofitServiceManager.getAlarmsByPage( + beginDate, alarmStatus, alarmType, endDate, offset + ) + val responseCode = response.separateResponseCode() + if (responseCode == 200) { + loadState.value = LoadState.Success + alarmList.value = gson.fromJson( + response, object : TypeToken() {}.type + ) + } else { + loadState.value = LoadState.Fail + response.toErrorMessage().show(BaseApplication.get()) + } + }, { + loadState.value = LoadState.Fail + }) } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_alarm.xml b/app/src/main/res/layout/fragment_alarm.xml index c218ab3..018c7f4 100644 --- a/app/src/main/res/layout/fragment_alarm.xml +++ b/app/src/main/res/layout/fragment_alarm.xml @@ -71,24 +71,6 @@ app:cardElevation="@dimen/dp_2" app:cardUseCompatPadding="true"> - - - - - + + - - @@ -130,7 +119,7 @@ android:layout_height="wrap_content" /> @@ -139,6 +128,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l.xml b/app/src/main/res/layout/item_alarm_rv_l.xml new file mode 100644 index 0000000..dcfca23 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_alarm_rv_l_title.xml b/app/src/main/res/layout/item_alarm_rv_l_title.xml new file mode 100644 index 0000000..2381e19 --- /dev/null +++ b/app/src/main/res/layout/item_alarm_rv_l_title.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_task_rv_l.xml b/app/src/main/res/layout/item_task_rv_l.xml index 346fc84..1eafe30 100644 --- a/app/src/main/res/layout/item_task_rv_l.xml +++ b/app/src/main/res/layout/item_task_rv_l.xml @@ -9,7 +9,7 @@ android:paddingHorizontal="@dimen/dp_15"> diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index 5c88cb5..f1c5749 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -7,8 +7,8 @@ - 请选择报警类型 - 已处置 + 请选择处置状态 + 正在报警 未处置