feat(nfc-task): NFC 任务打卡模块(单个+批量+硬件开锁)

REQ-20260506-0024

新增 NfcTaskManager:
- startTaskPunch(taskId):任务详情页单个 NFC 打卡
- startActivePunch():返回键触发主动打卡
  → checkNfcType 判断:hardwareNfcFlag=true 硬件开锁 / false 批量打卡
- NFC 超时自动关闭 + 震动/音效反馈
- isScanning 标记防重复触发

TaskApi 增加 3 个接口:
- POST watchTask/nfcToBeginTask(单个打卡)
- POST watchTask/nfcBatchBeginTask(批量打卡)
- GET nfcInfo/nfcOpenLock(类型判断)

返回键逻辑修正:
- 原:返回键→考勤打卡
- 现:返回键→主动打卡(批量任务 or 硬件开锁)
- 考勤打卡只从下拉面板触发
- onBackKeyPressed 改为返回 Boolean(true=已处理)

TaskDetailFragment:
- "开启打卡"按钮填充 NFC 打卡逻辑(替换 TODO)
- 扫描中按钮变灰禁用,成功/失败用 QuTipDialog

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
dongliang
2026-05-06 12:05:40 +09:30
parent 70da49f650
commit 1b24e2d044
7 changed files with 392 additions and 25 deletions

View File

@@ -9,9 +9,11 @@ import androidx.appcompat.app.AppCompatActivity
import com.xiaoqu.watch.databinding.ActivityMainBinding
import com.xiaoqu.watch.event.AppEvent
import com.xiaoqu.watch.event.EventBus
import com.xiaoqu.watch.data.prefs.UserPrefs
import com.xiaoqu.watch.device.screen.ScreenController
import com.xiaoqu.watch.device.sensor.AccelerometerWakeController
import com.xiaoqu.watch.service.manager.BluetoothScanManager
import com.xiaoqu.watch.service.manager.NfcTaskManager
import com.xiaoqu.watch.service.manager.NotificationManager
import com.xiaoqu.watch.service.manager.SystemStateMonitor
import com.xiaoqu.watch.service.manager.UpdateManager
@@ -45,6 +47,9 @@ class MainActivity : AppCompatActivity() {
@Inject lateinit var updateManager: UpdateManager
@Inject lateinit var screenController: ScreenController
@Inject lateinit var bluetoothScanManager: BluetoothScanManager
/** NFC 任务打卡管理器 */
@Inject lateinit var nfcTaskManager: NfcTaskManager
@Inject lateinit var userPrefs: UserPrefs
/** OTA 更新弹窗 */
lateinit var updateDialog: UpdateDialogView
lateinit var notificationBanner: NotificationBannerView
@@ -130,8 +135,8 @@ class MainActivity : AppCompatActivity() {
/** 下拉回调(由 HomeFragment 注册) */
var onSwipeDown: (() -> Unit)? = null
/** 返回键回调(由 HomeFragment 注册,触发 NFC 打卡 */
var onBackKeyPressed: (() -> Unit)? = null
/** 返回键回调(由 HomeFragment 注册)。返回 true = 已处理,不触发主动打卡 */
var onBackKeyPressed: (() -> Boolean)? = null
private var touchStartY = 0f
private var touchStartX = 0f
@@ -167,20 +172,45 @@ class MainActivity : AppCompatActivity() {
/**
* 物理返回键拦截:
* - 已绑定用户 → 开启 NFC 打卡模式(后续模块实现
* - 已绑定用户 → 主动打卡(批量任务打卡 or 硬件开锁
* - NFC 扫描中 → 忽略(防重复)
* - 未绑定 → 无操作
* - 所有情况阻止默认页面回退
*
* 注意:考勤打卡只从下拉面板触发,不走返回键
*/
private fun setupBackButton() {
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
Timber.d("Back button pressed - intercepted")
// 已绑定用户 → 触发 NFC 打卡(由 HomeFragment 注册回调)
onBackKeyPressed?.invoke()
// 由 HomeFragment 注册的回调处理面板展<E69DBF><E5B195>时收回
val callback = onBackKeyPressed
if (callback != null && callback()) {
// 回调返回 true = 已处理,不继续
return
}
// 回调返回 false 或无回调 → 触发主动打卡
startActivePunchFromBackKey()
}
})
}
/** 返回键触发主动打卡(批量任务 or 硬件开锁) */
private fun startActivePunchFromBackKey() {
// 已在 NFC 扫描中 → 忽略
if (nfcTaskManager.isScanning) return
// 未绑定 → 忽略
if (!userPrefs.isBound) return
Timber.d("返回键: 触发主动打卡")
nfcTaskManager.startActivePunch { success, message ->
if (message.isNotEmpty()) {
android.widget.Toast.makeText(this@MainActivity, message, android.widget.Toast.LENGTH_SHORT).show()
}
}
}
// ===== OTA 更新 =====
/** 设置更新弹窗按钮回调 */