Browse Source

2024-12-24 新增 / 修改

新增:
1. 导入高德API
2. 新增 客户资料模块 - 客户分布图界面

修改:
1. 物资进销存 - 物品领用 更改关联团组接口
zhaiy 1 week ago
parent
commit
e19804cda3

+ 13 - 5
app/build.gradle

@@ -15,8 +15,8 @@ android {
         applicationId "com.pan_american.android"
         minSdk 24
         targetSdk 34
-        versionCode 8
-        versionName "1.0.7"
+        versionCode 9
+        versionName "1.0.8"
 
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
     }
@@ -44,13 +44,21 @@ android {
         }
 
     }
+
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_17
         targetCompatibility JavaVersion.VERSION_17
     }
+
     kotlinOptions {
         jvmTarget = "17"
     }
+
+    sourceSets {
+        main{
+            jniLibs.srcDirs = ['libs']
+        }
+    }
 }
 
 dependencies {
@@ -91,6 +99,9 @@ dependencies {
     //EventBus
     implementation 'org.greenrobot:eventbus:3.3.1'
 
+    //权限获取组件
+    implementation 'pub.devrel:easypermissions:3.0.0'
+
     //SignalR
     implementation 'com.microsoft.signalr:signalr:1.0.0'
 
@@ -105,7 +116,4 @@ dependencies {
 
     //图片选择框架
     implementation 'io.github.leavesczy:matisse:2.1.0'
-
-    //地图API
-
 }

BIN
app/libs/AMap3DMap_10.0.1000_AMapSearch_9.7.4_AMapLocation_6.4.8_20241029.jar


BIN
app/libs/AMap_Location_V6.4.8_20241029.jar


BIN
app/libs/arm64-v8a/libAMapSDK_MAP_v10_0_1000.so


BIN
app/libs/armeabi-v7a/libAMapSDK_MAP_v10_0_1000.so


+ 20 - 17
app/src/main/AndroidManifest.xml

@@ -20,27 +20,26 @@
         android:maxSdkVersion="32" />
     <uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
     <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
-
-    <!--用于进行网络定位-->
+    <!-- 用于进行网络定位 -->
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <!--用于访问GPS定位-->
+    <!-- 用于访问GPS定位 -->
     <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
-    <!--用于获取运营商信息,用于支持提供运营商信息相关的接口-->
+    <!-- 用于获取运营商信息,用于支持提供运营商信息相关的接口 -->
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <!--用于访问wifi网络信息,wifi信息会用于进行网络定位-->
+    <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
     <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <!--用于获取wifi的获取权限,wifi信息会用来进行网络定位-->
+    <!-- 用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
-    <!--用于访问网络,网络定位需要上网-->
+    <!-- 用于访问网络,网络定位需要上网 -->
     <uses-permission android:name="android.permission.INTERNET" />
-    <!--用于写入缓存数据到扩展存储卡-->
+    <!-- 用于写入缓存数据到扩展存储卡 -->
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
-    <!--用于申请调用A-GPS模块-->
+    <!-- 用于申请调用A-GPS模块 -->
     <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
-    <!--如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限-->
-    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
-    <!--如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明-->
-    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
+    <!-- 如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限 -->
+    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <!-- 如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明 -->
+    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
 
     <application
         android:name=".OASystem"
@@ -54,9 +53,13 @@
         android:theme="@style/AppTheme"
         tools:targetApi="31">
         <activity
-            android:name=".ui.group_management.entry_and_exit_fee_detail.OtherPaymentDetailActivity"
+            android:name=".ui.customer_resource.customer_visit.CustomerDistributionMap"
             android:exported="false"
             android:launchMode="singleTop"/>
+        <activity
+            android:name=".ui.group_management.entry_and_exit_fee_detail.OtherPaymentDetailActivity"
+            android:exported="false"
+            android:launchMode="singleTop" />
         <activity
             android:name=".ui.group_management.entry_and_exit_fee_detail.EntryAndExitPaymentDetailActivity"
             android:exported="false"
@@ -298,7 +301,7 @@
 
         <meta-data
             android:name="com.amap.api.v2.apikey"
-            android:value="8502e62e1d6022fbf4288ed1aa390aa0	" />
+            android:value="8502e62e1d6022fbf4288ed1aa390aa0 " />
 
         <provider
             android:name="androidx.core.content.FileProvider"
@@ -311,9 +314,9 @@
         </provider>
 
         <service android:name=".data.network.TCPService" />
-        
+
+        <!--定位service-->
         <service android:name="com.amap.api.location.APSService" />
-        
     </application>
 
 </manifest>

+ 16 - 0
app/src/main/java/com/pan_american/android/OASystem.kt

@@ -3,6 +3,9 @@ package com.pan_american.android
 import android.annotation.SuppressLint
 import android.app.Application
 import android.content.Context
+import com.amap.api.location.AMapLocationClient
+import com.amap.api.maps.MapsInitializer
+import com.amap.api.services.core.ServiceSettings
 import com.pan_american.android.data.model.common.entity.Selector
 import com.pan_american.android.data.model.common.entity.SiftListItem
 import com.pan_american.android.data.model.customer_resource.market_sales_revenue.entity.YearQuarterlyData
@@ -351,6 +354,9 @@ class OASystem : Application() {
         //相册权限code
         const val GALLERY_REQUEST_CODE = 1003
 
+        //定位权限code
+        const val LOCATION_REQUEST_CODE = 1004
+
         //刷新主页消息和公告
         const val REFRESH_NAVIGATION = 2001
 
@@ -367,6 +373,16 @@ class OASystem : Application() {
     override fun onCreate() {
         super.onCreate()
         context = applicationContext
+
+        //定位隐私政策同意
+        AMapLocationClient.updatePrivacyShow(context,true,true)
+        AMapLocationClient.updatePrivacyAgree(context,true)
+        //地图隐私政策同意
+        MapsInitializer.updatePrivacyShow(context,true,true)
+        MapsInitializer.updatePrivacyAgree(context,true)
+        //搜索隐私政策同意
+        ServiceSettings.updatePrivacyShow(context,true,true)
+        ServiceSettings.updatePrivacyAgree(context,true)
     }
 
 }

+ 6 - 0
app/src/main/java/com/pan_american/android/data/network/APIService.kt

@@ -1151,6 +1151,12 @@ interface APIService {
     @POST("/api/PersonnelModule/GoodsList")
     fun getMaterialList(@Body materialSearchRequest: MaterialSearchRequest): Call<MaterialSearchResponse>
 
+    /**
+     * 雾子进销存,选择关联团组
+     */
+    @POST("/api/PersonnelModule/GoodsGroupNameInit")
+    fun getAssociateGroupList(@Body simpleGroupInfoRequest: SimpleGroupInfoRequest): Call<SimpleGroupInfoResponse>
+
     /**
      * 物资进销存,物资申领
      */

+ 289 - 0
app/src/main/java/com/pan_american/android/ui/customer_resource/customer_visit/CustomerDistributionMap.kt

@@ -0,0 +1,289 @@
+package com.pan_american.android.ui.customer_resource.customer_visit
+
+import android.Manifest
+import android.graphics.Color
+import android.os.Build
+import android.os.Bundle
+import android.util.Log
+import com.amap.api.location.AMapLocation
+import com.amap.api.location.AMapLocationClient
+import com.amap.api.location.AMapLocationClientOption
+import com.amap.api.location.AMapLocationListener
+import com.amap.api.maps.AMap
+import com.amap.api.maps.LocationSource
+import com.amap.api.maps.LocationSource.OnLocationChangedListener
+import com.amap.api.maps.UiSettings
+import com.amap.api.maps.model.MyLocationStyle
+import com.pan_american.android.OASystem
+import com.pan_american.android.R
+import com.pan_american.android.base.BaseActivity
+import com.pan_american.android.databinding.ActivityCustomerDistributionMapBinding
+import com.pan_american.android.databinding.LayoutTitleBinding
+import pub.devrel.easypermissions.AfterPermissionGranted
+import pub.devrel.easypermissions.EasyPermissions
+
+class CustomerDistributionMap : BaseActivity<ActivityCustomerDistributionMapBinding>(), AMapLocationListener, LocationSource, EasyPermissions.PermissionCallbacks {
+
+    private lateinit var titleBinding: LayoutTitleBinding
+
+    private lateinit var locationClient: AMapLocationClient
+
+    private lateinit var clientOption: AMapLocationClientOption
+
+    private lateinit var aMap: AMap
+
+    private lateinit var locationChangedListener: OnLocationChangedListener
+
+    private val myLocationStyle = MyLocationStyle()
+
+    private lateinit var uiSettings: UiSettings
+
+    override fun getViewBinding() = ActivityCustomerDistributionMapBinding.inflate(layoutInflater)
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        binding.mapView.onCreate(savedInstanceState)
+
+        initTitle()
+
+        //初始化定位
+        initLocation()
+
+        //初始化地图
+        initMap(savedInstanceState)
+
+        //检查Android 版本
+        checkingAndroidVersion()
+
+        initEvents()
+    }
+
+    override fun initTitle() {
+        titleBinding = LayoutTitleBinding.bind(binding.root).apply {
+            titleText.text = resources.getString(R.string.customer_distribution_map)
+
+            backButton.setOnClickListener {
+                back()
+            }
+        }
+    }
+
+    override fun initViews() {
+
+    }
+
+    override fun initEvents() {
+
+    }
+
+    /**
+     * 检查Android版本
+     */
+    private fun checkingAndroidVersion() {
+        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
+            //Android6.0及以上先获取权限再定位
+            requestPermission()
+        }else {
+            //Android6.0以下直接定位
+            locationClient.startLocation()
+        }
+    }
+
+    /**
+     * 动态请求权限
+     */
+    @AfterPermissionGranted(OASystem.LOCATION_REQUEST_CODE)
+    private fun requestPermission() {
+        val permissions = arrayOf(
+            Manifest.permission.ACCESS_COARSE_LOCATION,
+            Manifest.permission.ACCESS_FINE_LOCATION,
+            Manifest.permission.READ_PHONE_STATE,
+            Manifest.permission.WRITE_EXTERNAL_STORAGE
+        )
+
+        if (EasyPermissions.hasPermissions(this, *permissions)) {
+            //true 有权限 开始定位
+            //  这里不需要调用 startLocation(),移到 onPermissionsGranted 中
+            // 停止之前的定位,为 onPermissionsGranted 中的定位做准备
+            locationClient.stopLocation()
+        } else {
+            //false 无权限
+            EasyPermissions.requestPermissions(this, "使用该界面需要您开启定位权限", OASystem.LOCATION_REQUEST_CODE, *permissions)
+        }
+    }
+
+    /**
+     * 请求权限结果
+     */
+    override fun onRequestPermissionsResult(
+        requestCode: Int,
+        permissions: Array<out String>,
+        grantResults: IntArray
+    ) {
+        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+        //设置权限请求结果
+        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this)
+    }
+
+    override fun onPermissionsGranted(requestCode: Int, perms: MutableList<String>) {
+        if (requestCode == OASystem.LOCATION_REQUEST_CODE) {
+            locationClient.stopLocation() // 停止之前的定位请求 (非常重要!)
+            clientOption.setOnceLocation(true) // 只定位一次
+            locationClient.setLocationOption(clientOption) // 重新设置 option
+            locationClient.startLocation() // 启动定位
+        }
+    }
+
+    override fun onPermissionsDenied(requestCode: Int, perms: MutableList<String>) {
+
+    }
+
+    /**
+     * 初始化定位
+     */
+    private fun initLocation() {
+        //初始化定位
+        try {
+            locationClient = AMapLocationClient(OASystem.context)
+        } catch (e: Exception) {
+            e.printStackTrace()
+        }
+
+        //设置定位回调监听
+        locationClient.setLocationListener(this)
+        //初始化AMapLocationClientOption对象
+        clientOption = AMapLocationClientOption()
+        //设置定位模式为AMapLocationMode.Height_Accuracy,高精度模式。
+        clientOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy)
+        //获取最近3s内精度最高的一次定位结果:
+        //设置setOnceLocationLatest(boolean b)接口为true,启动定位时SDK会返回最近3s内精度最高的一次定位结果。
+        // 如果设置其为true,setOnceLocation(boolean b)接口也会被设置为true,反之不会,默认为false。
+        clientOption.setOnceLocationLatest(true)
+        //设置是否返回地址信息(默认返回地址信息)
+        clientOption.setNeedAddress(true)
+        //设置定位请求超时时间,单位是毫秒,默认30000毫秒,建议超时时间不要低于8000毫秒。
+        clientOption.setHttpTimeOut(20000)
+        //关闭缓存机制,高精度定位会产生缓存。
+        clientOption.setLocationCacheEnable(false)
+        //给定位客户端对象设置定位参数
+        locationClient.setLocationOption(clientOption)
+    }
+
+    /**
+     * 接收异步返回的定位结果
+     */
+    @Override
+    override fun onLocationChanged(aMapLocation: AMapLocation) {
+        if (aMapLocation.errorCode == 0) {
+            //地址
+//            val address = aMapLocation.address
+//
+//            val latitude = aMapLocation.latitude
+//
+//            val longitude = aMapLocation.longitude
+
+//            Log.e("location", "纬度: $latitude\n经度: $longitude\n地址: $address")
+
+            //停止定位后,本地服务并不会被销毁
+            // 不需要手动停止定位了,因为已经设置为单次定位
+            //locationClient.stopLocation()
+
+            //显示地图定位结果
+            locationChangedListener.onLocationChanged(aMapLocation)
+
+        } else {
+            //定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
+            Log.e("AmapError", "location Error, ErrCode:"
+                    + aMapLocation.errorCode + ", errInfo:"
+                    + aMapLocation.errorInfo
+            )
+        }
+    }
+
+    /**
+     * 初始化地图
+     */
+    private fun initMap(savedInstanceState: Bundle?) {
+
+        //在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图
+
+        binding.mapView.onCreate(savedInstanceState)
+
+        aMap = binding.mapView.map
+
+        //设置最小缩放级别
+        aMap.minZoomLevel = 3.0f
+
+        // 自定义精度范围的圆形边框颜色  都为0则透明
+        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0))
+
+        // 自定义精度范围的圆形边框宽度  0 无宽度
+        myLocationStyle.strokeWidth(0.0f)
+
+        // 设置圆形的填充颜色  都为0则透明
+        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0))
+
+        //设置定位蓝点的Style
+        aMap.myLocationStyle = myLocationStyle
+
+        // 设置定位监听
+        aMap.setLocationSource(this)
+
+        // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
+        aMap.isMyLocationEnabled = true
+
+        //实例化UiSettings类对象
+        uiSettings = aMap.uiSettings
+
+        //隐藏缩放按钮
+        uiSettings.isZoomControlsEnabled = false
+
+        //显示比例尺 默认不显示
+        uiSettings.isScaleControlsEnabled = true
+    }
+
+    /**
+     * 激活定位
+     */
+    override fun activate(listener: OnLocationChangedListener) {
+        locationChangedListener = listener
+
+        locationClient.startLocation()
+    }
+
+    /**
+     * 停止定位
+     */
+    override fun deactivate() {
+        locationClient.stopLocation()
+
+        locationClient.onDestroy()
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        binding.mapView.onResume()
+    }
+
+    override fun onPause() {
+        super.onPause()
+
+        binding.mapView.onPause()
+    }
+
+    override fun onSaveInstanceState(outState: Bundle) {
+        super.onSaveInstanceState(outState)
+
+        binding.mapView.onSaveInstanceState(outState)
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+
+        locationClient.onDestroy()
+
+        binding.mapView.onDestroy()
+    }
+}

+ 44 - 37
app/src/main/java/com/pan_american/android/ui/group_management/entry_and_exit_fee_detail/OtherPaymentDetailActivity.kt

@@ -147,16 +147,17 @@ class OtherPaymentDetailActivity : BaseActivity<ActivityOtherPaymentDetailBindin
 
                 selector.adapter = adapter
 
-                adapter.onRecyclerViewItemClick = object : ListAdapter.OnRecyclerViewItemClick<Selector> {
-                    override fun onItemClick(position: Int) {
-                        paymentTypeList[position].apply {
-                            binding.paymentType.text = name
-                            updateOtherPaymentRequest.setDataId = id
-
-                            popupWindow.dismiss()
+                adapter.onRecyclerViewItemClick =
+                    object : ListAdapter.OnRecyclerViewItemClick<Selector> {
+                        override fun onItemClick(position: Int) {
+                            paymentTypeList[position].apply {
+                                binding.paymentType.text = name
+                                updateOtherPaymentRequest.setDataId = id
+
+                                popupWindow.dismiss()
+                            }
                         }
                     }
-                }
             }
         }
 
@@ -213,22 +214,24 @@ class OtherPaymentDetailActivity : BaseActivity<ActivityOtherPaymentDetailBindin
 
                 selector.adapter = adapter
 
-                adapter.onRecyclerViewItemClick = object : ListAdapter.OnRecyclerViewItemClick<Selector> {
-                    override fun onItemClick(position: Int) {
-                        rateList[position].apply {
-                            binding.currency.text = currencyCode
-                            updateOtherPaymentRequest.currency = currencyId
-                            currencyRate = rate
-
-                            binding.totalPayment.text = String.format(
-                                resources.getString(R.string.decimal_format),
-                                binding.paymentPrinciple.text.toString().toDouble() * currencyRate
-                            )
+                adapter.onRecyclerViewItemClick =
+                    object : ListAdapter.OnRecyclerViewItemClick<Selector> {
+                        override fun onItemClick(position: Int) {
+                            rateList[position].apply {
+                                binding.currency.text = currencyCode
+                                updateOtherPaymentRequest.currency = currencyId
+                                currencyRate = rate
+
+                                binding.totalPayment.text = String.format(
+                                    resources.getString(R.string.decimal_format),
+                                    binding.paymentPrinciple.text.toString()
+                                        .toDouble() * currencyRate
+                                )
 
-                            popupWindow.dismiss()
+                                popupWindow.dismiss()
+                            }
                         }
                     }
-                }
             }
         }
 
@@ -275,7 +278,7 @@ class OtherPaymentDetailActivity : BaseActivity<ActivityOtherPaymentDetailBindin
 
                             dataResponse.data.apply {
                                 for (item in groupOtherRateData) {
-                                    when(item.currencyCode) {
+                                    when (item.currencyCode) {
                                         "USD" -> {
                                             for (currency in OASystem.entryAndExitDetailResponse.currencys) {
                                                 if (item.currencyCode == currency.currencyCode) {
@@ -353,28 +356,32 @@ class OtherPaymentDetailActivity : BaseActivity<ActivityOtherPaymentDetailBindin
     }
 
     private fun updateOtherPayment() {
-        apiService.updateEntryAndExitOtherPayment(updateOtherPaymentRequest).enqueue(object : Callback<BaseResponse> {
-            override fun onResponse(call: Call<BaseResponse>, response: Response<BaseResponse>) {
-                val updateResponse = response.body()
+        apiService.updateEntryAndExitOtherPayment(updateOtherPaymentRequest)
+            .enqueue(object : Callback<BaseResponse> {
+                override fun onResponse(
+                    call: Call<BaseResponse>,
+                    response: Response<BaseResponse>
+                ) {
+                    val updateResponse = response.body()
 
-                if (updateResponse != null) {
-                    if (updateResponse.code == 200) {
+                    if (updateResponse != null) {
+                        if (updateResponse.code == 200) {
 
-                        showMessage(resources.getString(R.string.update_success))
+                            showMessage(resources.getString(R.string.update_success))
 
-                        OASystem.needRefresh = true
+                            OASystem.needRefresh = true
 
-                        finish()
+                            finish()
 
-                    } else {
-                        showMessage(updateResponse.msg)
+                        } else {
+                            showMessage(updateResponse.msg)
+                        }
                     }
                 }
-            }
 
-            override fun onFailure(p0: Call<BaseResponse>, p1: Throwable) {
-                showErrorInfo(R.string.update_error)
-            }
-        })
+                override fun onFailure(p0: Call<BaseResponse>, p1: Throwable) {
+                    showErrorInfo(R.string.update_error)
+                }
+            })
     }
 }

+ 1 - 1
app/src/main/java/com/pan_american/android/ui/personnel_module/materials_operate/MaterialApplicationActivity.kt

@@ -137,7 +137,7 @@ class MaterialApplicationActivity : BaseActivity<ActivityMaterialApplicationBind
     }
 
     private fun getSimpleGroupInfoResource(type: Int) {
-        apiService.getGroupNameWithSearch(simpleGroupInfoRequest).enqueue(object :
+        apiService.getAssociateGroupList(simpleGroupInfoRequest).enqueue(object :
             Callback<SimpleGroupInfoResponse> {
             override fun onResponse(p0: Call<SimpleGroupInfoResponse>, response: Response<SimpleGroupInfoResponse>) {
                 val resourceResponse = response.body()

+ 9 - 0
app/src/main/java/com/pan_american/android/ui/workspace/WorkspaceFragment.kt

@@ -15,6 +15,7 @@ import com.pan_american.android.base.BaseFragment
 import com.pan_american.android.base.CustomAlertDialog
 import com.pan_american.android.databinding.FragmentWorkspaceBinding
 import com.pan_american.android.ui.customer_resource.company_customer.MarketCustomerActivity
+import com.pan_american.android.ui.customer_resource.customer_visit.CustomerDistributionMap
 import com.pan_american.android.ui.customer_resource.market_sales_revenue.MarketSalesRevenueActivity
 import com.pan_american.android.ui.customer_resource.related_invitee.RelatedInviteeActivity
 import com.pan_american.android.ui.efficiency_tools.address_book.AddressBookActivity
@@ -287,6 +288,9 @@ class WorkspaceFragment : BaseFragment<FragmentWorkspaceBinding>(), OnClickListe
                         }
                         binding.companyCustomerResource.visibility = View.VISIBLE
                         binding.companyCustomerResource.setOnClickListener(this)
+
+                        binding.customerVisits.visibility = View.VISIBLE
+                        binding.customerVisits.setOnClickListener(this)
                     }
                 }
 
@@ -466,6 +470,11 @@ class WorkspaceFragment : BaseFragment<FragmentWorkspaceBinding>(), OnClickListe
                 startActivity(intent)
             }
 
+            binding.customerVisits.id -> {
+                val intent = Intent(OASystem.context, CustomerDistributionMap::class.java)
+                startActivity(intent)
+            }
+
             binding.marketSalesRevenue.id -> {
                 val intent = Intent(OASystem.context, MarketSalesRevenueActivity::class.java)
                 startActivity(intent)

+ 17 - 0
app/src/main/res/layout/activity_customer_distribution_map.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical">
+
+    <include
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        layout="@layout/layout_title" />
+
+    <com.amap.api.maps.MapView
+        android:id="@+id/map_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent" />
+
+</LinearLayout>

+ 27 - 0
app/src/main/res/layout/fragment_workspace.xml

@@ -1046,6 +1046,33 @@
 
                     </LinearLayout>
 
+                    <LinearLayout
+                        android:id="@+id/customer_visits"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:orientation="vertical"
+                        android:visibility="gone">
+
+                        <TextView
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:drawablePadding="@dimen/common_padding"
+                            android:gravity="center_vertical"
+                            android:paddingTop="@dimen/common_padding"
+                            android:paddingBottom="@dimen/common_padding"
+                            android:text="@string/customer_distribution_map"
+                            android:textColor="@color/text_color"
+                            android:textSize="@dimen/text_size_medium"
+                            app:drawableStartCompat="@mipmap/icon_customer_visits" />
+
+                        <View
+                            android:layout_width="match_parent"
+                            android:layout_height="1dp"
+                            android:layout_marginStart="35dp"
+                            android:background="@color/line_color" />
+
+                    </LinearLayout>
+
                     <LinearLayout
                         android:id="@+id/market_sales_revenue"
                         android:layout_width="match_parent"

BIN
app/src/main/res/mipmap-xxhdpi/icon_customer_visits.png


+ 3 - 0
app/src/main/res/values/strings.xml

@@ -1381,6 +1381,9 @@
 
     <string name="entry_and_exit_payment_list_get_error">出入境费用明细费用列表获取失败</string>
 
+    <!-- 客户分布图 -->
+    <string name="customer_distribution_map">客户分布图</string>
+
     <!-- TODO: Remove or change this placeholder text -->
     <string name="hello_blank_fragment">Hello blank fragment</string>