- {{ item.amount }} {{ item.fromSymbol || "USDT" }}
+ {{ item.amount }} {{ item.fromSymbol || "" }}
{{ getChainName(item.fromChain) }}
@@ -203,7 +203,7 @@
充值金额
{{ selectedItem.amount }}
- {{ selectedItem.fromSymbol || "USDT" }}
@@ -306,36 +306,36 @@ export default {
// 充值记录数据
rechargeRecords: [
- {
- address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- amount: 100,
- fromSymbol: "USDT",
- fromChain: "tron",
- status: 2,
- createTime: "2024-01-15 14:30:25",
- id: 1,
- txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- },
- {
- address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- amount: 100,
- fromSymbol: "USDT",
- fromChain: "tron",
- status: 2,
- createTime: "2024-01-15 14:30:25",
- id: 2,
- txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- },
- {
- address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- amount: 100,
- fromSymbol: "USDT",
- fromChain: "tron",
- status: 2,
- createTime: "2024-01-15 14:30:25",
- id: 3,
- txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
- },
+ // {
+ // address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // amount: 100,
+ // fromSymbol: "USDT",
+ // fromChain: "tron",
+ // status: 2,
+ // createTime: "2024-01-15 14:30:25",
+ // id: 1,
+ // txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // },
+ // {
+ // address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // amount: 100,
+ // fromSymbol: "USDT",
+ // fromChain: "tron",
+ // status: 2,
+ // createTime: "2024-01-15 14:30:25",
+ // id: 2,
+ // txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // },
+ // {
+ // address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // amount: 100,
+ // fromSymbol: "USDT",
+ // fromChain: "tron",
+ // status: 2,
+ // createTime: "2024-01-15 14:30:25",
+ // id: 3,
+ // txHash: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
+ // },
// {
// address: "TQn9Y2khEsLJW1ChVWFMSMeRDow5KcbLSE",
// amount: 100,
diff --git a/power_leasing/src/views/account/securitySettings.vue b/power_leasing/src/views/account/securitySettings.vue
index 03deacb..4fcce1f 100644
--- a/power_leasing/src/views/account/securitySettings.vue
+++ b/power_leasing/src/views/account/securitySettings.vue
@@ -467,6 +467,7 @@
import { getBindInfo, bindGoogle, sendOpenGoogleCode,getGoogleStatus,closeStepTwo,sendCloseGoogleCode,openStepTwo } from '../../api/verification'
import { rsaEncrypt } from '../../utils/rsaEncrypt'
import { closeAccount, sendCloseAccount,sendUpdatePwdCode,updatePasswordInCenter} from '../../api/user'
+import { createPasswordValidator } from '../../utils/validators/password'
export default {
name: 'SecuritySettings',
data() {
@@ -510,6 +511,8 @@ export default {
statusLoading: false, // 状态查询的 loading
step1Visible: false,
step2Visible: false,
+ // 仅用于步骤 1/2 的弹窗切换:防止“下一步”触发 step1 @close 后把二维码清空
+ step1ClosingForStepTransition: false,
closeDialogVisible: false, // 关闭双重验证弹窗
openDialogVisible: false, // 开启双重验证弹窗
deleteAccountDialogVisible: false, // 注销账号弹窗
@@ -682,6 +685,7 @@ export default {
mounted() {
this.check2FAStatus()
this.loadUserEmail()
+ this.initChangePasswordRules()
},
beforeDestroy() {
if (this.countdownTimer) {
@@ -698,6 +702,31 @@ export default {
}
},
methods: {
+ /**
+ * 初始化“修改密码”表单校验规则(与登录页同源:createPasswordValidator)
+ * 说明:这里在 mounted 中初始化,避免在 data() 中因 this 不可用而无法引用 methods
+ */
+ initChangePasswordRules() {
+ // 空值提示按登录页一致:请输入密码
+ const validateNewPassword = createPasswordValidator({ emptyMessage: '请输入密码' })
+
+ this.changePasswordRules = {
+ emailCode: [
+ { required: true, message: '请输入邮箱验证码', trigger: 'blur' },
+ { min: 1, max: 10, message: '验证码长度为1-10位', trigger: 'blur' }
+ ],
+ password: [
+ { required: true, validator: validateNewPassword, trigger: 'blur' }
+ ],
+ confirmPassword: [
+ { required: true, validator: this.validateConfirmPassword, trigger: 'blur' }
+ ],
+ googleCode: [
+ { required: true, message: '请输入谷歌验证码', trigger: 'blur' },
+ { pattern: /^\d{6}$/, message: '请输入6位数字', trigger: 'blur' }
+ ]
+ }
+ },
/**
* 安全设置页敏感操作前置校验:必须已开启双重验证(Google Authenticator)
* getGoogleStatus 返回值:0 开启;1 未绑定;2 关闭
@@ -1033,9 +1062,15 @@ export default {
* 只有在用户真正取消(点击取消按钮或 X)时才清空
*/
handleStep1Close() {
+ // 关键:点击“下一步”时也会触发 step1 的 close 事件(因为 step1Visible=false),
+ // 这种场景不要清空二维码,否则“上一步”回来会一直显示加载中。
+ if (this.step1ClosingForStepTransition) {
+ this.step1ClosingForStepTransition = false
+ return
+ }
+ // 用户真正关闭(取消 / 右上角 X):清空二维码与密钥,避免下次进入使用旧数据
this.qrCodeUrl = ''
- // 不清空 secretKey,因为第二步提交时需要用到
- // 如果用户点击取消,会在 handleStep2Close 中清空
+ this.secretKey = ''
},
/**
* 进入第二步
@@ -1045,6 +1080,8 @@ export default {
this.$message.warning('请先获取二维码或密钥')
return
}
+ // 标记:本次关闭 step1 是为了进入 step2,不应清空二维码/密钥
+ this.step1ClosingForStepTransition = true
this.step1Visible = false
this.step2Visible = true
},
@@ -1241,11 +1278,14 @@ export default {
* 确认密码验证(用于表单验证规则)
*/
validateConfirmPassword(rule, value, callback) {
- if (!value) {
+ const confirmVal = (value || '').trim()
+ const passwordVal = (this.changePasswordForm.password || '').trim()
+
+ if (!confirmVal) {
callback(new Error('请再次输入新密码'))
return
}
- if (value !== this.changePasswordForm.password) {
+ if (confirmVal !== passwordVal) {
callback(new Error('两次输入的密码不一致'))
return
}
@@ -1287,12 +1327,10 @@ export default {
this.$message.success('密码修改成功')
this.changePasswordDialogVisible = false
this.handleChangePasswordDialogClose()
- } else {
- this.$message.error(res?.message || res?.msg || '修改密码失败,请检查输入信息')
- }
+ }
} catch (e) {
console.error('修改密码失败', e)
- this.$message.error('修改密码失败,请稍后重试')
+
} finally {
this.changingPassword = false
}
@@ -1732,12 +1770,14 @@ export default {
gap: 6px;
margin-top: 6px;
padding: 10px 12px;
- background: #f0f9ff;
- border: 1px solid #b3d8ff;
+ background: #f5f7ff;
+ border-left: 3px solid #667eea;
border-radius: 4px;
font-size: 12px;
- color: #606266;
+ color: #666;
line-height: 1.5;
+ text-align: left;
+ box-sizing: border-box;
}
.password-tip span {
diff --git a/power_leasing/src/views/account/sellerFundsFlow.vue b/power_leasing/src/views/account/sellerFundsFlow.vue
index 2f22210..8392999 100644
--- a/power_leasing/src/views/account/sellerFundsFlow.vue
+++ b/power_leasing/src/views/account/sellerFundsFlow.vue
@@ -11,6 +11,7 @@
0”等校验,不参与上限判断)
const feeInt = this.toScaledInt(this.withdrawForm.fee)
- const totalRequired = amountInt + feeInt
-
- // 钱包总余额(可用余额 + 冻结余额)
- const availableBalance = this.WalletData && (this.WalletData.walletBalance || this.WalletData.balance) || 0
- const blockedBalance = this.WalletData && (this.WalletData.blockedBalance || 0) || 0
- const totalBalance = parseFloat(availableBalance) + parseFloat(blockedBalance)
- const totalBalanceInt = this.toScaledInt(totalBalance)
-
- // 提现金额可以等于可用余额,但提现金额+手续费不能超过钱包总余额
- if (totalRequired > totalBalanceInt) {
- const totalText = this.formatDec6FromInt(totalRequired)
- callback(new Error(`提现金额加上手续费(${totalText} ${this.displayWithdrawSymbol})不能超过钱包余额`))
- return
- }
-
+
// 可用余额(用于判断提现金额是否超过可用余额)
+ const availableBalance = this.WalletData && (this.WalletData.walletBalance || this.WalletData.balance) || 0
const availableBalanceInt = this.toScaledInt(availableBalance)
// 允许提现金额等于可用余额,但不能大于
if (amountInt > availableBalanceInt) {
@@ -1088,7 +1078,7 @@ export default {
// 检查最小提现金额
// 最小提现金额 1 USDT
if (amountInt < 1000000) {
- callback(new Error('最小提现金额为1 USDT'))
+ callback(new Error('最小提现金额为1'))
return
}
diff --git a/power_leasing/src/views/account/withdrawRecord.vue b/power_leasing/src/views/account/withdrawRecord.vue
index 6f17a65..cd05d53 100644
--- a/power_leasing/src/views/account/withdrawRecord.vue
+++ b/power_leasing/src/views/account/withdrawRecord.vue
@@ -28,24 +28,24 @@
- -{{ formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').text }}
+ -{{ formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || '').text }}
- -{{ formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').text }}
+ -{{ formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || '').text }}
- {{ formatAmount(scope.row.serviceCharge, scope.row.coin || scope.row.toSymbol || 'USDT').text }}
+ {{ formatAmount(scope.row.serviceCharge, scope.row.coin || scope.row.toSymbol || '').text }}
@@ -54,20 +54,37 @@
{{ String(scope.row.coin || scope.row.toSymbol || '').toUpperCase() }}
-
+
-
- {{ scope.row.toAddress }}
-
- 复制
+
+
+
+ {{ scope.row.toAddress }}
+
+ 复制
+
-
+
-
- {{ scope.row.txHash }}
-
- 复制
+
+
+
+ {{ scope.row.txHash }}
+
+ 复制
+
@@ -82,7 +99,7 @@
@@ -111,6 +128,33 @@ export default {
return {
loading: false,
rows: [],
+ /** 是否启用模拟数据,仅用于页面展示 */
+ useMockRows: false,
+ /** 模拟数据集合 */
+ mockRows: [
+ {
+ createTime: '2026-01-23T09:12:30.000Z',
+ amount: '1289.12345678',
+ serviceCharge: '1.23',
+ toChain: 'ethereum',
+ coin: 'usdt',
+ toAddress: '0x2c1f3C6c9F0a2D7b8e9fA1b2C3D4e5F67890aBcD9f7a3d1c0b5e6f8a9c0d1e2f3a4b5c6d7e8f9012',
+ txHash: '0x9f7a3d1c0b5e6f8a9c0d1e2f3a4b5c6d7e8f90123456789abcdef1234567890',
+ status: 2,
+ updateTime: '2026-01-23T10:18:45.000Z'
+ },
+ {
+ createTime: '2026-01-22T15:06:12.000Z',
+ amount: '56.78',
+ serviceCharge: '0.12',
+ toChain: 'tron',
+ coin: 'usdt',
+ toAddress: 'TYD4xXGZf6hRk8JQ2q4mE3s9J8zY6pU2qA7q9s8d7f6g5h4j3k2l1zXcVbN',
+ txHash: '0xabc123def456',
+ status: 1,
+ updateTime: '2026-01-22T15:20:00.000Z'
+ }
+ ],
pageNum: 1,
pageSize: 20,
total: 0
@@ -163,6 +207,13 @@ export default {
async fetchList() {
this.loading = true
try {
+ if (this.useMockRows) {
+ // eslint-disable-next-line no-console
+ console.info('[withdrawRecord] 使用模拟数据展示效果')
+ this.rows = Array.isArray(this.mockRows) ? this.mockRows : []
+ this.total = this.rows.length
+ return
+ }
const res = await balanceWithdrawListV2({ pageNum: this.pageNum, pageSize: this.pageSize })
const data = res && (res.data || res)
const list = Array.isArray(data && data.rows) ? data.rows : (Array.isArray(data) ? data : [])
@@ -197,5 +248,17 @@ export default {
.amount-red { color: #ef4444; font-weight: 700; }
.mono-ellipsis { font-family: "Monaco", "Menlo", monospace; max-width: 360px; display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
.pagination { display: flex; justify-content: flex-end; margin-top: 8px; }
+/** 交易HASH列:文本省略,按钮优先显示,窄屏隐藏文本 */
+.hash-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
+.hash-text { flex: 1 1 auto; min-width: 0; }
+.hash-copy { flex: 0 0 auto; }
+/** 收款地址列:文本省略,按钮优先显示,窄屏隐藏文本 */
+.address-cell { display: flex; align-items: center; gap: 8px; min-width: 0; }
+.address-text { flex: 1 1 auto; min-width: 0; }
+.address-copy { flex: 0 0 auto; }
+@media (max-width: 1200px) {
+ .hash-text { display: none; }
+ .address-text { display: none; }
+}
diff --git a/power_leasing/src/views/account/withdrawalHistory.vue b/power_leasing/src/views/account/withdrawalHistory.vue
index f259c1e..579970e 100644
--- a/power_leasing/src/views/account/withdrawalHistory.vue
+++ b/power_leasing/src/views/account/withdrawalHistory.vue
@@ -75,7 +75,7 @@
>