操作密码弹窗修改2

This commit is contained in:
2026-06-02 16:45:31 +08:00
parent a1b9acb2a6
commit 5822e562de
9 changed files with 261 additions and 314 deletions

View File

@@ -27,6 +27,9 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.DefenseApplication">
<activity
android:name=".personal.LoginPasswordActivity"
android:exported="false" />
<activity
android:name=".personal.InvitationCodeActivity"
android:exported="false" />

View File

@@ -8,7 +8,6 @@ import android.graphics.Color
import android.graphics.Paint
import android.os.Bundle
import android.os.Environment
import android.text.TextPaint
import android.view.LayoutInflater
import android.view.View
import androidx.appcompat.app.AppCompatActivity
@@ -43,6 +42,7 @@ class InvitationCodeActivity : AppCompatActivity() {
private var lastClickTime: Long = 0 // 上次点击时间,用于防止多次点击
private var expireTimeDialog: BottomSheetDialog? = null // 时效选择弹窗
private var isLoading = false // 是否正在加载
private var hasGeneratedQrCode = false // 是否已经生成过二维码
companion object {
const val EXPIRE_24H = 24 * 60 * 60 * 1000L
@@ -64,9 +64,8 @@ class InvitationCodeActivity : AppCompatActivity() {
binding.tvExpireTime.text = getString(R.string.expire_24h)
// 默认显示灰色占位区域,二维码不可见
hideQrCode()
// 页面加载时查询推荐码状态
queryRecommendationCodeStatus()
// 初始按钮文字为"生成二维码"
binding.btnRegenerate.text = getString(R.string.generate_invite_code)
}
private fun initListener() {
@@ -91,116 +90,30 @@ class InvitationCodeActivity : AppCompatActivity() {
// 撤销邀请按钮
binding.btnCancelInvite.setOnClickListener {
cancelInvitation()
showPasswordDialog {
cancelInvitation()
}
}
// 重新生成按钮
// 生成/重新生成按钮
binding.btnRegenerate.setOnClickListener {
regenerateInvitation()
}
}
/**
* 查询推荐码状态
*/
private fun queryRecommendationCodeStatus() {
isLoading = true
CoroutineScope(Dispatchers.IO).launch {
try {
// 注意接口需要传入code参数但我们可能不知道当前的推荐码
// 这里使用空字符串或默认值进行查询
val response = RetrofitNetwork.getNetworkService().selectRecommendationCode("")
withContext(Dispatchers.Main) {
isLoading = false
if (response.code == 200) {
// 有推荐码,解析返回的数据
handleRecommendationCodeResponse(response.data)
} else {
// 没有推荐码或查询失败生成默认24小时的推荐码
generateDefaultRecommendationCode()
}
}
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
isLoading = false
// 网络异常生成默认24小时的推荐码
generateDefaultRecommendationCode()
}
showPasswordDialog {
generateOrRegenerateInvitation()
}
}
}
/**
* 处理推荐码查询响应
* 生成或重新生成邀请码
*/
private fun handleRecommendationCodeResponse(data: Any?) {
// 解析返回的数据,获取推荐码和过期时间
// 这里需要根据实际接口返回格式进行解析
if (data is Map<*, *>) {
generatedInviteCode = data["code"]?.toString() ?: ""
expireTimestamp = data["expireTime"]?.toString()?.toLongOrNull() ?: 0L
// 检查推荐码是否过期
if (expireTimestamp > 0 && System.currentTimeMillis() < expireTimestamp) {
// 推荐码有效,显示二维码
qrCodeContent = "{\"type\":\"invite\",\"code\":\"$generatedInviteCode\",\"expire\":$expireTimestamp}"
showQrCode()
generateQRCode()
// 根据过期时间设置显示的时效
val remainingTime = expireTimestamp - System.currentTimeMillis()
if (remainingTime > EXPIRE_24H) {
// 超过24小时认为是7天的
expireTimeInMillis = EXPIRE_7D
selectedExpireOption = 1
binding.tvExpireTime.text = getString(R.string.expire_7d)
} else {
expireTimeInMillis = EXPIRE_24H
selectedExpireOption = 0
binding.tvExpireTime.text = getString(R.string.expire_24h)
}
} else {
// 推荐码已过期生成新的默认24小时推荐码
generateDefaultRecommendationCode()
}
} else {
// 数据格式不对,生成新的推荐码
generateDefaultRecommendationCode()
}
}
/**
* 生成默认24小时的推荐码
*/
private fun generateDefaultRecommendationCode() {
expireTimeInMillis = EXPIRE_24H
selectedExpireOption = 0
binding.tvExpireTime.text = getString(R.string.expire_24h)
// 生成推荐码本地生成实际应该调用API
private fun generateOrRegenerateInvitation() {
// 根据当前选择的时效生成邀请码
generateQRCode()
showQrCode()
}
/**
* 处理生成推荐码成功
*/
private fun handleGenerateSuccess(data: Any?, expireDays: Int) {
// 解析返回的数据
if (data is Map<*, *>) {
generatedInviteCode = data["code"]?.toString() ?: ""
expireTimestamp = data["expireTime"]?.toString()?.toLongOrNull() ?: (System.currentTimeMillis() + expireTimeInMillis)
qrCodeContent = "{\"type\":\"invite\",\"code\":\"$generatedInviteCode\",\"expire\":$expireTimestamp}"
showQrCode()
generateQRCode()
} else {
// 如果接口没有返回推荐码,本地生成一个
generateInviteCode()
showQrCode()
generateQRCode()
}
// 更新按钮文字为"重新生成"
binding.btnRegenerate.text = getString(R.string.regenerate)
hasGeneratedQrCode = true
ToastUtils.showSuccess(this, getString(R.string.operation_success))
}
private fun showExpireTimeDialog() {
@@ -260,7 +173,9 @@ class InvitationCodeActivity : AppCompatActivity() {
}
private fun generateQRCode() {
val content = if (qrCodeContent.isNotEmpty()) qrCodeContent else generateInviteCode()
// 检查二维码是否过期,如果过期则生成新的邀请码
val isExpired = expireTimestamp > 0 && System.currentTimeMillis() > expireTimestamp
val content = if (qrCodeContent.isNotEmpty() && !isExpired) qrCodeContent else generateInviteCode()
val qrBitmap = createQRCodeWithLogo(content, 400, 400)
binding.ivQrCode.setImageBitmap(qrBitmap)
}
@@ -476,18 +391,48 @@ class InvitationCodeActivity : AppCompatActivity() {
generatedInviteCode = ""
qrCodeContent = ""
expireTimestamp = 0
hasGeneratedQrCode = false
// 恢复按钮文字为"生成邀请码"
binding.btnRegenerate.text = getString(R.string.generate_invite_code)
// 显示提示
ToastUtils.showSuccess(this, getString(R.string.operation_success))
}
/**
* 重新生成邀请码
* 显示密码输入对话框
* @param onSuccess 验证成功后的回调
*/
private fun regenerateInvitation() {
// 根据当前选择的时效重新生成邀请码
generateQRCode()
showQrCode()
ToastUtils.showSuccess(this, getString(R.string.operation_success))
private fun showPasswordDialog(onSuccess: () -> Unit) {
val dialog = PasswordInputDialog(this)
dialog.setTitle(getString(R.string.input_op_pwd))
dialog.setOnConfirmListener { password ->
verifyPassword(password, dialog, onSuccess)
}
dialog.show()
}
/**
* 验证操作密码
*/
private fun verifyPassword(password: String, dialog: PasswordInputDialog, onSuccess: () -> Unit) {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService()
.verifyOptionPassword(VerifyOptionPasswordRequest(password))
withContext(Dispatchers.Main) {
if (response.code == 200) {
dialog.dismiss()
onSuccess.invoke()
} else {
dialog.showError(getString(R.string.password_error))
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
dialog.showError(getString(R.string.network_error))
}
}
}
}
override fun onDestroy() {

View File

@@ -1,15 +1,16 @@
package com.example.defenseapplication.personal
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.blankj.utilcode.util.SPUtils
import com.example.defenseapplication.R
import com.example.defenseapplication.bean.UpdateUserInfo
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
import com.example.defenseapplication.databinding.OperationPasswordActivityBinding
import com.example.defenseapplication.utils.RetrofitNetwork
import com.example.defenseapplication.view.CustomDialogFragment
import com.example.defenseapplication.view.LoadingDialog
import com.example.defenseapplication.view.showDefenseDialog
import com.gyf.immersionbar.ImmersionBar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -20,6 +21,7 @@ import kotlinx.coroutines.withContext
class OperationPasswordActivity : AppCompatActivity() {
private lateinit var binding: OperationPasswordActivityBinding
private var isLoading = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -31,6 +33,7 @@ class OperationPasswordActivity : AppCompatActivity() {
.titleBar(binding.topBar)
.init()
getUserInfo()
initListener()
}
@@ -39,104 +42,151 @@ class OperationPasswordActivity : AppCompatActivity() {
finish()
}
binding.swOperationPassword.setOnCheckedChangeListener { _, isChecked ->
when (isChecked) {
true -> {
binding.etPassword.isEnabled = true
binding.etConfirmPassword.isEnabled = true
Toast.makeText(this, getString(R.string.operation_password_enabled), Toast.LENGTH_SHORT).show()
}
false -> {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().updateUserInfo(UpdateUserInfo(optionPassword = ""))
withContext(Dispatchers.Main) {
if (response.code == 200) {
binding.etPassword.isEnabled = false
binding.etConfirmPassword.isEnabled = false
SPUtils.getInstance().remove("operation_password")
Toast.makeText(this@OperationPasswordActivity, getString(R.string.operation_password_disabled), Toast.LENGTH_SHORT).show()
finish()
} else {
binding.swOperationPassword.isChecked = true
Toast.makeText(this@OperationPasswordActivity, response.msg ?: "操作失败", Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
binding.swOperationPassword.isChecked = true
Toast.makeText(this@OperationPasswordActivity, getString(R.string.network_error), Toast.LENGTH_SHORT).show()
}
}
}
}
}
binding.changePassword.setOnClickListener {
showOldPasswordDialog()
}
binding.etPassword.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
binding.swOperationPassword.setOnCheckedChangeListener { _, isChecked ->
if (!isLoading) {
updateOptionStatus(isChecked)
}
})
}
}
binding.etConfirmPassword.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
override fun afterTextChanged(s: Editable?) {
}
})
binding.btnConfirmReset.setOnClickListener {
val password = binding.etPassword.text.toString()
val confirmPassword = binding.etConfirmPassword.text.toString()
if (password.isEmpty()) {
Toast.makeText(this, getString(R.string.password_cannot_empty), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if (password.length != 6) {
Toast.makeText(this, getString(R.string.password_must_be_6_digits), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if (confirmPassword.isEmpty()) {
Toast.makeText(this, getString(R.string.please_confirm_password), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
if (password != confirmPassword) {
Toast.makeText(this, getString(R.string.password_mismatch), Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
binding.btnConfirmReset.isEnabled = false
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().updateUserInfo(UpdateUserInfo(optionPassword = password))
withContext(Dispatchers.Main) {
binding.btnConfirmReset.isEnabled = true
if (response.code == 200) {
SPUtils.getInstance().put("operation_password", password)
Toast.makeText(this@OperationPasswordActivity, getString(R.string.operation_success), Toast.LENGTH_SHORT).show()
finish()
} else {
Toast.makeText(this@OperationPasswordActivity, response.msg ?: "操作失败", Toast.LENGTH_SHORT).show()
private fun getUserInfo() {
isLoading = true
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().getUserInfo()
withContext(Dispatchers.Main) {
isLoading = false
if (response.code == 200) {
response.data?.optionStatus?.let { status ->
binding.swOperationPassword.isChecked = status == "0"
}
} else {
Toast.makeText(this@OperationPasswordActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
binding.btnConfirmReset.isEnabled = true
Toast.makeText(this@OperationPasswordActivity, getString(R.string.network_error), Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
isLoading = false
Toast.makeText(this@OperationPasswordActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
}
}
}
}
private fun updateOptionStatus(isChecked: Boolean) {
isLoading = true
val status = if (isChecked) "0" else "1"
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService()
.updateUserInfo(UpdateUserInfo(optionStatus = status))
withContext(Dispatchers.Main) {
isLoading = false
if (response.code != 200) {
binding.swOperationPassword.isChecked = !isChecked
Toast.makeText(this@OperationPasswordActivity, R.string.update_failed, Toast.LENGTH_SHORT).show()
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
isLoading = false
binding.swOperationPassword.isChecked = !isChecked
Toast.makeText(this@OperationPasswordActivity, R.string.network_error, Toast.LENGTH_SHORT).show()
}
}
}
}
private fun showOldPasswordDialog() {
val dialog = PasswordInputDialog(this)
dialog.setTitle(getString(R.string.input_op_pwd))
dialog.setOnConfirmListener { password ->
verifyOldPassword(password, dialog)
}
dialog.show()
}
private fun verifyOldPassword(password: String, dialog: PasswordInputDialog) {
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService()
.verifyOptionPassword(VerifyOptionPasswordRequest(password))
withContext(Dispatchers.Main) {
if (response.code == 200) {
dialog.dismiss()
showNewPasswordDialog()
} else {
dialog.showError(getString(R.string.password_error))
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
dialog.showError(getString(R.string.network_error))
}
}
}
}
private fun showNewPasswordDialog() {
val dialog = PasswordInputDialog(this)
dialog.setTitle(getString(R.string.input_new_op_pwd))
dialog.setOnConfirmListener { newPassword ->
updatePassword(newPassword, dialog)
}
dialog.show()
}
private fun updatePassword(newPassword: String, dialog: PasswordInputDialog) {
dialog.dismiss()
val loadingDialog = LoadingDialog(this)
loadingDialog.show()
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService()
.updateUserInfo(UpdateUserInfo(optionPassword = newPassword))
withContext(Dispatchers.Main) {
loadingDialog.dismiss()
if (response.code == 200) {
Toast.makeText(
this@OperationPasswordActivity,
R.string.password_update_success,
Toast.LENGTH_SHORT
).show()
finish()
} else {
Toast.makeText(
this@OperationPasswordActivity,
R.string.password_update_failed,
Toast.LENGTH_SHORT
).show()
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
loadingDialog.dismiss()
Toast.makeText(
this@OperationPasswordActivity,
R.string.network_error,
Toast.LENGTH_SHORT
).show()
}
}
}
}
private fun showSuccessDialog() {
val config = CustomDialogFragment.Config(
title = getString(R.string.tip),
message = getString(R.string.password_update_success),
positiveText = getString(R.string.confirm),
negativeText = null
)
showDefenseDialog(config, onPositiveClick = {
finish()
})
}
}

View File

@@ -2,23 +2,13 @@ package com.example.defenseapplication.personal
import android.content.Intent
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.defenseapplication.R
import com.example.defenseapplication.bean.VerifyOptionPasswordRequest
import com.example.defenseapplication.databinding.PasswordManagementActivityBinding
import com.example.defenseapplication.utils.RetrofitNetwork
import com.gyf.immersionbar.ImmersionBar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
//密码管理
class PasswordManagementActivity : AppCompatActivity() {
private lateinit var binding: PasswordManagementActivityBinding
private lateinit var passwordDialog: PasswordInputDialog
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = PasswordManagementActivityBinding.inflate(layoutInflater)
@@ -34,50 +24,12 @@ class PasswordManagementActivity : AppCompatActivity() {
}
binding.loginPassword.setOnClickListener {
startActivity(Intent(this, ChangePasswordActivity::class.java))
startActivity(Intent(this, LoginPasswordActivity::class.java))
}
binding.operationPassword.setOnClickListener {
showPasswordDialog()
startActivity(Intent(this, OperationPasswordActivity::class.java))
}
}
private fun showPasswordDialog() {
passwordDialog = PasswordInputDialog(this).apply {
setOnConfirmListener { inputPassword ->
CoroutineScope(Dispatchers.IO).launch {
try {
val response = RetrofitNetwork.getNetworkService().verifyOptionPassword(VerifyOptionPasswordRequest(inputPassword))
withContext(Dispatchers.Main) {
if (response.code == 200) {
startActivity(Intent(this@PasswordManagementActivity, OperationPasswordActivity::class.java))
dismiss()
} else {
Toast.makeText(this@PasswordManagementActivity, response.msg ?: "校验失败", Toast.LENGTH_SHORT).show()
showError(getString(R.string.password_error))
clearPassword()
}
}
} catch (e: Exception) {
withContext(Dispatchers.Main) {
Toast.makeText(this@PasswordManagementActivity, "网络请求失败", Toast.LENGTH_SHORT).show()
showError(getString(R.string.password_error))
clearPassword()
}
}
}
}
setOnDismissListener {
// Dialog dismissed
}
}
passwordDialog.show()
}
override fun onDestroy() {
if (::passwordDialog.isInitialized) {
passwordDialog.dismiss()
}
super.onDestroy()
}
}

View File

@@ -22,6 +22,7 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
private lateinit var binding: DialogPasswordInputBinding
private var onConfirmListener: ((String) -> Unit)? = null
private var onDismissListener: (() -> Unit)? = null
private var customTitle: String? = null
// 6个密码输入框数组
private lateinit var passwordEditTexts: Array<EditText>
@@ -61,6 +62,11 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
setupPasswordInput()
// 设置标题(如果通过 setTitle 设置了自定义标题)
customTitle?.let {
binding.tvTitle.text = it
}
binding.ivClose.setOnClickListener {
dismiss()
}
@@ -239,6 +245,14 @@ class PasswordInputDialog(context: Context) : Dialog(context) {
return this
}
fun setTitle(title: String): PasswordInputDialog {
this.customTitle = title
if (::binding.isInitialized) {
binding.tvTitle.text = title
}
return this
}
fun setOnDismissListener(listener: () -> Unit): PasswordInputDialog {
this.onDismissListener = listener
return this

View File

@@ -6,6 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/white"
tools:context=".personal.LoginPasswordActivity">
<!-- 标题栏 -->
@@ -28,7 +29,6 @@
android:layout_weight="1"
android:gravity="center"
android:text="@string/password_management"
android:textColor="@color/black"
android:textSize="16dp"
android:textStyle="bold" />
</LinearLayout>
@@ -36,7 +36,6 @@
android:id="@+id/change_password"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
@@ -45,7 +44,6 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/change_password"
android:textColor="@color/black"
android:textSize="16dp" />
<ImageView
android:layout_width="24dp"
@@ -58,7 +56,6 @@
android:id="@+id/retrieve_password"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
@@ -67,7 +64,6 @@
android:layout_weight="1"
android:layout_height="wrap_content"
android:text="@string/retrieve_password"
android:textColor="@color/black"
android:textSize="16dp" />
<ImageView
android:layout_width="24dp"

View File

@@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="@color/message_bg"
android:background="@color/white"
tools:context=".personal.OperationPasswordActivity">
<!-- 标题栏 -->
@@ -44,8 +44,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/operation_password_switch"
android:textSize="14dp"/>
android:textSize="16dp" />
<Switch
android:id="@+id/swOperationPassword"
android:layout_width="wrap_content"
@@ -57,65 +57,29 @@
</RelativeLayout>
<!-- 分割线 -->
<View
<LinearLayout
android:id="@+id/change_password"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/gray_divider"/>
android:layout_height="60dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingHorizontal="16dp">
<!-- 内容区域 -->
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="16dp">
<LinearLayout
android:layout_width="match_parent"
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical">
android:layout_weight="1"
android:text="@string/change_password"
android:textSize="16dp" />
<!-- 密码输入框 -->
<EditText
android:id="@+id/etPassword"
android:layout_width="match_parent"
android:layout_height="56dp"
android:background="@drawable/textinput_white_bg"
android:hint="@string/hint_operation_password"
android:inputType="numberPassword"
android:maxLength="6"
android:paddingHorizontal="16dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="16sp" />
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="12dp"
android:src="@drawable/right_back" />
<!-- 确认密码输入框 -->
<EditText
android:id="@+id/etConfirmPassword"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="16dp"
android:background="@drawable/textinput_white_bg"
android:hint="@string/hint_confirm_password"
android:inputType="numberPassword"
android:maxLength="6"
android:paddingHorizontal="16dp"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:textSize="16sp" />
</LinearLayout>
<!-- 确定重设密码按钮 -->
<android.widget.Button
android:id="@+id/btnConfirmReset"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="32dp"
android:background="@drawable/rounded_blue_bg"
android:text="@string/confirm_reset_password_btn"
android:textColor="@color/white"
android:textSize="16sp" />
</LinearLayout>
</ScrollView>
</LinearLayout>

View File

@@ -324,6 +324,7 @@
<string name="collect_face">采集人脸</string>
<string name="login_password">登录密码</string>
<string name="retrieve_password">找回密码</string>
<string name="input_new_op_pwd">请输入新操作密码</string>|
<string name="operation_password">操作密码</string>
<string name="enter_phone_number">请输入手机号</string>
<string name="enter_verification_code">请输入验证码</string>
@@ -440,6 +441,7 @@
<string name="regenerate">重新生成</string>
<string name="device_no">设备编号</string>
<string name="fw_version">固件版本</string>
<string name="generate_invite_code">生成邀请码</string>
<!-- WiFi管理 -->
<string name="not_set">未设置</string>
@@ -475,4 +477,15 @@
<string name="max_add_11_users">最多添加11个用户</string>
<string name="linked_user_phone_label">手机号码:%s</string>
<string name="linked_user_idcard_label">身份证号:%s</string>
<string name="direction_up">向上移动</string>
<string name="direction_down">向下移动</string>
<string name="direction_left">向左移动</string>
<string name="direction_right">向右移动</string>
<!-- 操作密码 -->
<string name="please_enable_operation_password_first">请先开启操作密码</string>
<string name="disable_operation_password_tip">确定要关闭操作密码吗?</string>
<string name="verify_failed">验证失败</string>
<string name="password_update_success">密码修改成功</string>
<string name="password_update_failed">密码修改失败</string>
</resources>

View File

@@ -232,6 +232,7 @@
<string name="use_smart_defense_app">Scan code to join via smart defense management APP</string>
<string name="cancel_invite">Cancel Invitation</string>
<string name="regenerate">Regenerate</string>
<string name="generate_invite_code">Generate Invite Code</string>
<!-- Dialog -->
<string name="tip">Tip</string>
@@ -308,6 +309,7 @@
<string name="face_in_circle">Please align your face within the circular area</string>
<string name="collect_face">Collect Face</string>
<string name="login_password">Login Password</string>
<string name="input_new_op_pwd">Enter new operation password</string>
<string name="enter_old_password">Enter old password</string>
<string name="confirm_reset_password">Confirm Reset Password</string>
<string name="retrieve_password">Retrieve Password</string>
@@ -485,4 +487,12 @@
<string name="direction_down">Move Down</string>
<string name="direction_left">Move Left</string>
<string name="direction_right">Move Right</string>
<!-- Operation Password -->
<string name="please_enable_operation_password_first">Please enable operation password first</string>
<string name="disable_operation_password_tip">Are you sure you want to disable operation password?</string>
<string name="verify_failed">Verification failed</string>
<string name="password_update_success">Password updated successfully</string>
<string name="password_update_failed">Failed to update password</string>
<string name="update_failed">Update failed</string>
</resources>