diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index bf4473c..43669c2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -115,6 +115,12 @@
android:configChanges="orientation|keyboardHidden"
android:exported="false"
android:screenOrientation="userLandscape" />
+
+
{
+ ARouter.getInstance()
+ .build(ARouterConstants.ACTIVITY_URL_INT_EXP_LOAD)
+ .navigation()
+ }
// 出港运抵
Constant.AuthName.GjcIntExpArrive -> {
ARouter.getInstance().build(ARouterConstants.ACTIVITY_URL_INT_EXP_ARRIVE)
@@ -689,6 +695,14 @@ class HomeFragment : Fragment() {
)
)
+ list.add(
+ RightMenu(
+ Constant.AuthName.GjcIntExpLoad,
+ com.lukouguoji.module_base.R.drawable.img_gjc_banxiangzuzhuang,
+ "出港装载"
+ )
+ )
+
list.add(
RightMenu(
Constant.AuthName.GjcIntExpArrive,
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInPage.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInPage.kt
new file mode 100644
index 0000000..b00e365
--- /dev/null
+++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcCheckInPage.kt
@@ -0,0 +1,14 @@
+package com.lukouguoji.module_base.bean
+
+/**
+ * 国际出港-分页查询请求参数
+ * 用于出港装载、检入记录等列表查询
+ */
+data class GjcCheckInPage(
+ var fdate: String? = null, // 航班日期
+ var fno: String? = null, // 航班号
+ var no: String? = null, // 运单号
+ var hno: String? = null, // 分单号
+ var pageNum: Int = 1, // 页码
+ var pageSize: Int = 10 // 每页条数
+)
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcDeclareParam.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcDeclareParam.kt
new file mode 100644
index 0000000..4f54a89
--- /dev/null
+++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcDeclareParam.kt
@@ -0,0 +1,8 @@
+package com.lukouguoji.module_base.bean
+
+/**
+ * 国际出港-装载申报/状态重置 请求参数
+ */
+data class GjcDeclareParam(
+ var loadList: List? = null // 装载记录列表
+)
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcExportLoad.kt b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcExportLoad.kt
new file mode 100644
index 0000000..6f61894
--- /dev/null
+++ b/module_base/src/main/java/com/lukouguoji/module_base/bean/GjcExportLoad.kt
@@ -0,0 +1,63 @@
+package com.lukouguoji.module_base.bean
+
+import androidx.databinding.ObservableBoolean
+
+/**
+ * 国际出港-出港装载Bean
+ * 对应API: IntExpLoad/pageQuery
+ */
+class GjcExportLoad {
+ var activeId: String = "" // 运单活跃号
+ var by1: String = "" // 第一承运人
+ var dep: String = "" // 始发港
+ var fdate: String = "" // 申报航班日期
+ var fid: String = "" // 航班主键id
+ var fno: String = "" // 申报航班号
+ var goods: String = "" // 品名
+ var lastLoadMsgId: String = "" // 上一次装载申报编号
+ var lastLoadStatus: String = "" // 上一次装载状态
+ var loadMsgId: String = "" // 报文申报编号
+ var loadStatus: String = "" // 装载申报状态("01"等状态码)
+ var loaddCount: Int = 0 // 装载删除计次
+ var loaddRate: Double = 0.0 // 装载删除费率
+ var loadsCount: Int = 0 // 装载申报计次
+ var loadsRate: Double = 0.0 // 装载申报费率
+ var no: String = "" // 主运单号
+ var packageType: String = "" // 包装类型代码
+ var pc: Int = 0 // 件数
+ var prefix: String = "" // 主运单前缀
+ var response: String = "" // 海关业务回执
+ var spCode: String = "" // 特码
+ var splitFlag: String = "" // 分批标志
+ var sysId: String = "" // 系统ID
+ var tallyStatus: String = "" // 理货状态
+ var weight: Double = 0.0 // 重量
+
+ // ========== UI扩展字段 ==========
+ val checked: ObservableBoolean = ObservableBoolean(false) // 选中状态
+
+ // 兼容现有API的isSelected属性
+ var isSelected: Boolean
+ get() = checked.get()
+ set(value) = checked.set(value)
+
+ /**
+ * 获取格式化的运单号(prefix + no)
+ */
+ fun getFullWaybillNo(): String {
+ return if (prefix.isNotEmpty()) "$prefix-$no" else no
+ }
+
+ /**
+ * 获取装载状态显示文字
+ */
+ fun getLoadStatusText(): String {
+ return when (loadStatus) {
+ "01" -> "已申报"
+ "02" -> "申报中"
+ "03" -> "申报失败"
+ "04" -> "已删除"
+ else -> loadStatus
+ }
+ }
+}
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt
index 5284347..938ee22 100644
--- a/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt
+++ b/module_base/src/main/java/com/lukouguoji/module_base/common/Constant.kt
@@ -247,6 +247,7 @@ interface Constant {
const val GjcIntExpAssembleActivity = "AppIntExpAssemble" //出港组装
const val GjcAssembleAllocateActivity = "AppIntExpAssembleAllocate" //组装分配
const val GjcIntExpOutHandover = "AppIntExpOutHandover" //出库交接
+ const val GjcIntExpLoad = "AppIntExpLoad" //出港装载
const val GjcIntExpArrive = "AppIntExpArrive" //出港运抵
/**
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt
index 2217184..20a680c 100644
--- a/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt
+++ b/module_base/src/main/java/com/lukouguoji/module_base/http/net/Api.kt
@@ -25,7 +25,10 @@ import com.lukouguoji.module_base.bean.GjcBoxAddInsertBean
import com.lukouguoji.module_base.bean.GjcBoxAssembleBean
import com.lukouguoji.module_base.bean.GjcBoxDetailsBean
import com.lukouguoji.module_base.bean.GjcBoxWeighingStatisticsBean
+import com.lukouguoji.module_base.bean.GjcCheckInPage
import com.lukouguoji.module_base.bean.GjcCheckInRecord
+import com.lukouguoji.module_base.bean.GjcDeclareParam
+import com.lukouguoji.module_base.bean.GjcExportLoad
import com.lukouguoji.module_base.bean.GjcGoodsAddBean
import com.lukouguoji.module_base.bean.GjcGoodsBean
import com.lukouguoji.module_base.bean.GjcGoodsDetailsBean
@@ -608,6 +611,34 @@ interface Api {
@POST("IntExpOutHandover/handover")
suspend fun completeHandover(@Body data: RequestBody): BaseResultBean
+ /**
+ * 国际出港-出港装载 分页查询
+ * 接口路径: /IntExpLoad/pageQuery
+ */
+ @POST("IntExpLoad/pageQuery")
+ suspend fun getIntExpLoadList(@Body data: RequestBody): BaseListBean
+
+ /**
+ * 国际出港-出港装载 分页合计
+ * 接口路径: /IntExpLoad/pageQueryTotal
+ */
+ @POST("IntExpLoad/pageQueryTotal")
+ suspend fun getIntExpLoadTotal(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际出港-出港装载 状态重置
+ * 接口路径: /IntExpLoad/resetDeclare
+ */
+ @POST("IntExpLoad/resetDeclare")
+ suspend fun resetDeclare(@Body data: RequestBody): BaseResultBean
+
+ /**
+ * 国际出港-出港装载 装载申报
+ * 接口路径: /IntExpLoad/declare
+ */
+ @POST("IntExpLoad/declare")
+ suspend fun declareLoad(@Body data: RequestBody): BaseResultBean
+
/**
* 国际出港运抵-分页列表
* 接口路径: /IntExpArrive/pageQuery
diff --git a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt
index 4bb422b..cbf9752 100644
--- a/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt
+++ b/module_base/src/main/java/com/lukouguoji/module_base/router/ARouterConstants.kt
@@ -143,6 +143,7 @@ object ARouterConstants {
const val ACTIVITY_URL_INT_EXP_MOVE = "/gjc/IntExpMoveActivity" //国际出港 出港移库
const val ACTIVITY_URL_GJC_ASSEMBLE_ALLOCATE = "/gjc/GjcAssembleAllocateActivity" //国际出港 组装分配
const val ACTIVITY_URL_INT_EXP_OUT_HANDOVER = "/gjc/IntExpOutHandoverActivity" //国际出港 出库交接
+ const val ACTIVITY_URL_INT_EXP_LOAD = "/gjc/IntExpLoadActivity" //国际出港 出港装载
const val ACTIVITY_URL_INT_EXP_ARRIVE = "/gjc/IntExpArriveActivity" //国际出港 出港运抵
///////////////// 国际进港模块
diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpLoadActivity.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpLoadActivity.kt
new file mode 100644
index 0000000..1780fe2
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/activity/IntExpLoadActivity.kt
@@ -0,0 +1,70 @@
+package com.lukouguoji.gjc.activity
+
+import android.app.Activity
+import android.content.Intent
+import android.os.Bundle
+import com.alibaba.android.arouter.facade.annotation.Route
+import com.lukouguoji.gjc.R
+import com.lukouguoji.gjc.databinding.ActivityIntExpLoadBinding
+import com.lukouguoji.gjc.viewModel.IntExpLoadViewModel
+import com.lukouguoji.module_base.base.BaseBindingActivity
+import com.lukouguoji.module_base.common.Constant
+import com.lukouguoji.module_base.common.ConstantEvent
+import com.lukouguoji.module_base.impl.FlowBus
+import com.lukouguoji.module_base.impl.observe
+import com.lukouguoji.module_base.ktx.addOnItemClickListener
+import com.lukouguoji.module_base.router.ARouterConstants
+
+/**
+ * 国际出港-出港装载页面
+ */
+@Route(path = ARouterConstants.ACTIVITY_URL_INT_EXP_LOAD)
+class IntExpLoadActivity :
+ BaseBindingActivity() {
+
+ override fun layoutId() = R.layout.activity_int_exp_load
+ override fun viewModelClass() = IntExpLoadViewModel::class.java
+
+ override fun initOnCreate(savedInstanceState: Bundle?) {
+ setBackArrow("出港装载")
+ binding.viewModel = viewModel
+
+ // 观察全选状态,更新图标透明度
+ viewModel.isAllChecked.observe(this) { isAllChecked ->
+ binding.checkIcon.alpha = if (isAllChecked) 1.0f else 0.5f
+ }
+
+ // 绑定分页
+ viewModel.pageModel.bindSmartRefreshLayout(binding.srl, binding.rv, viewModel, this)
+
+ // 设置item点击监听
+ binding.rv.addOnItemClickListener(viewModel)
+
+ // 监听刷新事件
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).observe(this) {
+ viewModel.refresh()
+ }
+
+ // 初始加载数据
+ viewModel.refresh()
+ }
+
+ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+ super.onActivityResult(requestCode, resultCode, data)
+ if (resultCode == Activity.RESULT_OK) {
+ val codedContent = data?.getStringExtra(Constant.Result.CODED_CONTENT) ?: return
+ when (requestCode) {
+ // 扫码运单号
+ Constant.RequestCode.WAYBILL -> {
+ viewModel.waybillNo.value = codedContent
+ viewModel.searchClick()
+ }
+ // 扫码分单号
+ Constant.RequestCode.CODE -> {
+ viewModel.houseWaybillNo.value = codedContent
+ viewModel.searchClick()
+ }
+ }
+ }
+ }
+}
diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpLoadViewHolder.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpLoadViewHolder.kt
new file mode 100644
index 0000000..2e449b6
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/holder/IntExpLoadViewHolder.kt
@@ -0,0 +1,29 @@
+package com.lukouguoji.gjc.holder
+
+import android.view.View
+import com.lukouguoji.gjc.databinding.ItemIntExpLoadBinding
+import com.lukouguoji.module_base.base.BaseViewHolder
+import com.lukouguoji.module_base.bean.GjcExportLoad
+
+/**
+ * 国际出港-出港装载 列表项ViewHolder
+ */
+class IntExpLoadViewHolder(view: View) :
+ BaseViewHolder(view) {
+
+ override fun onBind(item: Any?, position: Int) {
+ val bean = getItemBean(item) ?: return
+ binding.bean = bean
+ binding.position = position
+ binding.executePendingBindings()
+
+ // 添加图标点击事件 - 切换选择状态
+ binding.ivIcon.setOnClickListener {
+ // 反转checked状态
+ bean.checked.set(!bean.checked.get())
+
+ // 立即更新UI (图片自动切换)
+ binding.executePendingBindings()
+ }
+ }
+}
diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcBoxWeighingViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcBoxWeighingViewModel.kt
index d56379e..d7cfba6 100644
--- a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcBoxWeighingViewModel.kt
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/GjcBoxWeighingViewModel.kt
@@ -33,7 +33,6 @@ class GjcBoxWeighingViewModel : BasePageViewModel() {
val totalCount = MutableLiveData("0") // 合计票数
val totalPc = MutableLiveData("0") // 总件数
val totalWeight = MutableLiveData("0") // 总重量
- val cargoWeight = MutableLiveData("0") // 总货重
///////////////////////////////////////////////////////////////////////////
// 方法区
@@ -123,7 +122,6 @@ class GjcBoxWeighingViewModel : BasePageViewModel() {
totalCount.value = (data?.wbNumber ?: 0).toString()
totalPc.value = (data?.totalPc ?: 0).toString()
totalWeight.value = (data?.totalWeight ?: 0.0).toString()
- cargoWeight.value = (data?.cargoWeight ?: 0.0).toString()
}
}
}
diff --git a/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpLoadViewModel.kt b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpLoadViewModel.kt
new file mode 100644
index 0000000..7358e97
--- /dev/null
+++ b/module_gjc/src/main/java/com/lukouguoji/gjc/viewModel/IntExpLoadViewModel.kt
@@ -0,0 +1,190 @@
+package com.lukouguoji.gjc.viewModel
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.viewModelScope
+import com.lukouguoji.gjc.R
+import com.lukouguoji.gjc.holder.IntExpLoadViewHolder
+import com.lukouguoji.module_base.base.BasePageViewModel
+import com.lukouguoji.module_base.bean.GjcCheckInPage
+import com.lukouguoji.module_base.bean.GjcDeclareParam
+import com.lukouguoji.module_base.bean.GjcExportLoad
+import com.lukouguoji.module_base.common.Constant
+import com.lukouguoji.module_base.common.ConstantEvent
+import com.lukouguoji.module_base.http.net.NetApply
+import com.lukouguoji.module_base.impl.FlowBus
+import com.lukouguoji.module_base.ktx.commonAdapter
+import com.lukouguoji.module_base.ktx.launchCollect
+import com.lukouguoji.module_base.ktx.launchLoadingCollect
+import com.lukouguoji.module_base.ktx.showToast
+import com.lukouguoji.module_base.ktx.toRequestBody
+import com.lukouguoji.module_base.model.ScanModel
+import kotlinx.coroutines.launch
+
+/**
+ * 国际出港-出港装载 ViewModel
+ */
+class IntExpLoadViewModel : BasePageViewModel() {
+
+ // ========== 搜索条件 ==========
+ val flightDate = MutableLiveData("") // 航班日期
+ val flightNo = MutableLiveData("") // 航班号
+ val waybillNo = MutableLiveData("") // 运单号
+ val houseWaybillNo = MutableLiveData("") // 分单号
+
+ // ========== 统计信息 ==========
+ val totalCount = MutableLiveData("0") // 合计票数
+ val totalPc = MutableLiveData("0") // 总件数
+ val totalWeight = MutableLiveData("0") // 总重量
+
+ // ========== 全选状态 ==========
+ val isAllChecked = MutableLiveData(false)
+
+ init {
+ // 监听全选状态,自动更新所有列表项
+ isAllChecked.observeForever { checked ->
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return@observeForever
+ list.forEach { it.checked.set(checked) }
+ pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
+ }
+ }
+
+ // ========== 适配器配置 ==========
+ val itemViewHolder = IntExpLoadViewHolder::class.java
+ val itemLayoutId = R.layout.item_int_exp_load
+
+ /**
+ * 搜索按钮点击
+ */
+ fun searchClick() {
+ refresh()
+ }
+
+ /**
+ * 全选按钮点击 (切换全选状态)
+ */
+ fun checkAllClick() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+
+ // 切换全选状态
+ val shouldCheckAll = !isAllChecked.value!!
+ list.forEach { it.checked.set(shouldCheckAll) }
+ isAllChecked.value = shouldCheckAll
+
+ pageModel.rv?.commonAdapter()?.notifyDataSetChanged()
+ }
+
+ /**
+ * 扫码运单号
+ */
+ fun scanWaybill() {
+ ScanModel.startScan(getTopActivity(), Constant.RequestCode.WAYBILL)
+ }
+
+ /**
+ * 扫码分单号
+ */
+ fun scanHouseWaybill() {
+ ScanModel.startScan(getTopActivity(), Constant.RequestCode.CODE)
+ }
+
+ /**
+ * 状态重置 (批量操作)
+ */
+ fun resetDeclare() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+ val selectedItems = list.filter { it.isSelected }
+
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要重置的记录")
+ return
+ }
+
+ val param = GjcDeclareParam(loadList = selectedItems)
+ val requestData = param.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.resetDeclare(requestData) }) {
+ onSuccess = {
+ showToast("状态重置成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ }
+ }
+
+ /**
+ * 装载申报 (批量操作)
+ */
+ fun declareLoad() {
+ val list = pageModel.rv?.commonAdapter()?.items as? List ?: return
+ val selectedItems = list.filter { it.isSelected }
+
+ if (selectedItems.isEmpty()) {
+ showToast("请选择要申报的记录")
+ return
+ }
+
+ val param = GjcDeclareParam(loadList = selectedItems)
+ val requestData = param.toRequestBody()
+
+ launchLoadingCollect({ NetApply.api.declareLoad(requestData) }) {
+ onSuccess = {
+ showToast("装载申报成功")
+ viewModelScope.launch {
+ FlowBus.with(ConstantEvent.EVENT_REFRESH).emit("refresh")
+ }
+ refresh()
+ }
+ }
+ }
+
+ /**
+ * 删除申报 (批量操作)
+ * TODO: 待实现
+ */
+ fun deleteLoad() {
+ // 暂不实现,预留接口
+ }
+
+ /**
+ * 获取数据 (重写BasePageViewModel)
+ */
+ override fun getData() {
+ // 构建查询参数对象
+ val pageParams = GjcCheckInPage(
+ fdate = flightDate.value?.ifEmpty { null },
+ fno = flightNo.value?.ifEmpty { null },
+ no = waybillNo.value?.ifEmpty { null },
+ hno = houseWaybillNo.value?.ifEmpty { null },
+ pageNum = pageModel.page,
+ pageSize = pageModel.limit
+ )
+
+ // 列表参数 (含分页)
+ val listParams = pageParams.toRequestBody()
+
+ // 统计参数 (无分页)
+ val totalParams = GjcCheckInPage(
+ fdate = flightDate.value?.ifEmpty { null },
+ fno = flightNo.value?.ifEmpty { null },
+ no = waybillNo.value?.ifEmpty { null },
+ hno = houseWaybillNo.value?.ifEmpty { null }
+ ).toRequestBody()
+
+ // 获取列表 (带Loading)
+ launchLoadingCollect({ NetApply.api.getIntExpLoadList(listParams) }) {
+ onSuccess = { pageModel.handleListBean(it) }
+ }
+
+ // 获取统计信息 (后台请求,不阻塞列表)
+ launchCollect({ NetApply.api.getIntExpLoadTotal(totalParams) }) {
+ onSuccess = { result ->
+ val data = result.data
+ totalCount.value = (data?.wbNumber ?: 0).toString()
+ totalPc.value = (data?.totalPc ?: 0).toString()
+ totalWeight.value = (data?.totalWeight ?: 0.0).toString()
+ }
+ }
+ }
+}
diff --git a/module_gjc/src/main/res/layout/activity_gjc_box_weighing.xml b/module_gjc/src/main/res/layout/activity_gjc_box_weighing.xml
index 8ddcbd6..9aebf32 100644
--- a/module_gjc/src/main/res/layout/activity_gjc_box_weighing.xml
+++ b/module_gjc/src/main/res/layout/activity_gjc_box_weighing.xml
@@ -81,25 +81,29 @@
type="@{SearchLayoutType.INPUT}"
value="@={viewModel.uld}" />
-
+
+ android:gravity="center_vertical|start"
+ android:orientation="horizontal"
+ android:paddingHorizontal="24dp">
@@ -169,16 +173,6 @@
android:textStyle="bold"
tools:text="总重量:100" />
-
-
diff --git a/module_gjc/src/main/res/layout/activity_int_exp_load.xml b/module_gjc/src/main/res/layout/activity_int_exp_load.xml
new file mode 100644
index 0000000..26d9b31
--- /dev/null
+++ b/module_gjc/src/main/res/layout/activity_int_exp_load.xml
@@ -0,0 +1,215 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/module_gjc/src/main/res/layout/item_int_exp_load.xml b/module_gjc/src/main/res/layout/item_int_exp_load.xml
new file mode 100644
index 0000000..b0d1580
--- /dev/null
+++ b/module_gjc/src/main/res/layout/item_int_exp_load.xml
@@ -0,0 +1,270 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+