From 641d6300869c8d53e8b038e47eb0fe469891a95a Mon Sep 17 00:00:00 2001 From: tj <1378534974@qq.com> Date: 星期二, 01 四月 2025 10:29:07 +0800 Subject: [PATCH] 1.vip续费页面-会员信息 --- app/src/main/res/layout/fragment_member_info_card.xml | 9 + app/src/main/res/drawable/vip_white_background.xml | 16 ++ app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt | 8 app/src/main/res/drawable/vip_black_background.xml | 17 ++ app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt | 54 ++++++++ app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt | 88 ++++++++++++++ app/src/main/java/com/example/firstapp/activity/VipActivity.kt | 139 +++++++++++++++++++++- app/src/main/java/com/example/firstapp/database/service/ApiService.kt | 7 app/src/main/java/com/example/firstapp/database/request/ProductOrdersRequest.kt | 11 + app/src/main/java/com/example/firstapp/model/CardData.kt | 10 + 10 files changed, 331 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/example/firstapp/activity/VipActivity.kt b/app/src/main/java/com/example/firstapp/activity/VipActivity.kt index 56df585..1199c1b 100644 --- a/app/src/main/java/com/example/firstapp/activity/VipActivity.kt +++ b/app/src/main/java/com/example/firstapp/activity/VipActivity.kt @@ -10,7 +10,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 @@ -25,16 +24,22 @@ 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 +47,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) @@ -63,6 +78,9 @@ binding.ivBack.setOnClickListener{ finish() } + +// 会员基本信息初始化 + loadUserInfo() // 会员卡片初始化 vipCardInit() @@ -115,7 +133,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 +155,7 @@ // Snackbar.make(binding.root, "支付成功", Snackbar.LENGTH_LONG).show() runOnUiThread { Toast.makeText(this@VipActivity, "支付成功", Toast.LENGTH_LONG).show() + loadUserInfo() } } else -> { @@ -240,21 +271,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 +445,60 @@ 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() + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt b/app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt index f9b45f3..a12ce57 100644 --- a/app/src/main/java/com/example/firstapp/adapter/CardAdapter.kt +++ b/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) diff --git a/app/src/main/java/com/example/firstapp/database/request/ProductOrdersRequest.kt b/app/src/main/java/com/example/firstapp/database/request/ProductOrdersRequest.kt new file mode 100644 index 0000000..5d40cb9 --- /dev/null +++ b/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 +) \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/database/service/ApiService.kt b/app/src/main/java/com/example/firstapp/database/service/ApiService.kt index 1d4be56..2d47673 100644 --- a/app/src/main/java/com/example/firstapp/database/service/ApiService.kt +++ b/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() diff --git a/app/src/main/java/com/example/firstapp/model/CardData.kt b/app/src/main/java/com/example/firstapp/model/CardData.kt index 4c4ef14..1752dcf 100644 --- a/app/src/main/java/com/example/firstapp/model/CardData.kt +++ b/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() } \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt b/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt index 3671d10..3a30115 100644 --- a/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardFragment.kt +++ b/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 @@ -9,7 +10,9 @@ import android.view.View import android.view.ViewGroup import android.widget.ImageView +import android.widget.Toast 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 +20,11 @@ import com.bumptech.glide.request.target.Target import com.bumptech.glide.load.DataSource import com.example.firstapp.R +import com.example.firstapp.database.response.UserInfo +import com.example.firstapp.database.service.RetrofitClient import com.example.firstapp.databinding.FragmentMemberInfoCardBinding +import com.example.firstapp.utils.PreferencesManager +import kotlinx.coroutines.launch class MemberInfoCardFragment : Fragment() { @@ -26,11 +33,14 @@ fun newInstance() = MemberInfoCardFragment() } - private val viewModel: MemberInfoCardViewModel by viewModels() + val viewModel: MemberInfoCardViewModel by viewModels() // 绑定变量 private var _binding: FragmentMemberInfoCardBinding? = null private val binding get() = _binding!! + + private var currentUserInfo: UserInfo? = null // 确保使用你的实际数据类 + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -49,7 +59,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 +90,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,6 +117,45 @@ }) .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 } @@ -115,4 +164,37 @@ super.onDestroyView() _binding = null } + +// 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() +// } +// } +// +// } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt b/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt index 1530b32..a3ac89d 100644 --- a/app/src/main/java/com/example/firstapp/ui/vip/MemberInfoCardViewModel.kt +++ b/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 ="#5F6064" + + }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 + } + } + + } \ No newline at end of file diff --git a/app/src/main/res/drawable/vip_black_background.xml b/app/src/main/res/drawable/vip_black_background.xml new file mode 100644 index 0000000..c6e6a0b --- /dev/null +++ b/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> diff --git a/app/src/main/res/drawable/vip_white_background.xml b/app/src/main/res/drawable/vip_white_background.xml new file mode 100644 index 0000000..e5f1307 --- /dev/null +++ b/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> diff --git a/app/src/main/res/layout/fragment_member_info_card.xml b/app/src/main/res/layout/fragment_member_info_card.xml index 5f2d2a6..d1789c5 100644 --- a/app/src/main/res/layout/fragment_member_info_card.xml +++ b/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" -- Gitblit v1.9.3