| | |
| | | implementation 'com.github.bumptech.glide:glide:4.12.0' |
| | | annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' |
| | | |
| | | implementation 'com.squareup.okhttp3:okhttp:4.9.0' |
| | | |
| | | } |
| | |
| | | val cover: String, |
| | | val contactTel: String, |
| | | val passTime: String, |
| | | val overTime: String, |
| | | val showed: Boolean |
| | | ) |
| | |
| | | import com.example.firstapp.database.response.LoginResponse |
| | | import com.example.firstapp.database.response.SecurityResponse |
| | | import com.example.firstapp.database.response.UserInfo |
| | | import okhttp3.MultipartBody |
| | | import okhttp3.RequestBody |
| | | import retrofit2.Retrofit |
| | | import retrofit2.converter.gson.GsonConverterFactory |
| | | import retrofit2.http.GET |
| | | import retrofit2.http.Multipart |
| | | import retrofit2.http.POST |
| | | import retrofit2.http.Part |
| | | import retrofit2.http.Path |
| | | import retrofit2.http.Query |
| | | |
| | |
| | | |
| | | @GET("flower/api/supplier/info/{phone}") |
| | | suspend fun getUserInfo(@Path("phone") phone: String): ApiResponse<UserInfo> |
| | | |
| | | @Multipart |
| | | @POST("api/supplier/operation/update") |
| | | suspend fun updateProfile( |
| | | @Part("nickname") nickname: RequestBody, |
| | | @Part avatar: MultipartBody.Part? |
| | | ): ApiResponse<Unit> |
| | | } |
| | | |
| | | // 创建Retrofit实例(单例) |
| | |
| | | import android.widget.Toast |
| | | import androidx.activity.result.contract.ActivityResultContracts |
| | | import androidx.appcompat.app.AppCompatActivity |
| | | import androidx.core.content.ContextCompat |
| | | import androidx.fragment.app.Fragment |
| | | import androidx.lifecycle.lifecycleScope |
| | | import androidx.navigation.fragment.findNavController |
| | |
| | | } |
| | | |
| | | // 头像点击老的处理逻辑 |
| | | // binding.layoutUserInfo.setOnClickListener { |
| | | // val intent = Intent(requireContext(), EditProfileActivity::class.java).apply { |
| | | // putExtra("nickname", binding.tvNickname.text.toString()) |
| | | // putExtra("avatar_url", binding.ivAvatar.toString()) |
| | | // } |
| | | // editProfileLauncher.launch(intent) |
| | | // } |
| | | |
| | | binding.layoutUserInfo.setOnClickListener { |
| | | currentUserInfo?.let { user -> |
| | | val intent = Intent(requireContext(), EditProfileActivity::class.java).apply { |
| | |
| | | if (userInfo.showed) { |
| | | binding.ivVip.visibility = View.VISIBLE |
| | | binding.cardVip.visibility = View.VISIBLE |
| | | binding.tvVipExpire.text = "${userInfo.passTime} 到期" |
| | | binding.tvVipExpire.text = "${userInfo.overTime} 到期" |
| | | } else { |
| | | //非会员信息 |
| | | binding.btnRenew.text = "立即开通" |
| | | binding.linearVipContainer.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.gray)) |
| | | binding.cardVip.visibility = View.GONE |
| | | } |
| | | } |
| | |
| | | import android.os.Bundle |
| | | import android.provider.MediaStore |
| | | import android.view.View |
| | | import android.widget.ProgressBar |
| | | import android.widget.Toast |
| | | import androidx.activity.result.contract.ActivityResultContracts |
| | | import androidx.appcompat.app.AlertDialog |
| | | import androidx.appcompat.app.AppCompatActivity |
| | | import androidx.core.app.ActivityCompat |
| | | import androidx.core.content.ContextCompat |
| | | import androidx.lifecycle.lifecycleScope |
| | | import com.bumptech.glide.Glide |
| | | import com.example.firstapp.databinding.ActivityEditProfileBinding |
| | | import com.example.firstapp.database.service.ApiService |
| | | import kotlinx.coroutines.launch |
| | | import java.io.File |
| | | import okhttp3.MediaType.Companion.toMediaType |
| | | import okhttp3.MultipartBody |
| | | import okhttp3.RequestBody |
| | | import okhttp3.RequestBody.Companion.asRequestBody |
| | | import okhttp3.RequestBody.Companion.toRequestBody |
| | | |
| | | class EditProfileActivity : AppCompatActivity() { |
| | | private lateinit var binding: ActivityEditProfileBinding |
| | | private var selectedImageUri: Uri? = null |
| | | private lateinit var apiService: ApiService |
| | | private var loadingDialog: AlertDialog? = null |
| | | |
| | | private val pickImage = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> |
| | | if (result.resultCode == Activity.RESULT_OK) { |
| | |
| | | binding.btnSaveBottom.setOnClickListener { |
| | | saveAndFinish() |
| | | } |
| | | |
| | | binding.btnSaveBottom.setOnClickListener { |
| | | saveAndFinish() |
| | | } |
| | | } |
| | | |
| | | private fun saveAndFinish() { |
| | | lifecycleScope.launch { |
| | | try { |
| | | binding.btnSaveBottom.isEnabled = false |
| | | showLoading() |
| | | |
| | | val newNickname = binding.etNickname.text.toString() |
| | | if (newNickname.isEmpty()) { |
| | | Toast.makeText(this, "昵称不能为空", Toast.LENGTH_SHORT).show() |
| | | return |
| | | Toast.makeText(this@EditProfileActivity, "昵称不能为空", Toast.LENGTH_SHORT).show() |
| | | return@launch |
| | | } |
| | | |
| | | val resultIntent = Intent().apply { |
| | | putExtra("nickname", newNickname) |
| | | putExtra("avatar_uri", selectedImageUri?.toString()) |
| | | // 准备文件和参数 |
| | | val nicknameBody = newNickname.toRequestBody("text/plain".toMediaType()) |
| | | |
| | | // 如果选择了新头像,处理文件 |
| | | val avatarPart = selectedImageUri?.let { uri -> |
| | | val inputStream = contentResolver.openInputStream(uri) |
| | | val file = File(cacheDir, "avatar_temp") |
| | | inputStream?.use { input -> |
| | | file.outputStream().use { output -> |
| | | input.copyTo(output) |
| | | } |
| | | setResult(Activity.RESULT_OK, resultIntent) |
| | | } |
| | | |
| | | val requestFile = file.asRequestBody("image/*".toMediaType()) |
| | | MultipartBody.Part.createFormData("avatar", file.name, requestFile) |
| | | } |
| | | |
| | | // 调用更新接口 |
| | | apiService.updateProfile( |
| | | nickname = nicknameBody, |
| | | avatar = avatarPart |
| | | ) |
| | | |
| | | Toast.makeText(this@EditProfileActivity, "保存成功", Toast.LENGTH_SHORT).show() |
| | | finish() |
| | | |
| | | } catch (e: Exception) { |
| | | Toast.makeText(this@EditProfileActivity, "保存失败: ${e.message}", Toast.LENGTH_SHORT).show() |
| | | } finally { |
| | | binding.btnSaveBottom.isEnabled = true |
| | | hideLoading() |
| | | } |
| | | } |
| | | } |
| | | |
| | | private fun checkAndRequestPermission() { |
| | |
| | | pickImage.launch(intent) |
| | | } |
| | | |
| | | private fun showLoading() { |
| | | if (loadingDialog == null) { |
| | | loadingDialog = AlertDialog.Builder(this) |
| | | .setView(ProgressBar(this)) |
| | | .setCancelable(false) |
| | | .create() |
| | | } |
| | | loadingDialog?.show() |
| | | } |
| | | |
| | | private fun hideLoading() { |
| | | loadingDialog?.dismiss() |
| | | } |
| | | |
| | | private fun String.toRequestBody(mediaType: String): RequestBody { |
| | | return this.toRequestBody(mediaType.toMediaType()) |
| | | } |
| | | |
| | | private fun File.asRequestBody(mediaType: String): RequestBody { |
| | | return this.asRequestBody(mediaType.toMediaType()) |
| | | } |
| | | |
| | | companion object { |
| | | private const val PERMISSION_REQUEST_CODE = 100 |
| | | } |
对比新文件 |
| | |
| | | <vector xmlns:android="http://schemas.android.com/apk/res/android" |
| | | android:width="48dp" |
| | | android:height="48dp" |
| | | android:viewportWidth="1024" |
| | | android:viewportHeight="1024"> |
| | | <path |
| | | android:pathData="M512,512m-512,0a512,512 0,1 0,1024 0,512 512,0 1,0 -1024,0Z" |
| | | android:fillColor="#1A78EC"/> |
| | | <path |
| | | android:pathData="M515.5,181.1a334.5,334.5 0,0 1,325.9 259.2,49.3 49.3,0 0,1 12,-1.5c32.7,0 59.2,32.8 59.2,73.2s-26.5,73.1 -59.2,73.1a48.6,48.6 0,0 1,-10.5 -1.1,334.4 334.4,0 0,1 -651.3,14.5l-0.9,0.2 -6.1,0.4C151.9,599 125.4,566.3 125.4,525.9c0,-40.4 26.5,-73.2 59.2,-73.2l2.5,0.1A334.3,334.3 0,0 1,515.5 181.1z" |
| | | android:fillColor="#FCF6F6"/> |
| | | <path |
| | | android:pathData="M243.8,250.8m189.1,0l172.1,0q189.1,0 189.1,189.1l0,151.2q0,189.1 -189.1,189.1l-172.1,0q-189.1,0 -189.1,-189.1l0,-151.2q0,-189.1 189.1,-189.1Z" |
| | | android:fillColor="#182560"/> |
| | | <path |
| | | android:pathData="M365.7,402.3m19.9,0l33.3,0q19.9,0 19.9,19.9l0,179.6q0,19.9 -19.9,19.9l-33.3,0q-19.9,0 -19.9,-19.9l0,-179.6q0,-19.9 19.9,-19.9Z" |
| | | android:fillColor="#1A78EC"/> |
| | | <path |
| | | android:pathData="M621.7,402.3m19.9,0l33.3,0q19.9,0 19.9,19.9l0,179.6q0,19.9 -19.9,19.9l-33.3,0q-19.9,0 -19.9,-19.9l0,-179.6q0,-19.9 19.9,-19.9Z" |
| | | android:fillColor="#1A78EC"/> |
| | | </vector> |
| | |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:layout_margin="16dp" |
| | | android:background="@drawable/bg_button_black" |
| | | android:backgroundTint="@color/cardview_dark_background" |
| | | android:text="保存" |
| | | android:textColor="@android:color/white"/> |
| | | |
| | | |
| | | |
| | | </LinearLayout> |
| | |
| | | app:cardElevation="4dp"> |
| | | |
| | | <LinearLayout |
| | | android:id="@+id/linearVipContainer" |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:background="@android:color/black" |
| | |
| | | android:layout_weight="1" |
| | | android:orientation="vertical"> |
| | | |
| | | <!-- 第一行:VIP标题 + 有效期 --> |
| | | <LinearLayout |
| | | android:layout_width="match_parent" |
| | | android:layout_height="wrap_content" |
| | | android:orientation="horizontal" |
| | | android:gravity="center_vertical"> |
| | | |
| | | <TextView |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | |
| | | android:textSize="18sp" |
| | | android:textStyle="bold" /> |
| | | |
| | | <!-- 添加间隔 --> |
| | | |
| | | <TextView |
| | | android:id="@+id/tv_vip_expire" |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginTop="4dp" |
| | | android:textColor="#FFD700" |
| | | android:textSize="14sp" /> |
| | | </LinearLayout> |
| | | |
| | | <!-- 第二行:续费提示(上移调整) --> |
| | | <TextView |
| | | android:layout_width="wrap_content" |
| | | android:layout_height="wrap_content" |
| | | android:layout_marginTop="4dp" |
| | | android:text="续费畅享更多会员权益" |
| | | android:textColor="#B8741A" |
| | | android:textSize="12sp" |
| | | android:textStyle="bold"/> |
| | | </LinearLayout> |
| | | |
| | | <Button |
| | | android:id="@+id/btn_renew" |
| | | android:layout_width="wrap_content" |
| | |
| | | <color name="light_blue_A200">#FF40C4FF</color> |
| | | <color name="light_blue_A400">#FF00B0FF</color> |
| | | <color name="black_overlay">#66000000</color> |
| | | <color name="gray">#757575</color> |
| | | <color name="gray">#757575</color> <!-- 标准灰色 #808080 主要用到到会员模块--> |
| | | <color name="light_blue_50">#E1F5FE</color> |
| | | <color name="tab_selected">#FF039BE5</color> |
| | | <color name="light_blue_new">#02A7F0</color> |
| | |
| | | <string name="app_name">智信管家</string> |
| | | <string name="title_home">首页</string> |
| | | <string name="title_dashboard">数据统计</string> |
| | | <string name="title_notifications">设置</string> |
| | | <string name="title_notifications">我的</string> |
| | | |
| | | |
| | | <string name="notification_content">智信管家APP</string> |