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"