18034727885
2026-06-21 f32d25d2a605df16abe0e53a1b43b74649bda668
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package com.xw.yunwei.ui.user.mine.scheduling
 
import android.content.res.ColorStateList
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.content.ContextCompat
import androidx.viewpager2.widget.ViewPager2
import com.amap.api.maps.model.LatLng
import com.xw.common.R
import com.xw.common.TimeDialog
import com.xw.common.TimeDialog.Companion.getTime
import com.xw.common.utils.BindUtils.getResColor
import com.xw.common.utils.GpsHelper.Companion.navigate
import com.xw.common.utils.ToastUtilCommon
import com.xw.yunwei.BR
import com.xw.yunwei.BaseBusinessActivity
import com.xw.yunwei.databinding.ActivitySchedulingBinding
import com.xw.yunwei.ui.user.mine.scheduling.adapter.WeekPagerAdapter
import java.time.DayOfWeek
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.time.temporal.TemporalAdjusters
import java.util.Calendar
import java.util.Locale
 
/**
 * 排班考勤
 */
class SchedulingActivity : BaseBusinessActivity<ActivitySchedulingBinding, SchedulingVM>() {
    override fun getBindingVariable() = BR.viewModel
 
    val dialogTime: TimeDialog by lazy { TimeDialog(this) }
 
    val adapter by lazy {
        WeekPagerAdapter(LocalDate.of(2020, 1, 5), LocalDate.of(2050, 12, 31))
    }
 
    override fun init() {
        super.init()
        val time = getTime(System.currentTimeMillis())
        viewModel.today = time
        viewModel.selectTime.value = time
 
        val bgColorStateList = ColorStateList(
            arrayOf(
                intArrayOf(-android.R.attr.state_enabled),
                intArrayOf()
            ),
            intArrayOf(
                ContextCompat.getColor(this, R.color.blue_3),
                ContextCompat.getColor(this, R.color.blue_5)
            )
        )
 
        binding.clockIn.apply {
            backgroundTintList = bgColorStateList
            setTextColor(ContextCompat.getColor(this@SchedulingActivity, android.R.color.white))
        }
 
        binding.clockOut.apply {
            backgroundTintList = bgColorStateList
            setTextColor(ContextCompat.getColor(this@SchedulingActivity, android.R.color.white))
        }
        binding.viewPager.adapter = adapter
        binding.viewPager.offscreenPageLimit = 1
        scrollToDate(time)
        binding.viewPager.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
            override fun onPageScrollStateChanged(state: Int) {
                super.onPageScrollStateChanged(state)
                if (state == ViewPager2.SCROLL_STATE_IDLE) {
                    val item = adapter.getItem(binding.viewPager.currentItem)
                    viewModel.yearMonth.value = "${item.year}年${item.monthValue}月"
                }
            }
        })
    }
 
    //滚动到指定日期
    private fun scrollToDate(dateString: String) {
        val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")
        val localDate = LocalDate.parse(dateString, formatter)
        val localSundayDate = localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY))
        val between = ChronoUnit.WEEKS.between(adapter.startDate, localSundayDate)
        if (between < 0) {
            return
        }
        binding.viewPager.setCurrentItem(between.toInt(), false)
        adapter.selectDate = localDate
        viewModel.yearMonth.value = "${localDate.year}年${localDate.monthValue}月"
    }
 
    //格式化日期
    private fun formateDate(localDate: LocalDate): String {
        return "${localDate.year}-${
            String.format(Locale.getDefault(), "%02d", localDate.monthValue)
        }-${
            String.format(Locale.getDefault(), "%02d", localDate.dayOfMonth)
        }"
    }
 
    override fun setListener() {
        super.setListener()
        binding.dateSelect.setOnClickListener {
            val showTime = getTime(viewModel.selectTime.value)
            val minTime = getTime(formateDate(adapter.startDate))
            val maxTime = getTime(formateDate(adapter.endDate))
            dialogTime.show("选择日期", showTime, minTime, maxTime) {
                val time = getTime(it)
                scrollToDate(time)
                viewModel.selectTime.value = time
            }
        }
        binding.nav.setOnClickListener {
            viewModel.clockModel.value?.let {
                if ((it.xpCheckLocation?.locationLat
                        ?: 0.0) != 0.0 && (it.xpCheckLocation?.locationLon ?: 0.0) != 0.0
                ) {
                    navigate(
                        end = LatLng(
                            it.xpCheckLocation?.locationLat!!,
                            it.xpCheckLocation.locationLon!!
                        ),
                        context = this
                    )
                } else {
                    ToastUtilCommon.showError("数据异常")
                }
            }
        }
        adapter.setOnDateItemClickListener {
            viewModel.selectTime.value = formateDate(it)
            viewModel.yearMonth.value = "${it.year}年${it.monthValue}月"
        }
    }
 
    override fun onResume() {
        super.onResume()
        if (viewModel.today.isNotEmpty() && viewModel.today == viewModel.selectTime.value) {
            viewModel.querySchedule(viewModel.today, false)
        }
    }
 
    override fun setObservable() {
        super.setObservable()
        viewModel.selectTime.observe(this) {
            viewModel.querySchedule(it)
        }
        val setStatus: (AppCompatTextView, Int, Int, String) -> Unit = { tv, color, bg, text ->
            tv.setTextColor(color)
            tv.setBackgroundResource(bg)
            tv.text = text
        }
        viewModel.clockModel.observe(this) {
            it?.let {
                val now = Calendar.getInstance()
                val isToday =
                    viewModel.selectTime.value == null || viewModel.selectTime.value == getTime(now.timeInMillis)
                // 状态提示控制
                setStatus(
                    binding.clockIntStatus,
                    getResColor(if (it.xpClockIn?.hadLostWorkCheckedIn() == true) R.color.red_5 else if (it.clockIn == true) R.color.gray_7 else if (!isToday) R.color.gray_8 else R.color.orange_5),
                    if (it.xpClockIn?.hadLostWorkCheckedIn() == true) R.color.red_1 else if (it.clockIn == true) R.color.gray_3 else if (!isToday) R.color.gray_3 else R.color.orange_1,
                    if (it.xpClockIn?.hadLostWorkCheckedIn() == true) "缺卡" else if (it.clockIn == true) "已打卡" else if (!isToday) "不在打卡时间范围内" else "未打卡"
                )
                setStatus(
                    binding.clockOutStatus,
                    getResColor(if (it.xpClockIn?.hadLostOffWorkCheckedIn() == true) R.color.red_5 else if (it.clockOut == true) R.color.gray_7 else if (!isToday) R.color.gray_8 else R.color.orange_5),
                    if (it.xpClockIn?.hadLostOffWorkCheckedIn() == true) R.color.red_1 else if (it.clockOut == true) R.color.gray_3 else if (!isToday) R.color.gray_3 else R.color.orange_1,
                    if (it.xpClockIn?.hadLostOffWorkCheckedIn() == true) "缺卡" else if (it.clockOut == true) "已打卡" else if (!isToday) "不在打卡时间范围内" else "未打卡"
                )
                // 未上班打卡或缺卡 可上班打卡
                binding.clockIn.isEnabled =
                    it.clockIn != true || it.xpClockIn?.hadLostWorkCheckedIn() == true
 
                // 未下班打卡或缺卡 可下班打卡
                binding.clockOut.isEnabled =
                    it.clockOut != true || it.xpClockIn?.hadLostOffWorkCheckedIn() == true
            }
        }
    }
}