From 98de3f0b4671f0ca9d814ff9f0e3d504783cb7a9 Mon Sep 17 00:00:00 2001 From: dongliang Date: Tue, 28 Apr 2026 20:23:00 +0930 Subject: [PATCH] =?UTF-8?q?revert:=20=E5=88=A0=E9=99=A4=E8=80=83=E5=8B=A4?= =?UTF-8?q?=E6=89=93=E5=8D=A1=E6=A8=A1=E5=9D=97=E4=BB=A3=E7=A0=81=EF=BC=8C?= =?UTF-8?q?=E5=87=86=E5=A4=87=E9=87=8D=E6=96=B0=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 删除:PunchStatus.kt, PunchApi.kt, PunchFragment.kt, fragment_punch.xml 恢复:HomeFragment(去掉下拉手势/PunchApi/工作状态处理) 恢复:fragment_home.xml(去掉pullDownArea覆盖层) 恢复:nav_main.xml(去掉action_home_to_punch) 恢复:NetworkModule(去掉PunchApi提供者) 考勤模块将按NFC打卡流程重新从需求开始设计开发。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../xiaoqu/watch/data/punch/PunchStatus.kt | 24 -- .../java/com/xiaoqu/watch/di/NetworkModule.kt | 7 - .../com/xiaoqu/watch/network/api/PunchApi.kt | 26 -- .../com/xiaoqu/watch/ui/home/HomeFragment.kt | 114 +------- .../xiaoqu/watch/ui/punch/PunchFragment.kt | 256 ------------------ app/src/main/res/layout/fragment_home.xml | 50 ++-- app/src/main/res/layout/fragment_punch.xml | 88 ------ app/src/main/res/navigation/nav_main.xml | 3 - 8 files changed, 20 insertions(+), 548 deletions(-) delete mode 100644 app/src/main/java/com/xiaoqu/watch/data/punch/PunchStatus.kt delete mode 100644 app/src/main/java/com/xiaoqu/watch/network/api/PunchApi.kt delete mode 100644 app/src/main/java/com/xiaoqu/watch/ui/punch/PunchFragment.kt delete mode 100644 app/src/main/res/layout/fragment_punch.xml diff --git a/app/src/main/java/com/xiaoqu/watch/data/punch/PunchStatus.kt b/app/src/main/java/com/xiaoqu/watch/data/punch/PunchStatus.kt deleted file mode 100644 index d007fad..0000000 --- a/app/src/main/java/com/xiaoqu/watch/data/punch/PunchStatus.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.xiaoqu.watch.data.punch - -import com.google.gson.annotations.SerializedName - -/** - * 考勤状态数据类 - * 对应 watchTask/myCurrentAttendance API 返回 - * 来源:discovery-map.md 考勤章节(已验证字段名) - */ -data class PunchStatus( - /** 上班打卡状态:0=未上班, 1=已上班 */ - @SerializedName("onPunchState") val onPunchState: Int = 0, - /** 下班打卡状态:1=已下班, 其他=未下班 */ - @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 - /** 是否已下班 */ - val isOffDuty: Boolean get() = offPunchState == 1 -} diff --git a/app/src/main/java/com/xiaoqu/watch/di/NetworkModule.kt b/app/src/main/java/com/xiaoqu/watch/di/NetworkModule.kt index bb37484..49e5471 100644 --- a/app/src/main/java/com/xiaoqu/watch/di/NetworkModule.kt +++ b/app/src/main/java/com/xiaoqu/watch/di/NetworkModule.kt @@ -6,7 +6,6 @@ import com.xiaoqu.watch.network.EnvConfig import com.xiaoqu.watch.network.SignatureInterceptor import com.xiaoqu.watch.network.UnbindInterceptor import com.xiaoqu.watch.network.api.CommonApi -import com.xiaoqu.watch.network.api.PunchApi import com.xiaoqu.watch.network.api.TaskApi import dagger.Module import dagger.Provides @@ -70,10 +69,4 @@ object NetworkModule { fun provideTaskApi(retrofit: Retrofit): TaskApi { return retrofit.create(TaskApi::class.java) } - - @Provides - @Singleton - fun providePunchApi(retrofit: Retrofit): PunchApi { - return retrofit.create(PunchApi::class.java) - } } diff --git a/app/src/main/java/com/xiaoqu/watch/network/api/PunchApi.kt b/app/src/main/java/com/xiaoqu/watch/network/api/PunchApi.kt deleted file mode 100644 index 56aecc6..0000000 --- a/app/src/main/java/com/xiaoqu/watch/network/api/PunchApi.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.xiaoqu.watch.network.api - -import com.xiaoqu.watch.data.punch.PunchStatus -import com.xiaoqu.watch.network.ApiResponse -import retrofit2.http.Body -import retrofit2.http.GET -import retrofit2.http.POST - -/** - * 考勤打卡 API 接口 - * 来源:v1.2.5 punchApis.js + 用户确认NFC考勤流程 - */ -interface PunchApi { - - /** 查询当前考勤状态 */ - @GET("watchTask/myCurrentAttendance") - suspend fun getAttendance(): ApiResponse - - /** NFC 上班/下班打卡(v1.2.5 新增) */ - @POST("watchTask/nfcOnAndOffPunch") - suspend fun nfcOnAndOffPunch(@Body params: HashMap): ApiResponse - - /** 撤销打卡 */ - @POST("watchTask/revokePunch") - suspend fun revokePunch(@Body params: HashMap): ApiResponse -} diff --git a/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt b/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt index a167e8f..2746f7f 100644 --- a/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/xiaoqu/watch/ui/home/HomeFragment.kt @@ -15,13 +15,9 @@ 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 @@ -43,9 +39,6 @@ class HomeFragment : BaseFragment() { @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 @@ -100,14 +93,8 @@ class HomeFragment : BaseFragment() { // 加载任务统计数据 fetchStatistics() - // 检查当前工作状态(考勤) - fetchWorkState() - // 监听 MQTT 事件 observeEvents() - - // 下拉手势 → 进入考勤页 - setupPullDownGesture() } // ===== 主页 ===== @@ -261,9 +248,9 @@ class HomeFragment : BaseFragment() { findNavController().navigate(R.id.action_home_to_bind) } 4 -> { - // 工作状态变更(MQTT type=4/5 推送) + // 工作状态变更 Timber.d("首页: 收到工作状态变更") - handleWorkStateChange(event.rawJson) + // TODO: 考勤模块重新开发时实现 } } } @@ -283,101 +270,4 @@ class HomeFragment : BaseFragment() { 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, "首页: 解析工作状态变更异常") - } - } - - /** - * 设置下拉手势 → 进入考勤打卡页 - * 触摸区域:上半屏(140dp),只拦截垂直下拉,水平滑动透传给 ViewPager2 - */ - @android.annotation.SuppressLint("ClickableViewAccessibility") - private fun setupPullDownGesture() { - var startY = 0f - var startX = 0f - - binding.pullDownArea.setOnTouchListener { _, event -> - when (event.action) { - android.view.MotionEvent.ACTION_DOWN -> { - startY = event.y - startX = event.x - true // 拦截 DOWN - } - android.view.MotionEvent.ACTION_MOVE -> { - val dy = event.y - startY - val dx = event.x - startX - // 如果水平滑动幅度 > 垂直 → 不拦截,透传给 ViewPager2 - if (kotlin.math.abs(dx) > kotlin.math.abs(dy) + 10) { - false - } else { - true - } - } - android.view.MotionEvent.ACTION_UP -> { - val dy = event.y - startY - val dx = event.x - startX - // 下拉(dy > 50)且垂直幅度 > 水平 - if (dy > 50 && kotlin.math.abs(dy) > kotlin.math.abs(dx)) { - navigateToPunch() - } - true - } - else -> false - } - } - } - - /** 跳转到考勤打卡页 */ - private fun navigateToPunch() { - val currentDest = findNavController().currentDestination?.id - if (currentDest != R.id.homeFragment) return - findNavController().navigate(R.id.action_home_to_punch) - } } diff --git a/app/src/main/java/com/xiaoqu/watch/ui/punch/PunchFragment.kt b/app/src/main/java/com/xiaoqu/watch/ui/punch/PunchFragment.kt deleted file mode 100644 index 0c5162a..0000000 --- a/app/src/main/java/com/xiaoqu/watch/ui/punch/PunchFragment.kt +++ /dev/null @@ -1,256 +0,0 @@ -package com.xiaoqu.watch.ui.punch - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.FrameLayout -import androidx.lifecycle.lifecycleScope -import androidx.navigation.fragment.findNavController -import com.xiaoqu.watch.R -import com.xiaoqu.watch.data.punch.PunchStatus -import com.xiaoqu.watch.databinding.FragmentPunchBinding -import com.xiaoqu.watch.device.nfc.NfcController -import com.xiaoqu.watch.device.screen.ScreenController -import com.xiaoqu.watch.device.sensor.VibrationController -import com.xiaoqu.watch.device.sensor.VibrationDefaults -import com.xiaoqu.watch.event.AppEvent -import com.xiaoqu.watch.event.EventBus -import com.xiaoqu.watch.network.ApiResult -import com.xiaoqu.watch.network.api.PunchApi -import com.xiaoqu.watch.network.safeApiCall -import com.xiaoqu.watch.ui.common.BaseFragment -import com.xiaoqu.watch.ui.widget.QuConfirmDialog -import com.xiaoqu.watch.ui.widget.QuTipDialog -import com.xiaoqu.watch.util.DateUtil -import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.delay -import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch -import timber.log.Timber -import javax.inject.Inject - -/** - * 考勤打卡(半屏下拉面板) - * - 点击空白收回 - * - NFC 扫描时按钮变状态,不弹窗 - * - 打卡有语音+振动反馈 - */ -@AndroidEntryPoint -class PunchFragment : BaseFragment() { - - @Inject lateinit var punchApi: PunchApi - @Inject lateinit var nfcController: NfcController - @Inject lateinit var screenController: ScreenController - @Inject lateinit var vibrationController: VibrationController - @Inject lateinit var eventBus: EventBus - - private var currentPunchType = 0 - private var isScanning = false - private lateinit var tipDialog: QuTipDialog - private lateinit var confirmDialog: QuConfirmDialog - - override fun createBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentPunchBinding { - return FragmentPunchBinding.inflate(inflater, container, false) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - val dialogContainer = requireActivity().findViewById(R.id.dialog_container) - tipDialog = QuTipDialog(dialogContainer) - confirmDialog = QuConfirmDialog(dialogContainer) - - // 点击空白收回 - binding.dismissArea.setOnClickListener { - if (!isScanning) findNavController().popBackStack() - } - - // 显示时间并每秒更新 - updateTime() - viewLifecycleOwner.lifecycleScope.launch { - while (isActive) { delay(1000); updateTime() } - } - - // 获取考勤状态 - fetchAttendance() - } - - override fun onDestroyView() { - super.onDestroyView() - stopNfc() - } - - // ===== 时间 ===== - - private fun updateTime() { - binding.tvTime.text = DateUtil.formatTimeShort() - val info = DateUtil.getDateInfo() - binding.tvDate.text = "${info.month}\u6708${info.day}\u65E5 ${info.week}" - } - - // ===== 考勤状态 ===== - - private fun fetchAttendance() { - viewLifecycleOwner.lifecycleScope.launch { - val result = safeApiCall { punchApi.getAttendance() } - when (result) { - is ApiResult.Success -> displayStatus(result.data ?: PunchStatus()) - else -> displayStatus(PunchStatus()) - } - } - } - - /** 按钮即状态 */ - private fun displayStatus(status: PunchStatus) { - binding.btnRevoke.visibility = View.GONE - binding.tvLowPower.visibility = View.GONE - - when { - !status.isOnDuty -> { - binding.btnPunch.text = "上班打卡" - binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.primary)) - binding.btnPunch.setOnClickListener { startNfcPunch(0) } - } - status.isOnDuty && status.isOffDuty -> { - binding.btnPunch.text = "下班打卡" - binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.primary)) - binding.btnPunch.setOnClickListener { startNfcPunch(1) } - binding.btnRevoke.visibility = View.VISIBLE - binding.btnRevoke.setOnClickListener { doRevoke() } - binding.tvLowPower.visibility = View.VISIBLE - } - status.isOnDuty && !status.isOffDuty -> { - binding.btnPunch.text = "下班打卡" - binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.primary)) - binding.btnPunch.setOnClickListener { startNfcPunch(1) } - } - } - } - - // ===== NFC 打卡 ===== - - private fun startNfcPunch(punchType: Int) { - if (isScanning) return - currentPunchType = punchType - isScanning = true - - // 按钮变为扫描状态(不弹窗) - binding.btnPunch.text = "NFC 扫描中..." - binding.btnPunch.setBackgroundColor(requireContext().getColor(R.color.warning)) - binding.btnPunch.setOnClickListener { stopNfc(); resetButton() } - - // NFC 开启语音+振动(planId=8) - VibrationDefaults.getPattern(8)?.let { vibrationController.executePattern(it) } - - // 开启 NFC 扫描(加日志排查) - Timber.d("考勤: 开启 NFC") - nfcController.open() - Timber.d("考勤: NFC isOpen=${nfcController.isOpen()}, 开始扫描") - nfcController.startScan { nfcId -> - Timber.d("考勤: NFC 读到卡号 $nfcId") - stopNfc() - // 不弹确认,直接打卡 - doPunch(nfcId) - } - - // 10秒超时 - viewLifecycleOwner.lifecycleScope.launch { - delay(10000) - if (isScanning) { - stopNfc() - resetButton() - VibrationDefaults.getPattern(7)?.let { vibrationController.executePattern(it) } - } - } - } - - private fun stopNfc() { - isScanning = false - nfcController.stopScan() - if (nfcController.isOpen()) nfcController.close() - } - - private fun resetButton() { - isScanning = false - fetchAttendance() - } - - private fun doPunch(nfcId: String) { - viewLifecycleOwner.lifecycleScope.launch { - val params = hashMapOf("nfcId" to nfcId, "punchType" to currentPunchType) - val result = safeApiCall { punchApi.nfcOnAndOffPunch(params) } - - when (result) { - is ApiResult.Success -> { - // 成功语音+振动(planId=4) - VibrationDefaults.getPattern(4)?.let { vibrationController.executePattern(it) } - tipDialog.show( - status = QuTipDialog.Status.SUCCESS, title = "打卡成功", - back = true, step = 0, countdown = 2 - ) - if (currentPunchType == 0) { - screenController.turnOn(); emitWorkState(true) - } else { - screenController.turnOff(); emitWorkState(false) - } - fetchAttendance() - } - is ApiResult.Error -> { - VibrationDefaults.getPattern(7)?.let { vibrationController.executePattern(it) } - tipDialog.show( - status = QuTipDialog.Status.ERROR, title = "打卡失败", - desc = result.message, back = true, step = 0, countdown = 3 - ) - resetButton() - } - is ApiResult.NetworkError -> { - tipDialog.show( - status = QuTipDialog.Status.ERROR, title = "网络异常", - back = true, step = 0, countdown = 3 - ) - resetButton() - } - } - } - } - - private fun doRevoke() { - confirmDialog.showText( - text = "确定撤销打卡?", - onConfirm = { - viewLifecycleOwner.lifecycleScope.launch { - val result = safeApiCall { punchApi.revokePunch(hashMapOf()) } - when (result) { - is ApiResult.Success -> { - VibrationDefaults.getPattern(4)?.let { vibrationController.executePattern(it) } - tipDialog.show( - status = QuTipDialog.Status.SUCCESS, title = "撤销成功", - back = true, step = 0, countdown = 2 - ) - screenController.turnOn(); emitWorkState(true); fetchAttendance() - } - is ApiResult.Error -> { - tipDialog.show( - status = QuTipDialog.Status.ERROR, title = "撤销失败", - desc = result.message, back = true, step = 0, countdown = 3 - ) - } - is ApiResult.NetworkError -> { - tipDialog.show( - status = QuTipDialog.Status.ERROR, title = "网络异常", - back = true, step = 0, countdown = 3 - ) - } - } - } - } - ) - } - - private fun emitWorkState(isWorking: Boolean) { - viewLifecycleOwner.lifecycleScope.launch { - eventBus.emit(AppEvent.WorkStateChanged(isWorking)) - } - } -} diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 00b2534..be7702a 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,40 +1,26 @@ - - + + android:background="@color/background" + android:orientation="vertical" + android:paddingStart="21dp" + android:paddingTop="27dp" + android:paddingEnd="21dp"> - - + + android:layout_height="24dp" + android:layout_marginBottom="3dp" /> - - - - - - - - - - + + android:layout_height="0dp" + android:layout_weight="1" /> - + diff --git a/app/src/main/res/layout/fragment_punch.xml b/app/src/main/res/layout/fragment_punch.xml deleted file mode 100644 index a234c0b..0000000 --- a/app/src/main/res/layout/fragment_punch.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 8c9a02a..8f8d0e4 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -28,9 +28,6 @@ - -