fix: NfcTaskManager 重写修复编译错误
之前 python 脚本修复乱码时破坏了文件结构(花括号错位导致 private 方法变成 local function)。完整重写文件。 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,12 @@ import com.xiaoqu.watch.device.sensor.VibrationController
|
|||||||
import com.xiaoqu.watch.network.ApiResult
|
import com.xiaoqu.watch.network.ApiResult
|
||||||
import com.xiaoqu.watch.network.api.TaskApi
|
import com.xiaoqu.watch.network.api.TaskApi
|
||||||
import com.xiaoqu.watch.network.safeApiCall
|
import com.xiaoqu.watch.network.safeApiCall
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import javax.inject.Singleton
|
import javax.inject.Singleton
|
||||||
@@ -15,11 +20,11 @@ import javax.inject.Singleton
|
|||||||
*
|
*
|
||||||
* 统一处理三种 NFC 打卡场景:
|
* 统一处理三种 NFC 打卡场景:
|
||||||
* 1. 任务单个打卡(任务详情页"开启打卡"按钮)
|
* 1. 任务单个打卡(任务详情页"开启打卡"按钮)
|
||||||
* 2. 主动批量打卡(返回键触发,checkNfcType → nfcBatchBeginTask)
|
* 2. 主动批量打卡(返回键触发,checkNfcType -> nfcBatchBeginTask)
|
||||||
* 3. 硬件开锁(返回键触发,checkNfcType → 根据 status 播放语音)
|
* 3. 硬件开锁(返回键触发,checkNfcType -> 根据 status 播放语音)
|
||||||
*
|
*
|
||||||
* 与 PunchViewModel(考勤打卡)独立,互不干扰。
|
* 与 PunchViewModel(考勤打卡)独立,互不干扰。
|
||||||
* 通过 isScanning 防止两者同时操作 NFC。
|
* 通过 isScanning + nfcController.isOpen() 防止两者同时操作 NFC。
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
class NfcTaskManager @Inject constructor(
|
class NfcTaskManager @Inject constructor(
|
||||||
@@ -28,9 +33,7 @@ class NfcTaskManager @Inject constructor(
|
|||||||
private val taskApi: TaskApi
|
private val taskApi: TaskApi
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
/** 默认 NFC 超时(毫秒),可被 MQTT type=4 的 nfcOpenTime 覆盖 */
|
|
||||||
private const val DEFAULT_NFC_TIMEOUT_MS = 20_000L
|
private const val DEFAULT_NFC_TIMEOUT_MS = 20_000L
|
||||||
// 震动方案 planId
|
|
||||||
private const val PLAN_PUNCH_SUCCESS = 4
|
private const val PLAN_PUNCH_SUCCESS = 4
|
||||||
private const val PLAN_PUNCH_FAIL = 7
|
private const val PLAN_PUNCH_FAIL = 7
|
||||||
private const val PLAN_NFC_OPEN = 8
|
private const val PLAN_NFC_OPEN = 8
|
||||||
@@ -49,18 +52,11 @@ class NfcTaskManager @Inject constructor(
|
|||||||
/** NFC 超时时间(毫秒),通过 MQTT type=4 更新 */
|
/** NFC 超时时间(毫秒),通过 MQTT type=4 更新 */
|
||||||
var nfcTimeoutMs: Long = DEFAULT_NFC_TIMEOUT_MS
|
var nfcTimeoutMs: Long = DEFAULT_NFC_TIMEOUT_MS
|
||||||
|
|
||||||
/** 协程作用域 */
|
|
||||||
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
|
|
||||||
/** 超时 Job */
|
|
||||||
private var timeoutJob: Job? = null
|
private var timeoutJob: Job? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 场景 1:任务单个打卡
|
* 场景 1:任务单个打卡
|
||||||
* 开启 NFC → 读卡 → POST nfcToBeginTask → 回调结果
|
|
||||||
*
|
|
||||||
* @param taskId 任务 ID
|
|
||||||
* @param onResult 结果回调(主线程),success + message
|
|
||||||
*/
|
*/
|
||||||
fun startTaskPunch(taskId: Long, onResult: (success: Boolean, message: String) -> Unit) {
|
fun startTaskPunch(taskId: Long, onResult: (success: Boolean, message: String) -> Unit) {
|
||||||
if (isScanning || nfcController.isOpen()) {
|
if (isScanning || nfcController.isOpen()) {
|
||||||
@@ -68,20 +64,17 @@ class NfcTaskManager @Inject constructor(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
isScanning = true
|
isScanning = true
|
||||||
Timber.d("NFC任<EFBFBD><EFBFBD>打卡: 开启单个打卡, taskId=%d", taskId)
|
Timber.d("NFC任务打卡: 开启单个打卡, taskId=%d", taskId)
|
||||||
|
|
||||||
// 开启 NFC + 音效
|
|
||||||
vibrationController.executeByPlanId(PLAN_NFC_OPEN)
|
vibrationController.executeByPlanId(PLAN_NFC_OPEN)
|
||||||
nfcController.open()
|
nfcController.open()
|
||||||
|
|
||||||
// 开始扫描
|
|
||||||
nfcController.startScan { nfcId ->
|
nfcController.startScan { nfcId ->
|
||||||
Timber.d("NFC任务打卡: 读到卡号 %s", nfcId)
|
Timber.d("NFC任务打卡: 读到卡号 %s", nfcId)
|
||||||
cancelTimeout()
|
cancelTimeout()
|
||||||
nfcController.stopScan()
|
nfcController.stopScan()
|
||||||
nfcController.close()
|
nfcController.close()
|
||||||
|
|
||||||
// 调用打卡 API
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val params = hashMapOf<String, Any>("id" to taskId, "nfcId" to nfcId)
|
val params = hashMapOf<String, Any>("id" to taskId, "nfcId" to nfcId)
|
||||||
val result = safeApiCall { taskApi.nfcToBeginTask(params) }
|
val result = safeApiCall { taskApi.nfcToBeginTask(params) }
|
||||||
@@ -94,7 +87,7 @@ class NfcTaskManager @Inject constructor(
|
|||||||
is ApiResult.Error -> {
|
is ApiResult.Error -> {
|
||||||
Timber.w("NFC任务打卡: 打卡失败 - %s", result.message)
|
Timber.w("NFC任务打卡: 打卡失败 - %s", result.message)
|
||||||
vibrationController.executeByPlanId(PLAN_PUNCH_FAIL)
|
vibrationController.executeByPlanId(PLAN_PUNCH_FAIL)
|
||||||
onResult(false, result.message ?: "<EFBFBD><EFBFBD>卡失败")
|
onResult(false, result.message ?: "打卡失败")
|
||||||
}
|
}
|
||||||
is ApiResult.NetworkError -> {
|
is ApiResult.NetworkError -> {
|
||||||
Timber.w(result.exception, "NFC任务打卡: 网络异常")
|
Timber.w(result.exception, "NFC任务打卡: 网络异常")
|
||||||
@@ -106,49 +99,42 @@ class NfcTaskManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动超时
|
|
||||||
startTimeout {
|
startTimeout {
|
||||||
Timber.d("NFC任务打卡: 超时自动关闭")
|
Timber.d("NFC任务打卡: 超时自动关闭")
|
||||||
closeNfc()
|
closeNfc()
|
||||||
onResult(false, "超<EFBFBD><EFBFBD><EFBFBD>")
|
vibrationController.executeByPlanId(PLAN_NFC_CLOSE)
|
||||||
|
onResult(false, "超时")
|
||||||
isScanning = false
|
isScanning = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 场景 2+3:主动打卡(<EFBFBD><EFBFBD><EFBFBD>回键触发)
|
* 场景 2+3:主动打卡(返回键触发)
|
||||||
* 开启 NFC → 读卡 → checkNfcType → 批量打卡 or 硬件开锁
|
|
||||||
*
|
|
||||||
* @param onResult 结果回调(主线程),success + message
|
|
||||||
*/
|
*/
|
||||||
fun startActivePunch(onResult: (success: Boolean, message: String) -> Unit) {
|
fun startActivePunch(onResult: (success: Boolean, message: String) -> Unit) {
|
||||||
if (isScanning) {
|
|
||||||
if (isScanning || nfcController.isOpen()) {
|
if (isScanning || nfcController.isOpen()) {
|
||||||
Timber.d("NFC主动打卡: NFC 正在使用中,忽略")
|
Timber.d("NFC主动打卡: NFC 正在使用中,忽略")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
isScanning = true
|
isScanning = true
|
||||||
Timber.d("NFC主动<EFBFBD><EFBFBD>卡: 开启(返回键触发)")
|
Timber.d("NFC主动打卡: 开启(返回键触发)")
|
||||||
|
|
||||||
// 开启 NFC + <20><>效
|
|
||||||
vibrationController.executeByPlanId(PLAN_NFC_OPEN)
|
vibrationController.executeByPlanId(PLAN_NFC_OPEN)
|
||||||
nfcController.open()
|
nfcController.open()
|
||||||
|
|
||||||
// 开始扫描
|
|
||||||
nfcController.startScan { nfcId ->
|
nfcController.startScan { nfcId ->
|
||||||
Timber.d("NFC主动打卡: 读到<EFBFBD><EFBFBD><EFBFBD>号 %s", nfcId)
|
Timber.d("NFC主动打卡: 读到卡号 %s", nfcId)
|
||||||
cancelTimeout()
|
cancelTimeout()
|
||||||
nfcController.stopScan()
|
nfcController.stopScan()
|
||||||
nfcController.close()
|
nfcController.close()
|
||||||
vibrationController.executeByPlanId(PLAN_NFC_CLOSE)
|
vibrationController.executeByPlanId(PLAN_NFC_CLOSE)
|
||||||
|
|
||||||
// 判断类型:批量打卡 or 硬件开锁
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
handleNfcType(nfcId, onResult)
|
handleNfcType(nfcId, onResult)
|
||||||
isScanning = false
|
isScanning = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 启动超时
|
|
||||||
startTimeout {
|
startTimeout {
|
||||||
Timber.d("NFC主动打卡: 超时自动关闭")
|
Timber.d("NFC主动打卡: 超时自动关闭")
|
||||||
closeNfc()
|
closeNfc()
|
||||||
@@ -168,11 +154,7 @@ class NfcTaskManager @Inject constructor(
|
|||||||
isScanning = false
|
isScanning = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** 判断 NFC 类型并处理 */
|
||||||
* 判断 NFC 类型并处理
|
|
||||||
* hardwareNfcFlag=true → 硬件开锁(播<EFBC88><E692AD><EFBFBD>语音)
|
|
||||||
* hardwareNfcFlag=false → 批量任务打卡(调 API)
|
|
||||||
*/
|
|
||||||
private suspend fun handleNfcType(nfcId: String, onResult: (Boolean, String) -> Unit) {
|
private suspend fun handleNfcType(nfcId: String, onResult: (Boolean, String) -> Unit) {
|
||||||
val result = safeApiCall { taskApi.checkNfcType(nfcId) }
|
val result = safeApiCall { taskApi.checkNfcType(nfcId) }
|
||||||
when (result) {
|
when (result) {
|
||||||
@@ -182,12 +164,9 @@ class NfcTaskManager @Inject constructor(
|
|||||||
onResult(false, "数据异常")
|
onResult(false, "数据异常")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.hardwareNfcFlag) {
|
if (data.hardwareNfcFlag) {
|
||||||
// 硬件开锁
|
|
||||||
handleHardwareUnlock(data.status, onResult)
|
handleHardwareUnlock(data.status, onResult)
|
||||||
} else {
|
} else {
|
||||||
// 批量任务打卡
|
|
||||||
handleBatchPunch(nfcId, onResult)
|
handleBatchPunch(nfcId, onResult)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +185,7 @@ class NfcTaskManager @Inject constructor(
|
|||||||
|
|
||||||
/** 硬件开锁:根据 status 播放对应语音 */
|
/** 硬件开锁:根据 status 播放对应语音 */
|
||||||
private fun handleHardwareUnlock(status: Int, onResult: (Boolean, String) -> Unit) {
|
private fun handleHardwareUnlock(status: Int, onResult: (Boolean, String) -> Unit) {
|
||||||
Timber.d("NFC<EFBFBD><EFBFBD>动打卡: 硬件开锁, status=%d", status)
|
Timber.d("NFC主动打卡: 硬件开锁, status=%d", status)
|
||||||
when (status) {
|
when (status) {
|
||||||
0 -> {
|
0 -> {
|
||||||
vibrationController.executeByPlanId(PLAN_OPENING)
|
vibrationController.executeByPlanId(PLAN_OPENING)
|
||||||
@@ -224,9 +203,7 @@ class NfcTaskManager @Inject constructor(
|
|||||||
vibrationController.executeByPlanId(PLAN_NO_AUTH)
|
vibrationController.executeByPlanId(PLAN_NO_AUTH)
|
||||||
onResult(false, "无开锁权限")
|
onResult(false, "无开锁权限")
|
||||||
}
|
}
|
||||||
else -> {
|
else -> onResult(false, "未知状态")
|
||||||
onResult(false, "<EFBFBD><EFBFBD>知状态")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,20 +224,18 @@ class NfcTaskManager @Inject constructor(
|
|||||||
onResult(false, result.message ?: "打卡失败")
|
onResult(false, result.message ?: "打卡失败")
|
||||||
}
|
}
|
||||||
is ApiResult.NetworkError -> {
|
is ApiResult.NetworkError -> {
|
||||||
Timber.w(result.exception, "NFC主动打卡: 网络<EFBFBD><EFBFBD>常")
|
Timber.w(result.exception, "NFC主动打卡: 网络异常")
|
||||||
vibrationController.executeByPlanId(PLAN_PUNCH_FAIL)
|
vibrationController.executeByPlanId(PLAN_PUNCH_FAIL)
|
||||||
onResult(false, "网络异常")
|
onResult(false, "网络异常")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 关闭 NFC 硬件 */
|
|
||||||
private fun closeNfc() {
|
private fun closeNfc() {
|
||||||
nfcController.stopScan()
|
nfcController.stopScan()
|
||||||
nfcController.close()
|
nfcController.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 启动超时协程 */
|
|
||||||
private fun startTimeout(onTimeout: () -> Unit) {
|
private fun startTimeout(onTimeout: () -> Unit) {
|
||||||
timeoutJob = scope.launch {
|
timeoutJob = scope.launch {
|
||||||
delay(nfcTimeoutMs)
|
delay(nfcTimeoutMs)
|
||||||
@@ -268,7 +243,6 @@ class NfcTaskManager @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 取消超时协程 */
|
|
||||||
private fun cancelTimeout() {
|
private fun cancelTimeout() {
|
||||||
timeoutJob?.cancel()
|
timeoutJob?.cancel()
|
||||||
timeoutJob = null
|
timeoutJob = null
|
||||||
|
|||||||
Reference in New Issue
Block a user