revert: 删除考勤打卡模块代码,准备重新开发
删除: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) <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<PunchStatus>
|
||||
|
||||
/** NFC 上班/下班打卡(v1.2.5 新增) */
|
||||
@POST("watchTask/nfcOnAndOffPunch")
|
||||
suspend fun nfcOnAndOffPunch(@Body params: HashMap<String, Any>): ApiResponse<Any>
|
||||
|
||||
/** 撤销打卡 */
|
||||
@POST("watchTask/revokePunch")
|
||||
suspend fun revokePunch(@Body params: HashMap<String, Any>): ApiResponse<Any>
|
||||
}
|
||||
@@ -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<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
|
||||
@@ -100,14 +93,8 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
// 加载任务统计数据
|
||||
fetchStatistics()
|
||||
|
||||
// 检查当前工作状态(考勤)
|
||||
fetchWorkState()
|
||||
|
||||
// 监听 MQTT 事件
|
||||
observeEvents()
|
||||
|
||||
// 下拉手势 → 进入考勤页
|
||||
setupPullDownGesture()
|
||||
}
|
||||
|
||||
// ===== 主页 =====
|
||||
@@ -261,9 +248,9 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
|
||||
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<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, "首页: 解析工作状态变更异常")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置下拉手势 → 进入考勤打卡页
|
||||
* 触摸区域:上半屏(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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<FragmentPunchBinding>() {
|
||||
|
||||
@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<FrameLayout>(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<String, Any>("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))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 首页容器:状态栏 + ViewPager2 + 下拉触摸层(上半屏) -->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background">
|
||||
|
||||
<!-- 底层:状态栏 + ViewPager2 -->
|
||||
<LinearLayout
|
||||
<!-- 首页容器:固定状态栏 + ViewPager2 左右滑动 -->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="21dp"
|
||||
android:paddingTop="27dp"
|
||||
@@ -28,13 +23,4 @@
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- 上层:下拉触摸区域(上半屏,透明,不拦截水平滑动) -->
|
||||
<View
|
||||
android:id="@+id/pullDownArea"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="140dp"
|
||||
android:layout_gravity="top" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- 考勤打卡(半屏下拉面板)
|
||||
上半:时间+按钮(黑色背景)
|
||||
下半:透明,点击收回 -->
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#00000000">
|
||||
|
||||
<!-- 点击空白收回 -->
|
||||
<View
|
||||
android:id="@+id/dismissArea"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<!-- 上半屏面板 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:background="@color/background"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="21dp"
|
||||
android:paddingTop="27dp"
|
||||
android:paddingEnd="21dp"
|
||||
android:paddingBottom="21dp">
|
||||
|
||||
<!-- 时间 -->
|
||||
<TextView
|
||||
android:id="@+id/tvTime"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="48sp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:layout_marginBottom="5dp" />
|
||||
|
||||
<!-- 日期 -->
|
||||
<TextView
|
||||
android:id="@+id/tvDate"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:textColor="@color/text_secondary"
|
||||
android:textSize="20sp"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- 主按钮 -->
|
||||
<TextView
|
||||
android:id="@+id/btnPunch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:textColor="@color/text_primary"
|
||||
android:textSize="26sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- 撤销按钮 -->
|
||||
<TextView
|
||||
android:id="@+id/btnRevoke"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:padding="14dp"
|
||||
android:background="@color/grey_button"
|
||||
android:textColor="@color/error"
|
||||
android:textSize="22sp"
|
||||
android:text="撤销打卡"
|
||||
android:layout_marginTop="8dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- 低耗电提示 -->
|
||||
<TextView
|
||||
android:id="@+id/tvLowPower"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:text="低耗电模式已开启"
|
||||
android:textColor="@color/warning"
|
||||
android:textSize="18sp"
|
||||
android:layout_marginTop="11dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</FrameLayout>
|
||||
@@ -28,9 +28,6 @@
|
||||
<!-- 首页 → 任务列表 -->
|
||||
<action android:id="@+id/action_home_to_taskList"
|
||||
app:destination="@id/taskListFragment" />
|
||||
<!-- 首页 → 考勤打卡(下拉入口) -->
|
||||
<action android:id="@+id/action_home_to_punch"
|
||||
app:destination="@id/punchFragment" />
|
||||
</fragment>
|
||||
|
||||
<!-- 设备绑定页 -->
|
||||
|
||||
Reference in New Issue
Block a user