cloudroam
2025-04-01 1831c2a6304496729fc16af624c37e299beae83e
Merge remote-tracking branch 'origin/master'
已修改8个文件
已添加3个文件
346 ■■■■■ 文件已修改
app/src/main/java/com/example/firstapp/activity/VipActivity.kt 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/database/request/ProductOrdersRequest.kt 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/database/service/ApiService.kt 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/model/CardData.kt 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt 54 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/drawable/vip_black_background.xml 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/drawable/vip_white_background.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_vip.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/fragment_member_info_card.xml 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/example/firstapp/activity/VipActivity.kt
@@ -1,6 +1,7 @@
package com.example.firstapp.activity
import android.app.AlertDialog
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.util.TypedValue
@@ -10,7 +11,6 @@
import android.widget.Button
import android.widget.CheckBox
import android.widget.CompoundButton
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
@@ -19,22 +19,29 @@
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContentProviderCompat.requireContext
import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.ui.AppBarConfiguration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.example.firstapp.R
import com.example.firstapp.adapter.CardAdapter
import com.example.firstapp.database.request.ProductOrdersRequest
import com.example.firstapp.database.response.UserInfo
import com.example.firstapp.database.service.RetrofitClient
import com.example.firstapp.databinding.ActivityVipBinding
import com.example.firstapp.model.CardData
import com.example.firstapp.model.MemberBenefitItem
import com.example.firstapp.pay.PayAbility
import com.example.firstapp.ui.vip.MemberInfoCardFragment
import com.example.firstapp.utils.Log
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.example.firstapp.utils.PreferencesManager
import com.google.gson.Gson
import kotlinx.coroutines.launch
import java.math.BigDecimal
class VipActivity : AppCompatActivity() {
@@ -42,6 +49,16 @@
    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityVipBinding
    private var isPaymentSelected = false // 全局变量,默认未选中
    private var orderName = ""
    private var orderType=""
    private var currentPrice = BigDecimal.ZERO
    private var originalPrice = BigDecimal.ZERO
    private var paymentMethod = ""
    private var currentUserInfo: UserInfo? = null // 确保使用你的实际数据类
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
@@ -64,6 +81,9 @@
            finish()
        }
//        会员基本信息初始化
        loadUserInfo()
//        会员卡片初始化
        vipCardInit()
@@ -78,6 +98,10 @@
        // 勾选协议点击事件
        handlePrototalClick()
        // VIP会员服务协议
        handleVipProtocolClick()
    }
@@ -115,7 +139,19 @@
    private fun doAlipay(){
        lifecycleScope.launch {
            try {
                val response = RetrofitClient.apiService.getPayOrderInfo()
                var request = ProductOrdersRequest(
                    orderName=orderName,
                    orderType=orderType,
                    originalPrice=originalPrice,
                    currentPrice=currentPrice,
                    paymentMethod=""
                )
                Log.d("REQUEST", Gson().toJson(request))
                val response = RetrofitClient.apiService.getPayOrderInfo(request)
                Log.d("API_RESPONSE", response.toString())
                var orderInfo=response.data
                Log.d("AliPayHelper","获取订单信息时: ${response}")
                // 这里调用支付宝
@@ -125,6 +161,7 @@
//                                Snackbar.make(binding.root, "支付成功", Snackbar.LENGTH_LONG).show()
                            runOnUiThread {
                                Toast.makeText(this@VipActivity, "支付成功", Toast.LENGTH_LONG).show()
                                loadUserInfo()
                            }
                        }
                        else -> {
@@ -240,21 +277,66 @@
                "首月限时特惠",
                "连续包月",
                "首次开通",
                "9.9",
                BigDecimal("0.01"),
                "次月起12元/月",
                "自动续费可随时取消"
                "自动续费可随时取消",
            ),
            CardData.Yearly(
                "折合9元/月",
                "年卡",
                "108",
                "168"
                BigDecimal("0.01"),
                BigDecimal("168")
            ),
            CardData.SingleMonth(
                "1个月",
                "15"
                BigDecimal("0.01")
            )
        )
        // 这里获取列表的第一项作为初始化的值
        // 获取第一项作为初始化的值
        try {
            val curentPriceTmp = cardList.firstOrNull()
            // 确保 currentPrice 不为空并获取价格
            currentPrice = when (curentPriceTmp) {
                is CardData.ContinueMonthly -> curentPriceTmp.price
                is CardData.Yearly -> curentPriceTmp.price
                is CardData.SingleMonth -> curentPriceTmp.price
                else -> BigDecimal.ZERO // 兜底处理,避免 null 时报错
            }
            val title = when (curentPriceTmp) {
                is CardData.ContinueMonthly -> curentPriceTmp.title
                is CardData.Yearly -> curentPriceTmp.title
                is CardData.SingleMonth -> curentPriceTmp.title
                else -> ""
            }
            originalPrice =  when (curentPriceTmp) {
                is CardData.ContinueMonthly -> BigDecimal.ZERO
                is CardData.Yearly -> curentPriceTmp.originalPrice
                is CardData.SingleMonth -> BigDecimal.ZERO
                else -> BigDecimal.ZERO
            }
            // 初始化支付
            orderName = title
            orderType = title
            val alipayAmount:TextView = findViewById(R.id.alipay_amount);
            val wechatAmount:TextView = findViewById(R.id.wechat_amount);
            alipayAmount.text=currentPrice.toString()
            wechatAmount.text=currentPrice.toString()
        }catch (e: Exception) {
            Toast.makeText(this@VipActivity, e.message, Toast.LENGTH_LONG).show()
            Log.d("AliPayHelper","xuan: ${e.message}")
        }
        val adapter = CardAdapter(cardList) { cardViewList, cardData, cardView ->
            handleVipCardClick(cardViewList, cardData, cardView)
@@ -369,19 +451,74 @@
            is CardData.Yearly -> cardData.title
            is CardData.SingleMonth -> cardData.title
        }
        val price = when (cardData) {
        currentPrice = when (cardData) {
            is CardData.ContinueMonthly -> cardData.price
            is CardData.Yearly -> cardData.price
            is CardData.SingleMonth -> cardData.price
        }
        originalPrice =  when (cardData) {
            is CardData.ContinueMonthly -> BigDecimal.ZERO
            is CardData.Yearly -> cardData.originalPrice
            is CardData.SingleMonth -> BigDecimal.ZERO
        }
        val alipayAmount:TextView = findViewById(R.id.alipay_amount);
        val wechatAmount:TextView = findViewById(R.id.wechat_amount);
        alipayAmount.text=price
        wechatAmount.text=price
        alipayAmount.text=currentPrice.toString()
        wechatAmount.text=currentPrice.toString()
        // 处理点击事件,这里我们只是简单地展示一个 Toast
        Toast.makeText(this, "点击了: ${title}", Toast.LENGTH_SHORT).show()
        orderName = title
        orderType=title
    }
    private fun loadUserInfo() {
        // 获取Fragment实例
        val memberInfoCardFragment = supportFragmentManager.findFragmentById(R.id.memberInfoCardFragment) as MemberInfoCardFragment?
        lifecycleScope.launch {
            try {
                // 从本地获取保存的手机号
                val savedPhone = PreferencesManager.getPhone()
                if (savedPhone.isNullOrEmpty()) {
                    Toast.makeText(this@VipActivity, "用户未登录", Toast.LENGTH_SHORT).show()
                    return@launch
                }
                val response = RetrofitClient.apiService.getUserInfo(savedPhone)
                if (response.code == "0" && response.data != null) {
                    // 保存用户信息
                    currentUserInfo = response.data
                    val userInfo = response.data
                    // 调用ViewModel的刷新方法
                    memberInfoCardFragment?.viewModel?.updateMemberStatus(userInfo)
                }
            } catch (e: Exception) {
                e.printStackTrace()
                Toast.makeText(this@VipActivity, "获取用户信息失败", Toast.LENGTH_SHORT).show()
            }
        }
    }
    // VIP会员服务协议
    private fun handleVipProtocolClick(){
        binding.protocolVip.setOnClickListener{
            startContentActivity("privacy_policy", "VIP会员服务协议")
        }
    }
    private fun startContentActivity(type: String, title: String) {
        val intent = Intent(this, ContentDetailActivity::class.java).apply {
            putExtra(ContentDetailActivity.EXTRA_CONTENT_TYPE, type)
            putExtra(ContentDetailActivity.EXTRA_TITLE, title)
        }
        startActivity(intent)
    }
}
app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt
@@ -56,7 +56,7 @@
                holder.firstMonthTag.text = data.firstMonthTag
                holder.titleText.text = data.title
                holder.subTitleText.text = data.subTitle
                holder.priceText.text = data.price
                holder.priceText.text = data.price.toString()
                holder.nextPriceText.text = data.nextPrice
                holder.autoRenewText.text = data.autoRenew
@@ -68,8 +68,8 @@
                val data = cardList[position] as CardData.Yearly
                holder.discountTag.text = data.discountTag
                holder.titleText.text = data.title
                holder.priceText.text = data.price
                holder.originalPriceText.text = data.originalPrice
                holder.priceText.text = data.price.toString()
                holder.originalPriceText.text = data.originalPrice.toString()
                // 设置中划线
                val paint = holder.originalPriceText.paint
@@ -83,7 +83,7 @@
            is SingleMonthViewHolder -> {
                val data = cardList[position] as CardData.SingleMonth
                holder.titleText.text = data.title
                holder.priceText.text = data.price
                holder.priceText.text = data.price.toString()
                cardViewList.add(holder.cardView)
app/src/main/java/com/example/firstapp/database/request/ProductOrdersRequest.kt
对比新文件
@@ -0,0 +1,11 @@
package com.example.firstapp.database.request
import java.math.BigDecimal
data class ProductOrdersRequest(
    val orderName: String,
    val orderType: String,
    val originalPrice: BigDecimal,
    val currentPrice: BigDecimal,
    val paymentMethod: String
)
app/src/main/java/com/example/firstapp/database/service/ApiService.kt
@@ -3,6 +3,7 @@
import TokenResponse
import com.example.firstapp.database.entity.ApiResponse
import com.example.firstapp.database.entity.KeywordConfig
import com.example.firstapp.database.request.ProductOrdersRequest
import com.example.firstapp.database.request.SmsLoginRequest
import com.example.firstapp.database.request.SmsSendRequest
import com.example.firstapp.database.response.AlipayOrderInfoResponse
@@ -53,8 +54,8 @@
    @GET("config-security/enable-list-all")
    suspend fun getSecurityList(): SecurityResponse
    @GET("v2/alipay/pay-order-info")
    suspend fun getPayOrderInfo(): AlipayOrderInfoResponse
    @POST("v2/alipay/pay-order-info")
    suspend fun getPayOrderInfo(@Body request: ProductOrdersRequest): AlipayOrderInfoResponse
    // 获取用户信息
    @GET("api/customer/info/{phone}")
@@ -77,7 +78,7 @@
// 创建Retrofit实例(单例)
object RetrofitClient{
    private const val BASE_URL ="http://192.168.1.213:8080/flower/"
    private const val BASE_URL ="http://192.168.1.199:8080/flower/"
    // 创建OkHttpClient,配置拦截器和超时时间
    private val okHttpClient = OkHttpClient.Builder()
app/src/main/java/com/example/firstapp/model/CardData.kt
@@ -1,11 +1,13 @@
package com.example.firstapp.model
import java.math.BigDecimal
sealed class CardData {
    data class ContinueMonthly(
        val firstMonthTag: String,
        val title: String,
        val subTitle: String,
        val price: String,
        val price: BigDecimal,
        val nextPrice: String,
        val autoRenew: String
    ) : CardData()
@@ -13,12 +15,12 @@
    data class Yearly(
        val discountTag: String,
        val title: String,
        val price: String,
        val originalPrice: String
        val price: BigDecimal,
        val originalPrice: BigDecimal
    ) : CardData()
    data class SingleMonth(
        val title: String,
        val price: String
        val price: BigDecimal
    ) : CardData()
}
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt
@@ -1,5 +1,6 @@
package com.example.firstapp.ui.vip
import android.graphics.Color
import android.graphics.drawable.Drawable
import androidx.fragment.app.viewModels
import android.os.Bundle
@@ -8,8 +9,7 @@
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.lifecycleScope
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
@@ -17,7 +17,9 @@
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.load.DataSource
import com.example.firstapp.R
import com.example.firstapp.databinding.FragmentMemberInfoCardBinding
import kotlinx.coroutines.launch
class MemberInfoCardFragment : Fragment() {
@@ -26,11 +28,12 @@
        fun newInstance() = MemberInfoCardFragment()
    }
    private val viewModel: MemberInfoCardViewModel by viewModels()
     val viewModel: MemberInfoCardViewModel by viewModels()
    // 绑定变量
    private var _binding: FragmentMemberInfoCardBinding? = null
    private val binding get() = _binding!!
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
@@ -49,7 +52,7 @@
        // 绑定头像
        Glide.with(this)
            .load("http://192.168.1.201:9000/sms/avatar/avatar.jpg")
            .load(viewModel.cover)
            .transform(RoundedCorners(100))  // 设置圆角
            .error(R.drawable.error_placeholder) // 如果加载失败,显示占位图
            .listener(object : RequestListener<Drawable> {
@@ -80,7 +83,7 @@
        // 绑定会员徽章
        Glide.with(this)
            .load("http://192.168.1.201:9000/sms/member/vip_no.png")
            .load(viewModel.vipCover)
            .transform(RoundedCorners(100))  // 设置圆角
            .error(R.drawable.error_placeholder) // 如果加载失败,显示占位图
            .listener(object : RequestListener<Drawable> {
@@ -107,12 +110,51 @@
            })
            .into(binding.memberImageView)
        // 监听 cover 变化
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.cover.collect { coverUrl ->
                Glide.with(this@MemberInfoCardFragment)
                    .load(coverUrl)
                    .transform(RoundedCorners(100))
                    .error(R.drawable.error_placeholder)
                    .into(binding.memberAvatarView)
            }
        }
        // 监听 vipCover 变化
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.vipCover.collect { vipCoverUrl ->
                Glide.with(this@MemberInfoCardFragment)
                    .load(vipCoverUrl)
                    .transform(RoundedCorners(100))
                    .error(R.drawable.error_placeholder)
                    .into(binding.memberImageView)
            }
        }
        // 监听 background 变化
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.background.collect { backgroundColor ->
//                binding.memberCardCardView.setBackgroundColor(Color.parseColor(backgroundColor))
                binding.memberCardCardView.setBackgroundResource(backgroundColor)
            }
        }
        viewLifecycleOwner.lifecycleScope.launch {
            viewModel.color.collect { color ->
                binding.phoneNumberText.setTextColor(Color.parseColor(color))
                binding.memberStatus.setTextColor(Color.parseColor(color))
            }
        }
        return binding.root
    }
    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt
@@ -2,17 +2,38 @@
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.example.firstapp.R
import com.example.firstapp.database.response.UserInfo
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
class MemberInfoCardViewModel : ViewModel() {
    // TODO: Implement the ViewModel
    // 联系方式
    private val _phoneNumber = MutableStateFlow("18099999999")
    val phoneNumber: StateFlow<String> = _phoneNumber
    // 开通状态
    private val _memberStatus = MutableStateFlow("未开通")
    val memberStatus: StateFlow<String> = _memberStatus
    // 头像
    private val _cover = MutableStateFlow("")
    val cover: StateFlow<String> = _cover
    // vip头像
    private val _vipCover = MutableStateFlow("")
    val vipCover: StateFlow<String> = _vipCover
    // 背景色
    private val _background = MutableStateFlow(R.drawable.dialog_background)
    val background: StateFlow<Int> = _background
    // 背景色
    private val _color = MutableStateFlow("#E8EAEE")
    val color: StateFlow<String> = _color
    // 更新数据的方法
    fun updatePhoneNumber(phoneNumber: String) {
@@ -20,4 +41,35 @@
            _phoneNumber.value = phoneNumber
        }
    }
    fun updateMemberStatus(userInfo: UserInfo) {
        viewModelScope.launch {
            // 电话号码
            _phoneNumber.value=userInfo.contactTel
            // 开通状态
            if(userInfo.isMember){
                // 判断userInfo.memberOvertime是否为空,如果不为空,则截取字符串到年月日
                if(userInfo.memberOvertime.isNotEmpty()){
                    _memberStatus.value = userInfo.memberOvertime.substring(0,10)+" 到期"
                }
                // vip头像
                _vipCover.value ="http://192.168.1.201:9000/sms/member/vip.png"
                _background.value = R.drawable.vip_black_background
                _color.value ="#A9A9AB"
            }else{
                _memberStatus.value = "未开通"
                _vipCover.value ="http://192.168.1.201:9000/sms/member/vip_no.png"
                _background.value =R.drawable.vip_white_background
                _color.value ="#A4A4A4"
            }
            // 头像
            _cover.value = userInfo.cover
        }
    }
}
app/src/main/res/drawable/vip_black_background.xml
对比新文件
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 圆角 10dp -->
    <corners android:radius="10dp" />
    <!-- 背景色:黑色 -->
<!--    <solid android:color="#FFFFFF" />-->
    <solid android:color="#000000" />
    <!-- 内边距 -->
    <padding android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp"/>
    <stroke android:width="0dp" android:color="#FFFFFF"/>
</shape>
app/src/main/res/drawable/vip_white_background.xml
对比新文件
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 圆角 10dp -->
    <corners android:radius="10dp" />
    <!-- 背景色:白色 -->
    <solid android:color="#FFFFFF" />
    <!-- 内边距 -->
    <padding android:left="10dp"
        android:top="10dp"
        android:right="10dp"
        android:bottom="10dp"/>
    <stroke android:width="0dp" android:color="#FFFFFF"/>
</shape>
app/src/main/res/layout/activity_vip.xml
@@ -483,6 +483,7 @@
                    />
                <TextView
                    android:id="@+id/protocol_vip"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="《VIP会员服务协议》"
app/src/main/res/layout/fragment_member_info_card.xml
@@ -15,12 +15,15 @@
        <!-- CardView 内部的内容 -->
        <androidx.cardview.widget.CardView
            android:id="@+id/memberCardCardView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp"
            android:layout_marginRight="15dp"
            android:elevation="2dp"
            android:elevation="0dp"
            android:clipChildren="false"
            android:clipToOutline="true"
            app:cardCornerRadius="10dp">  <!-- 设置CardView的elevation -->
@@ -29,7 +32,9 @@
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="10dp"
                tools:ignore="MissingConstraints">
                tools:ignore="MissingConstraints"
                android:background="@android:color/transparent"
                >
                <ImageView
                    android:id="@+id/memberAvatarView"