feat: 考勤功能补全
1. 首页加载时检查工作状态(fetchWorkState) 2. MQTT type=4 工作状态推送处理(上班→亮屏,下班→关NFC+熄屏) 3. PunchStatus 增加打卡时间字段(onPunchTime/offPunchTime) 4. 考勤页显示打卡时间("已上班 07:02"/"已下班 17:05") 5. 首页注入 PunchApi/ScreenController/NfcController Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,11 @@ data class PunchStatus(
|
||||
/** 上班打卡状态:0=未上班, 1=已上班 */
|
||||
@SerializedName("onPunchState") val onPunchState: Int = 0,
|
||||
/** 下班打卡状态:1=已下班, 其他=未下班 */
|
||||
@SerializedName("offPunchState") val offPunchState: Int = 0
|
||||
@SerializedName("offPunchState") val offPunchState: Int = 0,
|
||||
/** 上班打卡时间(API 可能返回,待验证字段名) */
|
||||
@SerializedName("onPunchTime") val onPunchTime: String? = null,
|
||||
/** 下班打卡时间 */
|
||||
@SerializedName("offPunchTime") val offPunchTime: String? = null
|
||||
) {
|
||||
/** 是否已上班 */
|
||||
val isOnDuty: Boolean get() = onPunchState == 1
|
||||
|
||||
@@ -15,9 +15,13 @@ import com.xiaoqu.watch.data.prefs.UserPrefs
|
||||
import com.xiaoqu.watch.databinding.FragmentHomeBinding
|
||||
import com.xiaoqu.watch.event.AppEvent
|
||||
import com.xiaoqu.watch.event.EventBus
|
||||
import com.xiaoqu.watch.device.nfc.NfcController
|
||||
import com.xiaoqu.watch.device.screen.ScreenController
|
||||
import com.xiaoqu.watch.network.ApiResult
|
||||
import com.xiaoqu.watch.network.api.PunchApi
|
||||
import com.xiaoqu.watch.network.api.TaskApi
|
||||
import com.xiaoqu.watch.network.safeApiCall
|
||||
import org.json.JSONObject
|
||||
import com.xiaoqu.watch.ui.common.BaseFragment
|
||||
import com.xiaoqu.watch.ui.widget.StatusBarView
|
||||
import com.xiaoqu.watch.util.DateUtil
|
||||
@@ -39,6 +43,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
@Inject lateinit var userPrefs: UserPrefs
|
||||
@Inject lateinit var eventBus: EventBus
|
||||
@Inject lateinit var taskApi: TaskApi
|
||||
@Inject lateinit var punchApi: PunchApi
|
||||
@Inject lateinit var screenController: ScreenController
|
||||
@Inject lateinit var nfcController: NfcController
|
||||
|
||||
// ===== 固定状态栏(不随 ViewPager 滑动) =====
|
||||
private lateinit var statusBar: StatusBarView
|
||||
@@ -93,6 +100,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
// 加载任务统计数据
|
||||
fetchStatistics()
|
||||
|
||||
// 检查当前工作状态(考勤)
|
||||
fetchWorkState()
|
||||
|
||||
// 监听 MQTT 事件
|
||||
observeEvents()
|
||||
|
||||
@@ -251,9 +261,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
findNavController().navigate(R.id.action_home_to_bind)
|
||||
}
|
||||
4 -> {
|
||||
// 工作状态变更
|
||||
// 工作状态变更(MQTT type=4/5 推送)
|
||||
Timber.d("首页: 收到工作状态变更")
|
||||
// TODO: 更新考勤状态,控制蓝牙扫描
|
||||
handleWorkStateChange(event.rawJson)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -273,6 +283,57 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
findNavController().navigate(R.id.action_home_to_taskList, bundle)
|
||||
}
|
||||
|
||||
// ===== 工作状态(考勤联动) =====
|
||||
|
||||
/** 首页加载时检查当前工作状态 */
|
||||
private fun fetchWorkState() {
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
val result = safeApiCall { punchApi.getAttendance() }
|
||||
if (result is ApiResult.Success && result.data != null) {
|
||||
val status = result.data
|
||||
val isWorking = status.isOnDuty && !status.isOffDuty
|
||||
Timber.d("首页: 工作状态 isWorking=$isWorking (on=${status.onPunchState}, off=${status.offPunchState})")
|
||||
// 发送工作状态事件(其他模块可监听)
|
||||
eventBus.emit(AppEvent.WorkStateChanged(isWorking))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理 MQTT 工作状态变更(type=4/5)
|
||||
* 服务端推送上班/下班状态
|
||||
* v1.2.5: msg.action = 0(下班) / 1(上班)
|
||||
*/
|
||||
private fun handleWorkStateChange(rawJson: String) {
|
||||
try {
|
||||
val json = JSONObject(rawJson)
|
||||
val action = json.optInt("action", -1)
|
||||
val isWorking = action == 1
|
||||
|
||||
Timber.d("首页: MQTT 工作状态变更 action=$action isWorking=$isWorking")
|
||||
|
||||
// 发送工作状态事件
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
eventBus.emit(AppEvent.WorkStateChanged(isWorking))
|
||||
}
|
||||
|
||||
// 屏幕亮度联动
|
||||
if (isWorking) {
|
||||
screenController.turnOn()
|
||||
} else {
|
||||
// 下班 → 低耗电:关闭NFC + 熄屏
|
||||
nfcController.stopScan()
|
||||
if (nfcController.isOpen()) nfcController.close()
|
||||
screenController.turnOff()
|
||||
}
|
||||
|
||||
// 刷新统计数据
|
||||
fetchStatistics()
|
||||
} catch (e: Exception) {
|
||||
Timber.w(e, "首页: 解析工作状态变更异常")
|
||||
}
|
||||
}
|
||||
|
||||
/** 设置下拉手势 → 进入考勤打卡页(在状态栏区域检测) */
|
||||
@android.annotation.SuppressLint("ClickableViewAccessibility")
|
||||
private fun setupPullDownGesture() {
|
||||
|
||||
@@ -125,7 +125,8 @@ class PunchFragment : BaseFragment<FragmentPunchBinding>() {
|
||||
}
|
||||
// 已上班 + 已下班
|
||||
status.isOnDuty && status.isOffDuty -> {
|
||||
binding.tvPunchStatus.text = "已下班"
|
||||
val timeText = if (!status.offPunchTime.isNullOrEmpty()) "已下班 ${status.offPunchTime}" else "已下班"
|
||||
binding.tvPunchStatus.text = timeText
|
||||
binding.tvPunchStatus.setTextColor(requireContext().getColor(R.color.text_secondary))
|
||||
binding.btnPunch.text = "下班打卡"
|
||||
binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.primary))
|
||||
@@ -136,7 +137,8 @@ class PunchFragment : BaseFragment<FragmentPunchBinding>() {
|
||||
}
|
||||
// 已上班 + 未下班
|
||||
status.isOnDuty && !status.isOffDuty -> {
|
||||
binding.tvPunchStatus.text = "已上班"
|
||||
val timeText = if (!status.onPunchTime.isNullOrEmpty()) "已上班 ${status.onPunchTime}" else "已上班"
|
||||
binding.tvPunchStatus.text = timeText
|
||||
binding.tvPunchStatus.setTextColor(requireContext().getColor(R.color.success))
|
||||
binding.btnPunch.text = "下班打卡"
|
||||
binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.primary))
|
||||
|
||||
Reference in New Issue
Block a user