[未上传任务]
This commit is contained in:
yangyakun
2024-08-26 19:29:30 +08:00
parent 7d541edb6b
commit 581a7c4d78
15 changed files with 319 additions and 49 deletions

View File

@@ -23,6 +23,7 @@ public class DateTimeUtil {
public static final String yy_MM_dd = "yy.MM.dd";
public static final String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
public static final String MM_dd_HH_mm_china = "yyyy年MM月dd日";
public static String formatCalendarToString(Calendar calendar, String format){
if (calendar == null) return "";

View File

@@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "1fb2dea0f72d7abf11cbb9928b9572c3",
"identityHash": "066a91b8d796cc1004c4e438b2c125f3",
"entities": [
{
"tableName": "contrail_data_table",
@@ -495,7 +495,7 @@
},
{
"tableName": "event_data_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `event_type` TEXT, `task_id` INTEGER, `business_time` INTEGER, `write_version` INTEGER, `site_id` INTEGER, `seq` INTEGER, `event_save_time` INTEGER NOT NULL, `update_status` INTEGER NOT NULL)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `event_type` TEXT, `lineId` INTEGER, `lineName` TEXT, `task_id` INTEGER, `task_start_time` INTEGER, `business_time` INTEGER, `write_version` INTEGER, `site_id` INTEGER, `seq` INTEGER, `event_save_time` INTEGER NOT NULL, `update_status` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
@@ -509,12 +509,30 @@
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lineId",
"columnName": "lineId",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "lineName",
"columnName": "lineName",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "taskId",
"columnName": "task_id",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "taskStartTime",
"columnName": "task_start_time",
"affinity": "INTEGER",
"notNull": false
},
{
"fieldPath": "businessTime",
"columnName": "business_time",
@@ -575,7 +593,7 @@
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1fb2dea0f72d7abf11cbb9928b9572c3')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '066a91b8d796cc1004c4e438b2c125f3')"
]
}
}

View File

@@ -0,0 +1,18 @@
package com.mogo.och.weaknet.bean
data class WaitUploadLine(var lineName:String ,var lineId:Long,var task:MutableList<WaitUploadTask>){
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as WaitUploadLine
return lineId == other.lineId
}
override fun hashCode(): Int {
return lineId.hashCode()
}
}
data class WaitUploadTask(val taskStartTime:Long,val taskId:Long)

View File

@@ -17,12 +17,32 @@ data class EventDataBean(
*/
@ColumnInfo(name = "event_type", typeAffinity = ColumnInfo.TEXT)
var eventType: String? = null,
/**
* 任务id
*/
@ColumnInfo(name = "lineId", typeAffinity = ColumnInfo.INTEGER)
var lineId: Long? = null,
/**
* 任务id
*/
@ColumnInfo(name = "lineName", typeAffinity = ColumnInfo.TEXT)
var lineName: String? = null,
/**
* 任务id
*/
@ColumnInfo(name = "task_id", typeAffinity = ColumnInfo.INTEGER)
var taskId: Long? = null,
/**
* 任务id
*/
@ColumnInfo(name = "task_start_time", typeAffinity = ColumnInfo.INTEGER)
var taskStartTime: Long? = null,
/**
* 业务发生的时间
*/

View File

@@ -6,9 +6,8 @@ import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.weaknet.database.bean.ContrailDataBean
import com.mogo.och.weaknet.database.bean.EventDataBean
import com.mogo.och.weaknet.database.bean.LineDataBean
import io.reactivex.Observable
@Dao
interface EventDataDao {
@@ -28,4 +27,7 @@ interface EventDataDao {
@Query("SELECT * FROM ${EventDataBean.evnetDataTable} WHERE update_status = ${EventDataBean.notUpdate} LIMIT 10 OFFSET 0")
fun queryEventByStatusWithPage():List<EventDataBean>?
@Query("SELECT * FROM ${EventDataBean.evnetDataTable} WHERE update_status = ${EventDataBean.updated} and event_save_time > :zeroTime GROUP by task_start_time")
fun queryWaitUploadInfo(zeroTime: Long = DateTimeUtil.getCurrentDateZero()): Observable<List<EventDataBean>?>
}

View File

@@ -5,6 +5,8 @@ import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.weaknet.database.MyDataBase
import com.mogo.och.weaknet.database.bean.EventDataBean
import com.mogo.och.weaknet.database.dao.EventDataDao
import io.reactivex.Observable
object EventRepository {
@@ -16,10 +18,13 @@ object EventRepository {
eventDataDao = MyDataBase.instance.eventDataDao
}
fun saveEventTaskStart(taskId: Long) {
fun saveEventTaskStart(taskId: Long, lineId: Long, taskStartTime: Long, name: String) {
val event = EventDataBean()
event.eventType = EventDataBean.TaskStart
event.lineId = lineId
event.taskId = taskId
event.lineName = name
event.taskStartTime = taskStartTime
event.businessTime = DateTimeUtil.getCurrentTimeStamp()
event.writeVersion = DateTimeUtil.getCurrentTimeStamp()
event.siteId = 0L
@@ -30,23 +35,19 @@ object EventRepository {
}
}
fun saveEventTaskArriveSite(taskId: Long,siteId:Long,seq:Int) {
fun saveEventTaskArriveSite(
taskId: Long,
lineId: Long,
siteId: Long,
seq: Int,
taskStartTime: Long?,
lineName: String
) {
val event = EventDataBean()
event.eventType = EventDataBean.TaskArriveSite
event.taskId = taskId
event.businessTime = DateTimeUtil.getCurrentTimeStamp()
event.writeVersion = DateTimeUtil.getCurrentTimeStamp()
event.siteId = siteId
event.seq = seq
DbThreadUtils.runInIoThread{
eventDataDao?.insert(event)
eventCallback?.notifySyn()
}
}
fun saveEventTaskLeaveSite(taskId: Long,siteId:Long,seq:Int) {
val event = EventDataBean()
event.eventType = EventDataBean.TaskLeaveSite
event.lineId = lineId
event.taskStartTime = taskStartTime
event.lineName = lineName
event.taskId = taskId
event.businessTime = DateTimeUtil.getCurrentTimeStamp()
event.writeVersion = DateTimeUtil.getCurrentTimeStamp()
@@ -58,10 +59,37 @@ object EventRepository {
}
}
fun saveEventTaskEnd(taskId: Long) {
fun saveEventTaskLeaveSite(
taskId: Long,
lineId: Long,
siteId: Long,
seq: Int,
taskStartTime: Long?,
lineName: String
) {
val event = EventDataBean()
event.eventType = EventDataBean.TaskLeaveSite
event.lineId = lineId
event.taskId = taskId
event.taskStartTime = taskStartTime
event.lineName = lineName
event.businessTime = DateTimeUtil.getCurrentTimeStamp()
event.writeVersion = DateTimeUtil.getCurrentTimeStamp()
event.siteId = siteId
event.seq = seq
DbThreadUtils.runInIoThread {
eventDataDao?.insert(event)
eventCallback?.notifySyn()
}
}
fun saveEventTaskEnd(taskId: Long, lineId: Long, taskStartTime: Long?, lineName: String) {
val event = EventDataBean()
event.eventType = EventDataBean.TaskEnd
event.lineId = lineId
event.taskId = taskId
event.lineName = lineName
event.taskStartTime = taskStartTime
event.businessTime = DateTimeUtil.getCurrentTimeStamp()
event.writeVersion = DateTimeUtil.getCurrentTimeStamp()
event.siteId = 0L
@@ -80,12 +108,16 @@ object EventRepository {
eventDataDao?.insert(*waitUpdateEvent.toTypedArray())
}
fun deleteObsoleteData(){
fun deleteObsoleteData() {
eventDataDao?.deleteObsoleteData()?.let {
OchChainLogManager.writeChainLogDb("删除临时数据","Event删除数量:${it}")
OchChainLogManager.writeChainLogDb("删除临时数据", "Event删除数量:${it}")
}
}
fun queryWaitUploadData(): Observable<List<EventDataBean>?>? {
return eventDataDao?.queryWaitUploadInfo()
}
interface EventCallback {
fun notifySyn()
}

View File

@@ -16,7 +16,6 @@ import com.mogo.eagle.core.utilcode.util.ToastUtils
import com.mogo.och.common.module.manager.autopilot.line.LineManager
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.manager.loop.LoopInfo
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.common.module.utils.ResourcesUtils
@@ -243,7 +242,7 @@ object BusLineModel {
override fun startSuccess() {
SharedPrefsMgr.getInstance()
.putLong(BusSwitchLineActivity.LASTCOMMITLINEID, line.lineId)
EventRepository.saveEventTaskStart(task.id)
EventRepository.saveEventTaskStart(task.id,line.lineId,task.taskStartTime,line.name)
if (mBusLinesCallback != null) {
mBusLinesCallback!!.onChangeLineIdSuccess()
}
@@ -330,14 +329,23 @@ object BusLineModel {
startStation.drivingStatus = TaskSiteDataBean.drivingStatusCurrent
startStation.isLeaving = true
if (currentTask != null && currentTask!!.taskId != null) {
currentTask?.taskId?.let { taskId ->
TaskSiteRepository.updateLeave(taskId, startStation.siteId.toLong(), true)
// 设置滑动出发任务
EventRepository.saveEventTaskLeaveSite(
taskId,
startStation.siteId.toLong(),
startStation.seq
)
currentTask?.let { task ->
if (task.taskId!=null&&task.lineId!=null) {
TaskSiteRepository.updateLeave(task.taskId!!, startStation.siteId.toLong(), true)
// 设置滑动出发任务
LineManager.lineInfos?.lineName?.let { lineName->
EventRepository.saveEventTaskLeaveSite(
task.taskId!!,
task.lineId!!,
startStation.siteId.toLong(),
startStation.seq,
task.taskStartTime,
lineName
)
}
}
}
} else {
OchChainLogManager.writeChainLog(
@@ -357,10 +365,14 @@ object BusLineModel {
it.drivingStatus = TaskSiteDataBean.drivingStatusPassed
it.isLeaving = false
if(currentTask!=null&& currentTask!!.taskId!=null){
currentTask?.taskId?.let { taskId->
TaskSiteRepository.updateDrivingStatusAndLeave(taskId,it.siteId.toLong(),TaskSiteDataBean.drivingStatusPassed,false)
// 设置到站任务
EventRepository.saveEventTaskArriveSite(taskId,it.siteId.toLong(),it.seq)
currentTask?.let { task->
if (task.taskId!=null&&task.lineId!=null) {
TaskSiteRepository.updateDrivingStatusAndLeave(task.taskId!!,it.siteId.toLong(),TaskSiteDataBean.drivingStatusPassed,false)
// 设置到站任务
LineManager.lineInfos?.let {lineInfo ->
EventRepository.saveEventTaskArriveSite(task.taskId!!,task.lineId!!,it.siteId.toLong(),it.seq,task.taskStartTime,lineInfo.lineName)
}
}
}
}else{
OchChainLogManager.writeChainLog("到站_数据更新_error","task:${currentTask}__taskId:${currentTask?.taskId}")
@@ -405,9 +417,14 @@ object BusLineModel {
fun endTask() {
CallerOrderListenerManager.invokeOrderLineUpdate("")
currentTask?.taskId?.let {
TaskRepository.endTask(it)
EventRepository.saveEventTaskEnd(it)
currentTask?.let {task->
if (task.taskId!=null&&task.lineId!=null) {
TaskRepository.endTask(task.taskId!!)
LineManager.lineInfos?.lineName?.let {lineName->
EventRepository.saveEventTaskEnd(task.taskId!!,task.lineId!!,task.taskStartTime,lineName)
}
}
}
currentTask = null

View File

@@ -4,35 +4,52 @@ import com.mogo.commons.AbsMogoApplication
import com.mogo.eagle.core.data.BaseData
import com.mogo.eagle.core.utilcode.util.ThreadUtils
import com.mogo.och.common.module.manager.logchainanalytic.OchChainLogManager
import com.mogo.och.common.module.manager.loop.BizLoopManager
import com.mogo.och.common.module.network.OchCommonServiceCallback
import com.mogo.och.weaknet.bean.ShuttleEventRequest
import com.mogo.och.weaknet.bean.WaitUploadLine
import com.mogo.och.weaknet.bean.WaitUploadTask
import com.mogo.och.weaknet.database.bean.EventDataBean
import com.mogo.och.weaknet.database.repository.EventRepository
import com.mogo.och.weaknet.net.OrderServiceManager
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.atomic.AtomicBoolean
object EventModel : EventRepository.EventCallback {
private val isUpdating = AtomicBoolean(false)
fun load(){
EventRepository.eventCallback = this
BizLoopManager.postDelayed(loopUpdateInfo,2*60*1000)
}
fun release(){
EventRepository.eventCallback = null
}
private val loopUpdateInfo = object :Runnable{
override fun run() {
updateEvent()
}
}
override fun notifySyn() {
BizLoopManager.removeCallback(loopUpdateInfo)
updateEvent()
}
private fun updateEvent(){
isUpdating.set(true)
ThreadUtils.getSinglePool().submit {
val waitUpdateEvent = EventRepository.queryWaitUpdateEvent()
if(waitUpdateEvent.isNullOrEmpty()){
OchChainLogManager.writeChainLogDb("上报event","没有数据需要上报${Thread.currentThread().name}")
isUpdating.set(false)
return@submit
}
OchChainLogManager.writeChainLogDb("上报event","开始上报:${Thread.currentThread().name}")
@@ -44,15 +61,20 @@ object EventModel : EventRepository.EventCallback {
}
OchChainLogManager.writeChainLogDb("上报event成功","$transformDb2Net ${Thread.currentThread().name}")
EventRepository.saveUpdateSuccess(waitUpdateEvent)
isUpdating.set(false)
BizLoopManager.postDelayed(loopUpdateInfo,2*60*1000)
}
override fun onFail(code: Int, msg: String?) {
isUpdating.set(false)
OchChainLogManager.writeChainLogDb("上报event失败","$transformDb2Net ${Thread.currentThread().name}")
BizLoopManager.postDelayed(loopUpdateInfo,2*60*1000)
}
override fun onError() {
super.onError()
isUpdating.set(false)
OchChainLogManager.writeChainLogDb("上报event失败","$transformDb2Net ${Thread.currentThread().name}")
BizLoopManager.postDelayed(loopUpdateInfo,2*60*1000)
}
})
@@ -61,6 +83,33 @@ object EventModel : EventRepository.EventCallback {
}
fun haveDataWaitSyn(): Boolean {
TODO("Not yet implemented")
EventRepository.queryWaitUpdateEvent()?.let {
return it.isNotEmpty()
}
return false
}
fun queryWaitUploadInfo(): Observable<MutableList<WaitUploadLine>>? {
return EventRepository.queryWaitUploadData()
?.flatMap { waitUploadList->
val result = mutableListOf<WaitUploadLine>()
waitUploadList.forEach { wait->
if(wait.lineId!=null&&wait.lineName!=null&&wait.taskId!=null&&wait.taskStartTime!=null) {
val tempTask = WaitUploadTask(wait.taskStartTime!!,wait.taskId!!)
val tempLine = WaitUploadLine(wait.lineName!!, wait.lineId!!, mutableListOf(tempTask))
if(result.contains(tempLine)){
result.forEach{
if(it.lineId == tempLine.lineId){
it.task.add(tempTask)
}
}
}else{
result.add(tempLine)
}
}
}
Observable.just(result)
}?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
}
}

View File

@@ -234,6 +234,10 @@ object OrderModel {
*/
private fun updateBusTaskStatus() {
var arrivingOrArrivedStationIndex = 0 //已经到站或者即将到站的索引呢
if(BusLineModel.stationList.isNullOrEmpty()){
OchChainLogManager.writeChainLog("更新UI出错","${BusLineModel.currentTask}")
return
}
BusLineModel.stationList?.let {
for (i in it.indices) {
val station = it[i]
@@ -709,9 +713,9 @@ object OrderModel {
// 登出
@JvmStatic
fun logout() {
// TODO: 检测是否有本地任务没有同步到服务器端
if(EventModel.haveDataWaitSyn()){
ToastUtils.showShort(ResourcesUtils.getString(R.string.shuttle_logout_error))
return
}
LoginStatusManager.loginOut()
}

View File

@@ -6,7 +6,11 @@ import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.findViewTreeViewModelStoreOwner
import com.mogo.och.common.module.utils.DateTimeUtil
import com.mogo.och.shuttle.weaknet.R
import kotlinx.android.synthetic.main.shuttle_wadk_task_running.view.actvCurrentDate
import kotlinx.android.synthetic.main.shuttle_wadk_task_running.view.clLayout
import kotlinx.android.synthetic.main.shuttle_wadk_task_running.view.ivTaskRunningClose
@@ -20,13 +24,14 @@ class RunningTaskManagerView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ConstraintLayout(context, attrs, defStyleAttr) {
) : ConstraintLayout(context, attrs, defStyleAttr), RunningTastViewModel.RunningTaskViewCallback {
companion object {
const val TAG = "BadCaseManagerView"
}
private var clickListener:ClickListener?=null
private var viewModel:RunningTastViewModel?=null
init {
LayoutInflater.from(context).inflate(R.layout.shuttle_wadk_task_running, this, true)
@@ -55,6 +60,19 @@ class RunningTaskManagerView @JvmOverloads constructor(
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewModel = findViewTreeViewModelStoreOwner()?.let {
ViewModelProvider(it).get(RunningTastViewModel::class.java)
}
viewModel?.setDistanceCallback(this)
}
override fun onVisibilityAggregated(isVisible: Boolean) {
super.onVisibilityAggregated(isVisible)
if(isVisible){
viewModel?.queryNewData()
actvCurrentDate.setText(DateTimeUtil.formatLongToString(System.currentTimeMillis(),DateTimeUtil.MM_dd_HH_mm_china))
}
}
override fun onDetachedFromWindow() {

View File

@@ -0,0 +1,56 @@
package com.mogo.och.weaknet.ui.taskrunning
import androidx.lifecycle.ViewModel
import com.mogo.eagle.core.utilcode.mogo.logger.CallerLogger
import com.mogo.och.weaknet.bean.WaitUploadLine
import com.mogo.och.weaknet.model.EventModel
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
/**
* @author XuXinChao
* @description BadCase录包管理页面
* @since: 2022/12/15
*/
class RunningTastViewModel : ViewModel() {
private val TAG = RunningTastViewModel::class.java.simpleName
private var viewCallback:RunningTaskViewCallback?=null
fun setDistanceCallback(viewCallback:RunningTaskViewCallback){
this.viewCallback = viewCallback
}
override fun onCleared() {
}
fun queryNewData() {
EventModel.queryWaitUploadInfo()
?.subscribe(object : Observer<MutableList<WaitUploadLine>> {
override fun onSubscribe(d: Disposable) {
CallerLogger.d(TAG, "onSubscribe")
}
override fun onError(e: Throwable) {
CallerLogger.d(TAG, "onError${e.printStackTrace()}")
}
override fun onComplete() {
CallerLogger.d(TAG, "onComplete")
}
override fun onNext(data: MutableList<WaitUploadLine>) {
}
})
}
interface RunningTaskViewCallback{
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -23,16 +23,25 @@
android:layout_width="14dp"
android:layout_height="50dp"
android:layout_marginStart="80dp"
android:layout_marginTop="92dp"
android:layout_marginTop="95dp"
android:background="#2966EC"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatImageView
app:layout_constraintTop_toTopOf="@+id/tvManagerTitle"
app:layout_constraintBottom_toBottomOf="@+id/tvManagerTitle"
app:layout_constraintStart_toEndOf="@+id/tvManagerTitle"
android:src="@drawable/shuttle_task_wait_upload"
android:layout_marginStart="@dimen/dp_29"
android:layout_width="@dimen/dp_97"
android:layout_height="@dimen/dp_39"/>
<TextView
android:id="@+id/tvManagerTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="任务管理"
android:text="本地任务执行信息"
android:textColor="#FFFFFFFF"
android:textSize="42dp"
app:layout_constraintTop_toTopOf="@id/viewManagerTitleLine"
@@ -41,6 +50,28 @@
android:layout_marginStart="50dp"
/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actvCurrentDate"
app:layout_constraintTop_toBottomOf="@+id/ivTaskRunningClose"
android:layout_marginTop="@dimen/dp_53"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:background="@color/shuttle_color_80203076"
android:text="时间"
android:textColor="@color/white"
android:textSize="@dimen/dp_32"
android:gravity="center"
android:layout_width="0dp"
android:layout_height="61dp"/>
<androidx.recyclerview.widget.RecyclerView
app:layout_constraintTop_toBottomOf="@+id/tvManagerTitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="0dp"
android:layout_height="0dp"/>
<androidx.constraintlayout.widget.ConstraintLayout
app:layout_constraintTop_toBottomOf="@+id/tvManagerTitle"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -13,6 +13,8 @@
<color name="bus_leaving_end_dash_color">#427d8e</color>
<color name="bus_arrived_dash_color">#3FC281</color>
<color name="shuttle_color_80203076">#80203076</color>
<color name="bus_autopilot_text_color_normal">#FFFFFF</color>
<color name="bus_autopilot_text_color_disable">#99FFFFFF</color>
<color name="bus_autopilot_text_color_checked">#FF52BBFF</color>

View File

@@ -39,6 +39,8 @@
<string name="bus_dialog_confirm">确认</string>
<string name="bus_dialog_cancel">取消</string>
<string name="shuttle_logout_error">请在网络良好的区域完成任务信息同步后退出</string>
<string name="bus_no_task_tip">暂无任务</string>
<string name="shuttle_write_off_count">本站核销成功:%1$d人</string>
<string name="shuttle_write_off_count_default">本站核销成功0人</string>