From da223f89352863c3bf6007df9c628f0996cd8d9d Mon Sep 17 00:00:00 2001 From: yaoqin <497681109@qq.com> Date: Fri, 16 Jan 2026 15:03:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=8F=E5=91=A8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- power_leasing/.env.staging | 4 +- power_leasing/src/api/shops.js | 15 +- power_leasing/src/utils/productService.js | 56 ++-- power_leasing/src/utils/secureStorage.js | 2 +- .../src/utils/validators/password.js | 61 ++++ power_leasing/src/views/account/OrderList.vue | 28 +- .../src/views/account/SellerOrders.vue | 4 +- power_leasing/src/views/account/myShops.vue | 200 +++++++++++- .../src/views/account/orderDetail.vue | 2 +- power_leasing/src/views/account/orders.vue | 4 +- .../src/views/account/productMachineAdd.vue | 68 +++- power_leasing/src/views/account/products.vue | 71 ++++- .../src/views/account/securitySettings.vue | 103 +++++- .../src/views/account/sellerFundsFlow.vue | 1 + power_leasing/src/views/account/wallet.vue | 95 +++++- power_leasing/src/views/auth/login.vue | 51 +-- power_leasing/src/views/auth/register.vue | 20 +- .../src/views/auth/reset-password.vue | 24 +- power_leasing/src/views/cart/index.vue | 91 +++++- power_leasing/test.zip | Bin 2082456 -> 2091527 bytes power_leasing/test/css/app.9ce7bea6.css | 1 + power_leasing/test/index.html | 2 +- power_leasing/test/js/app.b471bca6.js | 2 + power_leasing/test/js/app.b471bca6.js.map | 1 + ...✅ Token存储降级方案修复说明.md | 104 ------ power_leasing/✅ 优化完成报告.md | 238 -------------- power_leasing/优化完成总结.md | 301 ------------------ power_leasing/🔴 最后手动步骤.md | 77 ----- 28 files changed, 738 insertions(+), 888 deletions(-) create mode 100644 power_leasing/src/utils/validators/password.js create mode 100644 power_leasing/test/css/app.9ce7bea6.css create mode 100644 power_leasing/test/js/app.b471bca6.js create mode 100644 power_leasing/test/js/app.b471bca6.js.map delete mode 100644 power_leasing/✅ Token存储降级方案修复说明.md delete mode 100644 power_leasing/✅ 优化完成报告.md delete mode 100644 power_leasing/优化完成总结.md delete mode 100644 power_leasing/🔴 最后手动步骤.md diff --git a/power_leasing/.env.staging b/power_leasing/.env.staging index b305d1b..8ad7e3f 100644 --- a/power_leasing/.env.staging +++ b/power_leasing/.env.staging @@ -7,8 +7,8 @@ NODE_ENV = production ENV = 'staging' # 测试环境 -# VUE_APP_BASE_API = 'http://10.168.2.220:8888' -VUE_APP_BASE_API = 'https://test.m2pool.com/api/' + VUE_APP_BASE_API = 'http://10.168.2.220:8888' +# VUE_APP_BASE_API = 'https://test.m2pool.com/api/' VUE_APP_BASE_URL = 'https://test.m2pool.com/' diff --git a/power_leasing/src/api/shops.js b/power_leasing/src/api/shops.js index 7c3716e..eb40a58 100644 --- a/power_leasing/src/api/shops.js +++ b/power_leasing/src/api/shops.js @@ -27,12 +27,21 @@ export function updateShop(data) { }) } -// 删除店铺 -export function deleteShop(id) { +// 删除店铺(兼容:deleteShop(id) / deleteShop({ id, gCode }) / deleteShop(id, gCode)) +export function deleteShop(id, gCode) { + // 兼容对象入参 + if (id && typeof id === 'object') { + const payload = id + return request({ + url: `/lease/shop/deleteShop`, + method: 'post', + data: payload + }) + } return request({ url: `/lease/shop/deleteShop`, method: 'post', - data: { id } + data: gCode != null ? { id, gCode } : { id } }) } diff --git a/power_leasing/src/utils/productService.js b/power_leasing/src/utils/productService.js index b798376..b507b40 100644 --- a/power_leasing/src/utils/productService.js +++ b/power_leasing/src/utils/productService.js @@ -18,34 +18,34 @@ * @type {Product[]} */ const products = [ - { - id: 'p1001', - title: '新能源充电桩(家用)', - description: '7kW 单相,智能预约,支持远程监控。', - price: 1299, - image: 'https://via.placeholder.com/300x200?text=%E5%85%85%E7%94%B5%E6%A1%A9' - }, - { - id: 'p1002', - title: '工业电能表', - description: '三相四线,远程抄表,Modbus 通信。', - price: 899, - image: 'https://via.placeholder.com/300x200?text=%E7%94%B5%E8%83%BD%E8%A1%A8' - }, - { - id: 'p1003', - title: '配电柜(入门版)', - description: 'IP54 防护,内置断路器与防雷模块。', - price: 5599, - image: 'https://via.placeholder.com/300x200?text=%E9%85%8D%E7%94%B5%E6%9F%9C' - }, - { - id: 'p1004', - title: '工矿照明灯', - description: '120W 高亮,耐腐蚀,适配多场景。', - price: 329, - image: 'https://via.placeholder.com/300x200?text=%E7%85%A7%E6%98%8E%E7%81%AF' - } + // { + // id: 'p1001', + // title: '新能源充电桩(家用)', + // description: '7kW 单相,智能预约,支持远程监控。', + // price: 1299, + // image: 'https://via.placeholder.com/300x200?text=%E5%85%85%E7%94%B5%E6%A1%A9' + // }, + // { + // id: 'p1002', + // title: '工业电能表', + // description: '三相四线,远程抄表,Modbus 通信。', + // price: 899, + // image: 'https://via.placeholder.com/300x200?text=%E7%94%B5%E8%83%BD%E8%A1%A8' + // }, + // { + // id: 'p1003', + // title: '配电柜(入门版)', + // description: 'IP54 防护,内置断路器与防雷模块。', + // price: 5599, + // image: 'https://via.placeholder.com/300x200?text=%E9%85%8D%E7%94%B5%E6%9F%9C' + // }, + // { + // id: 'p1004', + // title: '工矿照明灯', + // description: '120W 高亮,耐腐蚀,适配多场景。', + // price: 329, + // image: 'https://via.placeholder.com/300x200?text=%E7%85%A7%E6%98%8E%E7%81%AF' + // } ] /** diff --git a/power_leasing/src/utils/secureStorage.js b/power_leasing/src/utils/secureStorage.js index 442af37..04b321b 100644 --- a/power_leasing/src/utils/secureStorage.js +++ b/power_leasing/src/utils/secureStorage.js @@ -6,7 +6,7 @@ /** * 加密密钥(从环境变量或固定字符串派生) - * 注意:实际生产环境应该使用更安全的密钥管理方案 + * */ const ENCRYPTION_KEY_SOURCE = 'power-leasing-2024-secure-key-v1'; diff --git a/power_leasing/src/utils/validators/password.js b/power_leasing/src/utils/validators/password.js new file mode 100644 index 0000000..d3e9864 --- /dev/null +++ b/power_leasing/src/utils/validators/password.js @@ -0,0 +1,61 @@ +/** + * 密码校验工具(与登录页体验对齐:分步校验,返回最具体的错误提示) + * + * 规则: + * - 长度 8-32 位 + * - 必须包含:小写字母 / 大写字母 / 数字 / 特殊字符 + * - 不能包含中文字符 + * + * @param {{ emptyMessage?: string }} [options] + * @returns {(rule: any, value: any, callback: Function) => void} + */ +export const createPasswordValidator = (options = {}) => { + const emptyMessage = options.emptyMessage || '请输入密码' + + return (rule, value, callback) => { + if (!value) { + callback(new Error(emptyMessage)) + return + } + + const v = String(value) + + const checks = [ + { + test: (s) => s.length >= 8 && s.length <= 32, + msg: '密码长度应为8-32位' + }, + { + test: (s) => /[a-z]/.test(s), + msg: '密码应包含小写字母' + }, + { + test: (s) => /[A-Z]/.test(s), + msg: '密码应包含大写字母' + }, + { + test: (s) => /\d/.test(s), + msg: '密码应包含数字' + }, + { + test: (s) => /[\W_]/.test(s), + msg: '密码应包含特殊字符(如 !@#$%^&*)' + }, + { + test: (s) => !/[\u4e00-\u9fa5]/.test(s), + msg: '密码不能包含中文字符' + } + ] + + for (const check of checks) { + if (!check.test(v)) { + callback(new Error(check.msg)) + return + } + } + + callback() + } +} + + diff --git a/power_leasing/src/views/account/OrderList.vue b/power_leasing/src/views/account/OrderList.vue index a4e01fa..6ce1fcc 100644 --- a/power_leasing/src/views/account/OrderList.vue +++ b/power_leasing/src/views/account/OrderList.vue @@ -96,7 +96,7 @@ - + @@ -208,8 +208,17 @@ export default { items: { type: Array, default: () => [] }, emptyText: { type: String, default: '暂无数据' }, showCheckout: { type: Boolean, default: false }, - onCancel: { type: Function, default: null }, - isSeller: { type: Boolean, default: false } // 标识是否是卖家订单 + /** + * 是否为卖家侧订单列表(用于详情页跳转后左侧导航分组高亮) + */ + isSeller: { type: Boolean, default: false }, + /** + * 是否展示“订单完成时间”列 + * - 订单进行中:false + * - 订单已完成:true + */ + showEndTime: { type: Boolean, default: false }, + onCancel: { type: Function, default: null } }, data() { return { @@ -311,18 +320,13 @@ export default { }); return } + // 记录来源:用于详情页决定左侧导航分组(买家/卖家) + const from = this.isSeller ? 'seller' : 'buyer' + try { sessionStorage.setItem('orderDetailFrom', from) } catch (e) { /* noop */ } try { - // 判断是买家还是卖家订单,传递 from 参数 - const from = this.isSeller ? 'seller' : 'buyer' - // 保存到 sessionStorage,以便详情页可以读取 - try { - sessionStorage.setItem('orderDetailFrom', from) - } catch (e) { - console.warn('保存订单来源失败', e) - } this.$router.push({ path: `/account/order-detail/${id}`, - query: { from: from } + query: { from } }) } catch (e) { this.$message({ diff --git a/power_leasing/src/views/account/SellerOrders.vue b/power_leasing/src/views/account/SellerOrders.vue index 70d86c7..5d18cea 100644 --- a/power_leasing/src/views/account/SellerOrders.vue +++ b/power_leasing/src/views/account/SellerOrders.vue @@ -3,10 +3,10 @@

已售出订单

- + - + diff --git a/power_leasing/src/views/account/myShops.vue b/power_leasing/src/views/account/myShops.vue index 4b2975c..658c5d6 100644 --- a/power_leasing/src/views/account/myShops.vue +++ b/power_leasing/src/views/account/myShops.vue @@ -222,6 +222,15 @@ @input="handleEditFeeRateInput" /> +
+ + +
取消 @@ -263,7 +272,7 @@ import { getMyShop, updateShop, deleteShop, queryShop, closeShop ,updateShopConf import { coinList } from '@/utils/coinList' import { getShopConfig,getShopConfigV2 ,withdrawBalanceForSeller,updateShopConfigV2} from '@/api/wallet' import { rsaEncrypt, rsaEncryptSync } from '@/utils/rsaEncrypt' - +import { getGoogleStatus } from '@/api/verification' export default { name: 'AccountMyShops', @@ -281,7 +290,7 @@ export default { state: 0 }, visibleEdit: false, - editForm: { id: '', name: '', image: '', description: '', feeRate: '' }, + editForm: { id: '', name: '', image: '', description: '', feeRate: '', gCode: '' }, // 店铺配置列表 shopConfigs: [], visibleConfigEdit: false, @@ -370,6 +379,58 @@ export default { this.fetchMyShop() }, methods: { + /** + * 修改店铺:谷歌验证码输入(仅数字,最多6位) + */ + handleEditShopGoogleCodeInput(v) { + this.editForm.gCode = String(v || '').replace(/\D/g, '').slice(0, 6) + }, + /** + * 钱包相关敏感操作前置校验:必须已开启双重验证(Google Authenticator) + * getGoogleStatus 返回值:0 开启;1 未绑定;2 关闭 + * + * - status=0:允许继续操作 + * - status=1/2:弹窗提示并阻止操作,可跳转到“安全设置”页面开启/绑定 + * + * @param {string} actionLabel - 操作名称(用于文案:如“提现/修改/删除”) + * @returns {Promise} 是否允许继续 + */ + async ensureGoogleStatusEnabledForWalletOp(actionLabel) { + try { + const res = await getGoogleStatus() + if (!res || !(res.code === 0 || res.code === 200)) { + this.$message.error('获取双重验证状态失败,请稍后重试') + return false + } + + const status = (res && res.data && res.data.status != null) ? res.data.status : (res.data ?? 1) + if (Number(status) === 0) return true + + const title = '安全提示' + const reason = Number(status) === 1 ? '您尚未绑定双重验证' : '您已关闭双重验证' + const message = ` +
+
${reason}
+
+ 请先在安全设置中绑定并开启双重验证后,才可以进行${actionLabel || '该'}操作。 +
+
+ ` + + await this.$confirm(message, title, { + confirmButtonText: '去安全设置', + cancelButtonText: '取消', + type: 'warning', + dangerouslyUseHTMLString: true, + customClass: 'google-2fa-guard-dialog' + }) + this.$router.push('/account/security-settings') + return false + } catch (e) { + // 用户取消弹窗或接口异常都视为不允许继续 + return false + } + }, /** 余额展示:带币种单位 */ formatBalance(row) { try { @@ -399,6 +460,9 @@ export default { }, /** 打开提现对话框(行数据驱动) */ async handleWithdraw(row) { + const ok = await this.ensureGoogleStatusEnabledForWalletOp('提现') + if (!ok) return + this.currentWithdrawRow = row || {} const fee = Number(row && (row.serviceCharge != null ? row.serviceCharge : row.charge)) this.withdrawForm.fee = Number.isFinite(fee) ? this.formatDec6(fee) : '0.00' @@ -413,7 +477,10 @@ export default { { required: true, message: '请输入提现金额', trigger: 'blur' }, { validator: this.validateWithdrawAmount, trigger: 'blur' } ], - // 地址为只读已填,不再要求用户输入 + toAddress: [ + { required: true, message: '请输入收款钱包地址', trigger: 'blur' }, + { validator: this.validateWithdrawToAddress, trigger: 'blur' } + ], googleCode: [ { required: true, message: '请输入谷歌验证码', trigger: 'blur' }, { validator: this.validateGoogleCode, trigger: 'blur' } @@ -584,6 +651,17 @@ export default { if (!/^\d{6}$/.test(v)) { callback(new Error('谷歌验证码必须是6位数字')); return } callback() }, + /** + * 校验:收款地址不能为空 + * @param {any} rule + * @param {string} value + * @param {(err?: Error) => void} callback + */ + validateWithdrawToAddress(rule, value, callback) { + const v = String(value || '').trim() + if (!v) { callback(new Error('请输入收款钱包地址')); return } + callback() + }, /** * 手续费率显示:最多6位小数,去除多余的0;空值显示为 '-' */ @@ -707,6 +785,9 @@ export default { } }, async handleEditConfig(row) { + const ok = await this.ensureGoogleStatusEnabledForWalletOp('修改') + if (!ok) return + try { const res = await getChainAndCoin({ id: row.id }) if (res && (res.code === 0 || res.code === 200) && res.data) { @@ -745,7 +826,31 @@ export default { } }, async handleDeleteConfig(row) { - this.deleteShopConfig({id:row.id}) + const ok = await this.ensureGoogleStatusEnabledForWalletOp('删除') + if (!ok) return + + try { + const { value } = await this.$prompt( + '请输入 6 位谷歌验证码以删除该钱包绑定配置', + '安全验证', + { + confirmButtonText: '确认删除', + cancelButtonText: '取消', + type: 'warning', + inputPlaceholder: '6位数字验证码', + inputPattern: /^\d{6}$/, + inputErrorMessage: '谷歌验证码必须是6位数字' + } + ) + const gCode = String(value || '').trim() + if (!/^\d{6}$/.test(gCode)) { + this.$message.warning('谷歌验证码必须是6位数字') + return + } + await this.deleteShopConfig({ id: row.id, gCode }) + } catch (e) { + // 用户取消或弹窗关闭 + } }, /** @@ -828,6 +933,8 @@ export default { this.configForm.payCoins = (this.configForm.payCoins || []).filter(v => String(v) !== String(value)) }, async handleOpenEdit() { + const ok = await this.ensureGoogleStatusEnabledForWalletOp('修改店铺') + if (!ok) return try { // 先打开弹窗,提供更快的视觉反馈 this.visibleEdit = true @@ -839,7 +946,8 @@ export default { name: res.data.name, image: res.data.image, description: res.data.description, - feeRate: res.data.feeRate + feeRate: res.data.feeRate, + gCode: '' } @@ -850,7 +958,8 @@ export default { name: this.shop.name, image: this.shop.image, description: this.shop.description, - feeRate: this.shop.feeRate + feeRate: this.shop.feeRate, + gCode: '' } this.$message.warning(res && res.msg ? res.msg : '未获取到店铺详情') } @@ -861,7 +970,8 @@ export default { name: this.shop.name, image: this.shop.image, description: this.shop.description, - feeRate: this.shop.feeRate + feeRate: this.shop.feeRate, + gCode: '' } console.error('查询店铺详情失败:', error) @@ -918,7 +1028,14 @@ export default { } this.editForm.feeRate = rateNum.toString() - const payload = { ...this.editForm } + // 谷歌验证码:必填 6 位数字 + const gCode = String(this.editForm.gCode || '').trim() + if (!/^\d{6}$/.test(gCode)) { + this.$message.warning('请输入6位谷歌验证码') + return + } + + const payload = { ...this.editForm, gCode } const res = await updateShop(payload) if (res && (res.code === 0 || res.code === 200)) { this.$message({ @@ -941,9 +1058,27 @@ export default { } }, async handleDelete() { + const ok = await this.ensureGoogleStatusEnabledForWalletOp('删除店铺') + if (!ok) return try { - await this.$confirm('确定删除该店铺吗?此操作不可恢复', '提示', { type: 'warning' }) - const res = await deleteShop(this.shop.id) + const { value } = await this.$prompt( + '删除店铺将不可恢复,请输入 6 位谷歌验证码确认删除', + '安全验证', + { + confirmButtonText: '确认删除', + cancelButtonText: '取消', + type: 'warning', + inputPlaceholder: '6位数字验证码', + inputPattern: /^\d{6}$/, + inputErrorMessage: '谷歌验证码必须是6位数字' + } + ) + const gCode = String(value || '').trim() + if (!/^\d{6}$/.test(gCode)) { + this.$message.warning('谷歌验证码必须是6位数字') + return + } + const res = await deleteShop(this.shop.id, gCode) if (res && (res.code === 0 || res.code === 200)) { this.$message({ message: '删除成功', @@ -1074,6 +1209,51 @@ export default { /* 全局弹窗宽度微调(仅当前页面生效)*/ .el-dialog__body .row { margin-bottom: 12px; } +/* 双重验证拦截弹窗 - 轻渐变美化(仅当前页面生效) */ +.google-2fa-guard-dialog { + border-radius: 12px; + overflow: hidden; +} +.google-2fa-guard-dialog .el-message-box__header { + /* 与导航按钮同色系:#667eea -> #764ba2,降低透明度让其更淡 */ + background: linear-gradient(135deg, rgba(102, 126, 234, 0.16), rgba(118, 75, 162, 0.10)); + border-bottom: 1px solid rgba(102, 126, 234, 0.10); + padding: 14px 16px 10px; +} +.google-2fa-guard-dialog .el-message-box__title { + font-weight: 700; + color: #1f2d3d; +} +.google-2fa-guard-dialog .el-message-box__content { + padding: 14px 18px 6px; +} +.google-2fa-guard-dialog .el-message-box__message { + color: #374151; + line-height: 1.7; +} +.google-2fa-guard-dialog .google-2fa-guard__title { + font-size: 15px; + font-weight: 700; + color: #111827; + margin-bottom: 6px; +} +.google-2fa-guard-dialog .google-2fa-guard__desc { + font-size: 13px; + color: #4b5563; +} +.google-2fa-guard-dialog .el-message-box__btns { + padding: 10px 16px 14px; +} +.google-2fa-guard-dialog .el-button--primary { + border: none; + /* 与导航按钮一致的紫色渐变 */ + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); +} +.google-2fa-guard-dialog .el-button--primary:hover, +.google-2fa-guard-dialog .el-button--primary:focus { + filter: brightness(1.02); +} + /* 弹窗表单统一对齐与留白优化 */ .el-dialog__body .row { display: grid; diff --git a/power_leasing/src/views/account/orderDetail.vue b/power_leasing/src/views/account/orderDetail.vue index 3328923..20de93a 100644 --- a/power_leasing/src/views/account/orderDetail.vue +++ b/power_leasing/src/views/account/orderDetail.vue @@ -10,7 +10,7 @@
店铺:{{ order.shopName || '—' }}
金额(USDT):{{ order.totalPrice }}
创建时间:{{ formatDateTime(order.createTime) }}
-
订单完成时间:{{ formatDateTime(order.endTime) }}
+
订单完成时间:{{ formatDateTime(order.endTime) }}
diff --git a/power_leasing/src/views/account/orders.vue b/power_leasing/src/views/account/orders.vue index 94665ca..c94d506 100644 --- a/power_leasing/src/views/account/orders.vue +++ b/power_leasing/src/views/account/orders.vue @@ -3,10 +3,10 @@

订单列表

- + - + \n \n \n \n\n \n \n \n 矿机\n \n \n \n\n \n \n \n \n \n \n\n \n \n \n \n\n \n \n\n \n \n\n\n \n \n\n \n \n\n \n \n\n \n \n \n 上架\n 下架\n \n \n\n \n \n
\n 创建商品\n 重置\n 取消\n
\n
\n \n
\n \n\n\n\n\n ","\n\n\n\n\n","/**\r\n * 全局输入表情符号拦截守卫(极简,无侵入)\r\n * 作用:拦截所有原生 input/textarea 的输入事件,移除 Emoji,并重新派发 input 事件以同步 v-model\r\n * 注意:\r\n * - 跳过正在输入法合成阶段(compositionstart ~ compositionend),避免影响中文输入\r\n * - 默认对所有可编辑 input/textarea 生效;如需个别放行,可在元素上加 data-allow-emoji=\"true\"\r\n */\r\nexport const initNoEmojiGuard = () => {\r\n if (typeof window === 'undefined') return\r\n if (window.__noEmojiGuardInitialized) return\r\n window.__noEmojiGuardInitialized = true\r\n\r\n // 覆盖常见 Emoji、旗帜、杂项符号、ZWJ、变体选择符、组合键帽\r\n const emojiPattern = /[\\u{1F300}-\\u{1FAFF}]|[\\u{1F1E6}-\\u{1F1FF}]|[\\u{2600}-\\u{26FF}]|[\\u{2700}-\\u{27BF}]|[\\u{FE0F}]|[\\u{200D}]|[\\u{20E3}]/gu\r\n\r\n /**\r\n * 判断是否是需要拦截的可编辑元素\r\n * @param {EventTarget} el 事件目标\r\n * @returns {boolean}\r\n */\r\n const isEditableTarget = (el) => {\r\n if (!el || !(el instanceof Element)) return false\r\n if (el.getAttribute && el.getAttribute('data-allow-emoji') === 'true') return false\r\n const tag = el.tagName\r\n if (tag === 'INPUT') {\r\n const type = (el.getAttribute('type') || 'text').toLowerCase()\r\n // 排除不会产生文本的类型\r\n const disallow = ['checkbox', 'radio', 'file', 'hidden', 'button', 'submit', 'reset', 'range', 'color', 'date', 'datetime-local', 'month', 'time', 'week']\r\n return disallow.indexOf(type) === -1\r\n }\r\n if (tag === 'TEXTAREA') return true\r\n return false\r\n }\r\n\r\n // 记录输入法合成状态\r\n const setComposing = (el, composing) => {\r\n try { el.__noEmojiComposing = composing } catch (e) {}\r\n }\r\n const isComposing = (el) => !!(el && el.__noEmojiComposing)\r\n\r\n // 结束合成时做一次清洗\r\n document.addEventListener('compositionstart', (e) => {\r\n if (!isEditableTarget(e.target)) return\r\n setComposing(e.target, true)\r\n }, true)\r\n document.addEventListener('compositionend', (e) => {\r\n if (!isEditableTarget(e.target)) return\r\n setComposing(e.target, false)\r\n sanitizeAndRedispatch(e.target)\r\n }, true)\r\n\r\n // 主输入拦截:捕获阶段尽早处理\r\n document.addEventListener('input', (e) => {\r\n const target = e.target\r\n if (!isEditableTarget(target)) return\r\n if (isComposing(target)) return\r\n sanitizeAndRedispatch(target)\r\n }, true)\r\n\r\n /**\r\n * 清洗目标元素的值并在变更时重新派发 input 事件\r\n * @param {HTMLInputElement|HTMLTextAreaElement} target\r\n */\r\n function sanitizeAndRedispatch(target) {\r\n const before = String(target.value ?? '')\r\n if (!before) return\r\n if (!emojiPattern.test(before)) return\r\n const selectionStart = target.selectionStart\r\n const selectionEnd = target.selectionEnd\r\n const after = before.replace(emojiPattern, '')\r\n if (after === before) return\r\n target.value = after\r\n try {\r\n // 重置光标,尽量贴近原位置\r\n if (typeof selectionStart === 'number' && typeof selectionEnd === 'number') {\r\n const removed = before.length - after.length\r\n const nextPos = Math.max(0, selectionStart - removed)\r\n target.setSelectionRange(nextPos, nextPos)\r\n }\r\n } catch (e) {}\r\n // 重新派发 input 事件以同步 v-model\r\n const evt = new Event('input', { bubbles: true })\r\n target.dispatchEvent(evt)\r\n }\r\n}\r\n\r\n\r\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./fundsFlow.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./fundsFlow.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./fundsFlow.vue?vue&type=template&id=147a043d&scoped=true\"\nimport script from \"./fundsFlow.vue?vue&type=script&lang=js\"\nexport * from \"./fundsFlow.vue?vue&type=script&lang=js\"\nimport style0 from \"./fundsFlow.vue?vue&type=style&index=0&id=147a043d&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"147a043d\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./login.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./login.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./login.vue?vue&type=template&id=44221ada&scoped=true\"\nimport script from \"./login.vue?vue&type=script&lang=js\"\nexport * from \"./login.vue?vue&type=script&lang=js\"\nimport style0 from \"./login.vue?vue&type=style&index=0&id=44221ada&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"44221ada\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"account-page\"},[_c('div',{staticClass:\"account-layout\"},[_c('aside',{staticClass:\"sidebar\"},[_c('nav',{staticClass:\"side-nav\"},[_c('div',{staticClass:\"user-role\",attrs:{\"role\":\"group\",\"aria-label\":\"导航分组切换\"}},[_c('button',{staticClass:\"role-button\",class:{ active: _vm.activeRole === 'buyer' && !_vm.isSecuritySettingsPage },attrs:{\"aria-pressed\":_vm.activeRole === 'buyer' && !_vm.isSecuritySettingsPage,\"tabindex\":\"0\"},on:{\"click\":function($event){return _vm.handleClickRole('buyer')},\"keydown\":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;$event.preventDefault();return _vm.handleClickRole('buyer')},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"space\",32,$event.key,[\" \",\"Spacebar\"]))return null;$event.preventDefault();return _vm.handleClickRole('buyer')}]}},[_vm._v(\"买家相关\")]),_c('button',{staticClass:\"role-button\",class:{ active: _vm.activeRole === 'seller' && !_vm.isSecuritySettingsPage },attrs:{\"aria-pressed\":_vm.activeRole === 'seller' && !_vm.isSecuritySettingsPage,\"tabindex\":\"0\"},on:{\"click\":function($event){return _vm.handleClickRole('seller')},\"keydown\":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;$event.preventDefault();return _vm.handleClickRole('seller')},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"space\",32,$event.key,[\" \",\"Spacebar\"]))return null;$event.preventDefault();return _vm.handleClickRole('seller')}]}},[_vm._v(\"卖家相关\")])]),_vm._l((_vm.displayedLinks),function(item){return _c('router-link',{key:item.to,class:['side-link', _vm.isActiveLink(item.to) ? 'active' : ''],attrs:{\"to\":item.to}},[_vm._v(_vm._s(item.label))])})],2)]),_c('section',{staticClass:\"content\"},[_c('router-view')],1)])])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"receipt-page\"},[_c('div',{staticClass:\"card\",attrs:{\"aria-label\":\"收款记录\",\"tabindex\":\"0\"}},[_vm._m(0),(_vm.loading)?_c('div',{staticClass:\"loading\"},[_c('i',{staticClass:\"el-icon-loading\",attrs:{\"aria-label\":\"加载中\",\"role\":\"img\"}}),_vm._v(\" 加载中... \")]):_c('div',[_c('el-table',{ref:\"receiptTable\",staticStyle:{\"width\":\"100%\",\"table-layout\":\"auto\"},attrs:{\"data\":_vm.rows,\"border\":\"\",\"stripe\":\"\",\"size\":\"small\",\"row-key\":_vm.getRowKey,\"expand-row-keys\":_vm.expandedRowKeys,\"row-class-name\":_vm.getRowClassName,\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }},on:{\"row-click\":_vm.handleRowClick,\"expand-change\":_vm.handleExpandChange}},[(_vm.rows.length > 0)?_c('el-table-column',{attrs:{\"type\":\"expand\",\"width\":\"46\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"detail-panel\"},[_c('div',{staticClass:\"detail-grid\"},[_c('div',{staticClass:\"detail-item\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"订单号\")]),_c('span',{staticClass:\"detail-value mono\"},[_vm._v(_vm._s(scope.row.orderId || '-'))])]),_c('div',{staticClass:\"detail-item\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"付款链\")]),_c('span',{staticClass:\"detail-value\"},[_c('span',{staticClass:\"badge\"},[_vm._v(_vm._s(_vm.formatChain(scope.row.fromChain) || '-'))])])]),_c('div',{staticClass:\"detail-item\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"付款币种\")]),_c('span',{staticClass:\"detail-value\"},[_c('span',{staticClass:\"badge badge-blue\"},[_vm._v(_vm._s(String((scope.row.fromSymbol || scope.row.coin) || '') .toUpperCase()))])])]),_c('div',{staticClass:\"detail-item detail-item-full\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"付款地址\")]),_c('span',{staticClass:\"detail-value address\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":scope.row.fromAddress}},[_vm._v(_vm._s(scope.row.fromAddress || '-'))]),(scope.row.fromAddress)?_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.copy(scope.row.fromAddress)}}},[_vm._v(\"复制\")]):_vm._e()],1)])])])]}}],null,false,2778494901)}):_vm._e(),_c('el-table-column',{attrs:{\"label\":\"支付时间\",\"width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatFullTime(scope.row.createTime)))]}}])}),_c('el-table-column',{attrs:{\"label\":\"收款金额(USDT)\",\"width\":\"140\",\"align\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"amount-green\"},[(_vm.formatAmount(scope.row.realAmount, scope.row.coin || scope.row.toSymbol || 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":`+${_vm.formatAmount(scope.row.realAmount, scope.row.coin || scope.row.toSymbol || 'USDT').full}`,\"placement\":\"top\"}},[_c('span',[_vm._v(\" +\"+_vm._s(_vm.formatAmount(scope.row.realAmount, scope.row.coin || scope.row.toSymbol || 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" +\"+_vm._s(_vm.formatAmount(scope.row.realAmount, scope.row.coin || scope.row.toSymbol || 'USDT').text)+\" \")])],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"收款链\",\"width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatChain(scope.row.toChain)))]}}])}),_c('el-table-column',{attrs:{\"label\":\"收款币种\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(String(scope.row.coin || '').toUpperCase()))]}}])}),_c('el-table-column',{attrs:{\"label\":\"收款地址\",\"min-width\":\"200\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":scope.row.toAddress}},[_vm._v(_vm._s(scope.row.toAddress))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.copy(scope.row.toAddress)}}},[_vm._v(\"复制\")])]}}])}),_c('el-table-column',{attrs:{\"label\":\"交易HASH\",\"min-width\":\"200\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":scope.row.txHash}},[_vm._v(_vm._s(scope.row.txHash))]),(scope.row.txHash)?_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.copy(scope.row.txHash)}}},[_vm._v(\"复制\")]):_vm._e()]}}])}),_c('el-table-column',{attrs:{\"label\":\"支付状态\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":_vm.getStatusType(scope.row.status),\"size\":\"small\"}},[_vm._v(_vm._s(_vm.getStatusText(scope.row.status)))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"状态更新时间\",\"width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatFullTime(scope.row.updateTime)))]}}])})],1),(!_vm.rows.length)?_c('div',{staticClass:\"empty\"},[_c('div',{staticClass:\"empty-icon\"},[_vm._v(\"💳\")]),_c('div',{staticClass:\"empty-text\"},[_vm._v(\"暂无收款记录\")])]):_vm._e(),_c('div',{staticClass:\"pagination\"},[_c('el-pagination',{attrs:{\"background\":\"\",\"layout\":\"prev, pager, next, jumper\",\"current-page\":_vm.page,\"page-size\":_vm.pageSize,\"total\":_vm.total},on:{\"update:currentPage\":function($event){_vm.page=$event},\"update:current-page\":function($event){_vm.page=$event},\"current-change\":_vm.fetchList}})],1)],1)])])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"card-header\"},[_c('h3',{staticClass:\"card-title\"},[_vm._v(\"收款记录\")])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n","import mod from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./idnex.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./idnex.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./idnex.vue?vue&type=template&id=0f1fd789\"\nimport script from \"./idnex.vue?vue&type=script&lang=js\"\nexport * from \"./idnex.vue?vue&type=script&lang=js\"\nimport style0 from \"./idnex.vue?vue&type=style&index=0&id=0f1fd789&prod&lang=scss\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","import request from '../utils/request'\r\n\r\n//新增机器\r\nexport function addSingleOrBatchMachine(data) {\r\n return request({\r\n url: `/lease/product/machine/addSingleOrBatchMachine`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//根据矿机id 删除商品矿机\r\nexport function deleteMachine(data) {\r\n return request({\r\n url: `/lease/product/machine/delete`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//根据挖矿账户获取矿机列表\r\nexport function getUserMachineList(data) {\r\n return request({\r\n url: `/lease/product/machine/getUserMachineList`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n//根据 登录账户 获取挖矿账户及挖矿币种集合\r\nexport function getUserMinersList(data) {\r\n return request({\r\n url: `/lease/product/machine/getUserMinersList`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//编辑矿机 + 矿机上下架\r\nexport function updateMachine(data) {\r\n return request({\r\n url: `/lease/product/machine/updateMachine`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n//获取矿机列表\r\nexport function getMachineListForUpdate(data) {\r\n return request({\r\n url: `/lease/product/machine/getMachineListForUpdate`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//GPU下载客户端\r\nexport function downloadClient() {\r\n return request({\r\n url: `/lease/user/downloadClient`,\r\n method: 'get',\r\n responseType: 'blob' // 关键:必须设置为 blob 才能正确下载二进制文件\r\n })\r\n}\r\n\r\n\r\n//卖家页面---新增ASIC矿机\r\nexport function addAsicMachine(data) {\r\n return request({\r\n url: `/lease/v2/product/machine/addAsicMachine`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n///添加出售机器的币种获取ASIC\r\nexport function getSupportCoin() {\r\n return request({\r\n url: `/lease/v2/product/machine/getSupportCoin`,\r\n method: 'get', \r\n })\r\n}\r\n\r\n///添加出售机器的对应币种的算法获取ASIC\r\n/**\r\n * 根据币种获取支持的算法列表\r\n * @param {string} coin - 币种名称,例如 'BTC', 'ETH' 等\r\n * @returns {Promise} 返回算法列表\r\n */\r\nexport function getSupportAlgo(coin) {\r\n return request({\r\n url: `/lease/v2/product/machine/getSupportAlgo`,\r\n method: 'get',\r\n params: { coin } // 使用 params,request 拦截器会自动将参数拼接到 URL 查询字符串中\r\n })\r\n}\r\n\r\n\r\n","import mod from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./content.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./content.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./content.vue?vue&type=template&id=9935370e&scoped=true\"\nimport script from \"./content.vue?vue&type=script&lang=js\"\nexport * from \"./content.vue?vue&type=script&lang=js\"\nimport style0 from \"./content.vue?vue&type=style&index=0&id=9935370e&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"9935370e\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./index.vue?vue&type=template&id=5eac5e84&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=js\"\nexport * from \"./index.vue?vue&type=script&lang=js\"\nimport style0 from \"./index.vue?vue&type=style&index=0&id=5eac5e84&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5eac5e84\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./withdrawalHistory.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./withdrawalHistory.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./withdrawalHistory.vue?vue&type=template&id=37492658&scoped=true\"\nimport script from \"./withdrawalHistory.vue?vue&type=script&lang=js\"\nexport * from \"./withdrawalHistory.vue?vue&type=script&lang=js\"\nimport style0 from \"./withdrawalHistory.vue?vue&type=style&index=0&id=37492658&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"37492658\",\n null\n \n)\n\nexport default component.exports","import Vue from 'vue'\r\nimport App from './App.vue'\r\nimport router from './router'\r\nimport ElementUI from 'element-ui';\r\nimport 'element-ui/lib/theme-chalk/index.css';\r\n// 全局输入防表情守卫(极简、无侵入)\r\nimport { initNoEmojiGuard } from './utils/noEmojiGuard.js';\r\n// 引入请求拦截器清理函数(用于应用卸载时)\r\nimport { cleanupRequestListeners } from './utils/request.js';\r\n\r\n// 仅在生产环境禁用 console\r\nif (process.env.NODE_ENV === 'production') {\r\n console.log = () => {}\r\n console.debug = () => {}\r\n console.info = () => {}\r\n}\r\n\r\n\r\nVue.config.productionTip = false\r\nVue.use(ElementUI);\r\n// 初始化全局防表情拦截器\r\ninitNoEmojiGuard();\r\n\r\nconst vm = new Vue({\r\n router,\r\n render: h => h(App),\r\n beforeDestroy() {\r\n // 应用卸载时清理全局事件监听器,防止内存泄漏\r\n cleanupRequestListeners();\r\n }\r\n}).$mount('#app')\r\n\r\n// 将 Vue 实例挂载到 window 上,供 request.js 等工具使用\r\nwindow.vm = vm\r\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./shopNew.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./shopNew.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./shopNew.vue?vue&type=template&id=462a5e76&scoped=true\"\nimport script from \"./shopNew.vue?vue&type=script&lang=js\"\nexport * from \"./shopNew.vue?vue&type=script&lang=js\"\nimport style0 from \"./shopNew.vue?vue&type=style&index=0&id=462a5e76&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"462a5e76\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n","\n\n\n\n\n\n","import request from '../utils/request'\r\n\r\n//获取谷歌验证器二维码和密钥\r\nexport function getBindInfo(data) {\r\n return request({\r\n url: `/lease/auth/getBindInfo`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //绑定谷歌验证码\r\nexport function bindGoogle(data) {\r\n return request({\r\n url: `/lease/auth/bindGoogle`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n \r\n //开启谷歌验证器 发送邮箱验证码\r\nexport function sendOpenGoogleCode(data) {\r\n return request({\r\n url: `/lease/auth/sendOpenGoogleCode`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //关闭双重验证\r\nexport function closeStepTwo(data) {\r\n return request({\r\n url: `/lease/auth/closeStepTwo`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n \r\n //关闭谷歌验证器 发送邮箱验证码\r\nexport function sendCloseGoogleCode(data) {\r\n return request({\r\n url: `/lease/auth/sendCloseGoogleCode`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n //谷歌验证开启状态\r\nexport function getGoogleStatus(data) {\r\n return request({\r\n url: `/lease/auth/getGoogleStatus`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //开启谷歌验证\r\nexport function openStepTwo(data) {\r\n return request({\r\n url: `/lease/auth/openStepTwo`,\r\n method: 'post',\r\n data\r\n })\r\n }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"wallet-container\"},[_c('div',{staticClass:\"wallet-toolbar\",attrs:{\"role\":\"region\",\"aria-label\":\"钱包操作\"}},[_c('el-button',{staticClass:\"create-wallet-btn\",attrs:{\"type\":\"primary\"},on:{\"click\":_vm.openCreateWallet}},[_c('i',{staticClass:\"el-icon-plus\",staticStyle:{\"margin-right\":\"6px\"}}),_vm._v(\"充值 \")])],1),_c('section',{staticClass:\"wallet-card-section\"},_vm._l((_vm.walletList),function(w){return _c('div',{key:w.id,staticClass:\"wallet-card\"},[_c('div',{staticClass:\"wallet-header\"},[_c('h2',{staticClass:\"wallet-title\"},[_c('i',{staticClass:\"el-icon-wallet\"}),_vm._v(\" 我的钱包 \"),_c('el-tag',{staticStyle:{\"margin-left\":\"8px\"},attrs:{\"size\":\"mini\",\"effect\":\"dark\"}},[_vm._v(\" \"+_vm._s((w.fromChain || w.chain || '').toUpperCase())+\" \"+_vm._s((w.fromSymbol || w.coin || '').toUpperCase())+\" \")])],1),_c('div',{staticClass:\"wallet-balance\"},[_c('div',{staticClass:\"balance-item\"},[_c('span',{staticClass:\"balance-label\"},[_vm._v(\"可用余额\")]),_c('span',{staticClass:\"balance-amount\"},[_vm._v(_vm._s((w.walletBalance || w.balance || 0))+\" \"+_vm._s(_vm.displaySymbol(w)))])]),_c('div',{staticClass:\"balance-item\"},[_c('el-tooltip',{attrs:{\"placement\":\"top\",\"effect\":\"dark\"}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_vm._v(\" 冻结金额不能使用或提现,以下情况会冻结钱包余额:\"),_c('br'),_vm._v(\" 1. 下单机器后会冻结订单对应金额\"),_c('br'),_vm._v(\" 2. 提交提现后,金额正在提现中 \")]),_c('i',{staticClass:\"el-icon-question balance-tip-icon\"})]),_c('span',{staticClass:\"balance-label\"},[_vm._v(\"冻结余额\")]),_c('span',{staticClass:\"balance-amount frozen\"},[_vm._v(_vm._s((w.blockedBalance || 0))+\" \"+_vm._s(_vm.displaySymbol(w)))])],1),_c('el-button',{staticClass:\"withdraw-inline-btn\",attrs:{\"type\":\"success\",\"size\":\"mini\"},on:{\"click\":function($event){return _vm.handleWithdraw(w)}}},[_vm._v(\" 提现 \")])],1)])])}),0),_c('div',{staticClass:\"transaction-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"最近交易\")]),_c('div',{staticClass:\"transaction-list\"},[_vm._l((_vm.recentTransactions),function(transaction){return _c('div',{key:transaction.id,staticClass:\"transaction-item\"},[_c('div',{staticClass:\"transaction-info\"},[_c('span',{staticClass:\"transaction-type\"},[_vm._v(_vm._s(transaction.type))]),_c('span',{staticClass:\"transaction-time\"},[_vm._v(_vm._s(transaction.time))]),_c('el-tag',{staticClass:\"transaction-status\",attrs:{\"size\":\"mini\",\"type\":transaction.statusTagType || 'info'}},[_vm._v(\" \"+_vm._s(transaction.statusText || '-')+\" \")])],1),_c('div',{staticClass:\"transaction-amount\",class:transaction.amount > 0 ? 'positive' : 'negative'},[_vm._v(\" \"+_vm._s(transaction.amount > 0 ? '+' : '')+_vm._s(transaction.amountText)+\" USDT \")])])}),(_vm.recentTransactions.length === 0)?_c('div',{staticClass:\"empty-state\"},[_vm._v(\" 暂无交易记录 \")]):_vm._e()],2)]),_c('el-dialog',{attrs:{\"title\":\"钱包余额充值\",\"visible\":_vm.rechargeDialogVisible,\"width\":\"660px\"},on:{\"update:visible\":function($event){_vm.rechargeDialogVisible=$event},\"close\":_vm.resetRechargeForm}},[_c('div',{staticClass:\"recharge-content\"},[_c('div',{staticClass:\"wallet-address-section\"},[_c('h4',{staticClass:\"section-title\"},[_vm._v(\"钱包地址\")]),_c('div',{staticClass:\"charge-meta\"},[_c('el-tag',{staticClass:\"meta-tag\",attrs:{\"size\":\"small\",\"effect\":\"dark\",\"type\":\"warning\"}},[_c('i',{staticClass:\"el-icon-link\"}),_c('span',{staticClass:\"meta-title\"},[_vm._v(\"充值链:\")]),_c('span',{staticClass:\"meta-val\"},[_vm._v(_vm._s((_vm.WalletData.fromChain || _vm.WalletData.chain || '').toString().toUpperCase()))])]),_c('el-tag',{staticClass:\"meta-tag\",attrs:{\"size\":\"small\",\"effect\":\"dark\",\"type\":\"warning\"}},[_c('i',{staticClass:\"el-icon-coin\"}),_c('span',{staticClass:\"meta-title\"},[_vm._v(\"充值币种:\")]),_c('span',{staticClass:\"meta-val\"},[_vm._v(_vm._s((_vm.WalletData.fromSymbol || _vm.WalletData.coin || '').toString().toUpperCase()))])])],1),_c('div',{staticClass:\"address-container\"},[_c('el-input',{staticClass:\"address-input\",attrs:{\"readonly\":\"\",\"disabled\":true},model:{value:(_vm.WalletData.fromAddress),callback:function ($$v) {_vm.$set(_vm.WalletData, \"fromAddress\", $$v)},expression:\"WalletData.fromAddress\"}}),_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.copyAddress(_vm.WalletData.fromAddress)}}},[_vm._v(\" 复制 \")])],1),_c('p',{staticClass:\"address-tip\"},[_vm._v(\"请向此地址转账非\"+_vm._s(_vm.displaySymbol(_vm.WalletData))+\"资产,否则资产将无法找回.\")])]),_c('div',{staticClass:\"qr-code-section\"},[_c('h4',{staticClass:\"section-title\"},[_vm._v(\"扫码充值\")]),_c('div',{staticClass:\"qr-code-container\"},[_c('div',{ref:\"qrCodeRef\",staticClass:\"qr-code\"}),_c('p',{staticClass:\"qr-tip\"},[_vm._v(\"使用支持\"+_vm._s(_vm.displaySymbol(_vm.WalletData))+\"的钱包扫描二维码\")])])]),_c('div',{staticClass:\"recharge-notice\"},[_c('h4',{staticClass:\"section-title\"},[_vm._v(\"充值说明\")]),_c('ul',{staticClass:\"notice-list\"},[_c('li',[_vm._v(\"充值后请耐心等待余额更新或在资金流水页面查看最新充值记录\")]),_c('li',[_vm._v(\"最小充值金额:10 \"+_vm._s(_vm.displaySymbol(_vm.WalletData)))])])])]),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.rechargeDialogVisible = false}}},[_vm._v(\"关闭\")])],1)]),_c('el-dialog',{attrs:{\"title\":\"USDT提现\",\"visible\":_vm.withdrawDialogVisible,\"width\":\"720px\",\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){_vm.withdrawDialogVisible=$event},\"close\":_vm.resetWithdrawForm}},[_c('el-form',{ref:\"withdrawForm\",attrs:{\"model\":_vm.withdrawForm,\"rules\":_vm.withdrawRules,\"label-width\":\"120px\"}},[_c('el-form-item',{attrs:{\"label\":\"提现链\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"value\":(_vm.WalletData.fromChain || _vm.WalletData.chain || _vm.withdrawForm.toChain || '').toString().toUpperCase(),\"disabled\":true}})],1),_c('el-form-item',{attrs:{\"label\":\"提现币种\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"value\":_vm.displayWithdrawSymbol,\"disabled\":true}})],1),_c('el-form-item',{attrs:{\"label\":\"提现金额\",\"prop\":\"amount\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"placeholder\":\"请输入提现金额\",\"inputmode\":\"decimal\"},on:{\"input\":_vm.handleAmountInput},model:{value:(_vm.withdrawForm.amount),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"amount\", $$v)},expression:\"withdrawForm.amount\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"balance-info\"},[_c('div',{staticClass:\"balance-total\"},[_vm._v(\"钱包总余额:\"+_vm._s(_vm.totalBalance)+\" \"+_vm._s(_vm.displayWithdrawSymbol))]),_c('div',{staticClass:\"balance-row\"},[_c('span',[_vm._v(\"可用余额:\"+_vm._s(_vm.availableWithdrawBalance)+\" \"+_vm._s(_vm.displayWithdrawSymbol))]),_c('span',{staticClass:\"divider\"},[_vm._v(\"|\")]),_c('span',{staticClass:\"frozen-info\"},[_c('el-tooltip',{attrs:{\"placement\":\"top\",\"effect\":\"dark\"}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_vm._v(\" 冻结金额不能使用或提现,以下情况会冻结钱包余额:\"),_c('br'),_vm._v(\" 1. 下单机器后会冻结订单对应金额\"),_c('br'),_vm._v(\" 2. 提交提现后,金额正在提现中 \")]),_c('i',{staticClass:\"el-icon-question frozen-tip-icon\"})]),_vm._v(\" 冻结余额:\"+_vm._s((_vm.WalletData.blockedBalance || 0))+\" \"+_vm._s(_vm.displayWithdrawSymbol)+\" \"),_c('span',{staticClass:\"frozen-tip\"},[_vm._v(\"(购买机器下单后冻结,不可提现)\")])],1)])])],1),_c('el-form-item',{attrs:{\"label\":\"手续费\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"placeholder\":\"手续费\",\"disabled\":true},model:{value:(_vm.withdrawForm.fee),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"fee\", $$v)},expression:\"withdrawForm.fee\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"fee-info\"},[_vm._v(\" 网络手续费:\"+_vm._s(_vm.withdrawForm.fee || '0.00')+\" \"+_vm._s(_vm.displayWithdrawSymbol)+\" \")])],1),_c('el-form-item',{attrs:{\"label\":\"实际到账\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"placeholder\":\"实际到账金额\",\"disabled\":true},model:{value:(_vm.actualAmount),callback:function ($$v) {_vm.actualAmount=$$v},expression:\"actualAmount\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"actual-amount-info\"},[_vm._v(\" 实际到账:\"+_vm._s(_vm.actualAmount)+\" \"+_vm._s(_vm.displayWithdrawSymbol)+\" \")])],1),_c('el-form-item',{attrs:{\"label\":\"收款地址\",\"prop\":\"toAddress\"}},[_c('el-input',{staticStyle:{\"width\":\"100%\"},attrs:{\"type\":\"textarea\",\"rows\":3,\"placeholder\":\"请输入收款钱包地址\"},model:{value:(_vm.withdrawForm.toAddress),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"toAddress\", $$v)},expression:\"withdrawForm.toAddress\"}}),_c('div',{staticClass:\"address-tip\"},[_vm._v(\" 请确保地址正确,错误地址将导致资产丢失 \")])],1),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{ref:\"googleCodeInput\",staticStyle:{\"width\":\"100%\"},attrs:{\"placeholder\":\"请输入6位谷歌验证码\",\"maxlength\":\"6\"},on:{\"input\":_vm.handleGoogleCodeInput},model:{value:(_vm.withdrawForm.googleCode),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"googleCode\", $$v)},expression:\"withdrawForm.googleCode\"}},[_c('template',{slot:\"prepend\"},[_c('i',{staticClass:\"el-icon-key\"})])],2),_c('div',{staticClass:\"google-code-tip\"},[_vm._v(\" 为了保障您的账户安全,请输入您的谷歌验证器中的6位验证码 \")])],1)],1),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.withdrawDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.withdrawLoading},on:{\"click\":_vm.confirmWithdraw}},[_vm._v(\"确认提现\")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"链上充值\",\"visible\":_vm.createDialogVisible,\"close-on-click-modal\":false,\"close-on-press-escape\":false,\"width\":\"520px\"},on:{\"update:visible\":function($event){_vm.createDialogVisible=$event}}},[_c('el-form',{attrs:{\"label-width\":\"120px\"}},[_c('el-form-item',{attrs:{\"label\":\"选择充值链/币种\"}},[_c('el-cascader',{staticStyle:{\"width\":\"100%\"},attrs:{\"options\":_vm.options},model:{value:(_vm.createValue),callback:function ($$v) {_vm.createValue=$$v},expression:\"createValue\"}})],1)],1),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.createDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.createLoading},on:{\"click\":_vm.confirmCreateWallet}},[_vm._v(\"确定\")])],1)],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./header.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./header.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./header.vue?vue&type=template&id=5245f0be&scoped=true\"\nimport script from \"./header.vue?vue&type=script&lang=js\"\nexport * from \"./header.vue?vue&type=script&lang=js\"\nimport style0 from \"./header.vue?vue&type=style&index=0&id=5245f0be&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5245f0be\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./index.vue?vue&type=template&id=1da8165e&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=js\"\nexport * from \"./index.vue?vue&type=script&lang=js\"\nimport style0 from \"./index.vue?vue&type=style&index=0&id=1da8165e&prod&scoped=true&lang=css\"\nimport style1 from \"./index.vue?vue&type=style&index=1&id=1da8165e&prod&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"1da8165e\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{attrs:{\"id\":\"app\"}},[_c('router-view')],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n","/**\r\n * 密码校验工具(与登录页体验对齐:分步校验,返回最具体的错误提示)\r\n *\r\n * 规则:\r\n * - 长度 8-32 位\r\n * - 必须包含:小写字母 / 大写字母 / 数字 / 特殊字符\r\n * - 不能包含中文字符\r\n *\r\n * @param {{ emptyMessage?: string }} [options]\r\n * @returns {(rule: any, value: any, callback: Function) => void}\r\n */\r\nexport const createPasswordValidator = (options = {}) => {\r\n const emptyMessage = options.emptyMessage || '请输入密码'\r\n\r\n return (rule, value, callback) => {\r\n if (!value) {\r\n callback(new Error(emptyMessage))\r\n return\r\n }\r\n\r\n const v = String(value)\r\n\r\n const checks = [\r\n {\r\n test: (s) => s.length >= 8 && s.length <= 32,\r\n msg: '密码长度应为8-32位'\r\n },\r\n {\r\n test: (s) => /[a-z]/.test(s),\r\n msg: '密码应包含小写字母'\r\n },\r\n {\r\n test: (s) => /[A-Z]/.test(s),\r\n msg: '密码应包含大写字母'\r\n },\r\n {\r\n test: (s) => /\\d/.test(s),\r\n msg: '密码应包含数字'\r\n },\r\n {\r\n test: (s) => /[\\W_]/.test(s),\r\n msg: '密码应包含特殊字符(如 !@#$%^&*)'\r\n },\r\n {\r\n test: (s) => !/[\\u4e00-\\u9fa5]/.test(s),\r\n msg: '密码不能包含中文字符'\r\n }\r\n ]\r\n\r\n for (const check of checks) {\r\n if (!check.test(v)) {\r\n callback(new Error(check.msg))\r\n return\r\n }\r\n }\r\n\r\n callback()\r\n }\r\n}\r\n\r\n\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('el-container',{staticClass:\"containerApp\",staticStyle:{\"width\":\"100vw\",\"height\":\"100vh\"}},[_c('el-header',{staticClass:\"el-header\"},[_c('comHeard')],1),_c('el-main',{staticClass:\"el-main\"},[_c('appMain')],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./purchasedMachineDetail.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./purchasedMachineDetail.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./purchasedMachineDetail.vue?vue&type=template&id=d056bf30&scoped=true\"\nimport script from \"./purchasedMachineDetail.vue?vue&type=script&lang=js\"\nexport * from \"./purchasedMachineDetail.vue?vue&type=script&lang=js\"\nimport style0 from \"./purchasedMachineDetail.vue?vue&type=style&index=0&id=d056bf30&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"d056bf30\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./index.vue?vue&type=template&id=3a08b112&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=js\"\nexport * from \"./index.vue?vue&type=script&lang=js\"\nimport style0 from \"./index.vue?vue&type=style&index=0&id=3a08b112&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"3a08b112\",\n null\n \n)\n\nexport default component.exports","\n\n\n\n\n\n\n","import request from '../utils/request'\r\n\r\n//注册\r\nexport function register(data) {\r\n return request({\r\n url: `/lease/auth/register`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//登录\r\nexport function getLogin(data) {\r\n return request({\r\n url: `/lease/auth/login`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n \r\n//退出登录\r\nexport function getLogout(data) {\r\n return request({\r\n url: `/lease/auth/logout`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n \r\n//发送登录验证码\r\nexport function sendLoginCode(data) {\r\n return request({\r\n url: `/lease/auth/sendLoginCode`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //发送注册验证码\r\nexport function sendEmailCode(data) {\r\n return request({\r\n url: `/lease/auth/sendRegisterCode`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //发送修改密码验证码\r\nexport function sendUpdatePwdCode(data) {\r\n return request({\r\n url: `/lease/auth/sendUpdatePwdCode`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //修改密码\r\nexport function updatePassword(data) {\r\n return request({\r\n url: `/lease/auth/updatePassword`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n //注销账户\r\nexport function closeAccount(data) {\r\n return request({\r\n url: `/lease/auth/closeAccount`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n //注销邮箱验证码\r\n export function sendCloseAccount(data) {\r\n return request({\r\n url: `/lease/auth/sendCloseAccount`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n \r\n //个人中心修改密码\r\n export function updatePasswordInCenter(data) {\r\n return request({\r\n url: `/lease/auth/updatePasswordInCenter`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n\r\n \r\n\r\n\r\n\r\n\r\n\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"recharge-record-container\"},[_vm._m(0),_c('div',{staticClass:\"tab-container\"},[_c('el-tabs',{on:{\"tab-click\":_vm.handleTabClick},model:{value:(_vm.activeTab),callback:function ($$v) {_vm.activeTab=$$v},expression:\"activeTab\"}},[_c('el-tab-pane',{attrs:{\"label\":\"充值中\",\"name\":\"pending\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"充值中 (\"+_vm._s(_vm.pendingRecharges.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"recharge-list\"},[_vm._l((_vm.pendingRecharges),function(item){return _c('div',{key:item.id,staticClass:\"recharge-item pending\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(\" \"+_vm._s(item.amount)+\" \"+_vm._s(item.fromSymbol || \"USDT\")+\" \")]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.fromChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status pending-status\"},[_c('i',{staticClass:\"el-icon-loading\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.address)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.pendingRecharges.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无充值中的记录\")])]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"充值成功\",\"name\":\"success\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"充值成功 (\"+_vm._s(_vm.successRecharges.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"recharge-list\"},[_vm._l((_vm.successRecharges),function(item){return _c('div',{key:item.id,staticClass:\"recharge-item success\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(\" \"+_vm._s(item.amount)+\" \"+_vm._s(item.fromSymbol || \"USDT\")+\" \")]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.fromChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status success-status\"},[_c('i',{staticClass:\"el-icon-check\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.address)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.successRecharges.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无充值成功的记录\")])]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"充值失败\",\"name\":\"failed\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"充值失败 (\"+_vm._s(_vm.failedRecharges.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"recharge-list\"},[_vm._l((_vm.failedRecharges),function(item){return _c('div',{key:item.id,staticClass:\"recharge-item failed\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(\" \"+_vm._s(item.amount)+\" \"+_vm._s(item.fromSymbol || \"USDT\")+\" \")]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.fromChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status failed-status\"},[_c('i',{staticClass:\"el-icon-close\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.address)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.failedRecharges.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无充值失败的记录\")])]):_vm._e()],2)])])],1),_c('el-row',[_c('el-col',{staticStyle:{\"display\":\"flex\",\"justify-content\":\"center\"},attrs:{\"span\":24}},[_c('el-pagination',{staticStyle:{\"margin\":\"0 auto\",\"margin-top\":\"10px\"},attrs:{\"current-page\":_vm.currentPage,\"page-sizes\":_vm.pageSizes,\"page-size\":_vm.pagination.pageSize,\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total},on:{\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange,\"update:currentPage\":function($event){_vm.currentPage=$event},\"update:current-page\":function($event){_vm.currentPage=$event}}})],1)],1)],1),_c('el-dialog',{attrs:{\"title\":\"充值详情\",\"visible\":_vm.detailDialogVisible,\"width\":\"600px\"},on:{\"update:visible\":function($event){_vm.detailDialogVisible=$event},\"close\":_vm.closeDetail}},[(_vm.selectedItem)?_c('div',{staticClass:\"detail-content\"},[_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"基本信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"充值ID\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.selectedItem.id))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"充值金额\")]),_c('span',{staticClass:\"detail-value amount\"},[_vm._v(_vm._s(_vm.selectedItem.amount)+\" \"+_vm._s(_vm.selectedItem.fromSymbol || \"USDT\"))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"区块链网络\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.getChainName(_vm.selectedItem.fromChain)))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"充值状态\")]),_c('span',{staticClass:\"detail-value\"},[_c('el-tag',{attrs:{\"type\":_vm.getStatusType(_vm.selectedItem.status)}},[_vm._v(\" \"+_vm._s(_vm.getStatusText(_vm.selectedItem.status))+\" \")])],1)])])]),_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"地址信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"充值地址\")]),_c('div',{staticClass:\"address-container\"},[_c('span',{staticClass:\"detail-value address\"},[_vm._v(_vm._s(_vm.selectedItem.address))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.copyAddress(_vm.selectedItem.address)}}},[_vm._v(\" 复制 \")])],1)]),(_vm.selectedItem.txHash)?_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"交易哈希\")]),_c('div',{staticClass:\"address-container\"},[_c('span',{staticClass:\"detail-value address\"},[_vm._v(_vm._s(_vm.selectedItem.txHash))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.copyAddress(_vm.selectedItem.txHash)}}},[_vm._v(\" 复制 \")])],1)]):_vm._e()])]),_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"时间信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"充值时间\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.formatFullTime(_vm.selectedItem.createTime)))])])])])]):_vm._e(),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":_vm.closeDetail}},[_vm._v(\"关闭\")])],1)])],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"page-header\"},[_c('h1',{staticClass:\"page-title\"},[_vm._v(\"充值记录\")]),_c('p',{staticClass:\"page-subtitle\"},[_vm._v(\"查看您的充值申请和到账状态\")])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"panel\"},[_c('h2',{staticClass:\"panel-title\"},[_vm._v(\"新增店铺\")]),_c('div',{staticClass:\"panel-body\"},[_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label required\"},[_vm._v(\"店铺名称\")]),_c('el-input',{attrs:{\"placeholder\":\"请输入店铺名称\",\"maxlength\":30,\"show-word-limit\":\"\"},model:{value:(_vm.form.name),callback:function ($$v) {_vm.$set(_vm.form, \"name\", $$v)},expression:\"form.name\"}})],1),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"店铺描述\")]),_c('div',{staticClass:\"textarea-wrapper\"},[_c('el-input',{attrs:{\"type\":\"textarea\",\"rows\":4,\"maxlength\":300,\"placeholder\":\"请输入店铺描述\",\"show-word-limit\":\"\"},on:{\"input\":_vm.handleDescriptionInput},model:{value:(_vm.form.description),callback:function ($$v) {_vm.$set(_vm.form, \"description\", $$v)},expression:\"form.description\"}})],1)]),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label required\"},[_vm._v(\"手续费比例\")]),_c('el-input',{attrs:{\"placeholder\":\"比例区间 0.01 - 0.1 之间,最多6位小数\"},on:{\"input\":_vm.handleFeeRateInput},model:{value:(_vm.form.feeRate),callback:function ($$v) {_vm.$set(_vm.form, \"feeRate\", $$v)},expression:\"form.feeRate\"}})],1),_vm._m(0),_c('div',{staticClass:\"row\",staticStyle:{\"margin-top\":\"50px\"}},[_c('div',{staticClass:\"actions-center\"},[_c('el-button',{staticClass:\"btn-wide\",attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleCreate}},[_vm._v(\"创建店铺\")])],1)])])])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"row\",staticStyle:{\"margin-top\":\"-6px\"}},[_c('div'),_c('div',{staticStyle:{\"color\":\"#909399\",\"font-size\":\"12px\",\"text-align\":\"left\"}},[_vm._v(\" 为提升您的店铺曝光,您可为平台交易设置手续费比例,该手续费为商家向平台支付的交易佣金,手续费比例将作为影响店铺排名的关键因素,该比例越高,您的店铺排名就越靠前。 \")])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"funds-page\"},[_c('h3',{staticClass:\"title\",staticStyle:{\"margin-bottom\":\"18px\",\"text-align\":\"left\"}},[_vm._v(\"资金流水\")]),_c('div',{staticClass:\"tabs-card\"},[_c('el-tabs',{on:{\"tab-click\":_vm.handleTab},model:{value:(_vm.active),callback:function ($$v) {_vm.active=$$v},expression:\"active\"}},[_c('el-tab-pane',{attrs:{\"label\":\"充值记录\",\"name\":\"recharge\"}},[_c('div',{staticClass:\"list-wrap\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"全部充值 (\"+_vm._s(_vm.rechargeRows.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.loadRecharge}},[_vm._v(\"刷新\")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading.recharge),expression:\"loading.recharge\"}],staticClass:\"record-list\"},[_vm._l((_vm.rechargeRows),function(row,idx){return _c('div',{key:_vm.getRowKey(row, idx),staticClass:\"record-item\",class:_vm.statusClass(row.status),on:{\"click\":function($event){return _vm.toggleExpand('recharge', row, idx)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[(_vm.formatAmount(row.amount, row.fromSymbol).truncated)?_c('el-tooltip',{attrs:{\"content\":`${_vm.formatAmount(row.amount, row.fromSymbol).full} ${(row.fromSymbol || 'USDT').toUpperCase()}`,\"placement\":\"top\"}},[_c('span',[_vm._v(\" + \"+_vm._s(_vm.formatAmount(row.amount, row.fromSymbol).text)+\" \"+_vm._s((row.fromSymbol || 'USDT').toUpperCase())+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" + \"+_vm._s(_vm.formatAmount(row.amount, row.fromSymbol).text)+\" \"+_vm._s((row.fromSymbol || 'USDT').toUpperCase())+\" \")])],1),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.formatChain(row.fromChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status\"},[_c('el-tag',{attrs:{\"type\":_vm.getRechargeStatusType(row.status),\"size\":\"small\"}},[_vm._v(_vm._s(_vm.getRechargeStatusText(row.status)))])],1),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatFullTime(row.createTime)))])])]),_c('div',{directives:[{name:\"show\",rawName:\"v-show\",value:(_vm.isExpanded('recharge', row, idx)),expression:\"isExpanded('recharge', row, idx)\"}],staticClass:\"expand-panel\"},[_c('div',{staticClass:\"expand-grid\"},[_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"充值地址\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.fromAddress}},[_vm._v(_vm._s(row.fromAddress))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.fromAddress, '充值地址')}}},[_vm._v(\"复制\")])],1)]),(row.txHash)?_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"交易哈希\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.txHash}},[_vm._v(_vm._s(row.txHash))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.txHash, '交易哈希')}}},[_vm._v(\"复制\")])],1)]):_vm._e()])])])}),(!_vm.rechargeRows.length)?_c('div',{staticClass:\"empty\"},[_vm._v(\"暂无充值记录\")]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"提现记录\",\"name\":\"withdraw\"}},[_c('div',{staticClass:\"list-wrap\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"全部提现 (\"+_vm._s(_vm.withdrawRows.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.loadWithdraw}},[_vm._v(\"刷新\")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading.withdraw),expression:\"loading.withdraw\"}],staticClass:\"record-list\"},[_vm._l((_vm.withdrawRows),function(row,idx){return _c('div',{key:_vm.getRowKey(row, idx),staticClass:\"record-item\",class:_vm.statusClass(row.status),on:{\"click\":function($event){return _vm.toggleExpand('withdraw', row, idx)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[(_vm.formatAmount(row.amount, row.toSymbol).truncated)?_c('el-tooltip',{attrs:{\"content\":`${_vm.formatAmount(row.amount, row.toSymbol).full} ${(row.toSymbol || 'USDT').toUpperCase()}`,\"placement\":\"top\"}},[_c('span',[_vm._v(\" - \"+_vm._s(_vm.formatAmount(row.amount, row.toSymbol).text)+\" \"+_vm._s((row.toSymbol || 'USDT').toUpperCase())+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" - \"+_vm._s(_vm.formatAmount(row.amount, row.toSymbol).text)+\" \"+_vm._s((row.toSymbol || 'USDT').toUpperCase())+\" \")])],1),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.formatChain(row.toChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status\"},[_c('el-tag',{attrs:{\"type\":_vm.getWithdrawStatusType(row.status),\"size\":\"small\"}},[_vm._v(_vm._s(_vm.getWithdrawStatusText(row.status)))])],1),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatFullTime(row.createTime)))])])]),_c('div',{directives:[{name:\"show\",rawName:\"v-show\",value:(_vm.isExpanded('withdraw', row, idx)),expression:\"isExpanded('withdraw', row, idx)\"}],staticClass:\"expand-panel\"},[_c('div',{staticClass:\"expand-grid\"},[_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"收款地址\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.toAddress}},[_vm._v(_vm._s(row.toAddress))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.toAddress, '收款地址')}}},[_vm._v(\"复制\")])],1)]),(row.txHash)?_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"交易哈希\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.txHash}},[_vm._v(_vm._s(row.txHash))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.txHash, '交易哈希')}}},[_vm._v(\"复制\")])],1)]):_vm._e()])])])}),(!_vm.withdrawRows.length)?_c('div',{staticClass:\"empty\"},[_vm._v(\"暂无提现记录\")]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"消费记录\",\"name\":\"consume\"}},[_c('div',{staticClass:\"list-wrap\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"全部消费 (\"+_vm._s(_vm.consumeRows.length)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.loadConsume}},[_vm._v(\"刷新\")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading.consume),expression:\"loading.consume\"}],staticClass:\"record-list\"},[_vm._l((_vm.consumeRows),function(row,idx){return _c('div',{key:_vm.getRowKey(row, idx),staticClass:\"record-item\",class:_vm.statusClass(row.status),on:{\"click\":function($event){return _vm.toggleExpand('consume', row, idx)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[(_vm.formatAmount(row.realAmount, row.fromSymbol).truncated)?_c('el-tooltip',{attrs:{\"content\":`${_vm.formatAmount(row.realAmount, row.fromSymbol).full} ${(row.fromSymbol || 'USDT').toUpperCase()}`,\"placement\":\"top\"}},[_c('span',[_vm._v(\" - \"+_vm._s(_vm.formatAmount(row.realAmount, row.fromSymbol).text)+\" \"+_vm._s((row.fromSymbol || 'USDT').toUpperCase())+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" - \"+_vm._s(_vm.formatAmount(row.realAmount, row.fromSymbol).text)+\" \"+_vm._s((row.fromSymbol || 'USDT').toUpperCase())+\" \")])],1),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.formatChain(row.fromChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status\"},[_c('el-tag',{attrs:{\"type\":_vm.getPayStatusType(row.status),\"size\":\"small\"}},[_vm._v(_vm._s(_vm.getPayStatusText(row.status)))])],1),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatFullTime(row.createTime || row.time)))])])]),_c('div',{directives:[{name:\"show\",rawName:\"v-show\",value:(_vm.isExpanded('consume', row, idx)),expression:\"isExpanded('consume', row, idx)\"}],staticClass:\"expand-panel\"},[_c('div',{staticClass:\"expand-grid\"},[_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"订单号\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.orderId}},[_vm._v(_vm._s(row.orderId || ''))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.orderId, '订单号')}}},[_vm._v(\"复制\")])],1)]),_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"支付地址\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.fromAddress}},[_vm._v(_vm._s(row.fromAddress || ''))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.fromAddress, '支付地址')}}},[_vm._v(\"复制\")])],1)]),_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"收款地址\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.toAddress}},[_vm._v(_vm._s(row.toAddress || ''))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.toAddress, '收款地址')}}},[_vm._v(\"复制\")])],1)]),(row.txHash)?_c('div',{staticClass:\"expand-item\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"交易哈希\")]),_c('div',{staticClass:\"value value-row\"},[_c('span',{staticClass:\"mono-ellipsis\",attrs:{\"title\":row.txHash}},[_vm._v(_vm._s(row.txHash))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleCopy(row.txHash, '交易哈希')}}},[_vm._v(\"复制\")])],1)]):_vm._e()])])])}),(!_vm.consumeRows.length)?_c('div',{staticClass:\"empty\"},[_vm._v(\"暂无消费记录\")]):_vm._e()],2)])])],1),_c('el-row',[_c('el-col',{staticStyle:{\"display\":\"flex\",\"justify-content\":\"center\"},attrs:{\"span\":24}},[_c('el-pagination',{staticStyle:{\"margin\":\"0 auto\",\"margin-top\":\"10px\"},attrs:{\"current-page\":_vm.currentPage,\"page-sizes\":_vm.pageSizes,\"page-size\":_vm.pagination.pageSize,\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total},on:{\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange,\"update:currentPage\":function($event){_vm.currentPage=$event},\"update:current-page\":function($event){_vm.currentPage=$event}}})],1)],1)],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./SellerOrders.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./SellerOrders.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./SellerOrders.vue?vue&type=template&id=a4d97b16&scoped=true\"\nimport script from \"./SellerOrders.vue?vue&type=script&lang=js\"\nexport * from \"./SellerOrders.vue?vue&type=script&lang=js\"\nimport style0 from \"./SellerOrders.vue?vue&type=style&index=0&id=a4d97b16&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"a4d97b16\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./receiptRecord.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./receiptRecord.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./receiptRecord.vue?vue&type=template&id=115b6a3a&scoped=true\"\nimport script from \"./receiptRecord.vue?vue&type=script&lang=js\"\nexport * from \"./receiptRecord.vue?vue&type=script&lang=js\"\nimport style0 from \"./receiptRecord.vue?vue&type=style&index=0&id=115b6a3a&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"115b6a3a\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"product-new\"},[_c('el-card',{staticClass:\"product-form-card\"},[_c('div',{staticClass:\"card-header\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_c('h2',[_vm._v(\"新增商品\")]),_c('p',{staticClass:\"subtitle\"},[_vm._v(\"创建新的商品信息\")])]),_c('el-form',{ref:\"productForm\",staticClass:\"product-form\",attrs:{\"model\":_vm.form,\"rules\":_vm.rules,\"label-width\":\"120px\"}},[_c('el-form-item',{attrs:{\"label\":\"商品名称\",\"prop\":\"name\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入商品名称,如:Nexa-M2-Miner\",\"maxlength\":\"30\",\"show-word-limit\":\"\"},model:{value:(_vm.form.name),callback:function ($$v) {_vm.$set(_vm.form, \"name\", $$v)},expression:\"form.name\"}})],1),_c('el-form-item',{staticClass:\"align-like-input\",attrs:{\"label\":\"商品类型\",\"prop\":\"type\"}},[_c('el-radio-group',{model:{value:(_vm.form.type),callback:function ($$v) {_vm.$set(_vm.form, \"type\", $$v)},expression:\"form.type\"}},[_c('el-radio',{attrs:{\"label\":0}},[_vm._v(\"矿机\")])],1)],1),_c('el-form-item',{attrs:{\"label\":\"挖矿币种\",\"prop\":\"coin\"}},[_c('el-select',{staticStyle:{\"width\":\"100%\"},attrs:{\"placeholder\":\"请选择挖矿币种\"},model:{value:(_vm.form.coin),callback:function ($$v) {_vm.$set(_vm.form, \"coin\", $$v)},expression:\"form.coin\"}},_vm._l((_vm.coinOptions),function(coin){return _c('el-option',{key:coin.value,attrs:{\"label\":coin.label,\"value\":coin.value}})}),1)],1),_c('el-form-item',{attrs:{\"label\":\"商品描述\",\"prop\":\"description\"}},[_c('el-input',{attrs:{\"type\":\"textarea\",\"rows\":4,\"placeholder\":\"请输入商品描述\",\"maxlength\":\"100\",\"show-word-limit\":\"\"},model:{value:(_vm.form.description),callback:function ($$v) {_vm.$set(_vm.form, \"description\", $$v)},expression:\"form.description\"}})],1),_c('el-form-item',{staticClass:\"align-like-input\",attrs:{\"label\":\"商品状态\",\"prop\":\"state\"}},[_c('el-radio-group',{model:{value:(_vm.form.state),callback:function ($$v) {_vm.$set(_vm.form, \"state\", $$v)},expression:\"form.state\"}},[_c('el-radio',{attrs:{\"label\":0}},[_vm._v(\"上架\")]),_c('el-radio',{attrs:{\"label\":1}},[_vm._v(\"下架\")])],1)],1),_c('el-form-item',{staticClass:\"actions-row\"},[_c('div',{staticClass:\"form-actions\"},[_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"medium\",\"loading\":_vm.submitting},on:{\"click\":_vm.handleSubmit}},[_vm._v(\"创建商品\")]),_c('el-button',{attrs:{\"size\":\"medium\"},on:{\"click\":_vm.handleReset}},[_vm._v(\"重置\")]),_c('el-button',{attrs:{\"size\":\"medium\"},on:{\"click\":_vm.handleCancel}},[_vm._v(\"取消\")])],1)])],1)],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/**\n * @file 路由配置文件\n * @description 定义所有电商页面的路由配置\n */\n\n// 认证相关路由(独立布局,无Header)\nexport const authRoutes = [\n {\n path: '/login',\n name: 'Login',\n component: () => import('../views/auth/login.vue'),\n meta: {\n title: '用户登录',\n description: '登录到您的账户',\n requiresAuth: false // 不需要登录即可访问\n }\n },\n {\n path: '/register',\n name: 'Register',\n component: () => import('../views/auth/register.vue'),\n meta: {\n title: '用户注册',\n description: '创建新账户',\n requiresAuth: false\n }\n },\n {\n path: '/reset-password',\n name: 'ResetPassword',\n component: () => import('../views/auth/reset-password.vue'),\n meta: {\n title: '重置密码',\n description: '重置您的账户密码',\n requiresAuth: false\n }\n }\n]\n\n// 商品相关路由\nexport const productRoutes = [\n {\n path: '/productList',\n name: 'productList',\n \n component: () => import('../views/productList/index.vue'),\n meta: {\n title: '商品列表',\n description: '浏览所有可用商品',\n allAuthority: ['all']\n }\n },\n {\n path: '/product/:id',\n name: 'productDetail',\n component: () => import('../views/productDetail/index.vue'),\n meta: {\n title: '商品详情',\n description: '查看商品详细信息',\n allAuthority: ['all']\n }\n }\n]\n\n// 购物车相关路由\nexport const cartRoutes = [\n {\n path: '/cart',\n name: 'cart',\n component: () => import('../views/cart/index.vue'),\n meta: {\n title: '购物车',\n description: '管理购物车商品',\n allAuthority: ['all']\n }\n }\n]\n\n// 结算相关路由\nexport const checkoutRoutes = [\n {\n path: '/checkout',\n name: 'checkout',\n component: () => import('../views/checkout/index.vue'),\n meta: {\n title: '订单结算',\n description: '完成订单结算',\n allAuthority: ['all']\n }\n }\n]\n\n// 个人中心相关路由\nexport const accountRoutes = [\n {\n path: '/account',\n name: 'account',\n component: () => import('../views/account/index.vue'),\n redirect: '/account/shops',\n meta: {\n title: '个人中心',\n description: '管理个人资料和店铺',\n allAuthority: ['all']\n },\n children: [\n {\n path: 'wallet',\n name: 'Wallet',\n component: () => import('../views/account/wallet.vue'),\n meta: {\n title: '我的钱包',\n description: '查看钱包余额、充值和提现',\n allAuthority: ['all']\n }\n },\n {//充值记录\n path: 'rechargeRecord',\n name: 'RechargeRecord',\n component: () => import('../views/account/rechargeRecord.vue'),\n meta: {\n title: '充值记录',\n description: '查看充值记录',\n allAuthority: ['all']\n }\n },\n {//提现记录\n path: 'withdrawalHistory',\n name: 'WithdrawalHistory',\n component: () => import('../views/account/withdrawalHistory.vue'),\n meta: {\n title: '提现记录',\n description: '查看提现记录',\n allAuthority: ['all']\n }\n },\n {\n path: 'receipt-record',\n name: 'accountReceiptRecord',\n component: () => import('../views/account/receiptRecord.vue'),\n meta: {\n title: '收款记录',\n description: '卖家收款流水记录',\n allAuthority: ['all']\n }\n },\n {\n path: 'withdraw-record',\n name: 'accountWithdrawRecord',\n component: () => import('../views/account/withdrawRecord.vue'),\n meta: {\n title: '提现记录',\n description: '卖家提现流水记录',\n allAuthority: ['all']\n }\n },\n {\n path: 'shop-new',\n name: 'accountShopNew',\n component: () => import('../views/account/shopNew.vue'),\n meta: {\n title: '新增店铺',\n description: '创建新的店铺',\n allAuthority: ['all']\n }\n },\n {\n path: 'shop-config',\n name: 'accountShopConfig',\n component: () => import('../views/account/shopConfig.vue'),\n meta: {\n title: '钱包绑定',\n description: '绑定店铺收款钱包',\n allAuthority: ['all']\n }\n },\n {\n path: 'shops',\n name: 'accountMyShops',\n component: () => import('../views/account/myShops.vue'),\n meta: {\n title: '我的店铺',\n description: '查看我的店铺信息',\n allAuthority: ['all']\n }\n },\n {\n path: 'product-new',\n name: 'accountProductNew',\n component: () => import('../views/account/productNew.vue'),\n meta: {\n title: '新增商品',\n description: '创建新的商品',\n allAuthority: ['all']\n }\n },\n {\n path: 'products',\n name: 'accountProducts',\n component: () => import('../views/account/products.vue'),\n meta: {\n title: '商品列表',\n description: '管理店铺下的商品列表',\n allAuthority: ['all']\n }\n },\n {\n path: 'purchased-machine-config',\n name: 'accountPurchasedMachineConfig',\n component: () => import('../views/account/purchasedMachineConfig.vue'),\n meta: {\n title: '已购商品',\n description: '查看已购买商品的配置信息',\n allAuthority: ['all']\n }\n },\n {\n path: 'purchased-machine-detail/:id',\n name: 'purchasedMachineDetail',\n component: () => import('../views/account/purchasedMachineDetail.vue'),\n meta: {\n title: '已购商品详情',\n description: '查看已购买商品的详细信息',\n allAuthority: ['all']\n }\n },\n {\n path: 'funds-flow',\n name: 'accountFundsFlow',\n component: () => import('../views/account/fundsFlow.vue'),\n meta: {\n title: '资金流水',\n description: '充值/提现/消费记录切换查看',\n allAuthority: ['all']\n }\n },\n {\n path: 'seller-funds-flow',\n name: 'accountSellerFundsFlow',\n component: () => import('../views/account/sellerFundsFlow.vue'),\n meta: {\n title: '资金流水',\n description: '卖家收款/提现流水记录',\n allAuthority: ['all']\n }\n },\n {\n path: 'orders',\n name: 'accountOrders',\n component: () => import('../views/account/orders.vue'),\n meta: {\n title: '订单列表',\n description: '查看与管理订单(按状态筛选)',\n allAuthority: ['all']\n }\n },\n {\n path: 'seller-orders',\n name: 'accountSellerOrders',\n component: () => import('../views/account/SellerOrders.vue'),\n meta: {\n title: '已售出订单',\n description: '卖家侧订单列表',\n allAuthority: ['all']\n }\n },\n {\n path: 'order-detail/:id',\n name: 'accountOrderDetail',\n component: () => import('../views/account/orderDetail.vue'),\n meta: {\n title: '订单详情',\n description: '查看订单详细信息',\n allAuthority: ['all']\n }\n },\n {\n path: 'product-detail/:id',\n name: 'accountProductDetail',\n component: () => import('../views/account/productDetail.vue'),\n meta: {\n title: '商品详情',\n description: '个人中心 - 商品详情',\n allAuthority: ['all']\n }\n },\n {\n path: 'product-machine-add',\n name: 'accountProductMachineAdd',\n component: () => import('../views/account/productMachineAdd.vue'),\n meta: {\n title: '添加出售机器',\n description: '为商品添加出售机器',\n allAuthority: ['all']\n }\n },\n {\n path: 'security-settings',\n name: 'accountSecuritySettings',\n component: () => import('../views/account/securitySettings.vue'),\n meta: {\n title: '安全设置',\n description: '管理账户安全选项',\n allAuthority: ['all']\n }\n }\n ]\n }\n]\n\n// 所有子路由\nexport const childrenRoutes = [\n ...productRoutes,\n ...cartRoutes,\n ...checkoutRoutes,\n ...accountRoutes\n]\n\n// 主路由配置\nexport const mainRoutes = [\n // 认证路由(独立布局,无Header)\n ...authRoutes,\n \n // 主应用路由(带Layout)\n {\n path: '/',\n name: 'Home',\n component: () => import('../Layout/idnex.vue'),\n redirect: '/productList',\n children: childrenRoutes\n },\n \n // 404页面重定向到商品列表\n {\n path: '*',\n redirect: '/productList'\n }\n]\n\nexport default mainRoutes ","\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"orders-page\"},[_c('h2',{staticClass:\"title\"},[_vm._v(\"订单列表\")]),_c('el-tabs',{on:{\"tab-click\":_vm.handleTabClick},model:{value:(_vm.active),callback:function ($$v) {_vm.active=$$v},expression:\"active\"}},[_c('el-tab-pane',{attrs:{\"label\":\"订单进行中\",\"name\":\"7\"}},[_c('order-list',{attrs:{\"items\":_vm.orders[7],\"show-checkout\":true,\"show-end-time\":false,\"on-cancel\":_vm.handleCancelOrder,\"empty-text\":\"暂无进行中的订单\"}})],1),_c('el-tab-pane',{attrs:{\"label\":\"订单已完成\",\"name\":\"8\"}},[_c('order-list',{attrs:{\"items\":_vm.orders[8],\"show-checkout\":false,\"show-end-time\":true,\"empty-text\":\"暂无已完成的订单\"}})],1)],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"product-machine-add\"},[_c('div',{staticClass:\"header\"},[_c('el-button',{attrs:{\"type\":\"text\"},on:{\"click\":_vm.handleBack}},[_vm._v(\"返回\")]),_c('h2',{staticClass:\"title\"},[_vm._v(\"创建商品\")])],1),_c('el-card',{staticClass:\"form-card\",attrs:{\"shadow\":\"never\"}},[_c('el-form',{ref:\"machineForm\",attrs:{\"model\":_vm.form,\"rules\":_vm.rules,\"label-width\":\"160px\",\"size\":\"small\"}},[_c('el-form-item',{attrs:{\"label\":\"矿机种类\"}},[_c('el-radio-group',{on:{\"change\":_vm.handleMachineCategoryChange},model:{value:(_vm.form.machineCategory),callback:function ($$v) {_vm.$set(_vm.form, \"machineCategory\", $$v)},expression:\"form.machineCategory\"}},[_c('el-radio',{attrs:{\"label\":\"ASIC\"}},[_vm._v(\"ASIC\")]),_c('el-radio',{attrs:{\"label\":\"GPU\"}},[_vm._v(\"GPU\")])],1)],1),(_vm.form.machineCategory === 'GPU')?_c('div',{staticClass:\"gpu-guide-section\"},[_c('el-card',{staticClass:\"gpu-guide-card\",attrs:{\"shadow\":\"never\"}},[_c('div',{staticClass:\"gpu-guide-content\"},[_c('div',{staticClass:\"gpu-guide-title\"},[_vm._v(\"注意事项:\")]),_c('ol',{staticClass:\"gpu-guide-list\"},[_c('li',[_vm._v(\" GPU商品需先点击下方按钮,下载并在GPU所在主机启动客户端,在下载包中会有启动客户端的操作指引文档 \")]),_c('li',[_vm._v(\" 成功在GPU主机启动客户端后,GPU信息会自行添加至商品列表中,点击下方前往商品列表按钮可以前往该页面 \")]),_c('li',[_vm._v(\" 客户端和您的卖家账号绑定,如果您需要在本卖家账号\"),(_vm.userEmail)?_c('span',[_vm._v(\" (\"+_vm._s(_vm.userEmail)+\")\")]):_vm._e(),_vm._v(\"添加多个GPU商品,可通过下列两种方法实现:\"),_c('br'),_vm._v(\" 方法一:点击下方下载客户端按钮,将下载好的完整客户端包复制到不同的GPU主机并且启动,启动后客户端所在主机的GPU数据会自动添加到商品列表中 (推荐) \"),_c('br'),_vm._v(\" 方法二:在不同的客户端主机登陆您的卖家账号,进入本页面,点击下载对应操作系统客户端,成功启动客户端后也可自动添加GPU数据到商品列表中 \")]),_c('li',[_vm._v(\"目前只支持NVIDIA系列GPU\")])]),_c('div',{staticClass:\"gpu-guide-buttons\"},[_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":function($event){return _vm.handleDownloadClient('windows')}}},[_vm._v(\"Windows 客户端下载\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":function($event){return _vm.handleDownloadClient('linux')}}},[_vm._v(\"Linux 客户端下载\")]),_c('el-button',{attrs:{\"type\":\"success\"},on:{\"click\":_vm.handleGpuClientStarted}},[_vm._v(\"前往商品列表\")])],1)])])],1):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"币种/算法/算力/单位\",\"prop\":\"coinAndAlgoList\",\"required\":true}},[_c('div',{staticClass:\"coin-algo-rows\"},_vm._l((_vm.form.coinAndAlgoList),function(row,idx){return _c('div',{key:idx,staticClass:\"coin-algo-line\"},[_c('el-select',{staticClass:\"coin-input\",attrs:{\"placeholder\":\"请选择币种\",\"loading\":_vm.loadingCoins,\"filterable\":\"\",\"clearable\":\"\"},on:{\"change\":function($event){return _vm.handleCoinChange(idx, $event)}},model:{value:(row.coin),callback:function ($$v) {_vm.$set(row, \"coin\", $$v)},expression:\"row.coin\"}},_vm._l((_vm.coinOptions),function(coin){return _c('el-option',{key:coin,attrs:{\"label\":coin,\"value\":coin}})}),1),_c('el-select',{staticClass:\"algo-input\",attrs:{\"placeholder\":\"请选择算法\",\"loading\":_vm.loadingAlgos[idx],\"disabled\":!row.coin,\"filterable\":\"\",\"clearable\":\"\"},model:{value:(row.algorithm),callback:function ($$v) {_vm.$set(row, \"algorithm\", $$v)},expression:\"row.algorithm\"}},_vm._l(((_vm.algoOptionsMap[row.coin] || [])),function(algo){return _c('el-option',{key:algo,attrs:{\"label\":algo,\"value\":algo}})}),1),_c('el-input',{staticClass:\"power-input\",attrs:{\"placeholder\":\"理论算力\",\"inputmode\":\"decimal\"},on:{\"input\":function($event){return _vm.handleCoinRowTheoryInput(idx)}},model:{value:(row.theoryPower),callback:function ($$v) {_vm.$set(row, \"theoryPower\", $$v)},expression:\"row.theoryPower\"}}),_c('el-select',{staticClass:\"unit-select\",attrs:{\"placeholder\":\"单位\"},on:{\"change\":function($event){return _vm.handleCoinRowUnitChange(idx, $event)}},model:{value:(row.unit),callback:function ($$v) {_vm.$set(row, \"unit\", $$v)},expression:\"row.unit\"}},[_c('el-option',{attrs:{\"label\":\"KH/S\",\"value\":\"KH/S\"}}),_c('el-option',{attrs:{\"label\":\"MH/S\",\"value\":\"MH/S\"}}),_c('el-option',{attrs:{\"label\":\"GH/S\",\"value\":\"GH/S\"}}),_c('el-option',{attrs:{\"label\":\"TH/S\",\"value\":\"TH/S\"}}),_c('el-option',{attrs:{\"label\":\"PH/S\",\"value\":\"PH/S\"}})],1),_c('el-button',{staticClass:\"op-btn\",attrs:{\"type\":\"primary\",\"icon\":\"el-icon-plus\",\"circle\":\"\",\"aria-label\":'新增一行'},on:{\"click\":_vm.handleAddCoinAlgoRow}}),(_vm.form.coinAndAlgoList.length > 1)?_c('el-button',{staticClass:\"op-btn\",attrs:{\"icon\":\"el-icon-minus\",\"circle\":\"\",\"aria-label\":'删除该行'},on:{\"click\":function($event){return _vm.handleRemoveCoinAlgoRow(idx)}}}):_vm._e()],1)}),0)]):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"矿机型号\",\"prop\":\"type\",\"required\":true}},[_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"placeholder\":\"示例:龍珠\",\"maxlength\":20},on:{\"input\":_vm.handleTypeInput},model:{value:(_vm.form.type),callback:function ($$v) {_vm.$set(_vm.form, \"type\", $$v)},expression:\"form.type\"}})],1):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"最大租赁天数\",\"prop\":\"maxLeaseDays\"}},[_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"placeholder\":\"1-365\",\"inputmode\":\"numeric\"},on:{\"input\":function($event){return _vm.handleNumeric('maxLeaseDays')}},model:{value:(_vm.form.maxLeaseDays),callback:function ($$v) {_vm.$set(_vm.form, \"maxLeaseDays\", $$v)},expression:\"form.maxLeaseDays\"}},[_c('template',{slot:\"append\"},[_vm._v(\"天\")])],2)],1):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"功耗\",\"prop\":\"powerDissipation\"}},[_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"inputmode\":\"decimal\"},on:{\"input\":function($event){return _vm.handleNumeric('powerDissipation')}},model:{value:(_vm.form.powerDissipation),callback:function ($$v) {_vm.$set(_vm.form, \"powerDissipation\", $$v)},expression:\"form.powerDissipation\"}},[_c('template',{slot:\"append\"},[_vm._v(\"kw/h\")])],2)],1):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"统一售价\",\"prop\":_vm.payTypeDefs && _vm.payTypeDefs.length ? 'costMap' : 'cost',\"required\":true}},[_c('span',{attrs:{\"slot\":\"label\"},slot:\"label\"},[_vm._v(\"统一售价\")]),(_vm.payTypeDefs && _vm.payTypeDefs.length)?_c('div',{staticClass:\"cost-multi\"},_vm._l((_vm.payTypeDefs),function(pt){return _c('div',{key:pt.key,staticClass:\"cost-item\"},[_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"placeholder\":\"请输入价格\",\"inputmode\":\"decimal\"},on:{\"input\":(val) => _vm.handleCostMapInput(pt.key, val)},model:{value:(_vm.form.costMap[pt.key]),callback:function ($$v) {_vm.$set(_vm.form.costMap, pt.key, $$v)},expression:\"form.costMap[pt.key]\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(pt.label))])],2)],1)}),0):_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"placeholder\":\"请输入成本(USDT)\",\"inputmode\":\"decimal\"},on:{\"input\":function($event){return _vm.handleNumeric('cost')}},model:{value:(_vm.form.cost),callback:function ($$v) {_vm.$set(_vm.form, \"cost\", $$v)},expression:\"form.cost\"}},[_c('template',{slot:\"append\"},[_vm._v(\"USDT\")])],2)],1):_vm._e(),(_vm.form.machineCategory === 'ASIC')?_c('el-form-item',{attrs:{\"label\":\"出售机器数量(台)\",\"prop\":\"sellCount\",\"required\":true}},[_c('el-input',{staticStyle:{\"width\":\"50%\"},attrs:{\"placeholder\":\"1 - 9999\",\"inputmode\":\"numeric\"},on:{\"input\":_vm.handleSellCountInput,\"blur\":_vm.handleSellCountBlur},model:{value:(_vm.form.sellCount),callback:function ($$v) {_vm.$set(_vm.form, \"sellCount\", $$v)},expression:\"form.sellCount\"}})],1):_vm._e()],1)],1),(_vm.form.machineCategory === 'ASIC')?_c('div',{staticClass:\"actions\"},[_c('el-button',{on:{\"click\":_vm.handleBack}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.saving},on:{\"click\":_vm.handleSave}},[_vm._v(\"确认创建\")])],1):_vm._e(),_c('el-dialog',{staticClass:\"wallet-bind-dialog\",attrs:{\"title\":\"提示\",\"visible\":_vm.walletBindDialogVisible,\"width\":\"400px\",\"close-on-click-modal\":false,\"show-close\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){_vm.walletBindDialogVisible=$event}}},[_c('div',{staticClass:\"wallet-bind-content\"},[_c('i',{staticClass:\"el-icon-warning wallet-warning-icon\"}),_c('p',{staticClass:\"wallet-bind-message\"},[_vm._v(\" 请先在我的店铺绑定钱包地址后才能创建商品 \")]),_c('el-button',{staticClass:\"wallet-bind-btn\",attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleGoToWalletBind}},[_vm._v(\" 去绑定钱包 \")])],1)]),_c('el-dialog',{attrs:{\"title\":\"请确认上架信息\",\"visible\":_vm.confirmVisible,\"width\":\"560px\"},on:{\"update:visible\":function($event){_vm.confirmVisible=$event}}},[_c('div',{staticStyle:{\"text-align\":\"left\",\"line-height\":\"1.9\"}},[_c('div',[_vm._v(\" 币种:\"),_c('b',[_vm._v(_vm._s(_vm.confirmData.coin))])]),_c('div',[_vm._v(\" 算法:\"),_c('b',[_vm._v(_vm._s(_vm.confirmData.algorithm))])]),_c('div',[_vm._v(\" 最大租赁天数:\"),_c('b',[_vm._v(_vm._s(_vm.confirmData.maxLeaseDays || \"-\"))])]),_c('div',[_vm._v(\" 出售机器数量:\"),_c('b',[_vm._v(_vm._s(_vm.confirmData.saleNumbers || \"-\"))])]),_c('div',{staticStyle:{\"margin-top\":\"8px\"}},[_vm._v(\"售价:\")]),_c('el-table',{staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.confirmData.priceList,\"border\":\"\",\"size\":\"mini\"}},[_c('el-table-column',{attrs:{\"prop\":\"chain\",\"label\":\"链\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"coin\",\"label\":\"币种\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"label\":\"价格\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(\" \"+_vm._s(scope.row.price)+\" \")]}}])})],1),_c('p',{staticStyle:{\"color\":\"#666\",\"margin-top\":\"12px\"}},[_vm._v(\" 请仔细确认以上参数无误后提交。 \")])],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.confirmVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.saving},on:{\"click\":_vm.doSubmit}},[_vm._v(\"确认提交\")])],1)])],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import request from '../utils/request'\r\n\r\n//创建订单及订单详情\r\nexport function addOrders(data) {\r\n return request({\r\n url: `/lease/order/info/addOrders`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//取消订单\r\nexport function cancelOrder(data) {\r\n return request({\r\n url: `/lease/order/info/cancelOrder`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//根据订单id查询订单信息\r\nexport function getOrdersByIds(data) {\r\n return request({\r\n url: `/lease/order/info/getOrdersByIds`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//查询订单列表(买家侧)\r\nexport function getOrdersByStatus(data) {\r\n return request({\r\n url: `/lease/order/info/getOrdersByStatus`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n//查询订单列表(卖家侧)\r\nexport function getOrdersByStatusForSeller(data) {\r\n return request({\r\n url: `/lease/order/info/getOrdersByStatusForSeller`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//结算前链和币种查询\r\nexport function getChainAndListForSeller(data) {\r\n return request({\r\n url: `/lease/shop/getChainAndListForSeller`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n//获取实时币价\r\nexport function getCoinPrice(data) {\r\n return request({\r\n url: `/lease/order/info/getCoinPrice`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//获取支持的算法币种\r\nexport function getMachineSupportCoinAndAlgorithm(data) {\r\n return request({\r\n url: `/lease/v2/order/info/getMachineSupportCoinAndAlgorithm`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n//获取支持的矿池 和模型\r\nexport function getMachineSupportPool(data) {\r\n return request({\r\n url: `/lease/v2/order/info/getMachineSupportPool`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//创建订单\r\nexport function addOrdersV2(data) {\r\n return request({\r\n url: `/lease/v2/order/info/addOrdersV2`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n\r\n//已购矿机配置\r\nexport function getPurchasedItems(data) {\r\n return request({\r\n url: `/lease/v2/order/info/getPurchasedItems`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n//已购商品详情\r\nexport function getPurchasedInfoV2(data) {\r\n return request({\r\n url: `/lease/v2/order/info/getPurchasedInfo`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n","\r\n\r\n\r\n\r\n\r\n\r\n\r\n","\nimport { getProductById } from '../../utils/productService'\nimport { getMachineInfo, getPayTypes,getShopMachineList,addGoodsV2 } from '../../api/products'\nimport { truncateAmountByCoin, truncateTo6 } from '../../utils/amount'\nimport { getGoodsListV2 } from '../../api/shoppingCart'\n\nexport default {\n name: 'ProductDetail',\n data() {\n return {\n product: null,\n loading: false,\n // 默认展开的行keys\n expandedRowKeys: [],\n selectedMap: {},\n // 新接口:单层矿机列表 & 支付方式\n machineList: [],\n paymentMethodList: [],\n // 筛选状态\n selectedPayKey: null,\n filters: {\n chain: '',\n coin: '',\n minPrice: null,\n maxPrice: null,\n minPower: null,\n maxPower: null,\n minPowerDissipation: null,\n maxPowerDissipation: null,\n unit: 'GH/S',\n keyword: '' // 币种/算法搜索关键词\n },\n // 实际算力单位选项\n powerUnitOptions: ['KH/S', 'MH/S', 'GH/S', 'TH/S', 'PH/S'],\n // 排序状态:true 升序,false 降序\n sortStates: {\n priceSort: true,\n powerSort: true,\n powerDissipationSort: true\n },\n // 当前激活的排序字段(仅当用户点击后才会传参)\n activeSortField: '',\n // 首次进入时是否已按价格币种设置过支付方式筛选默认值\n payFilterDefaultApplied: false,\n params: {\n id: \"\",\n pageNum: 1,\n pageSize: 10,\n\n\n },\n confirmAddDialog: {\n visible: false,\n items: []\n },\n // 购物车中已存在的当前商品机器集合:id 与 user|miner 组合键\n cartMachineIdSet: new Set(),\n cartCompositeKeySet: new Set(),\n cartLoaded: false,\n machinesLoaded: false,\n /**\n * 可展开的产品系列数据\n * 每个系列(group)包含多个可选条目(variants)\n */\n productListData: [\n // {\n // id: 'grp-1',\n // group: 'A系列',\n // summary: {\n // theoryPower: '56T',\n // computingPower: '54T',\n // powerDissipation: '3200W',\n // algorithm: 'power',\n // type: 'A-Pro',\n // count: 3,\n // price: '¥1000+'\n // },\n // variants: [\n // { id: 'A-1', model: 'A1', theoryPower: '14T', computingPower: '13.5T', powerDissipation: '780W', algorithm: 'power', stock: 50, price: 999, quantity: 1 },\n // { id: 'A-2', model: 'A2', theoryPower: '18T', computingPower: '17.2T', powerDissipation: '900W', algorithm: 'power', stock: 40, price: 1299, quantity: 1 },\n // { id: 'A-3', model: 'A3', theoryPower: '24T', computingPower: '23.1T', powerDissipation: '1520W', algorithm: 'power', stock: 30, price: 1699, quantity: 1 }\n // ]\n // },\n // {\n // id: 'grp-2',\n // group: 'B系列',\n // summary: {\n // theoryPower: '72T',\n // computingPower: '70T',\n // powerDissipation: '4100W',\n // algorithm: 'power',\n // type: 'B-Max',\n // count: 2,\n // price: '¥2000+'\n // },\n // variants: [\n // { id: 'B-1', model: 'B1', theoryPower: '32T', computingPower: '31.2T', powerDissipation: '1800W', algorithm: 'power', stock: 28, price: 2199, quantity: 1 },\n // { id: 'B-2', model: 'B2', theoryPower: '40T', computingPower: '38.8T', powerDissipation: '2300W', algorithm: 'power', stock: 18, price: 2699, quantity: 1 }\n // ]\n // }\n ],\n tableData: [\n // {\n // theoryPower: \"55656\",//理论算力\n // computingPower: \"44545\",//实际算力\n // powerDissipation: \"5565\",//功耗\n // algorithm: \"power\",//算法\n // type: \"型号1\",//矿机型号\n // number:2001, \n // cost:\"1000\",//价格 \n // },\n // {\n // theoryPower: \"55656\",//理论算力\n // computingPower: \"44545\",//实际算力\n // powerDissipation: \"5565\",//功耗\n // algorithm: \"power\",//算法\n // type: \"型号1\",//矿机型号\n // number:2001, \n // cost:\"1000\",//价格 \n // },\n // {\n // theoryPower: \"55656\",//理论算力\n // computingPower: \"44545\",//实际算力\n // powerDissipation: \"5565\",//功耗\n // algorithm: \"power\",//算法\n // type: \"型号1\",//矿机型号\n // number:2001, \n // cost:\"1000\",//价格 \n // },\n // {\n // theoryPower: \"55656\",//理论算力\n // computingPower: \"44545\",//实际算力\n // powerDissipation: \"5565\",//功耗\n // algorithm: \"power\",//算法\n // type: \"型号1\",//矿机型号\n // number:2001, \n // cost:\"1000\",//价格 \n // },\n\n ],\n productDetailLoading: false,\n pageSizes: [10, 20, 50],\n currentPage: 1,\n total: 0,\n // 动态列表(模拟渲染)\n dynamicMeta: {},\n dynamicColumns: [],\n dynamicRows: [],\n dynamicSearch: {\n visible: false,\n keyword: ''\n },\n // 矿机种类:0-ASIC,1-GPU(默认GPU)\n machineType: 1,\n \n\n }\n },\n mounted() {\n // 读取用户上次选择的矿机种类(0: ASIC, 1: GPU)\n try{\n const savedType = Number(window && window.localStorage ? window.localStorage.getItem('pl_machineType') : NaN)\n if (savedType === 0 || savedType === 1) {\n this.machineType = savedType\n }\n }catch(e){/* noop */}\n // 不再使用本地模拟数据,动态表格完全依赖后端返回的 columns/rows\n // 仅当路由携带 shopId 时,才发起店铺商品请求\n const routeShopId =\n (this.$route && this.$route.params && (this.$route.params.shopId || this.$route.params.id)) ||\n (this.$route && this.$route.query && this.$route.query.shopId)\n if (routeShopId) {\n this.params.id = routeShopId\n this.product = true\n this.fetchGetMachineInfo(this.buildQueryParams())\n this.fetchPayTypes()\n } else {\n this.$message.warning('缺少店铺ID(shopId),无法加载商品列表')\n this.product = false\n }\n },\n methods: {\n // 动态表格单元格格式化(金额/算力/天数/文本)- 统一最多显示6位小数,hover展示完整\n formatDynamicCell(row, col) {\n try{\n let val = row[col.key]\n if (val === null || val === undefined || val === '') return { text: '—', full: '—', truncated: false }\n if (col.type === 'amount') {\n // 价格列:单位取 priceList 里的 coin;默认取第一条;选择支付方式后按选择展示\n if (col.key === 'price') {\n if (Array.isArray(row.priceList) && row.priceList.length) {\n const pv = this.getDisplayPrice(row)\n const pc = this.getDisplayPriceCoin(row)\n if (pv !== null && pv !== undefined) val = pv\n const nPrice = val\n const t = truncateTo6(nPrice)\n const coinUnit = (pc || '').toString().toUpperCase()\n return {\n text: coinUnit ? `${t.text} ${coinUnit}` : t.text,\n full: coinUnit ? `${t.full} ${coinUnit}` : t.full,\n truncated: t.truncated\n }\n }\n // 无 priceList:仅展示数值,不附加任何单位\n const t = truncateTo6(val)\n return { text: t.text, full: t.full, truncated: t.truncated }\n }\n // 列级优先:若列声明 currency=USDT,则固定展示为 \"xx.xx USDT\"\n const colCurrency = (col.currency || '').toString().toUpperCase()\n if (colCurrency === 'USDT') {\n const t = truncateTo6(val)\n return { text: `${t.text} USDT`, full: `${t.full} USDT`, truncated: t.truncated }\n }\n // 兜底:不再使用 meta 的货币符号,直接返回数值\n const t = truncateTo6(val)\n return { text: t.text, full: t.full, truncated: t.truncated }\n }\n if (col.type === 'hashrate') {\n // 接口已返回带单位的内容,直接返回字符串值,不拼接单位\n const s = String(val || '')\n return { text: s, full: s, truncated: false }\n }\n if (col.type === 'days') {\n const n = Number(val)\n if (!Number.isFinite(n)) return { text: String(val), full: String(val), truncated: false }\n const s = `${Math.floor(n)} 天`\n return { text: s, full: s, truncated: false }\n }\n const s = String(val)\n return { text: s, full: s, truncated: false }\n }catch(e){ return { text: '—', full: '—', truncated: false } }\n },\n /**\n * 如果存在 priceList,则用第一条的 chain|coin 作为默认筛选值,\n * 使“支付方式筛选”与价格列默认展示一致\n */\n ensureDefaultPayFilterFromPrices() {\n try{\n if (this.payFilterDefaultApplied) return\n const rows = Array.isArray(this.dynamicRows) ? this.dynamicRows : []\n const firstWithPriceList = rows.find(r => Array.isArray(r && r.priceList) && r.priceList.length)\n if (!firstWithPriceList) return\n const first = firstWithPriceList.priceList[0]\n const chain = String(first && first.chain || '').trim()\n const coin = String(first && first.coin || '').trim()\n if (!chain && !coin) return\n this.selectedPayKey = `${chain}|${coin}`\n this.filters.chain = chain\n this.filters.coin = coin\n this.payFilterDefaultApplied = true\n }catch(e){ /* noop */ }\n },\n /**\n * 获取行在当前支付方式下的展示价格\n * 优先匹配 selectedPayKey(chain|coin),否则回退 priceList[0];再否则回退 row.price\n */\n getDisplayPrice(row){\n try{\n const list = Array.isArray(row && row.priceList) ? row.priceList : []\n if (!list.length) return row && row.price\n const key = this.selectedPayKey\n if (key) {\n const [chainRaw, coinRaw] = String(key).split('|')\n const chain = String(chainRaw || '').toUpperCase().trim()\n const coin = String(coinRaw || '').toUpperCase().trim()\n const hit = list.find(it =>\n String(it && it.chain).toUpperCase().trim() === chain &&\n String(it && it.coin).toUpperCase().trim() === coin\n )\n if (hit && hit.price !== undefined && hit.price !== null) return hit.price\n }\n const first = list[0]\n if (first && first.price !== undefined && first.price !== null) return first.price\n return row && row.price\n }catch(e){ return row && row.price }\n },\n /**\n * 获取行在当前支付方式下价格的币种(coin)\n */\n getDisplayPriceCoin(row){\n try{\n const list = Array.isArray(row && row.priceList) ? row.priceList : []\n if (!list.length) return ''\n const key = this.selectedPayKey\n if (key) {\n const [chainRaw, coinRaw] = String(key).split('|')\n const chain = String(chainRaw || '').toUpperCase().trim()\n const coin = String(coinRaw || '').toUpperCase().trim()\n const hit = list.find(it =>\n String(it && it.chain).toUpperCase().trim() === chain &&\n String(it && it.coin).toUpperCase().trim() === coin\n )\n if (hit && hit.coin) return String(hit.coin)\n }\n const first = list[0]\n return first && first.coin ? String(first.coin) : ''\n }catch(e){ return '' }\n },\n _truncate(num, decimals=2){\n try{\n const f = Math.pow(10, decimals)\n return (Math.floor(Number(num)*f)/f).toFixed(decimals)\n }catch(e){ return String(num) }\n },\n // 判断是否为“框出来部分”的最后一列(最后一个 hashrate 列)\n isLastHashrateColumn(colIdx){\n try{\n const cols = this.getRenderedColumns()\n for (let i = cols.length - 1; i >= 0; i--) {\n if (String(cols[i] && cols[i].type).toLowerCase() === 'hashrate') {\n return i === colIdx\n }\n }\n return false\n }catch(e){ return false }\n },\n // 仅渲染前 8 个算力列,后接其它非算力列(如收益、回收期)\n getRenderedColumns(){\n try{\n const cols = Array.isArray(this.dynamicColumns) ? this.dynamicColumns : []\n const hashrate = cols.filter(c => String(c && c.type).toLowerCase() === 'hashrate').slice(0, 8)\n const others = cols.filter(c => String(c && c.type).toLowerCase() !== 'hashrate')\n return [...hashrate, ...others]\n }catch(e){ return [] }\n },\n // 打开动态搜索弹窗\n handleOpenDynamicSearch(){\n this.dynamicSearch.visible = true\n this.dynamicSearch.keyword = ''\n },\n // 确认搜索:向后端请求新的 columns/rows,替换动态表格\n async handleConfirmDynamicSearch(){\n const keyword = (this.dynamicSearch.keyword || '').trim()\n // 验证搜索关键词不能为空\n if (!keyword) {\n this.$message.warning('请输入币种代码或算法关键词')\n return\n }\n this.dynamicSearch.visible = false\n // 将关键词保存到 filters 中,然后调用接口\n this.filters.keyword = keyword\n // 重置分页到第一页\n this.params.pageNum = 1\n this.currentPage = 1\n // 调用接口获取数据\n const params = this.buildQueryParams()\n await this.fetchGetMachineInfo(params)\n },\n // 拉取动态表格数据(占位实现:如果后端已就绪,直接替换为真实接口)\n async fetchDynamicTable(params){\n try{\n // 这里预留与后端对接:\n // 期待返回格式:{ code, data: { meta, columns, rows } }\n // 示例中用本地 mock 演示:根据 keyword 过滤/调整列\n // 如果没有 keyword,就还原初始 mock\n if (!params || !params.keyword) {\n return\n }\n // 简单模拟:当 keyword 命中 'ERG',只保留 ERG + 价格/型号/回收期 等少量列\n const kw = String(params.keyword).toUpperCase()\n const baseCols = (this.dynamicColumns || []).filter(c => ['model','price','maxLeaseDays','monthIncome'].includes(c.key))\n const hitCols = (this.dynamicColumns || []).filter(c => String(c.label || c.key).toUpperCase().includes(kw))\n const nextCols = [...(baseCols.length?baseCols:[this.dynamicColumns[0]||[]]), ...hitCols]\n if (nextCols.length) {\n this.dynamicColumns = nextCols\n // 行数据无需特别处理(真实环境后端会按列同步返回),这里保留原 rows\n }\n }catch(e){\n // eslint-disable-next-line no-console\n console.warn('fetchDynamicTable mock error', e)\n }\n },\n // 切换矿机种类:0-ASIC,1-GPU\n handleMachineTypeChange(){\n // 切换前清空所有已勾选状态与确认弹窗\n try {\n if (Array.isArray(this.dynamicRows)) {\n this.dynamicRows.forEach(r => { if (r) this.$set(r, '_selected', false) })\n }\n if (this.confirmAddDialog) {\n this.confirmAddDialog.items = []\n this.confirmAddDialog.visible = false\n }\n } catch (e) { /* noop */ }\n // 变更类型后,重新请求数据与支付方式\n this.fetchGetMachineInfo(this.buildQueryParams())\n this.fetchPayTypes()\n // 本地记住用户选择\n try{\n if (window && window.localStorage) {\n window.localStorage.setItem('pl_machineType', String(this.machineType))\n }\n }catch(e){/* noop */}\n },\n // 行币种:优先行内 payCoin > coin,其次取全局表头币种\n getRowCoin(row) {\n try {\n const c = (row && (row.payCoin || row.coin)) || this.getPriceCoinSymbol() || ''\n return String(c).toUpperCase()\n } catch (e) { return '' }\n },\n // 金额格式化:不补0、不四舍五入;返回 {text,truncated,full}\n formatAmount(value, coin) {\n return truncateAmountByCoin(value, coin)\n },\n // 数值格式化:最多6位小数,截断不补0\n formatNum6(value) {\n return truncateTo6(value)\n },\n /**\n * 首次加载时,将“支付方式筛选”的默认选中值设为与价格列币种一致,\n * 并同步 filters.chain/filters.coin;仅执行一次,不触发额外查询。\n */\n ensureDefaultPayFilterSelection() {\n try {\n if (this.payFilterDefaultApplied) return\n const payList = Array.isArray(this.paymentMethodList) ? this.paymentMethodList : []\n if (!payList.length) return\n const coinSymbol = (this.getPriceCoinSymbol && this.getPriceCoinSymbol()) || ''\n if (!coinSymbol) return\n const hit = payList.find(it => String(it && it.payCoin).toUpperCase() === String(coinSymbol).toUpperCase())\n if (!hit) return\n const key = `${hit.payChain || ''}|${hit.payCoin || ''}`\n this.selectedPayKey = key\n this.filters.chain = String(hit.payChain || '').trim()\n this.filters.coin = String(hit.payCoin || '').trim()\n this.payFilterDefaultApplied = true\n } catch (e) { /* noop */ }\n },\n // 切换排序:field in ['priceSort','powerSort','powerDissipationSort']\n handleToggleSort(field) {\n try {\n if (!this.sortStates) this.sortStates = {}\n if (this.activeSortField !== field) {\n // 切换到新的字段:默认从升序开始(true)\n // 先将其它字段复位为升序(▲)\n Object.keys(this.sortStates).forEach(k => { this.sortStates[k] = true })\n this.activeSortField = field\n // 后端默认升序,首次点击应为降序\n this.sortStates[field] = false\n } else {\n // 同一字段:升降序切换\n this.sortStates[field] = !this.sortStates[field]\n }\n const params = this.buildQueryParams()\n this.fetchGetMachineInfo(params)\n } catch (e) { /* noop */ }\n },\n // 组合查询参数:店铺入口,必须包含 shopId 与 type(0-ASIC,1-GPU)\n buildQueryParams() {\n const q = { shopId: this.params.id, type: this.machineType }\n // 分页参数始终透传\n try {\n if (this.params && this.params.pageNum != null) q.pageNum = this.params.pageNum\n if (this.params && this.params.pageSize != null) q.pageSize = this.params.pageSize\n } catch (e) { /* noop */ }\n // 仅当用户真实填写(>=0)时才传参;默认/空值不传\n const addNum = (obj, key, name) => {\n const raw = obj[key]\n if (raw === null || raw === undefined || raw === '') return\n // 处理字符串格式的数字(可能包含尾随小数点)\n const str = String(raw).trim()\n if (str === '' || str === '.') return\n const n = Number(str)\n if (Number.isFinite(n) && n >= 0) q[name] = n\n }\n // 支付方式条件:有值才传\n if (this.filters.chain && String(this.filters.chain).trim()) q.chain = String(this.filters.chain).trim()\n if (this.filters.coin && String(this.filters.coin).trim()) q.coin = String(this.filters.coin).trim()\n if (this.filters.unit && String(this.filters.unit).trim()) q.unit = String(this.filters.unit).trim()\n addNum(this.filters, 'minPrice', 'minPrice')\n addNum(this.filters, 'maxPrice', 'maxPrice')\n addNum(this.filters, 'minPower', 'minPower')\n addNum(this.filters, 'maxPower', 'maxPower')\n addNum(this.filters, 'minPowerDissipation', 'minPowerDissipation')\n addNum(this.filters, 'maxPowerDissipation', 'maxPowerDissipation')\n // 币种/算法搜索关键词:有值才传\n if (this.filters.keyword && String(this.filters.keyword).trim()) {\n q.keyword = String(this.filters.keyword).trim()\n }\n // 排序参数:仅在用户点击某一列后传当前列\n try {\n if (this.activeSortField) {\n const s = this.sortStates || {}\n q[this.activeSortField] = !!s[this.activeSortField]\n }\n } catch (e) { /* noop */ }\n return q\n },\n // 拉取支付方式(兼容 shopId)\n async fetchPayTypes() {\n try {\n // 现规则:商品详情由店铺入口进入,使用 shopId 查询支付方式\n // 为兼容后端两种入参,优先传 shopId,后端若仍使用 productId 也能兼容处理\n const res = await getPayTypes({ shopId: this.params.id, productId: this.params.id })\n // 接口示例:{ code: 0, data: [ { payChain, payCoin, payCoinImage, shopId } ], msg: '' }\n if (res && (res.code === 0 || res.code === 200)) {\n const list = Array.isArray(res.data) ? res.data : []\n this.paymentMethodList = list\n // 支付方式加载后尝试设置默认筛选\n this.ensureDefaultPayFilterSelection()\n }\n } catch (e) {\n // 忽略错误,保持页面可用\n this.paymentMethodList = []\n }\n },\n\n async fetchGetMachineInfo(params) {\n this.productDetailLoading = true\n // 改为使用店铺机器列表接口\n const res = await getShopMachineList(params)\n if (res && (res.code === 200 || res.code === 0)) {\n const root = (res && res.data) ? res.data : res\n const columns = Array.isArray(root.columns) ? root.columns : (Array.isArray(res.columns) ? res.columns : [])\n const rows = Array.isArray(root.rows) ? root.rows : (Array.isArray(res.rows) ? res.rows : [])\n const total = Number(root.total != null ? root.total : (res.total != null ? res.total : 0))\n this.total = Number.isFinite(total) ? total : 0\n // 动态表格:列与行\n this.dynamicColumns = columns\n this.dynamicRows = rows.map(r => ({\n saleNumbers: 0,\n saleOutNumbers: 0,\n leaseTime: 1,\n purchaseQuantity: 1,\n _selected: false,\n ...r\n }))\n // 根据 rows 的 priceList 设置默认支付方式\n this.ensureDefaultPayFilterFromPrices()\n // 若后端同步返回支付方式,刷新本地支付方式\n try {\n const payList = root && root.payConfigList\n if (Array.isArray(payList) && payList.length) {\n this.paymentMethodList = payList\n this.ensureDefaultPayFilterSelection()\n }\n } catch (e) { /* noop */ }\n }\n\n this.productDetailLoading = false\n },\n /**\n * 加载商品详情\n */\n async loadProduct() {\n try {\n this.loading = true\n const productId = this.$route.params.id\n this.product = await getProductById(productId)\n\n if (!this.product) {\n this.$message({\n message: '商品不存在',\n type: 'error',\n showClose: true\n })\n }\n } catch (error) {\n console.error('加载商品详情失败:', error)\n this.$message({\n message: '加载商品详情失败,请稍后重试',\n type: 'error',\n showClose: true\n })\n } finally {\n this.loading = false\n }\n },\n //加入购物车\n async fetchAddCart(params) {\n const res = await addCart(params)\n\n return res\n },\n //查询购物车列表\n async fetchGetGoodsList(params) {\n const res = await getGoodsListV2(params)\n // 统计当前商品在购物车中已有的机器ID,用于禁用和默认勾选\n try {\n const productId = this.params && this.params.id ? Number(this.params.id) : Number(this.$route.params.id)\n // 兼容两种返回结构:1) 旧:直接是商品分组数组 2) 新:店铺数组 → shoppingCartInfoDtoList\n const rawRows = Array.isArray(res && res.rows)\n ? res.rows\n : Array.isArray(res && res.data && res.data.rows)\n ? res.data.rows\n : Array.isArray(res && res.data)\n ? res.data\n : []\n // 扁平化为商品分组\n const groups = rawRows.length && rawRows[0] && Array.isArray(rawRows[0].shoppingCartInfoDtoList)\n ? rawRows.flatMap(shop => Array.isArray(shop.shoppingCartInfoDtoList) ? shop.shoppingCartInfoDtoList : [])\n : rawRows\n const matched = groups.filter(g => Number(g.productId) === productId)\n const ids = new Set()\n const compositeKeys = new Set()\n matched.forEach(r => {\n const list = Array.isArray(r.productMachineDtoList) ? r.productMachineDtoList : []\n list.forEach(m => {\n if (!m) return\n if (m.id !== undefined && m.id !== null) ids.add(String(m.id))\n if (m.user && m.miner) compositeKeys.add(`${String(m.user)}|${String(m.miner)}`)\n })\n })\n this.cartMachineIdSet = ids\n this.cartCompositeKeySet = compositeKeys\n // 计算购物车总数量并通知头部,避免页面初次加载时徽标显示为0\n try {\n const totalCount = groups.reduce((sum, g) => sum + (Array.isArray(g && g.productMachineDtoList) ? g.productMachineDtoList.length : 0), 0)\n if (Number.isFinite(totalCount)) {\n window.dispatchEvent(new CustomEvent('cart-updated', { detail: { count: totalCount } }))\n }\n } catch (e) { /* noop */ }\n // 展开表格渲染后,默认勾选并禁用这些行\n this.$nextTick(() => {\n this.cartLoaded = true\n this.autoSelectAndDisable()\n })\n } catch (e) {\n console.warn('解析购物车数据失败', e)\n }\n },\n\n /**\n * 处理返回\n */\n handleBack() {\n this.$router.push('/productList')\n },\n\n\n\n /**\n * 点击系列行:切换展开/收起\n * @param {Object} row - 当前行\n */\n handleSeriesRowClick(row) {\n const key = row.id\n const lockedIds = Object.keys(this.selectedMap).filter(k => (this.selectedMap[k] || []).length > 0)\n const opened = this.expandedRowKeys.includes(key)\n if (opened) {\n // 关闭当前行,仅保留已勾选的行展开\n this.expandedRowKeys = lockedIds\n } else {\n // 打开当前行,同时保留已勾选的行展开\n this.expandedRowKeys = Array.from(new Set([key, ...lockedIds]))\n }\n },\n\n /**\n * 外层系列行样式\n */\n handleGetSeriesRowClassName() {\n return 'series-clickable-row'\n },\n\n // 子表选择变化\n handleInnerSelectionChange(parentRow, selections) {\n const key = parentRow.id\n this.$set(this.selectedMap, key, selections)\n const lockedIds = Object.keys(this.selectedMap).filter(k => (this.selectedMap[k] || []).length > 0)\n // 更新展开:锁定的行始终展开\n const openedSet = new Set(this.expandedRowKeys)\n lockedIds.forEach(id => openedSet.add(id))\n // 清理不再勾选且不是当前展开的行\n this.expandedRowKeys = Array.from(openedSet).filter(id => lockedIds.includes(id) || id === key || this.expandedRowKeys.includes(id))\n },\n\n // 展开行变化时:已取消自动与购物车对比,无需勾选/禁用\n handleExpandChange(row, expandedRows) {\n // no-op\n },\n\n // 已取消对比购物车的自动勾选/禁用逻辑\n autoSelectAndDisable() { },\n\n // 选择器可选控制:已在购物车中的机器不可再选\n isSelectable(row, index) {\n // 不再通过 selectable 禁用,以便勾选可见;通过行样式和交互阻止点击\n return true\n },\n\n // 判断在特定父行下是否已选择(配合自定义checkbox使用)\n isSelectedByParent(parentRow, row) {\n const key = parentRow && parentRow.id\n const list = (key && this.selectedMap[key]) || []\n return !!list.find(it => it && it.id === row.id)\n },\n\n // 手动切换选择(自定义checkbox与 selectedMap 同步),并维护每行的 _selected 状态\n handleManualSelect(parentRow, row, checked) {\n // 禁用:已售出或售出中的机器不可选择\n if (row && (row.saleState === 1 || row.saleState === 2)) {\n this.$message.warning('该机器已售出或售出中,无法选择')\n this.$set(row, '_selected', false)\n return\n }\n // 无价格:不可选择\n try {\n const hasPrice = (Array.isArray(row && row.priceList) && row.priceList.some(it => it && it.price !== null && it.price !== undefined))\n || (row && row.price !== null && row.price !== undefined && row.price !== '')\n if (!hasPrice) {\n this.$message.warning('该机器暂无价格,无法选择')\n this.$set(row, '_selected', false)\n return\n }\n } catch (e) { /* noop */ }\n const key = parentRow.id\n const list = (this.selectedMap[key] && [...this.selectedMap[key]]) || []\n const idx = list.findIndex(it => it && it.id === row.id)\n if (checked && idx === -1) list.push(row)\n if (!checked && idx > -1) list.splice(idx, 1)\n this.$set(this.selectedMap, key, list)\n this.$set(row, '_selected', !!checked)\n },\n\n // 为子表中已在购物车的行添加只读样式,并阻止点击取消\n handleGetInnerRowClass({ row }) {\n if (!row) return ''\n return (row.saleState === 1 || row.saleState === 2) ? 'sold-row' : ''\n },\n\n /**\n * 子行:减少数量\n * @param {number} groupIndex - 系列索引\n * @param {number} variantIndex - 变体索引\n */\n handleDecreaseVariantQuantity(groupIndex, variantIndex) {\n const item = this.productListData[groupIndex].variants[variantIndex]\n if (item.quantity > 1) {\n item.quantity--\n }\n },\n\n /**\n * 子行:增加数量\n * @param {number} groupIndex - 系列索引\n * @param {number} variantIndex - 变体索引\n */\n handleIncreaseVariantQuantity(groupIndex, variantIndex) {\n const item = this.productListData[groupIndex].variants[variantIndex]\n if (item.quantity < 99) {\n item.quantity++\n }\n },\n\n /**\n * 子行:输入数量校验\n * @param {number} groupIndex - 系列索引\n * @param {number} variantIndex - 变体索引\n */\n handleVariantQuantityInput(groupIndex, variantIndex) {\n const item = this.productListData[groupIndex].variants[variantIndex]\n const q = Number(item.quantity)\n if (!q || q < 1) item.quantity = 1\n if (q > 99) item.quantity = 99\n },\n\n /**\n * 子行:加入购物车\n * @param {Object} variant - 子项行数据\n */\n handleAddVariantToCart(variant) {\n if (!variant || !variant.onlyKey) return\n try {\n addToCart({\n id: variant.onlyKey,\n title: variant.model,\n price: variant.price,\n quantity: variant.quantity\n })\n this.$message.success(`已添加到购物车`)\n variant.quantity = 1\n } catch (error) {\n console.error('添加到购物车失败:', error)\n\n }\n },\n // 统一加入购物车\n handleAddSelectedToCart() {\n const allSelected = Object.values(this.selectedMap).flat().filter(Boolean)\n if (!allSelected.length) {\n this.$message.warning('请先勾选至少一台矿机')\n return\n }\n try {\n allSelected.forEach(item => {\n addToCart({\n id: item.onlyKey || item.id,\n title: item.type || item.model || '矿机',\n price: item.price,\n quantity: 1,\n leaseTime: Number(item.leaseTime || 1)\n })\n })\n this.$message.success(`已添加到购物车`)\n this.selectedMap = {}\n } catch (e) {\n console.error('统一加入购物车失败', e)\n\n }\n },\n // 打开确认弹窗(基于动态表格的勾选行)\n handleOpenAddToCartDialog() {\n const rows = Array.isArray(this.dynamicRows) ? this.dynamicRows : []\n const picked = rows.filter(r => !!r && !!r._selected)\n if (!picked.length) {\n this.$message.warning('请先勾选至少一台矿机')\n return\n }\n this.confirmAddDialog.items = picked.map(r => ({\n ...r,\n leaseTime: Number(r.leaseTime || 1),\n purchaseQuantity: Number(r.purchaseQuantity || 1)\n }))\n this.confirmAddDialog.visible = true\n },\n // 确认加入:调用 addGoodsV2(按条提交),GPU 不传 numbers\n async handleConfirmAddSelectedToCart() {\n const items = Array.isArray(this.confirmAddDialog.items) ? this.confirmAddDialog.items.filter(Boolean) : []\n if (!items.length) {\n this.$message.warning('请先勾选至少一台矿机')\n return\n }\n try {\n // 按接口要求:一次性传数组,每个对象代表一个勾选商品\n const payload = items.map(it => {\n const obj = {\n id: it.id,\n leaseTime: Number(it.leaseTime || 1)\n }\n if (this.machineType === 0) {\n obj.numbers = Number(it.purchaseQuantity || 1)\n }\n return obj\n })\n const res = await addGoodsV2(payload)\n if (res && (res.code === 0 || res.code === 200)) {\n this.$message({\n message: `已添加到购物车`,\n type: 'success',\n duration: 3000,\n showClose: true\n })\n }\n \n this.confirmAddDialog.visible = false\n // 清空勾选\n try {\n (this.dynamicRows || []).forEach(r => { if (r) this.$set(r, '_selected', false) })\n } catch (e) { /* noop */ }\n // 通知头部刷新\n try { window.dispatchEvent(new CustomEvent('cart-updated')) } catch (e) { /* noop */ }\n } catch (e) {\n // eslint-disable-next-line no-console\n console.error('addGoodsV2 error:', e)\n this.$message.error('加入购物车失败,请稍后重试')\n }\n },\n\n // 取消所有商品勾选(内层表格的自定义 checkbox)\n clearAllSelections() {\n try {\n // 清空选中映射(遗留字段)\n this.selectedMap = {}\n if (Array.isArray(this.machineList) && this.machineList.length) {\n this.machineList.forEach(m => { if (m) this.$set(m, '_selected', false) })\n return\n }\n const groups = Array.isArray(this.productListData) ? this.productListData : []\n groups.forEach(g => {\n const list = Array.isArray(g.productMachines) ? g.productMachines : []\n list.forEach(m => { if (m) this.$set(m, '_selected', false) })\n })\n } catch (e) { /* noop */ }\n },\n\n /**\n * 减少数量\n * @param {number} rowIndex - 表格行索引\n */\n handleDecreaseQuantity(rowIndex) {\n if (this.tableData[rowIndex].quantity > 1) {\n this.tableData[rowIndex].quantity--\n }\n },\n\n /**\n * 增加数量\n * @param {number} rowIndex - 表格行索引\n */\n handleIncreaseQuantity(rowIndex) {\n if (this.tableData[rowIndex].quantity < 99) {\n this.tableData[rowIndex].quantity++\n }\n },\n\n /**\n * 处理数量输入\n * @param {number} rowIndex - 表格行索引\n */\n handleQuantityInput(rowIndex) {\n const quantity = this.tableData[rowIndex].quantity\n if (quantity < 1) {\n this.tableData[rowIndex].quantity = 1\n } else if (quantity > 99) {\n this.tableData[rowIndex].quantity = 99\n }\n },\n\n /**\n * 处理数量输入框失焦\n * @param {number} rowIndex - 表格行索引\n */\n handleQuantityBlur(rowIndex) {\n const quantity = this.tableData[rowIndex].quantity\n if (!quantity || quantity < 1) {\n this.tableData[rowIndex].quantity = 1\n } else if (quantity > 99) {\n this.tableData[rowIndex].quantity = 99\n }\n },\n\n /**\n * 添加到购物车\n * @param {Object} rowData - 表格行数据\n */\n handleAddToCart(rowData) {\n if (!rowData || rowData.quantity < 1) {\n this.$message.warning('请选择有效的数量')\n return\n }\n\n try {\n addToCart({\n id: rowData.date, // 使用矿机名称作为ID\n title: rowData.date,\n price: rowData.price,\n quantity: rowData.quantity,\n leaseTime: Number(rowData.leaseTime || 1)\n })\n\n this.$message.success(`已添加到购物车`)\n\n // 重置数量\n rowData.quantity = 1\n } catch (error) {\n console.error('添加到购物车失败:', error)\n this.$message.error('添加到购物车失败,请稍后重试')\n }\n },\n handleSizeChange(val) {\n console.log(`每页 ${val} 条`);\n this.params.pageSize = val;\n this.params.pageNum = 1;\n this.currentPage = 1;\n // 携带当前激活的排序字段\n this.fetchGetMachineInfo(this.buildQueryParams());\n \n },\n handleCurrentChange(val) {\n console.log(`当前页: ${val}`);\n this.params.pageNum = val;\n // 携带当前激活的排序字段\n this.fetchGetMachineInfo(this.buildQueryParams());\n },\n }\n}","/**\n * 安全存储工具类\n * 使用 AES-GCM 加密算法对敏感数据进行加密存储\n * 防止 XSS 攻击导致的 Token 泄露\n */\n\n/**\n * 加密密钥(从环境变量或固定字符串派生)\n * \n */\nconst ENCRYPTION_KEY_SOURCE = 'power-leasing-2024-secure-key-v1';\n\n/**\n * 将字符串转换为 ArrayBuffer\n * @param {string} str - 要转换的字符串\n * @returns {ArrayBuffer}\n */\nfunction str2ab(str) {\n const encoder = new TextEncoder();\n return encoder.encode(str);\n}\n\n/**\n * 将 ArrayBuffer 转换为字符串\n * @param {ArrayBuffer} buffer - 要转换的 ArrayBuffer\n * @returns {string}\n */\nfunction ab2str(buffer) {\n const decoder = new TextDecoder();\n return decoder.decode(buffer);\n}\n\n/**\n * 将 ArrayBuffer 转换为 Base64 字符串\n * @param {ArrayBuffer} buffer - 要转换的 ArrayBuffer\n * @returns {string}\n */\nfunction arrayBufferToBase64(buffer) {\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let i = 0; i < bytes.byteLength; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\n/**\n * 将 Base64 字符串转换为 ArrayBuffer\n * @param {string} base64 - Base64 字符串\n * @returns {ArrayBuffer}\n */\nfunction base64ToArrayBuffer(base64) {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes.buffer;\n}\n\n/**\n * 派生加密密钥\n * @returns {Promise}\n */\nasync function getDerivedKey() {\n // 将密钥源字符串转换为 ArrayBuffer\n const keyMaterial = str2ab(ENCRYPTION_KEY_SOURCE);\n\n // 导入密钥材料\n const baseKey = await crypto.subtle.importKey(\n 'raw',\n keyMaterial,\n 'PBKDF2',\n false,\n ['deriveBits', 'deriveKey']\n );\n\n // 使用 PBKDF2 派生密钥\n // 盐值固定(实际应该存储随机盐值,但为了简化实现使用固定盐)\n const salt = str2ab('power-leasing-salt-2024');\n\n return await crypto.subtle.deriveKey(\n {\n name: 'PBKDF2',\n salt: salt,\n iterations: 100000,\n hash: 'SHA-256'\n },\n baseKey,\n { name: 'AES-GCM', length: 256 },\n false,\n ['encrypt', 'decrypt']\n );\n}\n\n/**\n * 加密数据\n * @param {string} plaintext - 明文数据\n * @returns {Promise} 加密后的数据(Base64 编码)\n */\nasync function encrypt(plaintext) {\n try {\n if (!plaintext || typeof plaintext !== 'string') {\n return null;\n }\n\n // 获取加密密钥\n const key = await getDerivedKey();\n\n // 生成随机 IV(初始化向量)\n const iv = crypto.getRandomValues(new Uint8Array(12));\n\n // 加密数据\n const encrypted = await crypto.subtle.encrypt(\n {\n name: 'AES-GCM',\n iv: iv\n },\n key,\n str2ab(plaintext)\n );\n\n // 将 IV 和加密数据组合(IV 不需要保密,可以明文存储)\n const combined = new Uint8Array(iv.length + encrypted.byteLength);\n combined.set(iv, 0);\n combined.set(new Uint8Array(encrypted), iv.length);\n\n // 转换为 Base64 字符串\n return arrayBufferToBase64(combined.buffer);\n } catch (error) {\n console.error('加密失败:', error);\n return null;\n }\n}\n\n/**\n * 解密数据\n * @param {string} ciphertext - 加密后的数据(Base64 编码)\n * @returns {Promise} 解密后的明文数据\n */\nasync function decrypt(ciphertext) {\n try {\n if (!ciphertext || typeof ciphertext !== 'string') {\n return null;\n }\n\n // 获取加密密钥\n const key = await getDerivedKey();\n\n // 解码 Base64\n const combined = base64ToArrayBuffer(ciphertext);\n\n // 分离 IV 和加密数据\n const iv = combined.slice(0, 12);\n const encrypted = combined.slice(12);\n\n // 解密数据\n const decrypted = await crypto.subtle.decrypt(\n {\n name: 'AES-GCM',\n iv: iv\n },\n key,\n encrypted\n );\n\n // 转换为字符串\n return ab2str(decrypted);\n } catch (error) {\n console.error('解密失败:', error);\n return null;\n }\n}\n\n/**\n * 安全存储类\n * 提供加密的 localStorage 操作接口\n */\nclass SecureStorage {\n /**\n * 安全地设置 localStorage 项(加密存储)\n * @param {string} key - 存储键名\n * @param {string} value - 要存储的值\n * @returns {Promise} 是否成功\n */\n async setItem(key, value) {\n try {\n if (!value) {\n localStorage.removeItem(key);\n return true;\n }\n\n // 加密数据\n const encrypted = await encrypt(value);\n if (encrypted) {\n localStorage.setItem(key, encrypted);\n return true;\n }\n return false;\n } catch (error) {\n console.error(`安全存储失败 [${key}]:`, error);\n return false;\n }\n }\n\n /**\n * 安全地获取 localStorage 项(解密读取)\n * @param {string} key - 存储键名\n * @returns {Promise} 解密后的值\n */\n async getItem(key) {\n try {\n const encrypted = localStorage.getItem(key);\n if (!encrypted) {\n return null;\n }\n\n // 解密数据\n return await decrypt(encrypted);\n } catch (error) {\n console.error(`安全读取失败 [${key}]:`, error);\n return null;\n }\n }\n\n /**\n * 移除 localStorage 项\n * @param {string} key - 存储键名\n */\n removeItem(key) {\n try {\n localStorage.removeItem(key);\n } catch (error) {\n console.error(`移除存储失败 [${key}]:`, error);\n }\n }\n\n /**\n * 检查 localStorage 项是否存在\n * @param {string} key - 存储键名\n * @returns {boolean}\n */\n hasItem(key) {\n try {\n return localStorage.getItem(key) !== null;\n } catch (error) {\n console.error(`检查存储失败 [${key}]:`, error);\n return false;\n }\n }\n}\n\n// 创建单例实例\nconst secureStorage = new SecureStorage();\n\nexport default secureStorage;\nexport { SecureStorage };\n","\r\n\r\n\r\n\r\n\r\n\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.productDetailLoading),expression:\"productDetailLoading\"}],staticClass:\"product-detail\"},[(_vm.loading)?_c('div',{staticClass:\"loading\"},[_c('i',{staticClass:\"el-icon-loading\",attrs:{\"aria-label\":\"加载中\",\"role\":\"img\"}}),_vm._v(\" 加载中... \")]):(_vm.product)?_c('div',{staticClass:\"detail-container\"},[_c('h2',{staticStyle:{\"margin\":\"10px\",\"text-align\":\"left\",\"margin-top\":\"28px\"}},[_vm._v(\"商品详情-选择矿机\")]),_c('section',{staticClass:\"pay-methods\",attrs:{\"aria-label\":\"支付方式\"}},[_c('div',{staticClass:\"pay-label\",attrs:{\"tabindex\":\"0\",\"aria-label\":\"支付方式标签\"}},[_vm._v(\"支付方式:\")]),_c('ul',{staticClass:\"pay-list\",attrs:{\"role\":\"list\",\"aria-label\":\"支付方式列表\"}},_vm._l((_vm.paymentMethodList),function(item,index){return _c('li',{key:index,staticClass:\"pay-item\",attrs:{\"aria-label\":`支付方式: ${item.payChain}`}},[_c('el-tooltip',{attrs:{\"content\":_vm.formatPayTooltip(item),\"placement\":\"top\",\"open-delay\":80}},[_c('img',{staticClass:\"pay-icon\",attrs:{\"src\":_vm.getPayImageUrl(item),\"alt\":`${(item.payChain || '').toUpperCase()} ${(item.payCoin || '').toUpperCase()}`.trim(),\"title\":_vm.formatPayTooltip(item),\"tabindex\":\"0\",\"role\":\"img\"},on:{\"keydown\":[function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;$event.preventDefault();return _vm.handlePayIconKeyDown(item)},function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"space\",32,$event.key,[\" \",\"Spacebar\"]))return null;$event.preventDefault();return _vm.handlePayIconKeyDown(item)}]}})])],1)}),0)]),_c('section',{staticClass:\"filter-bar\",attrs:{\"aria-label\":\"筛选条件\"}},[_c('div',{staticClass:\"filter-grid\"},[_c('div',{staticClass:\"filter-cell\"},[_c('label',{staticClass:\"filter-title\"},[_vm._v(\"矿机种类\")]),_c('div',{staticStyle:{\"display\":\"inline-flex\",\"align-items\":\"center\"}},[_c('el-radio-group',{attrs:{\"size\":\"small\"},on:{\"change\":_vm.handleMachineTypeChange},model:{value:(_vm.machineType),callback:function ($$v) {_vm.machineType=$$v},expression:\"machineType\"}},[_c('el-radio-button',{attrs:{\"label\":1}},[_vm._v(\"GPU\")]),_c('el-radio-button',{attrs:{\"label\":0}},[_vm._v(\"ASIC\")])],1)],1)]),_c('div',{staticClass:\"filter-cell\"},[_c('label',{staticClass:\"filter-title\",attrs:{\"for\":\"payFilter\"}},[_vm._v(\"支付方式筛选\")]),_c('el-select',{staticClass:\"filter-control\",staticStyle:{\"max-width\":\"260px\"},attrs:{\"id\":\"payFilter\",\"placeholder\":\"全部\",\"clearable\":\"\",\"filterable\":\"\",\"size\":\"small\"},on:{\"change\":_vm.handlePayFilterChange},scopedSlots:_vm._u([{key:\"prefix\",fn:function(){return [(_vm.getSelectedPayIcon())?_c('img',{staticStyle:{\"width\":\"16px\",\"height\":\"16px\",\"border-radius\":\"3px\",\"margin-right\":\"6px\"},attrs:{\"src\":_vm.getSelectedPayIcon(),\"alt\":\"\"}}):_vm._e()]},proxy:true}]),model:{value:(_vm.selectedPayKey),callback:function ($$v) {_vm.selectedPayKey=$$v},expression:\"selectedPayKey\"}},_vm._l((_vm.paymentMethodList),function(opt,i){return _c('el-option',{key:i,attrs:{\"label\":_vm.formatPayTooltip(opt),\"value\":`${opt.payChain || ''}|${opt.payCoin || ''}`}},[_c('div',{staticClass:\"pay-opt\"},[_c('img',{staticClass:\"pay-icon\",attrs:{\"src\":_vm.getPayImageUrl(opt),\"alt\":\"\"}}),_c('span',[_vm._v(_vm._s((opt.payChain || '').toUpperCase())+\" - \"+_vm._s((opt.payCoin || '').toUpperCase()))])])])}),1)],1),_c('div',{staticClass:\"filter-cell center-title\"},[_c('label',{staticClass:\"filter-title\"},[_vm._v(\"单价区间\"),(_vm.getPriceCoinSymbol())?_c('span',[_vm._v(\"(\"+_vm._s(_vm.getPriceCoinSymbol())+\")\")]):_vm._e()]),_c('div',{staticClass:\"range-controls\"},[_c('el-input',{staticClass:\"filter-control price-input\",attrs:{\"placeholder\":\"最小单价\",\"size\":\"small\",\"inputmode\":\"decimal\"},on:{\"input\":_vm.handleMinPriceInput},model:{value:(_vm.filters.minPrice),callback:function ($$v) {_vm.$set(_vm.filters, \"minPrice\", $$v)},expression:\"filters.minPrice\"}}),_c('span',{staticClass:\"filter-sep\"},[_vm._v(\"-\")]),_c('el-input',{staticClass:\"filter-control price-input\",attrs:{\"placeholder\":\"最大单价\",\"size\":\"small\",\"inputmode\":\"decimal\"},on:{\"input\":_vm.handleMaxPriceInput},model:{value:(_vm.filters.maxPrice),callback:function ($$v) {_vm.$set(_vm.filters, \"maxPrice\", $$v)},expression:\"filters.maxPrice\"}})],1)]),_c('div',{staticClass:\"filter-cell filter-actions\"},[_c('div',{staticClass:\"action-row\"},[_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\",\"aria-label\":\"执行筛选\"},on:{\"click\":_vm.handleSearchFilters}},[_vm._v(\"筛选查询\")]),_c('el-button',{attrs:{\"size\":\"small\",\"aria-label\":\"重置筛选\"},on:{\"click\":_vm.handleResetFilters}},[_vm._v(\"搜索重置\")])],1)])])]),(_vm.dynamicColumns && _vm.dynamicColumns.length)?_c('section',{staticClass:\"dynamic-hashrate\",attrs:{\"aria-label\":\"动态收益表\"}},[_c('el-table',{staticClass:\"dynamic-table\",attrs:{\"data\":_vm.dynamicRows,\"border\":\"\",\"stripe\":\"\",\"size\":\"small\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"width\":\"46\",\"fixed\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function({ row }){return [_c('el-checkbox',{attrs:{\"title\":_vm.isRowDisabled(row) ? (row && (row.saleState === 1 || row.saleState === 2) ? '该机器已售出或售出中,无法选择' : '该机器暂无价格,无法选择') : '选择该矿机',\"disabled\":_vm.isRowDisabled(row)},on:{\"change\":checked => _vm.handleManualSelectFlat(row, checked)},model:{value:(row._selected),callback:function ($$v) {_vm.$set(row, \"_selected\", $$v)},expression:\"row._selected\"}})]}}],null,false,1048063571)}),_vm._l((_vm.getRenderedColumns()),function(col,colIdx){return _c('el-table-column',{key:col.key || colIdx,attrs:{\"prop\":col.key,\"label\":col.label,\"fixed\":col.fixed || false,\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_c('div',{staticClass:\"col-header\",attrs:{\"title\":col.label}},[(col.icon)?_c('img',{staticClass:\"col-icon\",attrs:{\"src\":col.icon,\"alt\":\"\"}}):_vm._e(),_c('span',[_vm._v(_vm._s(col.label))]),(_vm.isLastHashrateColumn(colIdx))?_c('el-button',{staticClass:\"more-action\",attrs:{\"type\":\"text\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleOpenDynamicSearch.apply(null, arguments)}}},[_vm._v(\"更多\")]):_vm._e()],1)]},proxy:true},{key:\"default\",fn:function({ row }){return [_c('span',{class:_vm.getCellClass(col)},[(_vm.formatDynamicCell(row, col).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatDynamicCell(row, col).full,\"placement\":\"top\"}},[_c('span',[_vm._v(_vm._s(_vm.formatDynamicCell(row, col).text))])]):_c('span',[_vm._v(_vm._s(_vm.formatDynamicCell(row, col).text))])],1)]}}],null,true)})}),(_vm.machineType === 0)?_c('el-table-column',{attrs:{\"prop\":\"saleNumbers\",\"label\":\"总机器数\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.saleNumbers != null ? scope.row.saleNumbers : '—'))])]}}],null,false,1658856336)}):_vm._e(),(_vm.machineType === 0)?_c('el-table-column',{attrs:{\"prop\":\"saleOutNumbers\",\"label\":\"已售数量\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.saleOutNumbers != null ? scope.row.saleOutNumbers : '—'))])]}}],null,false,1678042608)}):_vm._e(),_c('el-table-column',{attrs:{\"prop\":\"leaseTime\",\"label\":\"租赁天数(天)\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input-number',{staticClass:\"input-full\",attrs:{\"min\":1,\"max\":_vm.getRowMaxLeaseDays(scope.row),\"precision\":0,\"step\":1,\"controls\":false,\"size\":\"mini\"},on:{\"change\":val => _vm.handleLeaseDaysChange(scope.row, val)},model:{value:(scope.row.leaseTime),callback:function ($$v) {_vm.$set(scope.row, \"leaseTime\", $$v)},expression:\"scope.row.leaseTime\"}})]}}],null,false,1697156763)}),(_vm.machineType === 0)?_c('el-table-column',{attrs:{\"prop\":\"purchaseQuantity\",\"label\":\"购买数量\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input-number',{staticClass:\"input-full\",attrs:{\"min\":1,\"max\":_vm.getRowMaxPurchase(scope.row),\"precision\":0,\"step\":1,\"controls\":false,\"size\":\"mini\",\"disabled\":_vm.getRowMaxPurchase(scope.row) <= 0},on:{\"change\":val => _vm.handlePurchaseQuantityChange(scope.row, val)},model:{value:(scope.row.purchaseQuantity),callback:function ($$v) {_vm.$set(scope.row, \"purchaseQuantity\", $$v)},expression:\"scope.row.purchaseQuantity\"}})]}}],null,false,3016046336)}):_vm._e(),_c('el-table-column',{attrs:{\"prop\":\"totalAmount\",\"label\":\"总价\",\"header-align\":\"left\",\"align\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[_vm._v(_vm._s(_vm.formatConfirmTotalText(scope.row)))])]}}],null,false,1059681298)})],2),_c('el-dialog',{attrs:{\"title\":\"搜索币种/算法\",\"visible\":_vm.dynamicSearch.visible,\"width\":\"420px\"},on:{\"update:visible\":function($event){return _vm.$set(_vm.dynamicSearch, \"visible\", $event)}}},[_c('div',{staticClass:\"dynamic-search-bar\",staticStyle:{\"display\":\"flex\",\"gap\":\"10px\",\"align-items\":\"center\"}},[_c('el-input',{attrs:{\"placeholder\":\"输入币种代码或算法关键词\",\"clearable\":\"\"},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleConfirmDynamicSearch.apply(null, arguments)}},model:{value:(_vm.dynamicSearch.keyword),callback:function ($$v) {_vm.$set(_vm.dynamicSearch, \"keyword\", $$v)},expression:\"dynamicSearch.keyword\"}}),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleConfirmDynamicSearch}},[_vm._v(\"搜索\")])],1)])],1):_vm._e(),_c('div',{staticStyle:{\"margin\":\"18px\",\"text-align\":\"right\"}},[_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.handleOpenAddToCartDialog}},[_vm._v(\"加入购物车\")])],1),_c('el-dialog',{attrs:{\"visible\":_vm.confirmAddDialog.visible,\"width\":\"70vw\",\"title\":`确认加入购物车(共 ${_vm.confirmAddDialog.items.length} 台)`},on:{\"update:visible\":function($event){return _vm.$set(_vm.confirmAddDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{on:{\"click\":function($event){_vm.confirmAddDialog.visible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleConfirmAddSelectedToCart}},[_vm._v(\"确认加入\")])]},proxy:true}])},[_c('div',[_c('el-table',{attrs:{\"data\":_vm.confirmAddDialog.items,\"height\":\"360\",\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"prop\":\"model\",\"label\":\"型号\",\"header-align\":\"left\",\"align\":\"left\"}}),_c('el-table-column',{attrs:{\"prop\":\"price\",\"label\":\"价格\",\"header-align\":\"left\",\"align\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[(_vm.formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).full,\"placement\":\"top\"}},[_c('span',[_vm._v(_vm._s(_vm.formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).text))])]):_c('span',[_vm._v(_vm._s(_vm.formatDynamicCell(scope.row, { key: 'price', type: 'amount' }).text))])],1)]}}])}),_c('el-table-column',{attrs:{\"prop\":\"leaseTime\",\"label\":\"租赁天数(天)\",\"header-align\":\"left\",\"align\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(Number(scope.row.leaseTime || 1)))]}}])}),(_vm.machineType === 0)?_c('el-table-column',{attrs:{\"prop\":\"purchaseQuantity\",\"label\":\"购买数量\",\"header-align\":\"left\",\"align\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(Number(scope.row.purchaseQuantity || 0)))]}}],null,false,1092190239)}):_vm._e(),_c('el-table-column',{attrs:{\"prop\":\"totalAmount\",\"label\":\"总价\",\"header-align\":\"left\",\"align\":\"left\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[_vm._v(_vm._s(_vm.formatConfirmTotalText(scope.row)))])]}}])})],1)],1)]),_c('el-row',{staticStyle:{\"margin-bottom\":\"20px\"}},[_c('el-col',{staticStyle:{\"display\":\"flex\",\"justify-content\":\"center\"},attrs:{\"span\":24}},[_c('el-pagination',{staticStyle:{\"margin\":\"0 auto\",\"margin-top\":\"10px\"},attrs:{\"current-page\":_vm.currentPage,\"page-sizes\":_vm.pageSizes,\"page-size\":_vm.params.pageSize,\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total},on:{\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange,\"update:currentPage\":function($event){_vm.currentPage=$event},\"update:current-page\":function($event){_vm.currentPage=$event}}})],1)],1)],1):_c('div',{staticClass:\"not-found\"},[_c('h2',[_vm._v(\"商品不存在\")]),_c('p',[_vm._v(\"抱歉,您查找的商品不存在或已被删除。\")]),_c('button',{staticClass:\"back-btn\",on:{\"click\":_vm.handleBack}},[_vm._v(\"返回商品列表\")])])])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./products.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./products.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./products.vue?vue&type=template&id=12678474&scoped=true\"\nimport script from \"./products.vue?vue&type=script&lang=js\"\nexport * from \"./products.vue?vue&type=script&lang=js\"\nimport style0 from \"./products.vue?vue&type=style&index=0&id=12678474&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"12678474\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-container\"},[_vm._m(0),_c('div',{staticClass:\"auth-card\"},[_c('div',{staticClass:\"close-btn\",attrs:{\"title\":\"返回商城\"},on:{\"click\":_vm.goToShop}},[_c('i',{staticClass:\"el-icon-close\"})]),_vm._m(1),_c('el-form',{ref:\"loginForm\",staticClass:\"auth-form\",attrs:{\"model\":_vm.loginForm,\"rules\":_vm.loginRules},nativeOn:{\"submit\":function($event){$event.preventDefault();return _vm.handleLogin.apply(null, arguments)}}},[_c('el-form-item',{attrs:{\"prop\":\"email\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入邮箱\",\"prefix-icon\":\"el-icon-message\",\"size\":\"large\",\"clearable\":\"\"},on:{\"change\":_vm.handleEmailChange},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleLogin.apply(null, arguments)}},model:{value:(_vm.loginForm.email),callback:function ($$v) {_vm.$set(_vm.loginForm, \"email\", $$v)},expression:\"loginForm.email\"}})],1),_c('el-form-item',{attrs:{\"prop\":\"password\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请输入密码(8-32位)\",\"prefix-icon\":\"el-icon-lock\",\"size\":\"large\",\"show-password\":\"\",\"clearable\":\"\"},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleLogin.apply(null, arguments)}},model:{value:(_vm.loginForm.password),callback:function ($$v) {_vm.$set(_vm.loginForm, \"password\", $$v)},expression:\"loginForm.password\"}}),_c('div',{staticClass:\"password-tip\"},[_c('i',{staticClass:\"el-icon-info\"}),_c('span',[_vm._v(\"密码需包含大小写字母、数字和特殊字符,长度8-32位\")])])],1),_c('el-form-item',{attrs:{\"prop\":\"code\"}},[_c('div',{staticClass:\"code-input-wrapper\"},[_c('el-input',{attrs:{\"placeholder\":\"请输入邮箱验证码\",\"prefix-icon\":\"el-icon-key\",\"size\":\"large\",\"maxlength\":\"10\",\"clearable\":\"\"},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleLogin.apply(null, arguments)}},model:{value:(_vm.loginForm.code),callback:function ($$v) {_vm.$set(_vm.loginForm, \"code\", $$v)},expression:\"loginForm.code\"}}),_c('el-button',{staticClass:\"send-code-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"disabled\":_vm.countdown > 0,\"loading\":_vm.sendingCode},on:{\"click\":_vm.handleSendCode}},[_vm._v(\" \"+_vm._s(_vm.countdown > 0 ? `${_vm.countdown}秒后重试` : '获取验证码')+\" \")])],1)]),_c('div',{staticClass:\"auth-options\"},[_c('span'),_c('router-link',{staticClass:\"link-text\",attrs:{\"to\":\"/reset-password\"}},[_vm._v(\" 忘记密码? \")])],1),_c('el-form-item',[_c('el-button',{staticClass:\"auth-submit-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"loading\":_vm.loading},on:{\"click\":_vm.handleLogin}},[_vm._v(\" \"+_vm._s(_vm.loading ? '登录中...' : '登录')+\" \")])],1),_c('div',{staticClass:\"auth-footer\"},[_c('span',{staticClass:\"footer-text\"},[_vm._v(\"还没有账号?\")]),_c('router-link',{staticClass:\"link-text link-primary\",attrs:{\"to\":\"/register\"}},[_vm._v(\" 立即注册 \")])],1)],1)],1)])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-background\"},[_c('div',{staticClass:\"bg-circle circle-1\"}),_c('div',{staticClass:\"bg-circle circle-2\"}),_c('div',{staticClass:\"bg-circle circle-3\"})])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-header\"},[_c('h1',{staticClass:\"auth-title\"},[_vm._v(\"欢迎登录\")]),_c('p',{staticClass:\"auth-subtitle\"},[_vm._v(\"Power Leasing - 算力租赁平台\")])])\n}]\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"purchased-machine-detail\"},[_c('div',{staticClass:\"toolbar\"},[_c('div',{staticClass:\"left-area\"},[_c('el-button',{staticClass:\"back-btn\",attrs:{\"type\":\"text\",\"icon\":\"el-icon-arrow-left\"},on:{\"click\":_vm.handleBack}},[_vm._v(\" 返回 \")]),_c('h2',{staticClass:\"page-title\"},[_vm._v(\"已购商品详情\")])],1)]),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"detail-content\"},[(_vm.detailData)?_c('el-card',{staticClass:\"detail-card\"},[_c('div',{staticClass:\"card-header\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_c('span',[_vm._v(\"基本信息\")])]),_c('el-descriptions',{attrs:{\"column\":2,\"border\":\"\"}},[_c('el-descriptions-item',{attrs:{\"label\":\"挖矿账户\"}},[_vm._v(\" \"+_vm._s(_vm.detailData.poolUser || '—')+\" \")]),_c('el-descriptions-item',{attrs:{\"label\":\"矿池名称\"}},[_vm._v(\" \"+_vm._s(_vm.detailData.pool || '—')+\" \")]),_c('el-descriptions-item',{attrs:{\"label\":\"矿池挖矿地址\"}},[(_vm.detailData.poolUrl)?_c('div',{staticClass:\"address-item\"},[_c('span',{staticClass:\"mono-ellipsis\"},[_vm._v(_vm._s(_vm.detailData.poolUrl))]),_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){return _vm.handleCopy(_vm.detailData.poolUrl, '矿池挖矿地址')}}},[_vm._v(\" 复制 \")])],1):_c('span',[_vm._v(\"—\")])]),_c('el-descriptions-item',{attrs:{\"label\":\"矿池所挖币种\"}},[_vm._v(\" \"+_vm._s(_vm.detailData.coin || '—')+\" \")]),_c('el-descriptions-item',{attrs:{\"label\":\"币种对应算法\"}},[_vm._v(\" \"+_vm._s(_vm.detailData.algorithm || '—')+\" \")]),_c('el-descriptions-item',{attrs:{\"label\":\"收款钱包\"}},[(_vm.detailData.walletAddress)?_c('div',{staticClass:\"address-item\"},[_c('span',{staticClass:\"mono-ellipsis\",staticStyle:{\"font-family\":\"monospace\"}},[_vm._v(_vm._s(_vm.detailData.walletAddress))]),_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){return _vm.handleCopy(_vm.detailData.walletAddress, '收款钱包')}}},[_vm._v(\" 复制 \")])],1):_c('span',[_vm._v(\"—\")])]),(_vm.detailData.watchUrl)?_c('el-descriptions-item',{attrs:{\"label\":\"挖矿信息页面地址\"}},[_c('div',{staticClass:\"address-item\"},[_c('span',{staticClass:\"mono-ellipsis\"},[_vm._v(_vm._s(_vm.detailData.watchUrl))]),_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){return _vm.handleCopy(_vm.detailData.watchUrl, '挖矿信息页面地址')}}},[_vm._v(\" 复制 \")])],1)]):_vm._e()],1)],1):_vm._e(),(_vm.detailData)?_c('el-card',{staticClass:\"detail-card\"},[_c('div',{staticClass:\"card-header\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_c('span',[_vm._v(\"已购矿机信息\")])]),(_vm.purchasedMachinesList && _vm.purchasedMachinesList.length > 0)?_c('el-table',{staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.purchasedMachinesList,\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"prop\":\"workerId\",\"label\":\"矿工号\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.workerId || '—'))])]}}],null,false,3323832681)}),_c('el-table-column',{attrs:{\"prop\":\"power\",\"label\":\"实时算力\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.power || '—'))])]}}],null,false,1271444333)}),_c('el-table-column',{attrs:{\"prop\":\"recordTime\",\"label\":\"最近实时算力记录时间\",\"min-width\":\"180\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(_vm.formatDateTime(scope.row.recordTime)))])]}}],null,false,889773213)}),_c('el-table-column',{attrs:{\"prop\":\"startTime\",\"label\":\"挖矿开始时间\",\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(_vm.formatDateTime(scope.row.startTime)))])]}}],null,false,1820455728)}),_c('el-table-column',{attrs:{\"prop\":\"endTime\",\"label\":\"挖矿结束时间\",\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(_vm.formatDateTime(scope.row.endTime)))])]}}],null,false,1075225151)}),_c('el-table-column',{attrs:{\"prop\":\"status\",\"label\":\"状态\",\"width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":_vm.getStatusType(scope.row.status)}},[_vm._v(\" \"+_vm._s(_vm.getStatusText(scope.row.status))+\" \")])]}}],null,false,2263538733)})],1):_c('div',{staticClass:\"empty-table\"},[_c('p',[_vm._v(\"暂无矿机信息\")])])],1):_vm._e(),(!_vm.loading && !_vm.detailData)?_c('div',{staticClass:\"empty-state\"},[_c('p',[_vm._v(\"未找到详情信息\")])]):_vm._e()],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n","// 金额截断显示工具(不补0、不四舍五入)\n// 规则:\n// - USDT: 最多6位小数\n// - ETH: 最多8位小数\n// - 其他币种: 最多6位小数\n// 返回 { text, truncated, full }\n\nexport function getMaxDecimalsByCoin() {\n // 全站统一:最多 6 位小数\n return 6;\n}\n\nexport function truncateAmountRaw(value, maxDecimals) {\n if (value === null || value === undefined) {\n return { text: '0', truncated: false, full: '0' };\n }\n const raw = String(value);\n if (!raw) return { text: '0', truncated: false, full: '0' };\n // 非数字字符串直接返回原值\n if (!/^-?\\d+(\\.\\d+)?$/.test(raw)) {\n return { text: raw, truncated: false, full: raw };\n }\n const isNegative = raw.startsWith('-');\n const abs = isNegative ? raw.slice(1) : raw;\n const [intPart, decPart = ''] = abs.split('.');\n const keep = decPart.slice(0, Math.max(0, maxDecimals));\n const truncated = decPart.length > maxDecimals;\n const text = (isNegative ? '-' : '') + (keep ? `${intPart}.${keep}` : intPart);\n return { text, truncated, full: raw };\n}\n\nexport function truncateAmountByCoin(value, coin) {\n const max = getMaxDecimalsByCoin(coin);\n return truncateAmountRaw(value, max);\n}\n\n// 默认 6 位截断(非币种语境也可复用)\nexport function truncateTo6(value) {\n return truncateAmountRaw(value, 6);\n}\n\n","// 全局 loading 状态管理器\r\nclass LoadingManager {\r\n constructor() {\r\n this.loadingStates = new Map(); // 存储所有 loading 状态\r\n this.setupListeners();\r\n }\r\n \r\n setupListeners() {\r\n // 监听网络重试完成事件\r\n window.addEventListener('network-retry-complete', () => {\r\n this.resetAllLoadingStates();\r\n });\r\n }\r\n \r\n // 设置 loading 状态\r\n setLoading(componentId, stateKey, value) {\r\n const key = `${componentId}:${stateKey}`;\r\n this.loadingStates.set(key, {\r\n value,\r\n timestamp: Date.now()\r\n });\r\n }\r\n \r\n // 获取 loading 状态\r\n getLoading(componentId, stateKey) {\r\n const key = `${componentId}:${stateKey}`;\r\n const state = this.loadingStates.get(key);\r\n return state ? state.value : false;\r\n }\r\n \r\n // 重置所有 loading 状态\r\n resetAllLoadingStates() {\r\n // 清除所有处于加载状态的组件\r\n const componentsToUpdate = [];\r\n \r\n this.loadingStates.forEach((state, key) => {\r\n if (state.value === true) {\r\n const [componentId, stateKey] = key.split(':');\r\n componentsToUpdate.push({ componentId, stateKey });\r\n this.loadingStates.set(key, { value: false, timestamp: Date.now() });\r\n }\r\n });\r\n \r\n // 使用事件通知各组件更新\r\n window.dispatchEvent(new CustomEvent('reset-loading-states', {\r\n detail: { componentsToUpdate }\r\n }));\r\n }\r\n \r\n // 重置特定组件的所有 loading 状态\r\n resetComponentLoadingStates(componentId) {\r\n const componentsToUpdate = [];\r\n \r\n this.loadingStates.forEach((state, key) => {\r\n if (key.startsWith(`${componentId}:`) && state.value === true) {\r\n const stateKey = key.split(':')[1];\r\n componentsToUpdate.push({ componentId, stateKey });\r\n this.loadingStates.set(key, { value: false, timestamp: Date.now() });\r\n }\r\n });\r\n \r\n return componentsToUpdate;\r\n }\r\n }\r\n \r\n // 创建单例实例\r\n const loadingManager = new LoadingManager();\r\n export default loadingManager;","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./productDetail.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./productDetail.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./productDetail.vue?vue&type=template&id=69d09b20&scoped=true\"\nimport script from \"./productDetail.vue?vue&type=script&lang=js\"\nexport * from \"./productDetail.vue?vue&type=script&lang=js\"\nimport style0 from \"./productDetail.vue?vue&type=style&index=0&id=69d09b20&prod&scoped=true&lang=css\"\nimport style1 from \"./productDetail.vue?vue&type=style&index=1&id=69d09b20&prod&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"69d09b20\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.productListLoading),expression:\"productListLoading\"}],staticClass:\"product-list\"},[_c('section',{staticClass:\"container\"},[_c('h1',{staticClass:\"page-title\"},[_vm._v(\"商品列表\")]),_c('section',{staticClass:\"filter-section\"},[_c('div',{staticClass:\"filter-row\"},[_c('el-input',{staticClass:\"search-input\",attrs:{\"size\":\"middle\",\"placeholder\":\"输入币种或算法搜索\",\"clearable\":\"\"},on:{\"clear\":_vm.handleAlgorithmClear},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleAlgorithmSearch.apply(null, arguments)}},scopedSlots:_vm._u([{key:\"append\",fn:function(){return [_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleAlgorithmSearch}},[_vm._v(\"搜索\")])]},proxy:true}]),model:{value:(_vm.searchAlgorithm),callback:function ($$v) {_vm.searchAlgorithm=$$v},expression:\"searchAlgorithm\"}})],1)]),_c('div',{staticClass:\"product-list-grid\"},[_vm._l((_vm.products),function(product,idx){return _c('div',{key:product.shopId || product.id || idx,staticClass:\"product-item\",attrs:{\"tabindex\":\"0\",\"aria-label\":\"查看详情\"},on:{\"click\":function($event){return _vm.handleProductClick(product)}}},[_c('img',{staticClass:\"product-image\",attrs:{\"src\":require(\"../../assets/imgs/commodity.png\"),\"alt\":product.name}}),_c('div',{staticClass:\"product-info\"},[_c('h4',{staticClass:\"title-line\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"店铺:\")]),_c('span',{staticClass:\"value ellipsis\",attrs:{\"title\":product.shopName || product.name}},[_vm._v(_vm._s(product.shopName || product.name))])]),_c('p',{staticClass:\"info-line coin-line\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"币种:\")]),_c('el-tooltip',{attrs:{\"content\":product.coin,\"placement\":\"top\",\"open-delay\":80}},[_c('span',{staticClass:\"value ellipsis\",attrs:{\"tabindex\":\"0\",\"aria-label\":`币种 ${product.coin}`}},[_vm._v(_vm._s(product.coin))])])],1),_c('p',{staticClass:\"info-line algorithm-line\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"算法:\")]),_c('el-tooltip',{attrs:{\"content\":product.algorithm,\"placement\":\"top\",\"open-delay\":80}},[_c('span',{staticClass:\"value ellipsis\",attrs:{\"tabindex\":\"0\",\"aria-label\":`算法 ${product.algorithm}`}},[_vm._v(_vm._s(product.algorithm))])])],1),_c('div',{staticClass:\"product-footer\"},[_c('div',{staticClass:\"paytypes\"},[_c('span',{staticClass:\"paytypes-label\"},[_vm._v(\"支付方式:\")]),_vm._l(((product.payTypes || [])),function(pt,idx){return _c('el-tooltip',{key:idx,attrs:{\"content\":_vm.formatPayType(pt),\"placement\":\"top\",\"open-delay\":80}},[_c('img',{staticClass:\"paytype-icon\",attrs:{\"src\":pt.image,\"alt\":_vm.formatPayType(pt)}})])})],2),_c('div',{staticClass:\"right-meta\"},[_c('span',{staticClass:\"product-sold\",attrs:{\"aria-label\":\"已售数量\"}},[_vm._v(\"已售:\"+_vm._s(product && product.saleNumber != null ? product.saleNumber : 0))])])])])])}),(_vm.products.length === 0 && !_vm.productListLoading)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-goods\"}),_c('p',[_vm._v(\"暂无商品数据\")]),_c('p',{staticStyle:{\"font-size\":\"12px\",\"color\":\"#999\",\"margin-top\":\"8px\"}},[_vm._v(\"请检查网络连接或联系管理员\")])]):_vm._e()],2)])])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"content-container\"},[_c('router-view')],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./OrderList.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./OrderList.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./OrderList.vue?vue&type=template&id=040ae77e&scoped=true\"\nimport script from \"./OrderList.vue?vue&type=script&lang=js\"\nexport * from \"./OrderList.vue?vue&type=script&lang=js\"\nimport style0 from \"./OrderList.vue?vue&type=style&index=0&id=040ae77e&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"040ae77e\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./index.vue?vue&type=template&id=c3bf12ce&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=js\"\nexport * from \"./index.vue?vue&type=script&lang=js\"\nimport style0 from \"./index.vue?vue&type=style&index=0&id=c3bf12ce&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"c3bf12ce\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./orders.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./orders.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./orders.vue?vue&type=template&id=aaa2ab74&scoped=true\"\nimport script from \"./orders.vue?vue&type=script&lang=js\"\nexport * from \"./orders.vue?vue&type=script&lang=js\"\nimport style0 from \"./orders.vue?vue&type=style&index=0&id=aaa2ab74&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"aaa2ab74\",\n null\n \n)\n\nexport default component.exports","import request from '../utils/request'\n\n//商品列表\nexport function getAddShop(data) {\n return request({\n url: `/lease/shop/addShop`,\n method: 'post',\n data\n })\n}\n\n// 我的店铺(获取当前用户店铺信息)\nexport function getMyShop(params) {\n return request({\n url: `/lease/shop/getShopByUserEmail`,\n method: 'get',\n params\n })\n}\n\n// 更新店铺\nexport function updateShop(data) {\n return request({\n url: `/lease/shop/updateShop`,\n method: 'post',\n data\n })\n}\n\n// 删除店铺(兼容:deleteShop(id) / deleteShop({ id, gCode }) / deleteShop(id, gCode))\nexport function deleteShop(id, gCode) {\n // 兼容对象入参\n if (id && typeof id === 'object') {\n const payload = id\n return request({\n url: `/lease/shop/deleteShop`,\n method: 'post',\n data: payload\n })\n }\n return request({\n url: `/lease/shop/deleteShop`,\n method: 'post',\n data: gCode != null ? { id, gCode } : { id }\n })\n}\n\n// 查询店铺信息(根据ID)\nexport function queryShop(data) {\n return request({\n url: `/lease/shop/getShopById`,\n method: 'post',\n data\n })\n}\n\n// 关闭店铺\nexport function closeShop(id) {\n return request({\n url: `/lease/shop/closeShop`,\n method: 'post',\n data: { id }\n })\n}\n\n// 根据 店铺id 查询店铺商品配置信息列表\nexport function getShopConfig(id) {\n return request({\n url: `/lease/shop/getShopConfig`,\n method: 'post',\n data: { id }\n })\n}\n\n\n// 新增商铺配置\nexport function addShopConfig(data) {\n return request({\n url: `/lease/shop/addShopConfig`,\n method: 'post',\n data\n })\n}\n\n// 根据配置id 修改配置\nexport function updateShopConfig(data) {\n return request({\n url: `/lease/shop/updateShopConfig`,\n method: 'post',\n data\n })\n}\n\n// 根据配置id 删除配置\nexport function deleteShopConfig(data) {\n return request({\n url: `/lease/shop/deleteShopConfig`,\n method: 'post',\n data\n })\n}\n\n\n// 钱包配置(用于修改卖家钱包地址)----获取链(一级)和币(二级) 下拉列表(获取本系统支持的链和币种)\nexport function getChainAndCoin(data) {\n return request({\n url: `/lease/shop/getChainAndCoin`,\n method: 'post',\n data\n })\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","import axios from 'axios'\nimport errorCode from './errorCode'\nimport { Notification, MessageBox, Message } from 'element-ui'\nimport loadingManager from './loadingManager';\nimport errorNotificationManager from './errorNotificationManager';\nimport secureStorage from './secureStorage';\n\n/**\n * Token 内存缓存\n * 由于请求拦截器必须同步执行,我们需要在内存中缓存解密后的 token\n * 当 token 更新时,会自动更新缓存\n */\nlet tokenCache = null;\nlet tokenInitPromise = null; // Token 初始化 Promise\n\n/**\n * 初始化 Token 缓存\n * 应用启动时自动从存储中加载 token(优先加密存储,降级为明文存储)\n */\nasync function initTokenCache() {\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] 开始初始化...');\n }\n\n // 方案1: 尝试从加密存储读取\n try {\n const encryptedToken = await secureStorage.getItem('leasToken');\n if (encryptedToken) {\n tokenCache = JSON.parse(encryptedToken);\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 从加密存储加载成功');\n }\n return; // 成功读取,直接返回\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Token缓存] ⚠️ 加密存储读取失败,尝试降级:', e.message);\n }\n }\n\n // 方案2: 降级为明文 localStorage 读取\n try {\n const rawToken = localStorage.getItem('leasToken');\n if (rawToken) {\n try {\n // 尝试解析 JSON\n tokenCache = JSON.parse(rawToken);\n if (tokenCache && typeof tokenCache === 'string') {\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 从明文存储加载成功(降级模式)');\n }\n\n // 尝试升级到加密存储(如果环境支持)\n try {\n const upgraded = await secureStorage.setItem('leasToken', JSON.stringify(tokenCache));\n if (upgraded && process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 已自动升级到加密存储');\n }\n } catch (upgradeError) {\n // 升级失败不影响使用,继续使用明文存储\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] 💡 当前环境不支持加密存储,保持明文模式');\n }\n }\n return;\n }\n } catch (jsonError) {\n // JSON 解析失败,可能是损坏的数据\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Token缓存] ⚠️ 检测到损坏的 token 数据,已清除');\n }\n localStorage.removeItem('leasToken');\n tokenCache = null;\n }\n }\n } catch (readError) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Token缓存] ❌ 明文存储读取失败:', readError);\n }\n }\n\n // 初始化完成\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] 初始化完成, 当前状态:', tokenCache ? '有 token' : '无 token');\n }\n}\n\n/**\n * 更新 Token 缓存(优先加密存储,自动降级为明文存储)\n * @param {string} token - 新的 token 值\n */\nasync function updateToken(token) {\n try {\n if (token) {\n // 方案1: 尝试加密存储\n try {\n const success = await secureStorage.setItem('leasToken', JSON.stringify(token));\n if (success) {\n tokenCache = token;\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 已保存到加密存储');\n }\n return; // 加密存储成功,直接返回\n }\n } catch (encryptError) {\n if (process.env.NODE_ENV === 'development') {\n console.warn('[Token缓存] ⚠️ 加密存储失败,降级为明文存储:', encryptError.message);\n }\n }\n\n // 方案2: 降级为明文 localStorage 存储\n try {\n localStorage.setItem('leasToken', JSON.stringify(token));\n tokenCache = token;\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 已保存到明文存储(降级模式)');\n }\n } catch (plainError) {\n console.error('[Token缓存] ❌ 明文存储也失败,可能 localStorage 不可用:', plainError);\n // 即使存储失败,也更新内存缓存,至少当前会话可用\n tokenCache = token;\n }\n } else {\n // 清除 token\n await clearToken();\n }\n } catch (e) {\n console.error('[Token缓存] ❌ 更新失败:', e);\n }\n}\n\n/**\n * 清除 Token 缓存(同时清除加密存储和明文存储)\n */\nasync function clearToken() {\n try {\n // 清除加密存储\n secureStorage.removeItem('leasToken');\n // 同时清除可能存在的明文存储(兼容降级模式)\n localStorage.removeItem('leasToken');\n // 清除内存缓存\n tokenCache = null;\n\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] ✅ 已清除所有存储');\n }\n } catch (e) {\n console.error('[Token缓存] ❌ 清除失败:', e);\n }\n}\n\n/**\n * 获取当前 Token(优先从内存缓存,支持等待异步初始化)\n * @param {boolean} waitForInit - 是否等待初始化完成\n * @returns {Promise|string|null}\n */\nfunction getToken(waitForInit = false) {\n // 如果需要等待初始化,返回 Promise\n if (waitForInit && tokenInitPromise) {\n return tokenInitPromise.then(() => tokenCache);\n }\n\n // 优先使用内存缓存(已解密)\n if (tokenCache !== null) {\n return tokenCache;\n }\n\n // 降级方案:尝试同步读取明文 token(仅用于旧数据兼容)\n try {\n const rawToken = localStorage.getItem('leasToken');\n if (rawToken) {\n try {\n // 尝试解析 JSON(旧的明文 token)\n const parsedToken = JSON.parse(rawToken);\n // 只有当它看起来像有效的 token 时才使用\n if (parsedToken && typeof parsedToken === 'string') {\n if (process.env.NODE_ENV === 'development') {\n console.log('[Token缓存] 使用降级方案(明文 token)');\n }\n return parsedToken;\n }\n } catch (e) {\n // JSON 解析失败,说明是加密数据,等待异步初始化\n }\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[Token缓存] 降级读取失败:', e);\n }\n }\n\n return null;\n}\n\n// 应用启动时初始化 Token 缓存(异步)\n// 保存 Promise 供请求拦截器使用\ntokenInitPromise = initTokenCache().finally(() => {\n // 初始化完成后,清空 Promise,避免后续请求继续等待\n tokenInitPromise = null;\n});\n\n// 导出 Token 管理函数供其他模块使用\nexport { updateToken, clearToken, getToken };\n\n// 处理 Request aborted 错误\nconst pendingRequestMap = new Map();\n\n/**\n * 生成请求唯一 key\n * 用于识别重复请求\n */\nfunction getRequestKey(config) {\n const { url, method, params, data } = config;\n return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');\n}\n// 创建axios实例\nconst service = axios.create({\n // axios中请求配置有baseURL选项,表示请求URL公共部分\n baseURL: process.env.VUE_APP_BASE_API,\n // 超时\n timeout: 10000,\n})\n\n// 网络错误相关配置\nconst NETWORK_ERROR_THROTTLE_TIME = 5000; // 错误提示节流时间\nconst RETRY_DELAY = 2000; // 重试间隔时间\nconst MAX_RETRY_TIMES = 3; // 最大重试次数\nconst RETRY_WINDOW = 60000; // 60秒重试窗口\nconst MAX_CONCURRENT_RETRIES = 3; // 最大并发重试数量(防止请求风暴)\nlet lastNetworkErrorTime = 0; // 上次网络错误提示时间\nlet pendingRequests = new Map(); // 待重试的请求队列\nlet activeRetries = 0; // 当前活跃的重试请求数量\n\n\n// 网络状态监听器\n// 网络状态最后提示时间\nlet lastNetworkStatusTime = {\n online: 0,\n offline: 0\n};\n\n// 创建一个全局标志,确保每次网络恢复只显示一次提示\nlet networkRecoveryInProgress = false;\n\n/**\n * 带并发控制的请求重试函数\n * 限制同时进行的重试请求数量,防止请求风暴\n * @param {Object} request - 请求配置对象\n * @returns {Promise}\n */\nasync function retryWithConcurrencyLimit(request) {\n // 等待直到有可用的并发槽位\n while (activeRetries >= MAX_CONCURRENT_RETRIES) {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n\n activeRetries++;\n try {\n const response = await service(request.config);\n return response;\n } finally {\n activeRetries--;\n }\n}\n\n/**\n * 网络恢复处理函数\n * 当网络重新连接时,重试所有待处理的请求\n */\nconst handleNetworkOnline = async () => {\n const now = Date.now();\n\n // 避免短时间内多次触发\n if (networkRecoveryInProgress) {\n if (process.env.NODE_ENV === 'development') {\n console.log('[网络] 网络恢复处理已在进行中,忽略重复事件');\n }\n return;\n }\n\n networkRecoveryInProgress = true;\n\n // 严格检查是否应该显示提示(30秒内不重复提示)\n if (now - lastNetworkStatusTime.online > 30000) {\n lastNetworkStatusTime.online = now;\n\n try {\n if (window.vm && window.vm.$message) {\n // 确保消息只显示一次\n window.vm.$message({\n message: window.vm.$i18n.t('home.networkReconnected') || '网络已重新连接,正在恢复数据...',\n type: 'success',\n duration: 5000,\n showClose: true,\n });\n if (process.env.NODE_ENV === 'development') {\n console.log('[网络] 显示网络恢复提示, 时间:', new Date().toLocaleTimeString());\n }\n }\n } catch (e) {\n if (process.env.NODE_ENV === 'development') {\n console.error('[网络] 显示网络恢复提示失败:', e);\n }\n }\n } else {\n if (process.env.NODE_ENV === 'development') {\n console.log('[网络] 抑制重复的网络恢复提示, 间隔过短:', now - lastNetworkStatusTime.online + 'ms');\n }\n }\n\n // 网络恢复时,使用并发控制重试所有待处理的请求\n const pendingPromises = [];\n\n pendingRequests.forEach(async (request, key) => {\n // 检查请求是否在重试窗口内\n if (now - request.timestamp <= RETRY_WINDOW) {\n try {\n // 使用并发控制重试请求\n const retryPromise = retryWithConcurrencyLimit(request);\n pendingPromises.push(retryPromise);\n\n // 等待请求完成后执行回调\n retryPromise.then(response => {\n // 执行请求特定的回调\n if (request.callback && typeof request.callback === 'function') {\n request.callback(response);\n }\n\n // 处理特定类型的请求\n if (window.vm) {\n // 处理图表数据请求(如果有)\n if (request.config.url.includes('getPoolPower') && response && response.data) {\n window.dispatchEvent(new CustomEvent('chart-data-updated', {\n detail: { type: 'poolPower', data: response.data }\n }));\n }\n else if (request.config.url.includes('getNetPower') && response && response.data) {\n window.dispatchEvent(new CustomEvent('chart-data-updated', {\n detail: { type: 'netPower', data: response.data }\n }));\n }\n else if (request.config.url.includes('getBlockInfo') && response && response.rows) {\n window.dispatchEvent(new CustomEvent('chart-data-updated', {\n detail: { type: 'blockInfo', data: response.rows }\n }));\n }\n }\n\n pendingRequests.delete(key);\n }).catch(error => {\n if (process.env.NODE_ENV === 'development') {\n console.error('重试请求失败:', error);\n }\n pendingRequests.delete(key);\n });\n } catch (error) {\n if (process.env.NODE_ENV === 'development') {\n console.error('创建重试请求失败:', error);\n }\n pendingRequests.delete(key);\n }\n } else {\n // 超出重试窗口,删除请求\n pendingRequests.delete(key);\n }\n });\n\n // 等待所有请求完成\n Promise.allSettled(pendingPromises).then(() => {\n // 重置所有 loading 状态\n if (loadingManager) {\n loadingManager.resetAllLoadingStates();\n }\n\n // 手动重置一些关键的 loading 状态\n if (window.vm) {\n // 常见的加载状态\n const commonLoadingProps = [\n 'minerChartLoading', 'reportBlockLoading', 'apiPageLoading',\n 'MiningLoading', 'miniLoading', 'bthLoading', 'editLoading'\n ];\n\n commonLoadingProps.forEach(prop => {\n if (typeof window.vm[prop] !== 'undefined') {\n window.vm[prop] = false;\n }\n });\n\n // 重置所有以Loading结尾的状态\n Object.keys(window.vm).forEach(key => {\n if (key.endsWith('Loading')) {\n window.vm[key] = false;\n }\n });\n }\n\n // 触发网络重试完成事件\n window.dispatchEvent(new CustomEvent('network-retry-complete'));\n\n // 重置网络恢复标志(5秒后允许再次处理网络恢复)\n setTimeout(() => {\n networkRecoveryInProgress = false;\n }, 5000);\n });\n};\n\n/**\n * 网络断开处理函数\n * 使用错误提示管理器控制网络断开提示\n */\nconst handleNetworkOffline = () => {\n if (window.vm && window.vm.$message && errorNotificationManager.canShowError('networkOffline')) {\n window.vm.$message({\n message: window.vm.$i18n.t('home.networkOffline') || '网络连接已断开,系统将在恢复连接后自动重试',\n type: 'error',\n duration: 5000,\n showClose: true,\n });\n }\n};\n\n// 注册网络状态监听器\nwindow.addEventListener('online', handleNetworkOnline);\nwindow.addEventListener('offline', handleNetworkOffline);\n\n/**\n * 清理所有事件监听器\n * 用于应用卸载时清理资源,防止内存泄漏\n */\nexport function cleanupRequestListeners() {\n window.removeEventListener('online', handleNetworkOnline);\n window.removeEventListener('offline', handleNetworkOffline);\n}\n\nservice.defaults.retry = 2;// 重试次数\nservice.defaults.retryDelay = 2000;\nservice.defaults.shouldRetry = (error) => {\n // 只有网络错误或超时错误才进行重试\n return error.message === \"Network Error\" || error.message.includes(\"timeout\");\n};\n\nlocalStorage.setItem('superReportError', \"\")\nlet superReportError = localStorage.getItem('superReportError')\nwindow.addEventListener(\"setItem\", () => {\n superReportError = localStorage.getItem('superReportError')\n});\n\n// request拦截器(异步,等待 token 初始化完成)\nservice.interceptors.request.use(async (config) => {\n superReportError = \"\"\n localStorage.setItem('superReportError', \"\")\n\n // 等待 token 初始化完成(如果还在初始化中)\n if (tokenInitPromise) {\n await tokenInitPromise;\n }\n\n // 从内存缓存获取 token(已解密)\n const token = getToken();\n if (token) {\n config.headers['Authorization'] = token\n } else if (process.env.NODE_ENV === 'development') {\n console.warn('[请求拦截器] Token 为空,请求可能失败:', config.url);\n }\n\n if (config.method == 'get' && config.data) {\n config.params = config.data\n }\n // get请求映射params参数\n if (config.method === 'get' && config.params) {\n let url = config.url + '?';\n for (const propName of Object.keys(config.params)) {\n const value = config.params[propName];\n var part = encodeURIComponent(propName) + \"=\";\n if (value !== null && typeof (value) !== \"undefined\") {\n if (typeof value === 'object') {\n for (const key of Object.keys(value)) {\n if (value[key] !== null && typeof (value[key]) !== 'undefined') {\n let params = propName + '[' + key + ']';\n let subPart = encodeURIComponent(params) + '=';\n url += subPart + encodeURIComponent(value[key]) + '&';\n }\n }\n } else {\n url += part + encodeURIComponent(value) + \"&\";\n }\n }\n }\n url = url.slice(0, -1);\n config.params = {};\n config.url = url;\n }\n\n // 生成请求唯一key 处理Request aborted 错误\n const requestKey = getRequestKey(config);\n\n // 如果有相同请求,先取消 处理Request aborted 错误\n if (pendingRequestMap.has(requestKey)) {\n const cancel = pendingRequestMap.get(requestKey);\n cancel(); // 取消上一次请求\n pendingRequestMap.delete(requestKey);\n }\n\n // 创建新的CancelToken 处理Request aborted 错误\n config.cancelToken = new axios.CancelToken(cancel => {\n pendingRequestMap.set(requestKey, cancel);\n });\n\n return config\n}, error => {\n Promise.reject(error)\n})\n\n// 响应拦截器\nservice.interceptors.response.use(res => {\n\n // 请求完成后移除\n const requestKey = getRequestKey(res.config);\n pendingRequestMap.delete(requestKey);\n \n // 特殊处理:如果是 blob 类型响应(文件下载),直接返回原始响应对象\n // 因为 blob 数据不是 JSON,不能解析 res.data.code\n if (res.config.responseType === 'blob' || res.data instanceof Blob) {\n // 检查响应状态码\n if (res.status >= 200 && res.status < 300) {\n return res // 返回完整响应对象,包含 headers 等信息\n } else {\n // blob 响应但状态码异常,尝试读取错误信息\n return Promise.reject(new Error(`下载失败,状态码: ${res.status}`))\n }\n }\n \n // 未设置状态码则默认成功状态\n const code = res.data.code || 200;\n // 获取错误信息\n const msg = errorCode[code] || res.data.msg || errorCode['default']\n if (code === 421) {\n localStorage.setItem('cs_disconnect_all', Date.now().toString()); // 告知客服页面断开连接\n // 清除 Token(包括加密存储和内存缓存)\n clearToken();\n // 触发登录状态变化事件,通知头部组件更新\n window.dispatchEvent(new CustomEvent('login-status-changed'))\n // 系统状态已过期,请重新点击SUPPORT按钮进入 \n superReportError = localStorage.getItem('superReportError')\n if (!superReportError) {\n superReportError = 421\n localStorage.setItem('superReportError', superReportError)\n \n // 获取 i18n 文本,如果 window.vm 不存在则使用默认中文\n const getText = (key, defaultValue) => {\n if (window.vm && window.vm.$i18n) {\n return window.vm.$i18n.t(key) || defaultValue\n }\n return defaultValue\n }\n \n // 获取路由跳转路径\n const getLoginPath = () => {\n if (window.vm && window.vm.$i18n && window.vm.$i18n.locale) {\n return `/${window.vm.$i18n.locale}/login`\n }\n return '/login'\n }\n \n const getHomePath = () => {\n if (window.vm && window.vm.$i18n && window.vm.$i18n.locale) {\n return `/${window.vm.$i18n.locale}/`\n }\n return '/'\n }\n \n MessageBox.confirm(\n getText('user.loginExpired', '登录状态已过期'), \n getText('user.overduePrompt', '您的登录状态已过期,请重新登录'), \n {\n distinguishCancelAndClose: true,\n confirmButtonText: getText('user.login', '登录'),\n cancelButtonText: getText('user.Home', '返回首页'),\n closeOnClickModal: false, // 点击空白处不关闭对话框\n showClose: false, // 隐藏关闭按钮\n type: 'warning'\n }\n ).then(() => {\n // 跳转到登录页\n if (window.vm && window.vm.$router) {\n window.vm.$router.push(getLoginPath())\n } else {\n window.location.href = getLoginPath()\n }\n localStorage.removeItem('token')\n localStorage.removeItem('superReportError')\n }).catch(() => {\n // 跳转到首页\n if (window.vm && window.vm.$router) {\n window.vm.$router.push(getHomePath())\n } else {\n window.location.href = getHomePath()\n }\n // 清除 Token(包括加密存储和内存缓存)\n clearToken();\n localStorage.removeItem('superReportError')\n });\n }\n\n\n return Promise.reject('登录状态已过期')\n } else if (code >= 500 && !superReportError) {\n superReportError = 500\n localStorage.setItem('superReportError', superReportError)\n Message({\n dangerouslyUseHTMLString: true,\n message: msg,\n type: 'error',\n showClose: true\n })\n // throw msg; // 抛出错误,中断请求链并触发后续的错误处理逻辑\n // return Promise.reject(new Error(msg))\n } else if (code !== 200) {\n\n\n\n Notification.error({\n title: msg\n })\n return Promise.reject('error')\n\n } else {\n\n return res.data\n }\n\n\n\n\n},\n error => {\n\n // 主动取消的请求,直接忽略,不提示\n if (\n error.code === 'ERR_CANCELED' ||\n (error.message && error.message.includes('canceled')) ||\n error.message?.includes('Request aborted')\n ) {\n // 静默处理,不提示,不冒泡\n return new Promise(() => {}); // 返回pending Promise,阻止控制台报错\n }\n\n\n\n \n // 请求异常也要移除 处理Request aborted 错误\n if (error.config) {\n const requestKey = getRequestKey(error.config);\n pendingRequestMap.delete(requestKey);\n }\n\n\n let { message } = error;\n if (message == \"Network Error\" || message.includes(\"timeout\")) {\n if (!navigator.onLine) {\n // 断网状态,添加到重试队列\n const requestKey = JSON.stringify({\n url: error.config.url,\n method: error.config.method,\n params: error.config.params,\n data: error.config.data\n });\n \n // 根据URL确定请求类型并记录回调\n let callback = null;\n if (error.config.url.includes('getPoolPower')) {\n callback = (data) => {\n if (window.vm) {\n // 清除loading状态\n window.vm.minerChartLoading = false;\n }\n };\n } else if (error.config.url.includes('getBlockInfo')) {\n callback = (data) => {\n if (window.vm) {\n window.vm.reportBlockLoading = false;\n }\n };\n }\n \n if (!pendingRequests.has(requestKey)) {\n pendingRequests.set(requestKey, {\n config: error.config,\n timestamp: Date.now(),\n retryCount: 0,\n callback: callback\n });\n \n console.log('请求已加入断网重连队列:', error.config.url);\n }\n } else {\n // 网络已连接,但请求失败,尝试重试\n // 确保 config 中有 __retryCount 字段\n error.config.__retryCount = error.config.__retryCount || 0;\n \n // 判断是否可以重试\n if (error.config.__retryCount < service.defaults.retry && service.defaults.shouldRetry(error)) {\n // 增加重试计数\n error.config.__retryCount += 1;\n \n console.log(`[请求重试] ${error.config.url} - 第 ${error.config.__retryCount} 次重试`);\n \n // 创建新的Promise等待一段时间后重试\n return new Promise(resolve => {\n setTimeout(() => {\n resolve(service(error.config));\n }, service.defaults.retryDelay);\n });\n }\n \n // 达到最大重试次数,不再重试\n console.log(`[请求失败] ${error.config.url} - 已达到最大重试次数`);\n }\n }\n\n if (!superReportError) {\n superReportError = \"error\"\n localStorage.setItem('superReportError', superReportError)\n //使用错误提示管理器errorNotificationManager\n if (errorNotificationManager.canShowError(message)) {\n if (message == \"Network Error\") {\n Message({\n message: window.vm.$i18n.t(`home.NetworkError`),\n type: 'error',\n duration: 4 * 1000,\n showClose: true\n });\n }\n else if (message.includes(\"timeout\")) {\n Message({\n message: window.vm.$i18n.t(`home.requestTimeout`),\n type: 'error',\n duration: 5 * 1000,\n showClose: true\n });\n }\n else if (message.includes(\"Request failed with status code\")) {\n Message({\n message: \"系统接口\" + message.substr(message.length - 3) + \"异常\",\n type: 'error',\n duration: 5 * 1000,\n showClose: true\n });\n } else {\n Message({\n message: message,\n type: 'error',\n duration: 5 * 1000,\n showClose: true\n });\n }\n } else {\n // 避免完全不提示,可以在控制台记录被抑制的错误\n console.log('[错误提示] 已抑制重复错误:', message);\n }\n }\n\n\n\n\n return Promise.reject(error)\n\n }\n)\n\n\n\nexport default service","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"account-purchased-machine-config\"},[_vm._m(0),_c('el-table',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.tableData,\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"prop\":\"coin\",\"label\":\"币种\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.coin || '—'))])]}}])}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"算法\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.algorithm || '—'))])]}}])}),_c('el-table-column',{attrs:{\"prop\":\"pool\",\"label\":\"矿池\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.pool || '—'))])]}}])}),_c('el-table-column',{attrs:{\"prop\":\"walletAddress\",\"label\":\"钱包地址\",\"min-width\":\"200\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"address-cell\"},[(scope.row.walletAddress)?_c('span',{staticClass:\"mono-ellipsis\",staticStyle:{\"font-family\":\"monospace\"}},[_vm._v(_vm._s(scope.row.walletAddress))]):_c('span',[_vm._v(\"—\")]),(scope.row.walletAddress)?_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){return _vm.handleCopy(scope.row.walletAddress, '钱包地址')}}},[_vm._v(\" 复制 \")]):_vm._e()],1)]}}])}),_c('el-table-column',{attrs:{\"prop\":\"poolUrl\",\"label\":\"矿池地址\",\"min-width\":\"200\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"address-cell\"},[(scope.row.poolUrl)?_c('span',{staticClass:\"mono-ellipsis\"},[_vm._v(_vm._s(scope.row.poolUrl))]):_c('span',[_vm._v(\"—\")]),(scope.row.poolUrl)?_c('el-button',{staticClass:\"copy-btn\",attrs:{\"type\":\"text\",\"size\":\"mini\",\"icon\":\"el-icon-document-copy\"},on:{\"click\":function($event){return _vm.handleCopy(scope.row.poolUrl, '矿池地址')}}},[_vm._v(\" 复制 \")]):_vm._e()],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"操作\",\"width\":\"120\",\"fixed\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){return _vm.handleViewDetail(scope.row)}}},[_vm._v(\" 详情 \")])]}}])})],1),_c('div',{staticClass:\"pagination\"},[_c('el-pagination',{attrs:{\"background\":\"\",\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total,\"current-page\":_vm.pagination.pageNum,\"page-sizes\":[10, 20, 50, 100],\"page-size\":_vm.pagination.pageSize},on:{\"update:currentPage\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:current-page\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:pageSize\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"update:page-size\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange}})],1)],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"toolbar\"},[_c('div',{staticClass:\"left-area\"},[_c('h2',{staticClass:\"page-title\"},[_vm._v(\"已购商品\")])])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./purchasedMachineConfig.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./purchasedMachineConfig.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./purchasedMachineConfig.vue?vue&type=template&id=f22fc604&scoped=true\"\nimport script from \"./purchasedMachineConfig.vue?vue&type=script&lang=js\"\nexport * from \"./purchasedMachineConfig.vue?vue&type=script&lang=js\"\nimport style0 from \"./purchasedMachineConfig.vue?vue&type=style&index=0&id=f22fc604&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"f22fc604\",\n null\n \n)\n\nexport default component.exports","import request from '../utils/request'\r\n\r\n//加入购物车\r\nexport function addCart(data) {\r\n return request({\r\n url: `/lease/shopping/cart/addGoods`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//查询购物车列表\r\nexport function getGoodsList(data) {\r\n return request({\r\n url: `/lease/shopping/cart/getGoodsList`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n //删除购物车商品 批量\r\nexport function deleteBatchGoods(data) {\r\n return request({\r\n url: `/lease/shopping/cart/deleteBatchGoods`,\r\n method: 'post',\r\n data\r\n })\r\n }\r\n\r\n \r\n // 批量删除购物车中已下架商品\r\nexport function deleteBatchGoodsForIsDelete(data) {\r\n return request({\r\n url: `/lease/shopping/cart/deleteBatchGoodsForIsDelete`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n//购物车列表V2\r\nexport function getGoodsListV2(data) {\r\n return request({\r\n url: `/lease/v2/shopping/cart/getGoodsListV2`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n//批量删除购物车中已下架商品\r\nexport function deleteBatchGoodsForIsDeleteV2(data) {\r\n return request({\r\n url: `/lease/v2/shopping/cart/deleteBatchGoodsForIsDeleteV2`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n//批批量删除购物车中商品\r\nexport function deleteBatchGoodsV2(data) {\r\n return request({\r\n url: `/lease/v2/shopping/cart/deleteBatchGoodsV2`,\r\n method: 'post',\r\n data\r\n })\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n","/**\n * @file 购物车管理(轻量,无 Vuex)\n * @description 提供添加、更新、删除、清空、查询购物车的函数。使用 localStorage 持久化。\n */\n\nconst STORAGE_KEY = 'power_leasing_cart_v1';\n\n/**\n * @typedef {Object} CartItem\n * @property {string} id - 商品ID\n * @property {string} title - 商品标题\n * @property {number} price - 单价\n * @property {number} quantity - 数量\n * @property {string} image - 图片URL\n */\n\n/**\n * 读取本地购物车\n * @returns {CartItem[]}\n */\nexport const readCart = () => {\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter(Boolean);\n } catch (error) {\n console.error('[cartManager] readCart error:', error);\n return [];\n }\n}\n\n/**\n * 持久化购物车\n * @param {CartItem[]} cart\n */\nconst writeCart = (cart) => {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(cart));\n // 同步派发购物车更新事件(总数量),用于头部徽标等全局更新\n try {\n const count = cart.reduce((s, c) => s + Number(c.quantity || 0), 0)\n window.dispatchEvent(new CustomEvent('cart-updated', { detail: { count } }))\n } catch (e) { /* noop */ }\n } catch (error) {\n console.error('[cartManager] writeCart error:', error);\n }\n}\n\n/**\n * 添加到购物车(若已存在则数量累加)\n * @param {CartItem} item\n * @returns {CartItem[]}\n */\nexport const addToCart = (item) => {\n if (!item || !item.id) return readCart();\n const cart = readCart();\n const index = cart.findIndex((c) => c.id === item.id);\n if (index >= 0) {\n const next = [...cart];\n next[index] = {\n ...next[index],\n quantity: Math.max(1, Number(next[index].quantity || 0) + Number(item.quantity || 1))\n };\n writeCart(next);\n return next;\n }\n const next = [...cart, { ...item, quantity: Math.max(1, Number(item.quantity || 1)) }];\n writeCart(next);\n return next;\n}\n\n/**\n * 更新数量\n * @param {string} productId\n * @param {number} quantity\n * @returns {CartItem[]}\n */\nexport const updateQuantity = (productId, quantity) => {\n const cart = readCart();\n const next = cart\n .map((c) => (c.id === productId ? { ...c, quantity: Math.max(1, Number(quantity) || 1) } : c));\n writeCart(next);\n return next;\n}\n\n/**\n * 移除商品\n * @param {string} productId\n * @returns {CartItem[]}\n */\nexport const removeFromCart = (productId) => {\n const cart = readCart();\n const next = cart.filter((c) => c.id !== productId);\n writeCart(next);\n return next;\n}\n\n/**\n * 清空购物车\n * @returns {CartItem[]}\n */\nexport const clearCart = () => {\n writeCart([]);\n return [];\n}\n\n/**\n * 计算总价\n * @returns {{ totalQuantity: number, totalPrice: number }}\n */\nexport const computeSummary = () => {\n const cart = readCart();\n const totalQuantity = cart.reduce((sum, cur) => sum + Number(cur.quantity || 0), 0);\n const totalPrice = cart.reduce((sum, cur) => sum + Number(cur.quantity || 0) * Number(cur.price || 0), 0);\n return { totalQuantity, totalPrice };\n}\n\nexport default {\n readCart,\n addToCart,\n updateQuantity,\n removeFromCart,\n clearCart,\n computeSummary\n}\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./shopConfig.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./shopConfig.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./shopConfig.vue?vue&type=template&id=14de5279&scoped=true\"\nimport script from \"./shopConfig.vue?vue&type=script&lang=js\"\nexport * from \"./shopConfig.vue?vue&type=script&lang=js\"\nimport style0 from \"./shopConfig.vue?vue&type=style&index=0&id=14de5279&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"14de5279\",\n null\n \n)\n\nexport default component.exports","/**\n * @file 导航配置文件\n * @description 定义所有可用的导航链接和菜单结构\n */\n\n// 主导航配置\nexport const mainNavigation = [\n {\n path: '/productList',\n name: '商城',\n icon: '🛍️',\n description: '浏览所有商品'\n },\n {\n path: '/cart',\n name: '购物车',\n icon: '🛒',\n description: '管理购物车商品'\n },\n // {\n // path: '/checkout',\n // name: '结算',\n // icon: '💳',\n // description: '完成订单结算'\n // },\n {\n path: '/account',\n name: '个人中心',\n icon: '👤',\n description: '管理个人资料和店铺'\n }\n]\n\n// 面包屑导航配置\nexport const breadcrumbConfig = {\n '/productList': ['首页', '商品列表'],\n '/product': ['首页', '商品列表', '商品详情'],\n '/cart': ['首页', '购物车'],\n '/checkout': ['首页', '购物车', '订单结算'],\n '/account': ['首页', '个人中心'],\n '/account/wallet': ['首页', '个人中心', '我的钱包'],\n '/account/shop-new': ['首页', '个人中心', '新增店铺'],\n '/account/shop-config': ['首页', '个人中心', '店铺配置'],\n '/account/shops': ['首页', '个人中心', '我的店铺'],\n '/account/product-new': ['首页', '个人中心', '新增商品'],\n '/account/products': ['首页', '个人中心', '商品列表']\n}\n\n// 获取面包屑导航\nexport const getBreadcrumb = (path) => {\n // 处理动态路由\n if (path.startsWith('/product/')) {\n return breadcrumbConfig['/product']\n }\n \n return breadcrumbConfig[path] || ['首页']\n}\n\n// 检查路由权限\nexport const checkRoutePermission = (route, userPermissions = []) => {\n if (!route.meta || !route.meta.allAuthority) {\n return true\n }\n \n const requiredPermissions = route.meta.allAuthority\n \n // 如果权限要求是 'all',则所有人都可以访问\n if (requiredPermissions.includes('all')) {\n return true\n }\n \n // 检查用户是否有所需权限\n return requiredPermissions.some(permission => \n userPermissions.includes(permission)\n )\n}\n\n// 获取页面标题\nexport const getPageTitle = (route) => {\n if (route.meta && route.meta.title) {\n return `${route.meta.title} - Power Leasing`\n }\n return 'Power Leasing - 电商系统'\n}\n\n// 获取页面描述\nexport const getPageDescription = (route) => {\n if (route.meta && route.meta.description) {\n return route.meta.description\n }\n return 'Power Leasing 电商系统 - 专业的电力设备租赁平台'\n}\n\nexport default {\n mainNavigation,\n breadcrumbConfig,\n getBreadcrumb,\n checkRoutePermission,\n getPageTitle,\n getPageDescription\n} ","\r\n\r\n\r\n\r\n\r\n\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"funds-page\"},[_c('h3',{staticClass:\"title\"},[_vm._v(\"资金流水\")]),_c('div',{staticClass:\"tabs-card\",attrs:{\"aria-label\":\"资金流水tab\",\"tabindex\":\"0\"}},[_c('el-tabs',{on:{\"tab-click\":_vm.handleTabClick},model:{value:(_vm.activeTab),callback:function ($$v) {_vm.activeTab=$$v},expression:\"activeTab\"}},[_c('el-tab-pane',{attrs:{\"label\":\"收款记录\",\"name\":\"receipt\"}}),_c('el-tab-pane',{attrs:{\"label\":\"提现记录\",\"name\":\"withdraw\"}})],1),_c('keep-alive',[_c(_vm.activeComponentName,{tag:\"component\"})],1)],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-container\"},[_vm._m(0),_c('div',{staticClass:\"auth-card\"},[_c('div',{staticClass:\"close-btn\",attrs:{\"title\":\"返回商城\"},on:{\"click\":_vm.goToShop}},[_c('i',{staticClass:\"el-icon-close\"})]),_vm._m(1),_c('el-form',{ref:\"registerForm\",staticClass:\"auth-form\",attrs:{\"model\":_vm.registerForm,\"rules\":_vm.registerRules},nativeOn:{\"submit\":function($event){$event.preventDefault();return _vm.handleRegister.apply(null, arguments)}}},[_c('el-form-item',{attrs:{\"prop\":\"email\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入邮箱\",\"prefix-icon\":\"el-icon-message\",\"size\":\"large\",\"clearable\":\"\"},on:{\"change\":_vm.handleEmailChange},model:{value:(_vm.registerForm.email),callback:function ($$v) {_vm.$set(_vm.registerForm, \"email\", $$v)},expression:\"registerForm.email\"}})],1),_c('el-form-item',{attrs:{\"prop\":\"code\"}},[_c('div',{staticClass:\"code-input-wrapper\"},[_c('el-input',{attrs:{\"placeholder\":\"请输入邮箱验证码\",\"prefix-icon\":\"el-icon-key\",\"size\":\"large\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.registerForm.code),callback:function ($$v) {_vm.$set(_vm.registerForm, \"code\", $$v)},expression:\"registerForm.code\"}}),_c('el-button',{staticClass:\"send-code-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"disabled\":_vm.countdown > 0,\"loading\":_vm.sendingCode},on:{\"click\":_vm.handleSendCode}},[_vm._v(\" \"+_vm._s(_vm.countdown > 0 ? `${_vm.countdown}秒后重试` : '获取验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"prop\":\"password\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请输入密码(8-32位)\",\"prefix-icon\":\"el-icon-lock\",\"size\":\"large\",\"show-password\":\"\",\"clearable\":\"\"},model:{value:(_vm.registerForm.password),callback:function ($$v) {_vm.$set(_vm.registerForm, \"password\", $$v)},expression:\"registerForm.password\"}}),_c('div',{staticClass:\"password-tip\"},[_c('i',{staticClass:\"el-icon-info\"}),_c('span',[_vm._v(\"密码需包含大小写字母、数字和特殊字符,长度8-32位\")])]),(_vm.registerForm.password)?_c('div',{staticClass:\"password-strength\"},[_c('span',{staticClass:\"strength-label\"},[_vm._v(\"密码强度:\")]),_c('span',{class:['strength-bar', _vm.passwordStrengthClass]},[_vm._v(\" \"+_vm._s(_vm.passwordStrengthText)+\" \")])]):_vm._e()],1),_c('el-form-item',{attrs:{\"prop\":\"confirmPassword\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请再次输入密码\",\"prefix-icon\":\"el-icon-lock\",\"size\":\"large\",\"show-password\":\"\",\"clearable\":\"\"},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleRegister.apply(null, arguments)}},model:{value:(_vm.registerForm.confirmPassword),callback:function ($$v) {_vm.$set(_vm.registerForm, \"confirmPassword\", $$v)},expression:\"registerForm.confirmPassword\"}})],1),_c('el-form-item',{attrs:{\"prop\":\"agree\"}},[_c('el-checkbox',{model:{value:(_vm.registerForm.agree),callback:function ($$v) {_vm.$set(_vm.registerForm, \"agree\", $$v)},expression:\"registerForm.agree\"}},[_vm._v(\" 我已阅读并同意 \"),_c('a',{staticClass:\"link-text\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();}}},[_vm._v(\"《用户协议》\")]),_vm._v(\" 和 \"),_c('a',{staticClass:\"link-text\",attrs:{\"href\":\"#\"},on:{\"click\":function($event){$event.preventDefault();}}},[_vm._v(\"《隐私政策》\")])])],1),_c('el-form-item',[_c('el-button',{staticClass:\"auth-submit-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"loading\":_vm.loading},on:{\"click\":_vm.handleRegister}},[_vm._v(\" \"+_vm._s(_vm.loading ? '注册中...' : '立即注册')+\" \")])],1),_c('div',{staticClass:\"auth-footer\"},[_c('span',{staticClass:\"footer-text\"},[_vm._v(\"已有账号?\")]),_c('router-link',{staticClass:\"link-text link-primary\",attrs:{\"to\":\"/login\"}},[_vm._v(\" 立即登录 \")])],1)],1)],1)])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-background\"},[_c('div',{staticClass:\"bg-circle circle-1\"}),_c('div',{staticClass:\"bg-circle circle-2\"}),_c('div',{staticClass:\"bg-circle circle-3\"})])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-header\"},[_c('h1',{staticClass:\"auth-title\"},[_vm._v(\"欢迎注册\")]),_c('p',{staticClass:\"auth-subtitle\"},[_vm._v(\"创建您的 Power Leasing 账号\")])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n","import request from '../utils/request'\n\n//钱包余额\nexport function getWalletInfo(data) {\n return request({\n url: `/lease/user/getWalletInfo`,\n method: 'post',\n data\n })\n}\n\n//余额提现\nexport function withdrawBalance(data) {\n return request({\n url: `/lease/user/withdrawBalance`,\n method: 'post',\n data\n })\n}\n\n\n\n//余额充值记录\nexport function balanceRechargeList(data) {\n return request({\n url: `/lease/user/balanceRechargeList`,\n method: 'post',\n data\n })\n}\n\n\n//提现记录\nexport function balanceWithdrawList(data) {\n return request({\n url: `/lease/user/balanceWithdrawList`,\n method: 'post',\n data\n })\n}\n\n\n// 卖家收款记录\nexport function sellerReceiptList(data) {\n return request({\n url: `/lease/user/balancePayList`,\n method: 'post',\n data\n })\n}\n\n\n//钱包绑定\nexport function addWalletShopConfig(data) {\n return request({\n url: `/lease/shop/addShopConfig`,\n method: 'post',\n data\n })\n}\n\n//获取支持的链和币种\nexport function getChainAndList(data) {\n return request({\n url: `/lease/shop/getChainAndList`,\n method: 'post',\n data\n })\n}\n\n\n//获取钱包绑定列表\nexport function getShopConfig(data) {\n return request({\n url: `/lease/shop/getShopConfig`,\n method: 'post',\n data\n })\n}\n\n\n//创建钱包\nexport function bindWallet(data) {\n return request({\n url: `/lease/user/bindWallet`,\n method: 'post',\n data\n })\n}\n\n//资金流水\nexport function transactionRecord(data) {\n return request({\n url: `/lease/user/transactionRecord`,\n method: 'post',\n data\n })\n}\n\n//钱包的最近交易\nexport function getRecentlyTransaction(data) {\n return request({\n url: `/lease/user/getRecentlyTransaction`,\n method: 'post',\n data\n })\n}\n\n//绑定钱包前查询商品列表\n// export function getProductListForShopWalletConfig(data) {\n// return request({\n// url: `/lease/product/getProductListForShopWalletConfig`,\n// method: 'post',\n// data\n// })\n// }\n\n\n//设置之前商品列表的新链的机器价格\nexport function updateProductListForShopWalletConfig(data) {\n return request({\n url: `/lease/product/updateProductListForShopWalletConfig`,\n method: 'post',\n data\n })\n}\n\n// 卖家绑定钱包明细\nexport function getShopConfigV2(data) {\n return request({\n url: `/lease/v2/shop/getShopConfigV2`,\n method: 'post',\n data\n })\n}\n\n\n// 卖家提现\nexport function withdrawBalanceForSeller(data) {\n return request({\n url: `/lease/v2/shop/withdrawBalanceForSeller`,\n method: 'post',\n data\n })\n}\n\n\n// 修改钱包配置\nexport function balanceWithdrawListV2(data) {\n return request({\n url: `/lease/v2/shop/balanceWithdrawList`,\n method: 'post',\n data\n })\n}\n\n// 修改店铺钱包配置 V2\nexport function updateShopConfigV2(data) {\n return request({\n url: `/lease/v2/shop/updateShopConfigV2`,\n method: 'post',\n data\n })\n}\n\n// 修获取店铺商品列表用于新增绑定店铺钱包-v2\nexport function getProductListForShopWalletConfig(data) {\n return request({\n url: `/lease/v2/product/machine/getProductListForShopWalletConfig`,\n method: 'post',\n data\n })\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.payLoading),expression:\"payLoading\"}]},[(!_vm.safeItems.length)?_c('div',{staticClass:\"empty\"},[_vm._v(_vm._s(_vm.emptyText))]):_c('el-table',{attrs:{\"data\":_vm.safeItems,\"border\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"type\":\"expand\",\"width\":\"46\"},scopedSlots:_vm._u([{key:\"default\",fn:function(outer){return [_c('el-table',{attrs:{\"data\":outer.row.orderItemDtoList || [],\"size\":\"small\",\"border\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' },\"row-key\":\"productMachineId\"}},[_c('el-table-column',{attrs:{\"prop\":\"productMachineId\",\"label\":\"机器ID\",\"min-width\":\"120\"}}),_c('el-table-column',{attrs:{\"label\":\"矿机类型\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatMachineType(scope.row && scope.row.type)))]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"payCoin\",\"label\":\"币种\",\"min-width\":\"100\"}}),_c('el-table-column',{attrs:{\"prop\":\"address\",\"label\":\"收款地址\",\"min-width\":\"240\"}}),_c('el-table-column',{attrs:{\"prop\":\"leaseTime\",\"label\":\"租赁天数\",\"min-width\":\"100\"}}),_c('el-table-column',{attrs:{\"label\":\"购买数量\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row && scope.row.numbers != null ? scope.row.numbers : '—'))]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"price\",\"label\":\"单价(USDT)\",\"min-width\":\"240\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"value strong\"},[(_vm.formatAmount(scope.row.price, scope.row.payCoin || 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(scope.row.price, scope.row.payCoin || 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(scope.row.price, scope.row.payCoin || 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(scope.row.price, scope.row.payCoin || 'USDT').text))])],1)]}}],null,true)})],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"店铺\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row && scope.row.shopName || '—'))]}}])}),_c('el-table-column',{attrs:{\"label\":\"订单号\",\"min-width\":\"220\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"value mono\"},[_vm._v(_vm._s(scope.row && scope.row.orderNumber || '—'))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"创建时间\",\"width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatDateTime(scope.row && scope.row.createTime)))]}}])}),_c('el-table-column',{attrs:{\"label\":\"商品数\",\"min-width\":\"70\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(Array.isArray(scope.row && scope.row.orderItemDtoList) ? scope.row.orderItemDtoList.length : 0))]}}])}),_c('el-table-column',{attrs:{\"label\":\"总金额(USDT)\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"value strong\"},[(_vm.formatAmount(scope.row && scope.row.totalPrice, 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(scope.row && scope.row.totalPrice, 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(scope.row && scope.row.totalPrice, 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(scope.row && scope.row.totalPrice, 'USDT').text))])],1)]}}])}),_c('el-table-column',{attrs:{\"width\":\"160\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_c('el-tooltip',{attrs:{\"placement\":\"top\",\"effect\":\"dark\"}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_vm._v(\" 实际支付金额/理论支付金额:\"),_c('br'),_vm._v(\" 1. 实际支付金额是按照矿机实际算力计算支付金额\"),_c('br'),_vm._v(\" 2. 理论支付金额是卖家定义出售价格 \")]),_c('span',{staticStyle:{\"display\":\"inline-flex\",\"align-items\":\"center\",\"gap\":\"6px\"}},[_c('i',{staticClass:\"el-icon-question\",staticStyle:{\"color\":\"#909399\"},attrs:{\"aria-label\":\"说明\",\"role\":\"img\"}}),_vm._v(\" 已支付金额(USDT) \")])])]},proxy:true},{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"value strong\"},[(_vm.formatAmount(scope.row && scope.row.payAmount, 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(scope.row && scope.row.payAmount, 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(scope.row && scope.row.payAmount, 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(scope.row && scope.row.payAmount, 'USDT').text))])],1)]}}])}),(_vm.showEndTime)?_c('el-table-column',{attrs:{\"label\":\"订单完成时间\",\"width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatDateTime(scope.row && scope.row.endTime)))]}}],null,false,2293356106)}):_vm._e(),_c('el-table-column',{attrs:{\"label\":\"操作\",\"min-width\":\"60\",\"fixed\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{staticStyle:{\"margin-right\":\"8px\"},attrs:{\"size\":\"mini\"},on:{\"click\":function($event){return _vm.handleGoDetail(scope.row)}}},[_vm._v(\"详情\")]),(_vm.shouldShowActions(scope.row))?[_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"mini\"},on:{\"click\":function($event){return _vm.handleCheckout(scope.row)}}},[_vm._v(\"去结算\")])]:_vm._e()]}}])})],1),_c('el-dialog',{attrs:{\"visible\":_vm.dialogVisible,\"width\":\"520px\",\"title\":\"请扫码支付\"},on:{\"update:visible\":function($event){_vm.dialogVisible=$event}}},[_c('div',{staticStyle:{\"text-align\":\"left\",\"margin-bottom\":\"12px\",\"color\":\"#666\"}},[_c('div',{staticStyle:{\"margin-bottom\":\"6px\"}},[_vm._v(\"总金额(USDT): \"),_c('b',[(_vm.formatAmount(_vm.paymentDialog.totalPrice, 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.paymentDialog.totalPrice, 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.paymentDialog.totalPrice, 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(_vm.paymentDialog.totalPrice, 'USDT').text))])],1)]),_c('div',{staticStyle:{\"margin-bottom\":\"6px\",\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"6px\"}},[_c('el-tooltip',{attrs:{\"placement\":\"top\",\"effect\":\"dark\"}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_vm._v(\" 实际支付金额/理论支付金额:\"),_c('br'),_vm._v(\" 1. 实际支付金额是按照矿机实际算力计算支付金额\"),_c('br'),_vm._v(\" 2. 理论支付金额是卖家定义出售价格 \")]),_c('i',{staticClass:\"el-icon-question\",staticStyle:{\"color\":\"#909399\"},attrs:{\"aria-label\":\"说明\",\"role\":\"img\"}})]),_c('span',[_vm._v(\"已支付金额(USDT):\")]),_c('b',{staticClass:\"value strong\"},[(_vm.formatAmount(_vm.paymentDialog.payAmount, 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.paymentDialog.payAmount, 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.paymentDialog.payAmount, 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(_vm.paymentDialog.payAmount, 'USDT').text))])],1)],1),_c('div',{staticStyle:{\"margin-bottom\":\"6px\"}},[_vm._v(\"待支付金额(USDT): \"),_c('b',{staticClass:\"value strong\"},[(_vm.formatAmount(_vm.paymentDialog.noPayAmount, 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.paymentDialog.noPayAmount, 'USDT').full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.paymentDialog.noPayAmount, 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(_vm.paymentDialog.noPayAmount, 'USDT').text))])],1)])]),_c('div',{staticStyle:{\"text-align\":\"center\"}},[(_vm.paymentDialog.img)?_c('img',{staticStyle:{\"width\":\"180px\",\"height\":\"180px\",\"margin-top\":\"18px\"},attrs:{\"src\":_vm.paymentDialog.img,\"alt\":\"支付二维码\"}}):_c('div',{staticStyle:{\"color\":\"#666\"}},[_vm._v(\"未返回支付二维码\")])]),_c('p',{staticStyle:{\"margin-bottom\":\"6px\",\"color\":\"red\",\"text-align\":\"left\"}},[_vm._v(\"注意:如果已经支付对应金额,不要在重复支付,待系统确认后会自动更新订单状态。因个人原因重复支付导致无法退款,平台不承担任何责任。\")]),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.dialogVisible=false}}},[_vm._v(\"关闭\")])],1)])],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"order-detail-page\"},[_c('h2',{staticClass:\"title\"},[_vm._v(\"订单详情\")]),(_vm.loading)?_c('div',{staticClass:\"loading\"},[_vm._v(\"加载中...\")]):_c('div',[_c('el-card',{staticClass:\"section\"},[_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"订单ID:\")]),_c('span',{staticClass:\"value mono\"},[_vm._v(_vm._s(_vm.order.id || '—'))])]),_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"订单号:\")]),_c('span',{staticClass:\"value mono\"},[_vm._v(_vm._s(_vm.order.orderNumber || '—'))])]),_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"状态:\")]),_c('span',{staticClass:\"value\"},[_vm._v(_vm._s(_vm.getOrderStatusText(_vm.order.status)))])]),_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"店铺:\")]),_c('span',{staticClass:\"value\"},[_vm._v(_vm._s(_vm.order.shopName || '—'))])]),_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"金额(USDT):\")]),_c('span',{staticClass:\"value strong\"},[_vm._v(_vm._s(_vm.order.totalPrice))])]),_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"创建时间:\")]),_c('span',{staticClass:\"value\"},[_vm._v(_vm._s(_vm.formatDateTime(_vm.order.createTime)))])]),(Number(_vm.order.status) === 8)?_c('div',{staticClass:\"row\"},[_c('span',{staticClass:\"label\"},[_vm._v(\"订单完成时间:\")]),_c('span',{staticClass:\"value\"},[_vm._v(_vm._s(_vm.formatDateTime(_vm.order.endTime)))])]):_vm._e()]),_c('el-card',{staticClass:\"section\",staticStyle:{\"margin-top\":\"12px\"}},[_c('div',{staticClass:\"sub-title\"},[_vm._v(\"机器列表\")]),_c('el-table',{staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.items,\"border\":\"\",\"size\":\"small\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"prop\":\"productMachineId\",\"label\":\"机器ID\",\"min-width\":\"120\"}}),_c('el-table-column',{attrs:{\"label\":\"矿机类型\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatMachineType(scope.row && scope.row.type)))]}}])}),_c('el-table-column',{attrs:{\"prop\":\"payCoin\",\"label\":\"币种\",\"min-width\":\"100\"}}),_c('el-table-column',{attrs:{\"prop\":\"leaseTime\",\"label\":\"租赁天数\",\"min-width\":\"100\"}}),_c('el-table-column',{attrs:{\"label\":\"购买数量\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row && scope.row.numbers != null ? scope.row.numbers : '—'))]}}])}),_c('el-table-column',{attrs:{\"prop\":\"price\",\"label\":\"单价(USDT)\",\"min-width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"address\",\"label\":\"收款地址\",\"min-width\":\"240\"}})],1)],1),_c('div',{staticClass:\"actions\"},[_c('el-button',{on:{\"click\":function($event){return _vm.$router.back()}}},[_vm._v(\"返回\")])],1)],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./withdrawRecord.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./withdrawRecord.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./withdrawRecord.vue?vue&type=template&id=72b1f929&scoped=true\"\nimport script from \"./withdrawRecord.vue?vue&type=script&lang=js\"\nexport * from \"./withdrawRecord.vue?vue&type=script&lang=js\"\nimport style0 from \"./withdrawRecord.vue?vue&type=style&index=0&id=72b1f929&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"72b1f929\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"orders-page\"},[_c('h2',{staticClass:\"title\"},[_vm._v(\"已售出订单\")]),_c('el-tabs',{on:{\"tab-click\":_vm.handleTabClick},model:{value:(_vm.active),callback:function ($$v) {_vm.active=$$v},expression:\"active\"}},[_c('el-tab-pane',{attrs:{\"label\":\"订单进行中\",\"name\":\"7\"}},[_c('order-list',{attrs:{\"items\":_vm.orders[7],\"show-checkout\":false,\"show-end-time\":false,\"is-seller\":true,\"empty-text\":\"暂无进行中的订单\"}})],1),_c('el-tab-pane',{attrs:{\"label\":\"订单已完成\",\"name\":\"8\"}},[_c('order-list',{attrs:{\"items\":_vm.orders[8],\"show-checkout\":false,\"show-end-time\":true,\"is-seller\":true,\"empty-text\":\"暂无已完成的订单\"}})],1)],1)],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./rechargeRecord.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./rechargeRecord.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./rechargeRecord.vue?vue&type=template&id=5cf693fa&scoped=true\"\nimport script from \"./rechargeRecord.vue?vue&type=script&lang=js\"\nexport * from \"./rechargeRecord.vue?vue&type=script&lang=js\"\nimport style0 from \"./rechargeRecord.vue?vue&type=style&index=0&id=5cf693fa&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5cf693fa\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./reset-password.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./reset-password.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./reset-password.vue?vue&type=template&id=f62bdade&scoped=true\"\nimport script from \"./reset-password.vue?vue&type=script&lang=js\"\nexport * from \"./reset-password.vue?vue&type=script&lang=js\"\nimport style0 from \"./reset-password.vue?vue&type=style&index=0&id=f62bdade&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"f62bdade\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.statusLoading),expression:\"statusLoading\"}],staticClass:\"security-settings\"},[_c('div',{staticClass:\"security-item-wrapper\"},[_c('div',{staticClass:\"security-item\"},[_vm._m(0),_c('div',{staticClass:\"security-right\"},[_c('span',{staticClass:\"security-status\",class:_vm.getStatusClass},[_vm._v(\" \"+_vm._s(_vm.getStatusText)+\" \")]),_c('el-button',{staticClass:\"security-btn two-factor-btn\",attrs:{\"type\":\"text\",\"loading\":_vm.loading},on:{\"click\":_vm.handleButtonClick}},[_vm._v(\" \"+_vm._s(_vm.getButtonText)+\" \")])],1)]),_c('div',{staticClass:\"security-divider\"})]),_c('div',{staticClass:\"security-item-wrapper\"},[_c('div',{staticClass:\"security-item\"},[_vm._m(1),_c('div',{staticClass:\"security-right\"},[_c('el-button',{staticClass:\"security-btn change-password-btn\",attrs:{\"type\":\"text\"},on:{\"click\":_vm.handleChangePassword}},[_vm._v(\" 修改 \")])],1)]),_c('div',{staticClass:\"security-divider\"})]),_c('div',{staticClass:\"security-item-wrapper\"},[_c('div',{staticClass:\"security-item\"},[_vm._m(2),_c('div',{staticClass:\"security-right\"},[_c('el-button',{staticClass:\"security-btn delete-account-btn\",attrs:{\"type\":\"text\"},on:{\"click\":_vm.handleDeleteAccount}},[_vm._v(\" 注销 \")])],1)]),_c('div',{staticClass:\"security-divider\"})]),_c('el-dialog',{attrs:{\"title\":\"开启双重验证 - 步骤 1/2\",\"visible\":_vm.step1Visible,\"width\":\"600px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.step1Visible=$event},\"close\":_vm.handleStep1Close}},[_c('div',{staticClass:\"step1-content\"},[_c('div',{staticClass:\"instruction-text\"},[_c('p',[_vm._v(\"请使用您手机上的谷歌身份验证器 (Google Authenticator) 或其它兼容应用程序扫描下方二维码,也可手动输入以下密钥。\")])]),_c('div',{staticClass:\"qr-section\"},[(_vm.qrCodeUrl)?_c('div',{staticClass:\"qr-code-wrapper\"},[_c('img',{staticClass:\"qr-code\",attrs:{\"src\":_vm.getQrCodeSrc,\"alt\":\"二维码\"}})]):_c('div',{staticClass:\"qr-loading\"},[_c('i',{staticClass:\"el-icon-loading\"}),_c('span',[_vm._v(\"加载中...\")])])]),_c('div',{staticClass:\"secret-key-section\"},[_c('div',{staticClass:\"secret-key-label\"},[_vm._v(\"或手动输入密钥:\")]),_c('div',{staticClass:\"secret-key-input-group\"},[_c('el-input',{staticClass:\"secret-key-input\",attrs:{\"readonly\":\"\"},model:{value:(_vm.secretKey),callback:function ($$v) {_vm.secretKey=$$v},expression:\"secretKey\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"disabled\":!_vm.secretKey},on:{\"click\":_vm.handleCopySecret}},[_vm._v(\" 复制 \")])],1)]),_c('div',{staticClass:\"warning-box\"},[_c('i',{staticClass:\"el-icon-warning\"}),_c('div',{staticClass:\"warning-text\"},[_c('p',[_vm._v(\"请妥善保存密钥,避免被盗或丢失。如遇手机丢失等情况,可通过该密钥恢复您的谷歌验证。如密钥丢失,需要提交工单通过人工客服重置,处理时间需7天。\")])])])]),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.step1Visible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"disabled\":!_vm.qrCodeUrl || !_vm.secretKey},on:{\"click\":_vm.handleNextToStep2}},[_vm._v(\" 下一步 \")])],1)]),_c('el-dialog',{attrs:{\"title\":\"开启双重验证 - 步骤 2/2\",\"visible\":_vm.step2Visible,\"width\":\"500px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.step2Visible=$event},\"close\":_vm.handleStep2Close}},[_c('el-form',{ref:\"verifyForm\",attrs:{\"model\":_vm.verifyForm,\"rules\":_vm.verifyRules,\"label-position\":\"top\"}},[_c('el-form-item',{attrs:{\"label\":\"登录密码\",\"prop\":\"password\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请输入密码(8-32位)\",\"show-password\":\"\",\"clearable\":\"\"},model:{value:(_vm.verifyForm.password),callback:function ($$v) {_vm.$set(_vm.verifyForm, \"password\", $$v)},expression:\"verifyForm.password\"}}),_c('div',{staticClass:\"password-tip\"},[_c('i',{staticClass:\"el-icon-info\"}),_c('span',[_vm._v(\"密码需包含大小写字母、数字和特殊字符,长度8-32位\")])])],1),_c('el-form-item',{attrs:{\"label\":\"邮箱验证码\",\"prop\":\"emailCode\"}},[_c('div',{staticClass:\"code-input-group\"},[_c('el-input',{staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入邮箱验证码\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.verifyForm.emailCode),callback:function ($$v) {_vm.$set(_vm.verifyForm, \"emailCode\", $$v)},expression:\"verifyForm.emailCode\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.sendingCode,\"disabled\":_vm.countdown > 0},on:{\"click\":_vm.handleSendEmailCode}},[_vm._v(\" \"+_vm._s(_vm.countdown > 0 ? `${_vm.countdown}秒后重试` : '发送验证码')+\" \")])],1),_c('div',{staticClass:\"help-link\"},[_c('a',{attrs:{\"href\":\"javascript:void(0)\"},on:{\"click\":_vm.handleCannotGetCode}},[_vm._v(\"无法获取验证码?\")])])]),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位动态口令\",\"maxlength\":\"6\"},on:{\"input\":_vm.handleGoogleCodeInput},model:{value:(_vm.verifyForm.googleCode),callback:function ($$v) {_vm.$set(_vm.verifyForm, \"googleCode\", $$v)},expression:\"verifyForm.googleCode\"}}),_c('div',{staticClass:\"help-link\"},[_c('a',{attrs:{\"href\":\"javascript:void(0)\"},on:{\"click\":_vm.handleCannotGetGoogleCode}},[_vm._v(\"无法获取验证码?\")])])],1)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":_vm.handleBackToStep1}},[_vm._v(\"上一步\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.submitting},on:{\"click\":_vm.handleConfirm}},[_vm._v(\" 确定 \")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"关闭双重验证\",\"visible\":_vm.closeDialogVisible,\"width\":\"500px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.closeDialogVisible=$event},\"close\":_vm.handleCloseDialogClose}},[_c('el-form',{ref:\"closeForm\",attrs:{\"model\":_vm.closeForm,\"rules\":_vm.closeRules,\"label-position\":\"top\"}},[_c('el-form-item',{attrs:{\"label\":\"邮箱验证码\",\"prop\":\"emailCode\"}},[_c('div',{staticClass:\"code-input-group\"},[_c('el-input',{staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入邮箱验证码\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.closeForm.emailCode),callback:function ($$v) {_vm.$set(_vm.closeForm, \"emailCode\", $$v)},expression:\"closeForm.emailCode\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.sendingCloseCode,\"disabled\":_vm.closeCountdown > 0},on:{\"click\":_vm.handleSendCloseEmailCode}},[_vm._v(\" \"+_vm._s(_vm.closeCountdown > 0 ? `${_vm.closeCountdown}秒后重试` : '发送验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位动态口令\",\"maxlength\":\"6\",\"clearable\":\"\"},on:{\"input\":_vm.handleCloseGoogleCodeInput},model:{value:(_vm.closeForm.googleCode),callback:function ($$v) {_vm.$set(_vm.closeForm, \"googleCode\", $$v)},expression:\"closeForm.googleCode\"}})],1)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.closeDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.closing},on:{\"click\":_vm.handleConfirmClose}},[_vm._v(\" 确定 \")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"开启双重验证\",\"visible\":_vm.openDialogVisible,\"width\":\"500px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.openDialogVisible=$event},\"close\":_vm.handleOpenDialogClose}},[_c('el-form',{ref:\"openForm\",attrs:{\"model\":_vm.openForm,\"rules\":_vm.openRules,\"label-position\":\"top\"}},[_c('el-form-item',{attrs:{\"label\":\"邮箱验证码\",\"prop\":\"emailCode\"}},[_c('div',{staticClass:\"code-input-group\"},[_c('el-input',{staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入邮箱验证码\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.openForm.emailCode),callback:function ($$v) {_vm.$set(_vm.openForm, \"emailCode\", $$v)},expression:\"openForm.emailCode\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.sendingOpenCode,\"disabled\":_vm.openCountdown > 0},on:{\"click\":_vm.handleSendOpenEmailCode}},[_vm._v(\" \"+_vm._s(_vm.openCountdown > 0 ? `${_vm.openCountdown}秒后重试` : '发送验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位动态口令\",\"maxlength\":\"6\",\"clearable\":\"\"},on:{\"input\":_vm.handleOpenGoogleCodeInput},model:{value:(_vm.openForm.googleCode),callback:function ($$v) {_vm.$set(_vm.openForm, \"googleCode\", $$v)},expression:\"openForm.googleCode\"}})],1)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.openDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.opening},on:{\"click\":_vm.handleConfirmOpen}},[_vm._v(\" 确定 \")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"修改密码\",\"visible\":_vm.changePasswordDialogVisible,\"width\":\"500px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.changePasswordDialogVisible=$event},\"close\":_vm.handleChangePasswordDialogClose}},[_c('el-form',{ref:\"changePasswordForm\",attrs:{\"model\":_vm.changePasswordForm,\"rules\":_vm.changePasswordRules,\"label-position\":\"top\"}},[_c('el-form-item',{attrs:{\"label\":\"用户邮箱\"}},[_c('el-input',{staticClass:\"email-display\",attrs:{\"value\":_vm.userEmail,\"readonly\":\"\",\"disabled\":\"\"}})],1),_c('el-form-item',{attrs:{\"label\":\"邮箱验证码\",\"prop\":\"emailCode\"}},[_c('div',{staticClass:\"code-input-group\"},[_c('el-input',{staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入邮箱验证码\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.changePasswordForm.emailCode),callback:function ($$v) {_vm.$set(_vm.changePasswordForm, \"emailCode\", $$v)},expression:\"changePasswordForm.emailCode\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.sendingChangePasswordCode,\"disabled\":_vm.changePasswordCountdown > 0},on:{\"click\":_vm.handleSendChangePasswordCode}},[_vm._v(\" \"+_vm._s(_vm.changePasswordCountdown > 0 ? `${_vm.changePasswordCountdown}秒后重试` : '获取验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"label\":\"新密码\",\"prop\":\"password\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请输入新密码(8-32位)\",\"show-password\":\"\",\"clearable\":\"\"},model:{value:(_vm.changePasswordForm.password),callback:function ($$v) {_vm.$set(_vm.changePasswordForm, \"password\", $$v)},expression:\"changePasswordForm.password\"}}),_c('div',{staticClass:\"password-tip\"},[_c('i',{staticClass:\"el-icon-info\"}),_c('span',[_vm._v(\"密码需包含大小写字母、数字和特殊字符,长度8-32位\")])])],1),_c('el-form-item',{attrs:{\"label\":\"确认新密码\",\"prop\":\"confirmPassword\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请再次输入新密码\",\"show-password\":\"\",\"clearable\":\"\"},model:{value:(_vm.changePasswordForm.confirmPassword),callback:function ($$v) {_vm.$set(_vm.changePasswordForm, \"confirmPassword\", $$v)},expression:\"changePasswordForm.confirmPassword\"}})],1),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位动态口令\",\"maxlength\":\"6\",\"clearable\":\"\"},on:{\"input\":_vm.handleChangePasswordGoogleCodeInput},model:{value:(_vm.changePasswordForm.googleCode),callback:function ($$v) {_vm.$set(_vm.changePasswordForm, \"googleCode\", $$v)},expression:\"changePasswordForm.googleCode\"}})],1)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.changePasswordDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.changingPassword},on:{\"click\":_vm.handleConfirmChangePassword}},[_vm._v(\" 确认修改 \")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"注销账号\",\"visible\":_vm.deleteAccountDialogVisible,\"width\":\"500px\",\"close-on-click-modal\":false},on:{\"update:visible\":function($event){_vm.deleteAccountDialogVisible=$event},\"close\":_vm.handleDeleteAccountDialogClose}},[_c('el-form',{ref:\"deleteAccountForm\",attrs:{\"model\":_vm.deleteAccountForm,\"rules\":_vm.deleteAccountRules,\"label-position\":\"top\"}},[_c('el-form-item',{attrs:{\"label\":\"用户邮箱\"}},[_c('el-input',{staticClass:\"email-display\",attrs:{\"value\":_vm.userEmail,\"readonly\":\"\",\"disabled\":\"\"}})],1),_c('el-form-item',{attrs:{\"label\":\"邮箱验证码\",\"prop\":\"emailCode\"}},[_c('div',{staticClass:\"code-input-group\"},[_c('el-input',{staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入邮箱验证码\",\"maxlength\":\"10\",\"clearable\":\"\"},model:{value:(_vm.deleteAccountForm.emailCode),callback:function ($$v) {_vm.$set(_vm.deleteAccountForm, \"emailCode\", $$v)},expression:\"deleteAccountForm.emailCode\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.sendingDeleteAccountCode,\"disabled\":_vm.deleteAccountCountdown > 0},on:{\"click\":_vm.handleSendDeleteAccountCode}},[_vm._v(\" \"+_vm._s(_vm.deleteAccountCountdown > 0 ? `${_vm.deleteAccountCountdown}秒后重试` : '获取验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位动态口令\",\"maxlength\":\"6\",\"clearable\":\"\"},on:{\"input\":_vm.handleDeleteAccountGoogleCodeInput},model:{value:(_vm.deleteAccountForm.googleCode),callback:function ($$v) {_vm.$set(_vm.deleteAccountForm, \"googleCode\", $$v)},expression:\"deleteAccountForm.googleCode\"}})],1)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.deleteAccountDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"danger\",\"loading\":_vm.deletingAccount},on:{\"click\":_vm.handleConfirmDeleteAccount}},[_vm._v(\" 确定注销 \")])],1)],1)],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"security-left\"},[_c('div',{staticClass:\"security-icon\"},[_c('i',{staticClass:\"el-icon-lock\"})]),_c('div',{staticClass:\"security-info\"},[_c('div',{staticClass:\"security-title\"},[_vm._v(\"双重验证\")]),_c('p',{staticClass:\"security-desc\"},[_vm._v(\"用于登录帐户、结算订单、提现、修改登录密码等,涉及账户安全的重要操作。\")])])])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"security-left\"},[_c('div',{staticClass:\"security-icon\"},[_c('i',{staticClass:\"el-icon-edit\"})]),_c('div',{staticClass:\"security-info\"},[_c('div',{staticClass:\"security-title\"},[_vm._v(\"修改密码\")]),_c('p',{staticClass:\"security-desc\"},[_vm._v(\"定期修改密码可以提高账户安全性,建议使用强密码并定期更换。\")])])])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"security-left\"},[_c('div',{staticClass:\"security-icon\"},[_c('i',{staticClass:\"el-icon-warning\"})]),_c('div',{staticClass:\"security-info\"},[_c('div',{staticClass:\"security-title\"},[_vm._v(\"注销账号\")]),_c('p',{staticClass:\"security-desc\"},[_vm._v(\"注销账号将永久删除您的账户和所有相关数据,此操作不可恢复,请谨慎操作。\")])])])\n}]\n\nexport { render, staticRenderFns }","/**\r\n * RSA 加密工具\r\n * 使用 jsencrypt 库进行 RSA 公钥加密\r\n */\r\n\r\n// 导入 jsencrypt\r\nimport JSEncrypt from 'jsencrypt'\r\n\r\n// RSA 公钥(Base64 格式,不带 BEGIN/END 标记)\r\nconst RSA_PUBLIC_KEY_BASE64 = `MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsQVIKYozXCfnXUw8+omYLdcdL1pTzmQh35YPsvn22wM4SQJKvMmXmcS6bI5Bu+5zCjL0F56DzfKz0BNZEwb46UshUOO+KFBUr8CxjYE8NOgIsoe5FUn57O6er9/KySaWlkpGZX49K+l3e90R+dFUEfRE/ijYpeZWkLRwcgWZ+2u6HGpl9h/eF6XD0aW9asDjdAbxUQ48TlaWgfP+OHC+Zy2GKGQG16EcDMczrN6a2HbFnwRIUKrFP67UqyRq11BTUziOhXLY8J0MFuwXUk2OY4VpqjrJjHHjlHYADjIL/5K4Io2AhRU9+QSsKFR2wGxi4e8vw2IXDzscrDuah/7YSwIDAQAB`\r\n\r\n// RSA 公钥(PEM 格式)\r\nconst RSA_PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----\r\n${RSA_PUBLIC_KEY_BASE64}\r\n-----END PUBLIC KEY-----`\r\n\r\n/**\r\n * 获取 JSEncrypt 构造函数\r\n * @returns {Function} JSEncrypt 构造函数\r\n */\r\nfunction getJSEncrypt() {\r\n // 优先使用已导入的 JSEncrypt\r\n if (JSEncrypt) {\r\n return JSEncrypt\r\n }\r\n \r\n // 尝试从全局获取(可能通过 CDN 引入)\r\n if (typeof window !== 'undefined' && window.JSEncrypt) {\r\n return window.JSEncrypt\r\n }\r\n \r\n return null\r\n}\r\n\r\n/**\r\n * RSA 加密函数(同步版本)\r\n * @param {string} plainText - 要加密的明文\r\n * @returns {string|null} 加密后的密文(Base64 编码),失败返回 null\r\n */\r\nexport function rsaEncryptSync(plainText) {\r\n if (!plainText || typeof plainText !== 'string') {\r\n console.error('RSA 加密:输入必须是非空字符串')\r\n return null\r\n }\r\n\r\n try {\r\n const Encrypt = getJSEncrypt()\r\n if (!Encrypt) {\r\n console.error('JSEncrypt 未加载')\r\n return null\r\n }\r\n\r\n const encrypt = new Encrypt()\r\n encrypt.setPublicKey(RSA_PUBLIC_KEY)\r\n const encrypted = encrypt.encrypt(plainText)\r\n \r\n if (!encrypted) {\r\n console.error('RSA 加密失败:返回值为空')\r\n return null\r\n }\r\n \r\n return encrypted\r\n } catch (error) {\r\n console.error('RSA 加密异常:', error)\r\n return null\r\n }\r\n}\r\n\r\n/**\r\n * RSA 加密函数(异步版本,兼容同步调用)\r\n * @param {string} plainText - 要加密的明文\r\n * @returns {Promise} 加密后的密文(Base64 编码),失败返回 null\r\n */\r\nexport async function rsaEncrypt(plainText) {\r\n if (!plainText || typeof plainText !== 'string') {\r\n console.error('RSA 加密:输入必须是非空字符串')\r\n return null\r\n }\r\n\r\n try {\r\n const Encrypt = getJSEncrypt()\r\n if (!Encrypt) {\r\n console.error('JSEncrypt 未加载')\r\n return null\r\n }\r\n\r\n const encrypt = new Encrypt()\r\n encrypt.setPublicKey(RSA_PUBLIC_KEY)\r\n const encrypted = encrypt.encrypt(plainText)\r\n \r\n if (!encrypted) {\r\n console.error('RSA 加密失败:返回值为空')\r\n return null\r\n }\r\n \r\n return encrypted\r\n } catch (error) {\r\n console.error('RSA 加密异常:', error)\r\n return null\r\n }\r\n}\r\n","\r\n\r\n\r\n\r\n\r\n\r\n","\n\n\n\n ","/**\r\n * 错误提示管理器\r\n * 用于控制错误提示的频率,避免短时间内重复显示相同类型的错误\r\n */\r\nclass ErrorNotificationManager {\r\n constructor() {\r\n // 记录最近显示的错误信息\r\n this.recentErrors = new Map();\r\n // 默认节流时间 (30秒)\r\n this.throttleTime = 30000;\r\n // 错误类型映射\r\n this.errorTypes = {\r\n 'Network Error': 'network',\r\n 'timeout': 'timeout',\r\n 'Request failed with status code': 'statusCode',\r\n // 添加网络状态类型\r\n 'networkReconnected': 'networkStatus',\r\n 'NetworkError': 'network'\r\n };\r\n }\r\n\r\n /**\r\n * 获取错误类型\r\n * @param {String} message 错误信息\r\n * @returns {String} 错误类型\r\n */\r\n getErrorType(message) {\r\n for (const [key, type] of Object.entries(this.errorTypes)) {\r\n if (message.includes(key)) {\r\n return type;\r\n }\r\n }\r\n return 'unknown';\r\n }\r\n\r\n /**\r\n * 检查是否可以显示错误\r\n * @param {String} message 错误信息\r\n * @returns {Boolean} 是否可以显示\r\n */\r\n canShowError(message) {\r\n const errorType = this.getErrorType(message);\r\n const now = Date.now();\r\n \r\n // 检查同类型的错误是否最近已经显示过\r\n if (this.recentErrors.has(errorType)) {\r\n const lastTime = this.recentErrors.get(errorType);\r\n if (now - lastTime < this.throttleTime) {\r\n console.log(`[错误提示] 已抑制重复错误: ${errorType}`);\r\n return false;\r\n }\r\n }\r\n \r\n // 更新最后显示时间\r\n this.recentErrors.set(errorType, now);\r\n return true;\r\n }\r\n\r\n /**\r\n * 清理过期的错误记录\r\n */\r\n cleanup() {\r\n const now = Date.now();\r\n this.recentErrors.forEach((time, type) => {\r\n if (now - time > this.throttleTime) {\r\n this.recentErrors.delete(type);\r\n }\r\n });\r\n }\r\n}\r\n\r\n// 创建单例实例\r\nconst errorNotificationManager = new ErrorNotificationManager();\r\nexport default errorNotificationManager;","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./myShops.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./myShops.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./myShops.vue?vue&type=template&id=e4e60f4a&scoped=true\"\nimport script from \"./myShops.vue?vue&type=script&lang=js\"\nexport * from \"./myShops.vue?vue&type=script&lang=js\"\nimport style0 from \"./myShops.vue?vue&type=style&index=0&id=e4e60f4a&prod&scoped=true&lang=css\"\nimport style1 from \"./myShops.vue?vue&type=style&index=1&id=e4e60f4a&prod&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"e4e60f4a\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./wallet.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./wallet.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./wallet.vue?vue&type=template&id=39a94e74&scoped=true\"\nimport script from \"./wallet.vue?vue&type=script&lang=js\"\nexport * from \"./wallet.vue?vue&type=script&lang=js\"\nimport style0 from \"./wallet.vue?vue&type=style&index=0&id=39a94e74&prod&scoped=true&lang=css\"\nimport style1 from \"./wallet.vue?vue&type=style&index=1&id=39a94e74&prod&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"39a94e74\",\n null\n \n)\n\nexport default component.exports","\r\n\r\n\r\n\r\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./sellerFundsFlow.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./sellerFundsFlow.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./sellerFundsFlow.vue?vue&type=template&id=c9f8700c&scoped=true\"\nimport script from \"./sellerFundsFlow.vue?vue&type=script&lang=js\"\nexport * from \"./sellerFundsFlow.vue?vue&type=script&lang=js\"\nimport style0 from \"./sellerFundsFlow.vue?vue&type=style&index=0&id=c9f8700c&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"c9f8700c\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"header-container\"},[_c('nav',{staticClass:\"navbar\"},[_c('div',{staticClass:\"nav-left\"},_vm._l((_vm.navigation),function(nav){return _c('router-link',{key:nav.path,staticClass:\"nav-btn\",class:{ active: _vm.isNavActive(nav.path) },attrs:{\"to\":nav.path,\"title\":nav.description}},[_c('span',{staticClass:\"nav-icon\"},[_vm._v(_vm._s(nav.icon))]),_c('span',{staticClass:\"nav-text\"},[_vm._v(_vm._s(nav.name))]),(nav.path === '/cart')?_c('span',{staticClass:\"cart-count\"},[_vm._v(\"(\"+_vm._s(_vm.cartItemCount)+\")\")]):_vm._e()])}),1),_c('div',{staticClass:\"nav-right\"},[(_vm.isLoginStatusLoading)?_c('div',{staticClass:\"auth-loading\"},[_c('span',{staticClass:\"loading-placeholder\"})]):(!_vm.isLoggedIn)?_c('div',{staticClass:\"auth-buttons\"},[_c('button',{staticClass:\"auth-btn register-btn\",on:{\"click\":_vm.goToRegister}},[_vm._v(\" 注册 \")]),_c('button',{staticClass:\"auth-btn login-btn\",on:{\"click\":_vm.goToLogin}},[_vm._v(\" 登录 \")])]):_c('div',{staticClass:\"user-info\"},[_c('span',{staticClass:\"user-email\"},[_vm._v(_vm._s(_vm.userEmail))]),_c('router-link',{staticClass:\"security-link\",attrs:{\"to\":\"/account/security-settings\",\"active-class\":\"active\"}},[_vm._v(\" 安全设置 \")]),_c('el-button',{staticClass:\"logout-btn\",attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":_vm.handleLogout}},[_vm._v(\" 退出 \")])],1)])])])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n\n\n ","/**\r\n * @file 商品数据服务(轻量静态数据源)\r\n * @description 提供商品列表与详情查询。无需后端即可演示。\r\n */\r\n\r\n/**\r\n * @typedef {Object} Product\r\n * @property {string} id - 商品唯一标识\r\n * @property {string} title - 商品标题\r\n * @property {string} description - 商品描述\r\n * @property {number} price - 商品单价(元)\r\n * @property {string} image - 商品图片URL(此处使用占位图)\r\n */\r\n\r\n/**\r\n * 内置演示商品数据\r\n * 使用简短且清晰的字段,满足演示所需\r\n * @type {Product[]}\r\n */\r\nconst products = [\r\n // {\r\n // id: 'p1001',\r\n // title: '新能源充电桩(家用)',\r\n // description: '7kW 单相,智能预约,支持远程监控。',\r\n // price: 1299,\r\n // image: 'https://via.placeholder.com/300x200?text=%E5%85%85%E7%94%B5%E6%A1%A9'\r\n // },\r\n // {\r\n // id: 'p1002',\r\n // title: '工业电能表',\r\n // description: '三相四线,远程抄表,Modbus 通信。',\r\n // price: 899,\r\n // image: 'https://via.placeholder.com/300x200?text=%E7%94%B5%E8%83%BD%E8%A1%A8'\r\n // },\r\n // {\r\n // id: 'p1003',\r\n // title: '配电柜(入门版)',\r\n // description: 'IP54 防护,内置断路器与防雷模块。',\r\n // price: 5599,\r\n // image: 'https://via.placeholder.com/300x200?text=%E9%85%8D%E7%94%B5%E6%9F%9C'\r\n // },\r\n // {\r\n // id: 'p1004',\r\n // title: '工矿照明灯',\r\n // description: '120W 高亮,耐腐蚀,适配多场景。',\r\n // price: 329,\r\n // image: 'https://via.placeholder.com/300x200?text=%E7%85%A7%E6%98%8E%E7%81%AF'\r\n // }\r\n]\r\n\r\n/**\r\n * 获取全部商品\r\n * @returns {Promise}\r\n */\r\nexport const listProducts = async () => {\r\n return Promise.resolve(products);\r\n}\r\n\r\n/**\r\n * 根据ID获取商品\r\n * @param {string} productId - 商品ID\r\n * @returns {Promise}\r\n */\r\nexport const getProductById = async (productId) => {\r\n const product = products.find((p) => p.id === productId);\r\n return Promise.resolve(product);\r\n}\r\n\r\nexport default {\r\n listProducts,\r\n getProductById\r\n}\r\n\r\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./securitySettings.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./securitySettings.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./securitySettings.vue?vue&type=template&id=cbc61476&scoped=true\"\nimport script from \"./securitySettings.vue?vue&type=script&lang=js\"\nexport * from \"./securitySettings.vue?vue&type=script&lang=js\"\nimport style0 from \"./securitySettings.vue?vue&type=style&index=0&id=cbc61476&prod&scoped=true&lang=css\"\nimport style1 from \"./securitySettings.vue?vue&type=style&index=1&id=cbc61476&prod&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"cbc61476\",\n null\n \n)\n\nexport default component.exports","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./index.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./index.vue?vue&type=template&id=6b6c93c3&scoped=true\"\nimport script from \"./index.vue?vue&type=script&lang=js\"\nexport * from \"./index.vue?vue&type=script&lang=js\"\nimport style0 from \"./index.vue?vue&type=style&index=0&id=6b6c93c3&prod&scoped=true&lang=scss\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"6b6c93c3\",\n null\n \n)\n\nexport default component.exports","\r\n\r\n\r\n\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"account-product-detail\"},[_c('div',{staticClass:\"header\"},[_c('el-button',{attrs:{\"type\":\"text\"},on:{\"click\":_vm.handleBack}},[_vm._v(\"返回\")]),_c('h2',{staticClass:\"title\"},[_vm._v(\"商品详情\")])],1),_c('el-card',{staticClass:\"detail-card\",attrs:{\"shadow\":\"never\"}},[_c('el-form',{staticClass:\"detail-form\",attrs:{\"model\":_vm.product,\"label-width\":\"90px\",\"size\":\"small\"}},[_c('el-row',{attrs:{\"gutter\":16}},[_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"商品ID\"}},[_c('el-input',{attrs:{\"value\":_vm.product && _vm.product.id,\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"店铺ID\"}},[_c('el-input',{attrs:{\"value\":_vm.product && _vm.product.shopId,\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"名称\"}},[_c('el-input',{attrs:{\"value\":_vm.product && _vm.product.name,\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"币种\"}},[_c('el-input',{attrs:{\"value\":_vm.product && _vm.product.coin,\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"算法\"}},[_c('el-input',{attrs:{\"value\":_vm.product && _vm.product.algorithm,\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"类型\"}},[_c('el-input',{attrs:{\"value\":_vm.product && (_vm.product.type === 1 ? '算力套餐' : '挖矿机器'),\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}},[_c('el-form-item',{attrs:{\"label\":\"状态\"}},[_c('el-input',{attrs:{\"value\":_vm.product && (_vm.product.state === 1 ? '下架' : '上架'),\"disabled\":\"\"}})],1)],1),_c('el-col',{attrs:{\"span\":12}}),_c('el-col',{attrs:{\"span\":24}},[_c('el-form-item',{attrs:{\"label\":\"描述\"}},[_c('el-input',{attrs:{\"type\":\"textarea\",\"rows\":3,\"value\":_vm.product && _vm.product.description,\"disabled\":\"\"}})],1)],1)],1)],1)],1),_c('el-card',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.updateLoading),expression:\"updateLoading\"}],staticClass:\"detail-card\",attrs:{\"shadow\":\"never\"}},[_c('div',{staticClass:\"section-title\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_vm._v(\"机器组合\")]),(_vm.machineList && _vm.machineList.length)?_c('div',[_c('el-table',{staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.machineList,\"border\":\"\",\"stripe\":\"\"}},[_c('el-table-column',{attrs:{\"prop\":\"user\",\"label\":\"挖矿账户\"}}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"矿机ID\"}}),_c('el-table-column',{attrs:{\"prop\":\"miner\",\"label\":\"机器编号\"}}),_c('el-table-column',{attrs:{\"label\":\"实际算力\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row.computingPower)+\" \"+_vm._s(scope.row.unit || ''))]}}],null,false,881627289)},[_c('template',{slot:\"header\"},[_c('el-tooltip',{attrs:{\"content\":\"实际算力为该机器在本矿池过去24H的平均算力\",\"effect\":\"dark\",\"placement\":\"top\"}},[_c('i',{staticClass:\"el-icon-question label-help\",attrs:{\"aria-label\":\"帮助\",\"tabindex\":\"0\"}})]),_c('span',[_vm._v(\"实际算力\")])],1)],2),_c('el-table-column',{attrs:{\"label\":\"理论算力\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{class:{ 'changed-input': _vm.isCellChanged(scope.row, 'theoryPower') },staticStyle:{\"max-width\":\"260px\"},attrs:{\"size\":\"small\",\"inputmode\":\"decimal\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"input\":function($event){return _vm.handleTheoryPowerInput(scope.$index)},\"blur\":function($event){return _vm.handleTheoryPowerBlur(scope.$index)}},model:{value:(scope.row.theoryPower),callback:function ($$v) {_vm.$set(scope.row, \"theoryPower\", $$v)},expression:\"scope.row.theoryPower\"}},[_c('template',{slot:\"append\"},[_c('el-select',{staticClass:\"append-select append-select--unit\",staticStyle:{\"width\":\"90px\"},attrs:{\"size\":\"mini\",\"disabled\":_vm.isRowDisabled(scope.row)},model:{value:(scope.row.unit),callback:function ($$v) {_vm.$set(scope.row, \"unit\", $$v)},expression:\"scope.row.unit\"}},_vm._l((_vm.unitOptions),function(u){return _c('el-option',{key:u,attrs:{\"label\":u,\"value\":u}})}),1)],1)],2)]}}],null,false,1615065668)}),_c('el-table-column',{attrs:{\"label\":\"功耗(kw/h)\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{class:{ 'changed-input': _vm.isCellChanged(scope.row, 'powerDissipation') },staticStyle:{\"max-width\":\"260px\"},attrs:{\"size\":\"small\",\"inputmode\":\"decimal\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"input\":function($event){return _vm.handleNumericCell(scope.$index, 'powerDissipation')},\"blur\":function($event){return _vm.handlePowerDissipationBlur(scope.$index)}},model:{value:(scope.row.powerDissipation),callback:function ($$v) {_vm.$set(scope.row, \"powerDissipation\", $$v)},expression:\"scope.row.powerDissipation\"}})]}}],null,false,2013801812)}),_c('el-table-column',{attrs:{\"label\":\"型号\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{class:{ 'changed-input': _vm.isCellChanged(scope.row, 'type') },staticStyle:{\"max-width\":\"180px\"},attrs:{\"size\":\"small\",\"maxlength\":20,\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"input\":function($event){return _vm.handleTypeCell(scope.$index)}},model:{value:(scope.row.type),callback:function ($$v) {_vm.$set(scope.row, \"type\", $$v)},expression:\"scope.row.type\"}})]}}],null,false,4182654038)}),_c('el-table-column',{attrs:{\"label\":\"售价\",\"width\":\"188\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{class:{ 'changed-input': _vm.isCellChanged(scope.row, 'price') },staticStyle:{\"max-width\":\"260px\"},attrs:{\"size\":\"small\",\"inputmode\":\"decimal\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"input\":function($event){return _vm.handleNumericCell(scope.$index, 'price')},\"blur\":function($event){return _vm.handlePriceBlur(scope.$index)}},model:{value:(scope.row._priceEditing),callback:function ($$v) {_vm.$set(scope.row, \"_priceEditing\", $$v)},expression:\"scope.row._priceEditing\"}},[_c('template',{slot:\"append\"},[_c('el-select',{staticClass:\"append-select append-select--coin\",staticStyle:{\"width\":\"120px\"},attrs:{\"size\":\"mini\"},on:{\"change\":function($event){return _vm.handlePayTypeChange(scope.$index)}},model:{value:(scope.row._selectedPayIndex),callback:function ($$v) {_vm.$set(scope.row, \"_selectedPayIndex\", $$v)},expression:\"scope.row._selectedPayIndex\"}},_vm._l(((scope.row.priceList || [])),function(pt,i){return _c('el-option',{key:pt.payTypeId || i,attrs:{\"label\":[String(pt.chain||'').toUpperCase(), String(pt.coin||'').toUpperCase()].filter(Boolean).join('-'),\"value\":i}})}),1)],1)],2)]}}],null,false,3035245774)},[_c('template',{slot:\"header\"},[_c('el-tooltip',{attrs:{\"effect\":\"dark\",\"placement\":\"top\"}},[_c('div',{attrs:{\"slot\":\"content\"},slot:\"content\"},[_vm._v(\" 卖家最终收款金额 = 机器售价 × 波动率\"),_c('br'),_vm._v(\" 波动率规则:\"),_c('br'),_vm._v(\" 1)0% - 5%(包含5%):波动率 = 1(按售价结算)\"),_c('br'),_vm._v(\" 2)5%以上:波动率 = 实际算力 / 理论算力,且不会超过 1,即最终结算时不会超过机器售价 \")]),_c('i',{staticClass:\"el-icon-question label-help\",attrs:{\"aria-label\":\"帮助\",\"tabindex\":\"0\"}})]),_c('span',[_vm._v(\"售价(按结算币种)\")])],1)],2),_c('el-table-column',{attrs:{\"label\":\"最大租赁天数(天)\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{class:{ 'changed-input': _vm.isCellChanged(scope.row, 'maxLeaseDays') },staticStyle:{\"max-width\":\"260px\"},attrs:{\"size\":\"small\",\"inputmode\":\"numeric\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"input\":function($event){return _vm.handleMaxLeaseDaysInput(scope.$index)},\"blur\":function($event){return _vm.handleMaxLeaseDaysBlur(scope.$index)}},model:{value:(scope.row.maxLeaseDays),callback:function ($$v) {_vm.$set(scope.row, \"maxLeaseDays\", $$v)},expression:\"scope.row.maxLeaseDays\"}},[_c('template',{slot:\"append\"},[_vm._v(\"天\")])],2)]}}],null,false,3414109227)}),_c('el-table-column',{attrs:{\"label\":\"上下架\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-switch',{attrs:{\"active-value\":0,\"inactive-value\":1,\"active-text\":\"上架\",\"inactive-text\":\"下架\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"change\":function($event){return _vm.handleStateChange(scope.$index)}},model:{value:(scope.row.state),callback:function ($$v) {_vm.$set(scope.row, \"state\", $$v)},expression:\"scope.row.state\"}})]}}],null,false,1620801377)}),_c('el-table-column',{attrs:{\"label\":\"售出状态\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":scope.row.saleState === 0 ? 'info' : (scope.row.saleState === 1 ? 'danger' : 'warning')}},[_vm._v(\" \"+_vm._s(scope.row.saleState === 0 ? '未售出' : (scope.row.saleState === 1 ? '已售出' : '售出中'))+\" \")])]}}],null,false,1904393654)}),_c('el-table-column',{attrs:{\"label\":\"操作\",\"fixed\":\"right\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{staticStyle:{\"color\":\"#f56c6c\"},attrs:{\"type\":\"text\",\"size\":\"small\",\"disabled\":_vm.isRowDisabled(scope.row)},on:{\"click\":function($event){return _vm.handleDeleteMachine(scope.row)}}},[_vm._v(\"删除\")])]}}],null,false,979761678)})],1)],1):_c('div',{staticClass:\"empty-text\"},[_vm._v(\"暂无组合数据\")])]),(_vm.machineList && _vm.machineList.length)?_c('div',{staticClass:\"actions\"},[_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleOpenConfirm}},[_vm._v(\"提交修改机器\")])],1):_vm._e(),_c('el-dialog',{attrs:{\"title\":\"确认提交修改\",\"visible\":_vm.confirmVisible,\"width\":\"520px\"},on:{\"update:visible\":function($event){_vm.confirmVisible=$event}}},[_c('div',[_c('p',[_vm._v(\"请仔细确认已选择机器机器组合里的机器价格及相关参数定义。\")]),_c('p',[_vm._v(\"机器修改上架后,一经售出,在机器出售期间不能修改价格及机器参数。\")])]),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.confirmVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleSubmitMachines}},[_vm._v(\"确认提交修改\")])],1)])],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"withdrawal-history-container\"},[_vm._m(0),_c('div',{staticClass:\"tab-container\"},[_c('el-tabs',{on:{\"tab-click\":_vm.handleTabClick},model:{value:(_vm.activeTab),callback:function ($$v) {_vm.activeTab=$$v},expression:\"activeTab\"}},[_c('el-tab-pane',{attrs:{\"label\":\"提现中\",\"name\":\"pending\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"提现中 (\"+_vm._s(_vm.total)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"withdrawal-list\"},[_vm._l((_vm.pendingWithdrawals),function(item){return _c('div',{key:item.id,staticClass:\"withdrawal-item pending\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(_vm._s(item.amount)+\" \"+_vm._s(item.toSymbol || 'USDT'))]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.toChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status pending-status\"},[_c('i',{staticClass:\"el-icon-loading\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.toAddress)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.pendingWithdrawals.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无提现中的记录\")])]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"提现成功\",\"name\":\"success\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"提现成功 (\"+_vm._s(_vm.total)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"withdrawal-list\"},[_vm._l((_vm.successWithdrawals),function(item){return _c('div',{key:item.id,staticClass:\"withdrawal-item success\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(_vm._s(item.amount)+\" \"+_vm._s(item.toSymbol || 'USDT'))]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.toChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status success-status\"},[_c('i',{staticClass:\"el-icon-check\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.toAddress)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.successWithdrawals.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无提现成功的记录\")])]):_vm._e()],2)])]),_c('el-tab-pane',{attrs:{\"label\":\"提现失败\",\"name\":\"failed\"}},[_c('div',{staticClass:\"tab-content\"},[_c('div',{staticClass:\"list-header\"},[_c('span',{staticClass:\"list-title\"},[_vm._v(\"提现失败 (\"+_vm._s(_vm.total)+\")\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.refreshData}},[_c('i',{staticClass:\"el-icon-refresh\"}),_vm._v(\" 刷新 \")])],1),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"withdrawal-list\"},[_vm._l((_vm.failedWithdrawals),function(item){return _c('div',{key:item.id,staticClass:\"withdrawal-item failed\",on:{\"click\":function($event){return _vm.showDetail(item)}}},[_c('div',{staticClass:\"item-main\"},[_c('div',{staticClass:\"item-left\"},[_c('div',{staticClass:\"amount\"},[_vm._v(_vm._s(item.amount)+\" \"+_vm._s(item.toSymbol || 'USDT'))]),_c('div',{staticClass:\"chain\"},[_vm._v(_vm._s(_vm.getChainName(item.toChain)))])]),_c('div',{staticClass:\"item-right\"},[_c('div',{staticClass:\"status failed-status\"},[_c('i',{staticClass:\"el-icon-close\"}),_vm._v(\" \"+_vm._s(_vm.getStatusText(item.status))+\" \")]),_c('div',{staticClass:\"time\"},[_vm._v(_vm._s(_vm.formatTime(item.createTime)))])])]),_c('div',{staticClass:\"item-footer\"},[_c('div',{staticClass:\"footer-left\"},[_c('span',{staticClass:\"address\"},[_vm._v(_vm._s(_vm.formatAddress(item.toAddress)))]),(item.txHash)?_c('span',{staticClass:\"tx-hash\"},[_c('i',{staticClass:\"el-icon-link\"}),_vm._v(\" \"+_vm._s(_vm.formatAddress(item.txHash))+\" \")]):_vm._e()]),_c('i',{staticClass:\"el-icon-arrow-right\"})])])}),(_vm.failedWithdrawals.length === 0)?_c('div',{staticClass:\"empty-state\"},[_c('i',{staticClass:\"el-icon-document\"}),_c('p',[_vm._v(\"暂无提现失败的记录\")])]):_vm._e()],2)])])],1),_c('el-row',[_c('el-col',{staticStyle:{\"display\":\"flex\",\"justify-content\":\"center\"},attrs:{\"span\":24}},[_c('el-pagination',{staticStyle:{\"margin\":\"0 auto\",\"margin-top\":\"10px\"},attrs:{\"current-page\":_vm.currentPage,\"page-sizes\":_vm.pageSizes,\"page-size\":_vm.pagination.pageSize,\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total},on:{\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange,\"update:currentPage\":function($event){_vm.currentPage=$event},\"update:current-page\":function($event){_vm.currentPage=$event}}})],1)],1)],1),_c('el-dialog',{attrs:{\"title\":\"提现详情\",\"visible\":_vm.detailDialogVisible,\"width\":\"600px\"},on:{\"update:visible\":function($event){_vm.detailDialogVisible=$event},\"close\":_vm.closeDetail}},[(_vm.selectedItem)?_c('div',{staticClass:\"detail-content\"},[_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"基本信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"提现ID\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.selectedItem.id))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"提现金额\")]),_c('span',{staticClass:\"detail-value amount\"},[_vm._v(_vm._s(_vm.selectedItem.amount)+\" \"+_vm._s(_vm.selectedItem.toSymbol || 'USDT'))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"区块链网络\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.getChainName(_vm.selectedItem.toChain)))])]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"提现状态\")]),_c('span',{staticClass:\"detail-value\"},[_c('el-tag',{attrs:{\"type\":_vm.getStatusType(_vm.selectedItem.status)}},[_vm._v(\" \"+_vm._s(_vm.getStatusText(_vm.selectedItem.status))+\" \")])],1)])])]),_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"地址信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"收款地址\")]),_c('div',{staticClass:\"address-container\"},[_c('span',{staticClass:\"detail-value address\"},[_vm._v(_vm._s(_vm.selectedItem.toAddress))]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.copyAddress(_vm.selectedItem.toAddress)}}},[_vm._v(\" 复制 \")])],1)]),_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"交易哈希\")]),_c('div',{staticClass:\"address-container\"},[_c('span',{staticClass:\"detail-value address\"},[_vm._v(_vm._s(_vm.selectedItem.txHash))]),(_vm.selectedItem.txHash)?_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.copyAddress(_vm.selectedItem.txHash)}}},[_vm._v(\" 复制 \")]):_vm._e()],1)])])]),_c('div',{staticClass:\"detail-section\"},[_c('h3',{staticClass:\"section-title\"},[_vm._v(\"时间信息\")]),_c('div',{staticClass:\"detail-list\"},[_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"提现时间\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.formatFullTime(_vm.selectedItem.createTime)))])]),(_vm.selectedItem.updateTime)?_c('div',{staticClass:\"detail-row\"},[_c('span',{staticClass:\"detail-label\"},[_vm._v(\"完成时间\")]),_c('span',{staticClass:\"detail-value\"},[_vm._v(_vm._s(_vm.formatFullTime(_vm.selectedItem.updateTime)))])]):_vm._e()])])]):_vm._e(),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":_vm.closeDetail}},[_vm._v(\"关闭\")])],1)])],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"page-header\"},[_c('h1',{staticClass:\"page-title\"},[_vm._v(\"提现记录\")]),_c('p',{staticClass:\"page-subtitle\"},[_vm._v(\"查看您的提现申请和交易状态\")])])\n}]\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"panel\"},[_c('h2',{staticClass:\"panel-title\"},[_vm._v(\"我的店铺\")]),_c('div',{staticClass:\"panel-body\"},[_c('el-card',{staticClass:\"guide-card\",staticStyle:{\"margin-bottom\":\"16px\"},attrs:{\"shadow\":\"never\"}},[_c('div',{staticClass:\"guide-header\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_vm._v(\"店铺层级说明\")]),_c('div',{staticClass:\"guide-content\"},[_c('p',{staticClass:\"hierarchy\"},[_vm._v(\"层级结构:店铺 → 商品 → 出售机器\")]),_c('ol',{staticClass:\"guide-steps\"},[_c('li',[_c('b',[_vm._v(\"店铺(唯一)\")]),_vm._v(\":每个用户在平台\"),_c('strong',[_vm._v(\"仅能创建一个店铺\")]),_vm._v(\"。创建成功后, 请在本页点击 \"),_c('b',[_vm._v(\"钱包绑定\")]),_vm._v(\",配置自己的收款地址(支持不同链与币种)。 \")]),_c('li',[_c('b',[_vm._v(\"创建商品\")]),_vm._v(\":完成钱包绑定后,即可在“我的店铺”页面 点击\"),_c('b',[_vm._v(\"新增商品\")]),_vm._v(\"按钮。 \"),_c('ul',{staticClass:\"guide-substeps\"},[_c('li',[_c('b',[_vm._v(\"ASIC 商品创建\")]),_vm._v(\":选择矿机种类为 ASIC,填写页面商品信息后创建,商品可按 \"),_c('b',[_vm._v(\"币种\")]),_vm._v(\" 进行分类管理,创建的商品会在商城对买家展示; 商品可理解为“不同算法、币种的机器集合分类”。 \")]),_c('li',[_c('b',[_vm._v(\"GPU 商品创建\")]),_vm._v(\":选择矿机种类为 GPU,查看页面注意事项并下载对应客户端,启动后读取自动创建。创建完成请进入 \"),_c('b',[_vm._v(\"商品列表\")]),_vm._v(\" 为该商品手动配置售价等相关信息并上架。 \")])])])]),_c('div',{staticClass:\"guide-note\"},[_vm._v(\"提示:建议先创建店铺 → 完成钱包绑定 → 创建商品的顺序,避免漏配导致无法收款或无法下单。\")])])]),(_vm.loaded && _vm.hasShop)?_c('el-card',{staticClass:\"shop-card\",attrs:{\"shadow\":\"hover\"}},[_c('div',{staticClass:\"shop-row\"},[_c('div',{staticClass:\"shop-cover\"},[_c('img',{attrs:{\"src\":_vm.shop.image || _vm.defaultCover,\"alt\":\"店铺封面\"}})]),_c('div',{staticClass:\"shop-info\"},[_c('div',{staticClass:\"shop-title\"},[_c('span',{staticClass:\"name\"},[_vm._v(_vm._s(_vm.shop.name || '未命名店铺'))]),_c('el-tag',{attrs:{\"size\":\"small\",\"type\":_vm.shopStateTagType}},[_vm._v(\" \"+_vm._s(_vm.shopStateText)+\" \")])],1),_c('div',{staticClass:\"desc\"},[_vm._v(_vm._s(_vm.shop.description || '这家店还没有描述~'))]),_c('div',{staticClass:\"meta\"},[_c('span',[_vm._v(\"手续费率:\"+_vm._s(_vm.formatFeeRate(_vm.shop.feeRate)))])]),_c('div',{staticClass:\"actions\"},[_c('el-button',{attrs:{\"size\":\"small\",\"type\":\"primary\"},on:{\"click\":_vm.handleOpenEdit}},[_vm._v(\"修改店铺\")]),_c('el-button',{attrs:{\"size\":\"small\",\"type\":\"warning\"},on:{\"click\":_vm.handleToggleShop}},[_vm._v(\" \"+_vm._s(_vm.shop.state === 2 ? '开启店铺' : '关闭店铺')+\" \")]),_c('el-button',{attrs:{\"size\":\"small\",\"type\":\"danger\"},on:{\"click\":_vm.handleDelete}},[_vm._v(\"删除店铺\")]),_c('el-button',{attrs:{\"size\":\"small\",\"type\":\"success\"},on:{\"click\":_vm.handleAddProduct}},[_vm._v(\"新增商品\")]),_c('el-button',{attrs:{\"size\":\"small\",\"type\":\"success\"},on:{\"click\":_vm.handleWalletBind}},[_vm._v(\"钱包绑定\")])],1)])])]):_vm._e(),(_vm.loaded && _vm.hasShop)?_c('el-card',{staticClass:\"shop-config-card\",staticStyle:{\"margin-top\":\"16px\"},attrs:{\"shadow\":\"never\"}},[_c('div',{staticClass:\"clearfix\",attrs:{\"slot\":\"header\"},slot:\"header\"},[_c('span',[_vm._v(\"已绑定钱包\")])]),_c('el-table',{staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.shopConfigs,\"border\":\"\"}},[_c('el-table-column',{attrs:{\"prop\":\"chain\",\"label\":\"链\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"label\":\"支付币种\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"coin-list\"},[(Array.isArray(scope.row.children) && scope.row.children.length)?_vm._l((scope.row.children),function(c,idx){return _c('el-tooltip',{key:idx,attrs:{\"content\":String(c && c.payCoin ? c.payCoin : '').toUpperCase(),\"placement\":\"top\"}},[(c && c.image)?_c('img',{staticClass:\"coin-img\",attrs:{\"src\":c.image,\"alt\":(c.payCoin || '').toUpperCase()}}):_vm._e()])}):[_vm._v(\" \"+_vm._s(String(scope.row.payCoin || '').toUpperCase())+\" \")]],2)]}}],null,false,569036476)}),_c('el-table-column',{attrs:{\"prop\":\"payAddress\",\"label\":\"收款钱包地址\",\"show-overflow-tooltip\":\"\"}}),_c('el-table-column',{attrs:{\"label\":\"余额\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"balance-num\"},[_vm._v(_vm._s(_vm.formatAmount(scope.row)))]),_c('span',{staticClass:\"balance-unit\"},[_vm._v(\" \"+_vm._s(_vm.formatCoin(scope.row)))])]}}],null,false,59971880)}),_c('el-table-column',{attrs:{\"label\":\"操作\",\"width\":\"240\",\"fixed\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{staticStyle:{\"color\":\"#409EFF\"},attrs:{\"type\":\"text\"},on:{\"click\":function($event){return _vm.handleWithdraw(scope.row)}}},[_vm._v(\"提现\")]),_c('el-divider',{attrs:{\"direction\":\"vertical\"}}),_c('el-button',{attrs:{\"type\":\"text\"},on:{\"click\":function($event){return _vm.handleEditConfig(scope.row)}}},[_vm._v(\"修改\")]),_c('el-divider',{attrs:{\"direction\":\"vertical\"}}),_c('el-button',{staticStyle:{\"color\":\"#e74c3c\"},attrs:{\"type\":\"text\"},on:{\"click\":function($event){return _vm.handleDeleteConfig(scope.row)}}},[_vm._v(\"删除\")])]}}],null,false,1325460802)})],1)],1):(_vm.loaded && !_vm.hasShop)?_c('div',{staticClass:\"no-shop\"},[_c('el-empty',{attrs:{\"description\":\"暂无店铺\"}},[_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleGoNew}},[_vm._v(\"新建店铺\")])],1)],1):_c('el-empty',{attrs:{\"description\":\"正在加载店铺信息...\"}}),_c('el-dialog',{attrs:{\"title\":_vm.withdrawDialogTitle,\"visible\":_vm.withdrawDialogVisible,\"width\":\"720px\",\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){_vm.withdrawDialogVisible=$event}}},[_c('el-form',{ref:\"withdrawForm\",attrs:{\"model\":_vm.withdrawForm,\"rules\":_vm.withdrawRules,\"label-width\":\"120px\"}},[_c('el-form-item',{attrs:{\"label\":\"提现链\"}},[_c('el-input',{attrs:{\"value\":String((_vm.currentWithdrawRow.chain || '')).toUpperCase(),\"disabled\":true}})],1),_c('el-form-item',{attrs:{\"label\":\"提现币种\"}},[_c('el-input',{attrs:{\"value\":_vm.displayWithdrawSymbol,\"disabled\":true}})],1),_c('el-form-item',{attrs:{\"label\":\"提现金额\",\"prop\":\"amount\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入提现金额\",\"inputmode\":\"decimal\"},on:{\"input\":_vm.handleAmountInput},model:{value:(_vm.withdrawForm.amount),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"amount\", $$v)},expression:\"withdrawForm.amount\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"balance-info\"},[_vm._v(\" 可用余额: \"+_vm._s(_vm.availableWithdrawBalance)+\" \"+_vm._s(_vm.displayWithdrawSymbol)+\" \")])],1),_c('el-form-item',{attrs:{\"label\":\"手续费\"}},[_c('el-input',{attrs:{\"disabled\":true},model:{value:(_vm.withdrawForm.fee),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"fee\", $$v)},expression:\"withdrawForm.fee\"}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"fee-info\"},[_vm._v(\"网络手续费: \"+_vm._s(_vm.withdrawForm.fee || '0')+\" \"+_vm._s(_vm.displayWithdrawSymbol))])],1),_c('el-form-item',{attrs:{\"label\":\"实际到账\"}},[_c('el-input',{attrs:{\"value\":_vm.actualAmount,\"disabled\":true}},[_c('template',{slot:\"append\"},[_vm._v(_vm._s(_vm.displayWithdrawSymbol))])],2),_c('div',{staticClass:\"actual-amount-info\"},[_vm._v(\"实际到账: \"+_vm._s(_vm.actualAmount)+\" \"+_vm._s(_vm.displayWithdrawSymbol))])],1),_c('el-form-item',{attrs:{\"label\":\"收款地址\",\"prop\":\"toAddress\"}},[_c('el-input',{ref:\"withdrawToAddressInput\",attrs:{\"placeholder\":\"请输入收款钱包地址\",\"disabled\":!_vm.withdrawAddressEditable},model:{value:(_vm.withdrawForm.toAddress),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"toAddress\", $$v)},expression:\"withdrawForm.toAddress\"}},[_c('template',{slot:\"append\"},[_c('el-button',{attrs:{\"type\":\"text\"},on:{\"click\":_vm.handleEditAddressClick}},[_vm._v(\"修改\")])],1)],2),_c('div',{staticClass:\"address-tip\"},[_vm._v(\"请确认地址正确,错误地址将导致资产丢失\")])],1),_c('el-form-item',{attrs:{\"label\":\"谷歌验证码\",\"prop\":\"googleCode\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入6位谷歌验证码\",\"maxlength\":\"6\"},on:{\"input\":_vm.handleGoogleCodeInput},model:{value:(_vm.withdrawForm.googleCode),callback:function ($$v) {_vm.$set(_vm.withdrawForm, \"googleCode\", $$v)},expression:\"withdrawForm.googleCode\"}},[_c('template',{slot:\"prepend\"},[_c('i',{staticClass:\"el-icon-key\"})])],2)],1)],1),_c('div',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.withdrawDialogVisible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.withdrawLoading},on:{\"click\":_vm.confirmWithdraw}},[_vm._v(\"确认提现\")])],1)],1),_c('el-dialog',{attrs:{\"title\":\"修改店铺\",\"visible\":_vm.visibleEdit,\"width\":\"520px\"},on:{\"update:visible\":function($event){_vm.visibleEdit=$event}}},[_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"店铺名称\")]),_c('el-input',{attrs:{\"placeholder\":\"请输入店铺名称\",\"maxlength\":30,\"show-word-limit\":\"\"},model:{value:(_vm.editForm.name),callback:function ($$v) {_vm.$set(_vm.editForm, \"name\", $$v)},expression:\"editForm.name\"}})],1),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"店铺描述\")]),_c('el-input',{attrs:{\"type\":\"textarea\",\"rows\":3,\"placeholder\":\"请输入描述\",\"maxlength\":300,\"show-word-limit\":\"\"},model:{value:(_vm.editForm.description),callback:function ($$v) {_vm.$set(_vm.editForm, \"description\", $$v)},expression:\"editForm.description\"}})],1),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"手续费比例\")]),_c('el-input',{attrs:{\"placeholder\":\"比例区间 0.01 - 0.1 之间,最多6位小数\"},on:{\"input\":_vm.handleEditFeeRateInput},model:{value:(_vm.editForm.feeRate),callback:function ($$v) {_vm.$set(_vm.editForm, \"feeRate\", $$v)},expression:\"editForm.feeRate\"}})],1),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"谷歌验证码\")]),_c('el-input',{attrs:{\"placeholder\":\"请输入6位谷歌验证码\",\"maxlength\":\"6\"},on:{\"input\":_vm.handleEditShopGoogleCodeInput},model:{value:(_vm.editForm.gCode),callback:function ($$v) {_vm.$set(_vm.editForm, \"gCode\", $$v)},expression:\"editForm.gCode\"}})],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.visibleEdit=false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.submitEdit}},[_vm._v(\"保存\")])],1)]),_c('el-dialog',{attrs:{\"title\":\"修改配置\",\"visible\":_vm.visibleConfigEdit,\"width\":\"560px\"},on:{\"update:visible\":function($event){_vm.visibleConfigEdit=$event},\"close\":_vm.handleConfigEditClose}},[_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"钱包地址\")]),_c('el-input',{attrs:{\"placeholder\":\"请输入钱包地址\"},model:{value:(_vm.configForm.payAddress),callback:function ($$v) {_vm.$set(_vm.configForm, \"payAddress\", $$v)},expression:\"configForm.payAddress\"}})],1),_c('div',{staticClass:\"row\"},[_c('label',{staticClass:\"label\"},[_vm._v(\"谷歌验证码\")]),_c('el-input',{attrs:{\"placeholder\":\"请输入6位谷歌验证码\",\"maxlength\":\"6\"},on:{\"input\":_vm.handleConfigGoogleCodeInput},model:{value:(_vm.configForm.googleCode),callback:function ($$v) {_vm.$set(_vm.configForm, \"googleCode\", $$v)},expression:\"configForm.googleCode\"}},[_c('template',{slot:\"prepend\"},[_c('i',{staticClass:\"el-icon-key\"})])],2)],1),_c('span',{staticClass:\"dialog-footer\",attrs:{\"slot\":\"footer\"},slot:\"footer\"},[_c('el-button',{on:{\"click\":function($event){_vm.visibleConfigEdit=false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.submitConfigEdit}},[_vm._v(\"确认修改\")])],1)])],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","\n\n \n \n \n \n \n ","\r\n\r\n\r\n\r\n\r\n\r\n","\n\n\n\n \n\n","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./register.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./register.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./register.vue?vue&type=template&id=57d53cdc&scoped=true\"\nimport script from \"./register.vue?vue&type=script&lang=js\"\nexport * from \"./register.vue?vue&type=script&lang=js\"\nimport style0 from \"./register.vue?vue&type=style&index=0&id=57d53cdc&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"57d53cdc\",\n null\n \n)\n\nexport default component.exports","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"account-products\"},[_c('div',{staticClass:\"toolbar\"},[_vm._m(0),_c('div',{staticClass:\"right-area\"},[_c('el-select',{staticClass:\"mr-12\",staticStyle:{\"width\":\"140px\"},attrs:{\"placeholder\":\"矿机种类\",\"size\":\"small\"},on:{\"change\":_vm.handleTypeChange},model:{value:(_vm.listParams.type),callback:function ($$v) {_vm.$set(_vm.listParams, \"type\", $$v)},expression:\"listParams.type\"}},[_c('el-option',{attrs:{\"label\":'ASIC',\"value\":0}}),_c('el-option',{attrs:{\"label\":'GPU',\"value\":1}})],1),_c('el-input',{staticClass:\"mr-12\",staticStyle:{\"width\":\"280px\"},attrs:{\"placeholder\":_vm.searchPlaceholder,\"size\":\"small\",\"clearable\":\"\"},on:{\"clear\":_vm.handleClear},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleSearch.apply(null, arguments)}},model:{value:(_vm.searchKeyword),callback:function ($$v) {_vm.searchKeyword=$$v},expression:\"searchKeyword\"}}),_c('el-button',{attrs:{\"type\":\"primary\",\"size\":\"small\"},on:{\"click\":_vm.handleSearch}},[_vm._v(\"搜索\")]),_c('el-button',{staticClass:\"ml-8\",attrs:{\"size\":\"small\"},on:{\"click\":_vm.handleReset}},[_vm._v(\"重置\")])],1)]),(_vm.payTypes && _vm.payTypes.length)?_c('div',{staticClass:\"paytypes-bar\"},[_c('span',{staticClass:\"pt-label\"},[_vm._v(\"支持结算方式:\")]),_c('div',{staticClass:\"pt-icons\"},_vm._l((_vm.payTypes),function(pt,idx){return _c('el-tooltip',{key:idx,attrs:{\"content\":_vm.formatPayTypeHead(pt),\"placement\":\"top\",\"open-delay\":80}},[_c('img',{staticClass:\"paytype-icon\",attrs:{\"src\":_vm.getPayImage(pt),\"alt\":_vm.formatPayTypeHead(pt)}})])}),1)]):_vm._e(),(_vm.listParams.type === 0 && _vm.payTypes && _vm.payTypes.length)?_c('div',{staticClass:\"price-select-bar\",staticStyle:{\"margin\":\"8px 0 4px\",\"display\":\"flex\",\"justify-content\":\"flex-end\",\"align-items\":\"center\"}},[_c('span',{staticStyle:{\"margin-right\":\"8px\",\"color\":\"#606266\",\"font-size\":\"14px\"}},[_vm._v(\"筛选售价:\")]),_c('el-select',{staticStyle:{\"width\":\"220px\"},attrs:{\"size\":\"small\",\"placeholder\":\"选择价格展示币种\"},on:{\"change\":_vm.handlePayTypeChange},model:{value:(_vm.selectedPayKey),callback:function ($$v) {_vm.selectedPayKey=$$v},expression:\"selectedPayKey\"}},[_c('template',{slot:\"prefix\"},[(_vm.getSelectedPayImage())?_c('img',{staticClass:\"paytype-icon\",staticStyle:{\"width\":\"16px\",\"height\":\"16px\",\"border-radius\":\"3px\",\"margin-right\":\"6px\"},attrs:{\"src\":_vm.getSelectedPayImage()}}):_vm._e()]),_vm._l((_vm.payTypes),function(pt,idx){return _c('el-option',{key:'pt-opt-top-' + idx,attrs:{\"label\":_vm.formatPayTypeHead(pt),\"value\":_vm.buildPayKey(pt)}},[_c('span',{staticStyle:{\"display\":\"inline-flex\",\"align-items\":\"center\",\"gap\":\"6px\"}},[_c('img',{staticClass:\"paytype-icon\",attrs:{\"src\":_vm.getPayImage(pt)}}),_c('span',[_vm._v(_vm._s(_vm.formatPayTypeHead(pt)))])])])})],2)],1):_vm._e(),(_vm.listParams.type === 0)?_c('el-table',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],key:'asic-table',staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.shopMachineList || [],\"border\":\"\",\"stripe\":\"\"}},[_c('el-table-column',{attrs:{\"label\":\"矿机类型\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":scope.row.type == 0 ? 'warning' : 'success'}},[_vm._v(\" \"+_vm._s(scope.row.type == 0 ? 'ASIC' : 'GPU')+\" \")])]}}],null,false,1255276155)}),_c('el-table-column',{attrs:{\"label\":\"币种\",\"min-width\":\"140\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"ellipsis-cell\"},[_vm._v(_vm._s(_vm.getRowCoinText(scope.row)))])]}}],null,false,3296547820)}),_c('el-table-column',{attrs:{\"label\":\"算法\",\"min-width\":\"160\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"ellipsis-cell\"},[_vm._v(_vm._s(_vm.getRowAlgorithmText(scope.row)))])]}}],null,false,1057179176)}),_c('el-table-column',{attrs:{\"prop\":\"name\",\"label\":\"矿机型号\"}}),_c('el-table-column',{attrs:{\"label\":\"理论算力\",\"min-width\":\"170\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"ellipsis-cell\"},[_vm._v(_vm._s(_vm.getTheoryText(scope.row)))])]}}],null,false,4122576080)}),_c('el-table-column',{attrs:{\"label\":\"功耗(kw/h)\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(_vm.getPowerDissText(scope.row)))])]}}],null,false,2386465872)}),_c('el-table-column',{attrs:{\"prop\":\"saleNumbers\",\"label\":\"总机器数量\"}}),_c('el-table-column',{attrs:{\"prop\":\"saleOutNumbers\",\"label\":\"已售数量\"}}),_c('el-table-column',{attrs:{\"prop\":\"maxLeaseDays\",\"label\":\"最大租赁天数\"}}),_c('el-table-column',{scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[_vm._v(_vm._s(_vm.getRowPriceText(scope.row)))])]}}],null,false,1822165360)},[_c('template',{slot:\"header\"},[_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"8px\"}},[_c('span',[_vm._v(\"售价\")])])])],2),_c('el-table-column',{attrs:{\"label\":\"状态\",\"width\":\"80\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":scope.row.state === 0 ? 'success' : 'info'}},[_vm._v(\" \"+_vm._s(scope.row.state === 0 ? '上架' : '下架')+\" \")])]}}],null,false,4131197732)}),_c('el-table-column',{attrs:{\"label\":\"操作\",\"fixed\":\"right\",\"width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.handleEdit(scope.row)}}},[_vm._v(\"修改\")]),_c('el-button',{staticStyle:{\"color\":\"#f56c6c\"},attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.handleDelete(scope.row)}}},[_vm._v(\"删除\")])]}}],null,false,198470154)})],1):_c('el-table',{key:'gpu-table-' + String(_vm.listParams.type),staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.shopMachineList || [],\"border\":\"\",\"stripe\":\"\"}},[_c('el-table-column',{attrs:{\"label\":\"矿机类型\",\"width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":scope.row.type == 1 ? 'success' : 'warning'}},[_vm._v(\" \"+_vm._s(scope.row.type == 1 ? 'GPU' : 'ASIC')+\" \")])]}}])}),_c('el-table-column',{attrs:{\"prop\":\"miner\",\"label\":\"矿机编号\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.miner || '-'))])]}}])}),_c('el-table-column',{attrs:{\"prop\":\"name\",\"label\":\"显卡型号\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.name || '-'))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"状态\",\"width\":\"180\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"gpu-state\"},[_c('el-switch',{attrs:{\"active-value\":0,\"inactive-value\":1,\"value\":(_vm.updateMap[_vm.getRowId(scope.row)] && _vm.updateMap[_vm.getRowId(scope.row)].state) != null ? _vm.updateMap[_vm.getRowId(scope.row)].state : 1},on:{\"change\":function($event){return _vm.handleToggleState(scope.row, $event)}}}),_c('span',{staticClass:\"gpu-state-text\",class:{ on: ((_vm.updateMap[_vm.getRowId(scope.row)] && _vm.updateMap[_vm.getRowId(scope.row)].state) === 0) }},[_vm._v(\" \"+_vm._s(((_vm.updateMap[_vm.getRowId(scope.row)] && _vm.updateMap[_vm.getRowId(scope.row)].state) === 0) ? '上架' : '下架')+\" \")])],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"售价\",\"min-width\":\"300\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('div',{staticClass:\"gpu-price-row\"},_vm._l((_vm.payTypes),function(pt,idx){return _c('div',{key:idx,staticClass:\"gpu-price-item\"},[_c('span',{staticClass:\"gpu-price-label\"},[_vm._v(_vm._s(_vm.formatPayTypeHead(pt)))]),_c('el-input',{staticClass:\"gpu-price-input\",attrs:{\"size\":\"small\",\"value\":_vm.getPriceValue(_vm.getRowId(scope.row), pt),\"placeholder\":\"价格\"},on:{\"input\":function($event){return _vm.handlePriceInput(scope.row, pt, $event)},\"blur\":function($event){return _vm.handlePriceBlur(scope.row, pt)}}})],1)}),0)]}}])}),_c('el-table-column',{attrs:{\"label\":\"最大租赁天数\",\"width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{staticStyle:{\"width\":\"120px\"},attrs:{\"size\":\"small\",\"value\":String((_vm.updateMap[_vm.getRowId(scope.row)] && _vm.updateMap[_vm.getRowId(scope.row)].maxLeaseDays) || ''),\"placeholder\":\"1-365\"},on:{\"input\":function($event){return _vm.handleMaxLeaseDaysInput(scope.row, $event)}}})]}}])}),_c('el-table-column',{attrs:{\"label\":\"操作\",\"fixed\":\"right\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-button',{staticStyle:{\"color\":\"#f56c6c\"},attrs:{\"type\":\"text\",\"size\":\"small\"},on:{\"click\":function($event){return _vm.handleDelete(scope.row)}}},[_vm._v(\"删除\")])]}}])})],1),(_vm.listParams.type === 0)?_c('div',{staticClass:\"pagination\"},[_c('el-pagination',{attrs:{\"background\":\"\",\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total,\"current-page\":_vm.pagination.pageNum,\"page-sizes\":[10, 20, 50, 100],\"page-size\":_vm.pagination.pageSize},on:{\"update:currentPage\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:current-page\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:pageSize\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"update:page-size\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange}})],1):_c('div',{staticStyle:{\"margin-top\":\"12px\",\"display\":\"flex\",\"justify-content\":\"space-between\",\"align-items\":\"center\"}},[_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleUpdateGpu}},[_vm._v(\"更新商品信息\")]),_c('el-pagination',{attrs:{\"background\":\"\",\"layout\":\"total, sizes, prev, pager, next, jumper\",\"total\":_vm.total,\"current-page\":_vm.pagination.pageNum,\"page-sizes\":[10, 20, 50, 100],\"page-size\":_vm.pagination.pageSize},on:{\"update:currentPage\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:current-page\":function($event){return _vm.$set(_vm.pagination, \"pageNum\", $event)},\"update:pageSize\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"update:page-size\":function($event){return _vm.$set(_vm.pagination, \"pageSize\", $event)},\"size-change\":_vm.handleSizeChange,\"current-change\":_vm.handleCurrentChange}})],1),_c('el-dialog',{attrs:{\"visible\":_vm.editDialog.visible,\"close-on-click-modal\":false,\"width\":\"70VW\",\"title\":'编辑商品 - ' + ((_vm.editDialog.form && _vm.editDialog.form.name) ? _vm.editDialog.form.name : '')},on:{\"update:visible\":function($event){return _vm.$set(_vm.editDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{on:{\"click\":function($event){_vm.editDialog.visible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.editDialog.saving},on:{\"click\":_vm.handleSaveEdit}},[_vm._v(\"确认修改\")])]},proxy:true}])},[(_vm.editDialog.form)?_c('el-form',{ref:\"editForm\",staticClass:\"edit-form\",attrs:{\"model\":_vm.editDialog.form,\"label-width\":\"160px\"}},[_c('el-form-item',{attrs:{\"label\":\"矿机型号\"}},[_c('el-input',{attrs:{\"maxlength\":\"60\"},model:{value:(_vm.editDialog.form.name),callback:function ($$v) {_vm.$set(_vm.editDialog.form, \"name\", (typeof $$v === 'string'? $$v.trim(): $$v))},expression:\"editDialog.form.name\"}})],1),_c('el-form-item',{attrs:{\"label\":\"币种/算法/算力/单位\"}},[_c('div',{staticClass:\"coin-algo-rows\"},_vm._l((_vm.editDialog.form.coinAndAlgoList),function(row,idx){return _c('div',{key:'edit-ca-' + idx,staticClass:\"coin-algo-line\"},[_c('el-select',{staticClass:\"coin-input\",attrs:{\"placeholder\":\"请选择币种\",\"loading\":_vm.loadingCoins,\"filterable\":\"\",\"clearable\":\"\"},on:{\"change\":function($event){return _vm.editHandleCoinChange(idx, $event)}},model:{value:(row.coin),callback:function ($$v) {_vm.$set(row, \"coin\", $$v)},expression:\"row.coin\"}},_vm._l((_vm.coinOptions),function(coin){return _c('el-option',{key:coin,attrs:{\"label\":coin,\"value\":coin}})}),1),_c('el-select',{staticClass:\"algo-input\",attrs:{\"placeholder\":\"请选择算法\",\"loading\":_vm.loadingAlgos[idx],\"disabled\":!row.coin,\"filterable\":\"\",\"clearable\":\"\"},model:{value:(row.algorithm),callback:function ($$v) {_vm.$set(row, \"algorithm\", $$v)},expression:\"row.algorithm\"}},_vm._l(((_vm.algoOptionsMap[row.coin] || [])),function(algo){return _c('el-option',{key:algo,attrs:{\"label\":algo,\"value\":algo}})}),1),_c('el-input',{staticClass:\"power-input\",attrs:{\"placeholder\":\"理论算力\",\"inputmode\":\"decimal\"},on:{\"input\":function($event){return _vm.editHandleRowTheoryInput(idx)}},model:{value:(row.theoryPower),callback:function ($$v) {_vm.$set(row, \"theoryPower\", $$v)},expression:\"row.theoryPower\"}}),_c('el-select',{staticClass:\"unit-select\",attrs:{\"placeholder\":\"单位\"},on:{\"change\":function($event){return _vm.editHandleRowUnitChange(idx, $event)}},model:{value:(row.unit),callback:function ($$v) {_vm.$set(row, \"unit\", $$v)},expression:\"row.unit\"}},[_c('el-option',{attrs:{\"label\":\"KH/S\",\"value\":\"KH/S\"}}),_c('el-option',{attrs:{\"label\":\"MH/S\",\"value\":\"MH/S\"}}),_c('el-option',{attrs:{\"label\":\"GH/S\",\"value\":\"GH/S\"}}),_c('el-option',{attrs:{\"label\":\"TH/S\",\"value\":\"TH/S\"}}),_c('el-option',{attrs:{\"label\":\"PH/S\",\"value\":\"PH/S\"}})],1),_c('el-button',{staticClass:\"op-btn\",attrs:{\"type\":\"primary\",\"icon\":\"el-icon-plus\",\"circle\":\"\",\"aria-label\":'新增一行'},on:{\"click\":_vm.editHandleAddRow}}),((_vm.editDialog.form.coinAndAlgoList || []).length > 1)?_c('el-button',{staticClass:\"op-btn\",attrs:{\"icon\":\"el-icon-minus\",\"circle\":\"\",\"aria-label\":'删除该行'},on:{\"click\":function($event){return _vm.editHandleRemoveRow(idx)}}}):_vm._e()],1)}),0)]),_c('el-form-item',{attrs:{\"label\":\"最大租赁天数\"}},[_c('el-input',{staticStyle:{\"width\":\"200px\"},attrs:{\"placeholder\":\"1-365\"},on:{\"input\":function($event){_vm.editDialog.form.maxLeaseDays = (String(_vm.editDialog.form.maxLeaseDays||'').replace(/[^\\d]/g,''))}},model:{value:(_vm.editDialog.form.maxLeaseDays),callback:function ($$v) {_vm.$set(_vm.editDialog.form, \"maxLeaseDays\", $$v)},expression:\"editDialog.form.maxLeaseDays\"}})],1),_c('el-form-item',{staticClass:\"align-like-input\",attrs:{\"label\":\"状态\"}},[_c('el-radio-group',{model:{value:(_vm.editDialog.form.state),callback:function ($$v) {_vm.$set(_vm.editDialog.form, \"state\", $$v)},expression:\"editDialog.form.state\"}},[_c('el-radio',{attrs:{\"label\":0}},[_vm._v(\"上架\")]),_c('el-radio',{attrs:{\"label\":1}},[_vm._v(\"下架\")])],1)],1),_c('el-form-item',{attrs:{\"label\":\"功耗(kw/h)\"}},[_c('el-input',{staticStyle:{\"width\":\"200px\"},attrs:{\"type\":\"number\",\"min\":\"0\",\"step\":\"0.00000001\",\"inputmode\":\"decimal\",\"placeholder\":\"功耗\"},on:{\"input\":function($event){_vm.editDialog.form.powerDissipation = _vm.normalizePowerInput(_vm.editDialog.form.powerDissipation)}},model:{value:(_vm.editDialog.form.powerDissipation),callback:function ($$v) {_vm.$set(_vm.editDialog.form, \"powerDissipation\", $$v)},expression:\"editDialog.form.powerDissipation\"}})],1),_c('el-form-item',{attrs:{\"label\":\"出售数量(台)\"}},[_c('el-input',{staticStyle:{\"width\":\"200px\"},attrs:{\"placeholder\":\"整数\"},on:{\"input\":function($event){_vm.editDialog.form.saleNumbers = _vm.normalizeSaleNumbersInput(_vm.editDialog.form.saleNumbers)}},model:{value:(_vm.editDialog.form.saleNumbers),callback:function ($$v) {_vm.$set(_vm.editDialog.form, \"saleNumbers\", $$v)},expression:\"editDialog.form.saleNumbers\"}})],1),_c('el-form-item',{attrs:{\"label\":\"售价(多币种)\"}},[_c('div',{staticClass:\"gpu-price-row\"},_vm._l((_vm.editDialog.priceList),function(pl,idx){return _c('div',{key:'ep-' + idx,staticClass:\"gpu-price-item\"},[_c('span',{staticClass:\"gpu-price-label\"},[_vm._v(_vm._s(_vm.formatPayTypeHead(pl)))]),_c('el-input',{staticClass:\"gpu-price-input\",attrs:{\"size\":\"small\",\"value\":pl.price,\"placeholder\":\"价格\"},on:{\"input\":function($event){return _vm.handleEditPriceInput(idx, $event)}}})],1)}),0)])],1):_vm._e()],1)],1)\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"left-area\"},[_c('h2',{staticClass:\"page-title\"},[_vm._v(\"商品列表\")])])\n}]\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"panel\"},[_c('h2',{staticClass:\"panel-title page-title\"},[_vm._v(\"钱包绑定\")]),_c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"panel-body\"},[_c('el-form',{staticClass:\"config-form\",attrs:{\"model\":_vm.form,\"label-width\":\"120px\"}},[_c('el-form-item',{attrs:{\"label\":\"选择链/币种\"}},[_c('el-cascader',{staticStyle:{\"width\":\"420px\"},attrs:{\"options\":_vm.options,\"props\":_vm.cascaderProps,\"show-all-levels\":false,\"clearable\":\"\",\"filterable\":\"\"},on:{\"change\":_vm.handleChange,\"expand-change\":_vm.handleExpandChange},scopedSlots:_vm._u([{key:\"default\",fn:function({ node, data }){return [_c('span',{staticClass:\"custom-node\",attrs:{\"aria-label\":\"cascader-item\",\"tabindex\":\"0\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.handleItemClick(node, data)}}},[_c('span',{staticClass:\"node-label\"},[_vm._v(_vm._s(data.label))]),(node.isLeaf && node.checked)?_c('span',{staticClass:\"leaf-checked\",attrs:{\"aria-hidden\":\"true\"}},[_vm._v(\"✓\")]):_vm._e()])]}}]),model:{value:(_vm.value),callback:function ($$v) {_vm.value=$$v},expression:\"value\"}})],1),_c('el-form-item',{attrs:{\"label\":\"已选择币种\"}},[_c('div',{staticClass:\"selected-coins\",attrs:{\"aria-label\":\"selected-coins\",\"tabindex\":\"0\"}},[_vm._l((_vm.selectedCoins),function(coin){return _c('el-tag',{key:coin,attrs:{\"type\":\"warning\",\"effect\":\"light\",\"closable\":\"\",\"disable-transitions\":\"\"},on:{\"close\":function($event){return _vm.handleRemoveSelectedCoin(coin)}}},[_vm._v(\" \"+_vm._s(coin)+\" \")])}),(_vm.selectedCoins.length === 0)?_c('span',{staticClass:\"placeholder\"},[_vm._v(\"未选择\")]):_vm._e()],2)]),_c('el-form-item',{attrs:{\"label\":\"收款钱包地址\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入\"},model:{value:(_vm.form.payAddress),callback:function ($$v) {_vm.$set(_vm.form, \"payAddress\", $$v)},expression:\"form.payAddress\"}})],1),_c('el-form-item',[_c('el-button',{staticStyle:{\"width\":\"200px\"},attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleSave}},[_vm._v(\"确认绑定\")])],1)],1),_c('el-dialog',{attrs:{\"visible\":_vm.preCheck.visible,\"width\":\"80vw\",\"close-on-click-modal\":false,\"title\":\"检测到关联商品\"},on:{\"update:visible\":function($event){return _vm.$set(_vm.preCheck, \"visible\", $event)},\"close\":_vm.handlePreCheckClose},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{on:{\"click\":function($event){_vm.preCheck.visible = false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"disabled\":!_vm.canSubmitPreCheck},on:{\"click\":_vm.handleConfirmBindAfterPreview}},[_vm._v(\"继续绑定\")])]},proxy:true}])},[_c('div',{staticStyle:{\"margin-bottom\":\"10px\"}},[_c('el-alert',{attrs:{\"type\":\"warning\",\"closable\":false,\"show-icon\":\"\",\"description\":\"检测到以下商品与本次绑定的链/币相关。继续绑定后,可能需要为这些商品配置该新链下的价格。是否继续?\"}})],1),_c('p',{staticStyle:{\"color\":\"red\",\"font-size\":\"12px\",\"margin-top\":\"6px\",\"text-align\":\"right\"}},[_vm._v(\"* 请填写每个商品对应币种的价格,商品包含机器统一设置价格,如需单台修改请在商品列表-详情页操作\")]),_c('el-table',{attrs:{\"data\":_vm.preCheck.rows,\"height\":\"360\",\"border\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"label\":\"商品类型\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(Number(scope.row.type) === 0 ? 'ASIC' : (Number(scope.row.type) === 1 ? 'GPU' : '-')))]}}])}),_c('el-table-column',{attrs:{\"label\":\"矿工账号\",\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row.user || '-'))]}}])}),_c('el-table-column',{attrs:{\"label\":\"矿机编号\",\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row.miner || '-'))]}}])}),_c('el-table-column',{attrs:{\"label\":\"链\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(){return [_vm._v(\" \"+_vm._s((_vm.form.chain || '').toUpperCase())+\" \")]},proxy:true}])}),_c('el-table-column',{attrs:{\"label\":\"币种\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(){return [_vm._v(\" \"+_vm._s(_vm.form.payCoin.split(',').map(s=>s.trim().toUpperCase()).join(','))+\" \")]},proxy:true}])}),_c('el-table-column',{attrs:{\"label\":\"商品状态\",\"min-width\":\"100\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(Number(scope.row.state) === 1 ? '下架' : '上架'))]}}])}),_vm._l((_vm.coinsForBind),function(sym){return _c('el-table-column',{key:'price-'+sym,attrs:{\"label\":sym + ' 价格',\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{staticClass:\"price-input\",attrs:{\"size\":\"mini\",\"placeholder\":\"请输入\",\"inputmode\":\"decimal\"},scopedSlots:_vm._u([{key:\"append\",fn:function(){return [_vm._v(_vm._s(sym))]},proxy:true}],null,true),model:{value:(_vm.preCheck.rowPrices[_vm.getRowKey(scope.row, scope.$index)][sym]),callback:function ($$v) {_vm.$set(_vm.preCheck.rowPrices[_vm.getRowKey(scope.row, scope.$index)], sym, $$v)},expression:\"preCheck.rowPrices[getRowKey(scope.row, scope.$index)][sym]\"}})]}}],null,true)})})],2)],1)],1)])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import { getShopList } from '../../api/products'\nexport default {\n name: 'ProductList',\n data() {\n return {\n products: [\n // {\n // id: 1,\n // name: \"Nexa\",\n // price: `10000~20000`,\n // image: \"https://img.yzcdn.cn/vant/apple-1.jpg\",\n // desc: \"NexaPow\",\n // },\n // {\n // id: 2,\n // name: \"grs\",\n // price: `10000~20000`,\n // image: \"https://img.yzcdn.cn/vant/apple-1.jpg\",\n // desc: \"groestl\",\n // },\n // {\n // id: 3,\n // name: \"mona\",\n // price: `10000~20000`,\n // image: \"https://img.yzcdn.cn/vant/apple-1.jpg\",\n // desc: \"Lyra2REv2\",\n // },\n // {\n // id: 4,\n // name: \"dgb\",\n // price: `10000~20000`,\n // image: \"https://img.yzcdn.cn/vant/apple-1.jpg\",\n // desc: \"DigiByte(Skein)\",\n // },\n ],\n loading: false,\n powerList: [\n // {\n // value: 1,\n // label: \"NexaPow\",\n // children: [\n // {\n // value: 1 - 1,\n // label: \"挖矿账户1\",\n // },\n // {\n // value: 1 - 2,\n // label: \"挖矿账户2\",\n // },\n // ],\n // },\n // {\n // value: 2,\n // label: \"Grepow\",\n // children: [\n // {\n // value: 2 - 1,\n // label: \"挖矿账户1\",\n // },\n // {\n // value: 2 - 2,\n // label: \"挖矿账户2\",\n // },\n // ],\n // },\n // {\n // value: 3,\n // label: \"mofang\",\n // children: [\n // {\n // value: 3 - 1,\n // label: \"挖矿账户1\",\n // },\n // ],\n // },\n ], \n currencyList: [\n {\n path: \"nexaAccess\",\n value: \"nexa\",\n label: \"nexa\",\n\n imgUrl: `https://m2pool.com/img/nexa.png`,\n name: \"course.NEXAcourse\",\n show: true,\n amount: 10000,\n },\n {\n path: \"grsAccess\",\n value: \"grs\",\n label: \"grs\",\n\n imgUrl: `https://m2pool.com/img/grs.svg`,\n name: \"course.GRScourse\",\n show: true,\n amount: 1,\n },\n {\n path: \"monaAccess\",\n value: \"mona\",\n label: \"mona\",\n\n imgUrl: `https://m2pool.com/img/mona.svg`,\n name: \"course.MONAcourse\",\n show: true,\n amount: 1,\n },\n {\n path: \"dgbsAccess\",\n value: \"dgbs\",\n // label: \"dgb-skein-pool1\",\n label: \"dgb(skein)\",\n\n imgUrl: `https://m2pool.com/img/dgb.svg`,\n name: \"course.dgbsCourse\",\n show: true,\n amount: 1,\n },\n {\n path: \"dgbqAccess\",\n value: \"dgbq\",\n // label: \"dgb(qubit-pool1)\",\n label: \"dgb(qubit)\",\n\n imgUrl: `https://m2pool.com/img/dgb.svg`,\n name: \"course.dgbqCourse\",\n show: true,\n amount: 1,\n },\n {\n path: \"dgboAccess\",\n value: \"dgbo\",\n // label: \"dgb-odocrypt-pool1\",\n label: \"dgb(odocrypt)\",\n\n imgUrl: `https://m2pool.com/img/dgb.svg`,\n name: \"course.dgboCourse\",\n show: true,\n amount: 1,\n },\n {\n path: \"rxdAccess\",\n value: \"rxd\",\n label: \"radiant(rxd)\",\n\n imgUrl: `https://m2pool.com/img/rxd.png`,\n name: \"course.RXDcourse\",\n show: true,\n amount: 100,\n },\n {\n path: \"enxAccess\",\n value: \"enx\",\n label: \"Entropyx(enx)\",\n\n imgUrl: `https://m2pool.com/img/enx.svg`,\n name: \"course.ENXcourse\",\n show: true,\n amount: 5000,\n },\n {\n path: \"alphminingPool\",\n value: \"alph\",\n label: \"alephium\",\n\n imgUrl: `https://m2pool.com/img/alph.svg`,\n name: \"course.alphCourse\",\n show: true,\n amount: 1,\n },\n ],\n screenCurrency: \"\",\n searchAlgorithm: \"\",\n params:{\n pageNum: \"1\",\n pageSize: \"10\",\n keyword:\"\"\n },\n productListLoading:false,\n }\n },\n mounted() {\n this.fetchShopList()\n },\n methods: {\n // 获取商场页面的店铺列表\n async fetchShopList(params) {\n this.productListLoading = true\n try{\n // 仅允许 pageNum、pageSize、keyword 三个参数\n const payload = {\n pageNum: this.params.pageNum,\n pageSize: this.params.pageSize\n }\n const kw = params && typeof params === 'object' ? params.keyword : this.params.keyword\n if (kw) payload.keyword = kw\n const res = await getShopList(payload)\n if (res && (res.code === 0 || res.code === 200)) {\n // 这里直接将店铺列表赋值到 products,用于页面渲染\n this.products = Array.isArray(res.rows) ? res.rows : []\n } else {\n this.products = []\n }\n }catch(e){\n console.error('获取店铺列表失败:', e)\n this.products = []\n }\n this.productListLoading = false\n },\n \n // 算法搜索(使用同一接口,传入 algorithm 参数)\n handleAlgorithmSearch() {\n const keyword = (this.searchAlgorithm || '').trim()\n this.params.keyword = keyword\n this.fetchShopList(keyword ? { keyword } : undefined)\n \n },\n // 清空搜索关键字\n handleAlgorithmClear() {\n this.searchAlgorithm = \"\"\n this.params.keyword = \"\"\n this.fetchShopList()\n },\n handleProductClick(product) {\n\n const id = (product && (product.shopId != null ? product.shopId : product.id)) \n if (id !== undefined && id !== null) {\n this.$router.push(`/product/${id}`); \n } \n\n \n },\n\n\n\n }\n}","import { render, staticRenderFns } from \"./App.vue?vue&type=template&id=662f903c\"\nvar script = {}\nimport style0 from \"./App.vue?vue&type=style&index=0&id=662f903c&prod&lang=scss\"\n\n\n/* normalize component */\nimport normalizer from \"!../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\nexport default component.exports","export const coinList = [\r\n {\r\n path: \"nexaAccess\",\r\n value: \"nexa\",\r\n label: \"nexa\",\r\n\r\n imgUrl: `https://m2pool.com/img/nexa.png`,\r\n name: \"course.NEXAcourse\",\r\n show: true,\r\n amount: 10000,\r\n },\r\n {\r\n path: \"grsAccess\",\r\n value: \"grs\",\r\n label: \"grs\",\r\n\r\n imgUrl: `https://m2pool.com/img/grs.svg`,\r\n name: \"course.GRScourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n {\r\n path: \"monaAccess\",\r\n value: \"mona\",\r\n label: \"mona\",\r\n\r\n imgUrl: `https://m2pool.com/img/mona.svg`,\r\n name: \"course.MONAcourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n {\r\n path: \"dgbsAccess\",\r\n value: \"dgbs\",\r\n // label: \"dgb-skein-pool1\",\r\n label: \"dgb(skein)\",\r\n\r\n imgUrl: `https://m2pool.com/img/dgb.svg`,\r\n name: \"course.dgbsCourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n {\r\n path: \"dgbqAccess\",\r\n value: \"dgbq\",\r\n // label: \"dgb(qubit-pool1)\",\r\n label: \"dgb(qubit)\",\r\n\r\n imgUrl: `https://m2pool.com/img/dgb.svg`,\r\n name: \"course.dgbqCourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n {\r\n path: \"dgboAccess\",\r\n value: \"dgbo\",\r\n // label: \"dgb-odocrypt-pool1\",\r\n label: \"dgb(odocrypt)\",\r\n\r\n imgUrl: `https://m2pool.com/img/dgb.svg`,\r\n name: \"course.dgboCourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n {\r\n path: \"rxdAccess\",\r\n value: \"rxd\",\r\n label: \"radiant(rxd)\",\r\n\r\n imgUrl: `https://m2pool.com/img/rxd.png`,\r\n name: \"course.RXDcourse\",\r\n show: true,\r\n amount: 100,\r\n },\r\n {\r\n path: \"enxAccess\",\r\n value: \"enx\",\r\n label: \"Entropyx(enx)\",\r\n\r\n imgUrl: `https://m2pool.com/img/enx.svg`,\r\n name: \"course.ENXcourse\",\r\n show: true,\r\n amount: 5000,\r\n },\r\n {\r\n path: \"alphminingPool\",\r\n value: \"alph\",\r\n label: \"alephium\",\r\n\r\n imgUrl: `https://m2pool.com/img/alph.svg`,\r\n name: \"course.alphCourse\",\r\n show: true,\r\n amount: 1,\r\n },\r\n ]","import mod from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./productNew.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../node_modules/thread-loader/dist/cjs.js!../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-40.use[1]!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/index.js??vue-loader-options!./productNew.vue?vue&type=script&lang=js\"","import { render, staticRenderFns } from \"./productNew.vue?vue&type=template&id=538996de&scoped=true\"\nimport script from \"./productNew.vue?vue&type=script&lang=js\"\nexport * from \"./productNew.vue?vue&type=script&lang=js\"\nimport style0 from \"./productNew.vue?vue&type=style&index=0&id=538996de&prod&scoped=true&lang=css\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../node_modules/@vue/cli-service/node_modules/@vue/vue-loader-v15/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"538996de\",\n null\n \n)\n\nexport default component.exports","import Vue from 'vue'\nimport VueRouter from 'vue-router'\nimport { mainRoutes } from './routes'\n\nVue.use(VueRouter)\n\nconst router = new VueRouter({\n mode: 'history',\n base: process.env.BASE_URL,\n routes: mainRoutes\n})\n\n// 路由守卫 - 设置页面标题和权限检查\nrouter.beforeEach((to, from, next) => {\n // 设置页面标题\n if (to.meta && to.meta.title) {\n document.title = `${to.meta.title} - Power Leasing`\n } else {\n document.title = 'Power Leasing - 电商系统'\n }\n \n // 检查权限\n if (to.meta && to.meta.allAuthority) {\n // 这里可以添加权限检查逻辑\n // 目前所有页面都是 ['all'] 权限,所以直接通过\n console.log(`访问页面: ${to.meta.title}, 权限: ${to.meta.allAuthority.join(', ')}`)\n }\n \n next()\n})\n\n// 路由错误处理\nrouter.onError((error) => {\n console.error('路由错误:', error)\n // 可以在这里添加错误处理逻辑,比如跳转到错误页面\n})\n\nexport default router\n","export default {\r\n '401': '认证失败,无法访问系统资源,请重新登录',\r\n '403': '当前操作没有权限',\r\n '404': '访问资源不存在',\r\n 'default': '系统未知错误,请反馈给管理员'\r\n}\r\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-container\"},[_vm._m(0),_c('div',{staticClass:\"auth-card\"},[_c('div',{staticClass:\"close-btn\",attrs:{\"title\":\"返回商城\"},on:{\"click\":_vm.goToShop}},[_c('i',{staticClass:\"el-icon-close\"})]),_vm._m(1),_c('el-form',{ref:\"resetForm\",staticClass:\"auth-form\",attrs:{\"model\":_vm.resetForm,\"rules\":_vm.resetRules},nativeOn:{\"submit\":function($event){$event.preventDefault();return _vm.handleReset.apply(null, arguments)}}},[_c('el-form-item',{attrs:{\"prop\":\"email\"}},[_c('el-input',{attrs:{\"placeholder\":\"请输入注册时的邮箱\",\"prefix-icon\":\"el-icon-message\",\"size\":\"large\",\"clearable\":\"\"},model:{value:(_vm.resetForm.email),callback:function ($$v) {_vm.$set(_vm.resetForm, \"email\", $$v)},expression:\"resetForm.email\"}})],1),_c('el-form-item',{attrs:{\"prop\":\"code\"}},[_c('div',{staticClass:\"code-input-wrapper\"},[_c('el-input',{attrs:{\"placeholder\":\"请输入邮箱验证码\",\"prefix-icon\":\"el-icon-key\",\"size\":\"large\",\"maxlength\":\"10\",\"clearable\":\"\"},on:{\"change\":_vm.handleEmailChange},model:{value:(_vm.resetForm.code),callback:function ($$v) {_vm.$set(_vm.resetForm, \"code\", $$v)},expression:\"resetForm.code\"}}),_c('el-button',{staticClass:\"send-code-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"disabled\":_vm.countdown > 0,\"loading\":_vm.sendingCode},on:{\"click\":_vm.handleSendCode}},[_vm._v(\" \"+_vm._s(_vm.countdown > 0 ? `${_vm.countdown}秒后重试` : '获取验证码')+\" \")])],1)]),_c('el-form-item',{attrs:{\"prop\":\"password\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请输入新密码(8-32位)\",\"prefix-icon\":\"el-icon-lock\",\"size\":\"large\",\"show-password\":\"\",\"clearable\":\"\"},model:{value:(_vm.resetForm.password),callback:function ($$v) {_vm.$set(_vm.resetForm, \"password\", $$v)},expression:\"resetForm.password\"}}),_c('div',{staticClass:\"password-tip\"},[_c('i',{staticClass:\"el-icon-info\"}),_c('span',[_vm._v(\"密码需包含大小写字母、数字和特殊字符,长度8-32位\")])]),(_vm.resetForm.password)?_c('div',{staticClass:\"password-strength\"},[_c('span',{staticClass:\"strength-label\"},[_vm._v(\"密码强度:\")]),_c('span',{class:['strength-bar', _vm.passwordStrengthClass]},[_vm._v(\" \"+_vm._s(_vm.passwordStrengthText)+\" \")])]):_vm._e()],1),_c('el-form-item',{attrs:{\"prop\":\"confirmPassword\"}},[_c('el-input',{attrs:{\"type\":\"password\",\"placeholder\":\"请再次输入新密码\",\"prefix-icon\":\"el-icon-lock\",\"size\":\"large\",\"show-password\":\"\",\"clearable\":\"\"},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleReset.apply(null, arguments)}},model:{value:(_vm.resetForm.confirmPassword),callback:function ($$v) {_vm.$set(_vm.resetForm, \"confirmPassword\", $$v)},expression:\"resetForm.confirmPassword\"}})],1),_c('el-form-item',[_c('el-button',{staticClass:\"auth-submit-btn\",attrs:{\"type\":\"primary\",\"size\":\"large\",\"loading\":_vm.loading},on:{\"click\":_vm.handleReset}},[_vm._v(\" \"+_vm._s(_vm.loading ? '重置中...' : '确认重置')+\" \")])],1),_c('div',{staticClass:\"auth-footer\"},[_c('router-link',{staticClass:\"link-text link-primary\",attrs:{\"to\":\"/login\"}},[_c('i',{staticClass:\"el-icon-back\"}),_vm._v(\" 返回登录 \")])],1)],1)],1)])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-background\"},[_c('div',{staticClass:\"bg-circle circle-1\"}),_c('div',{staticClass:\"bg-circle circle-2\"}),_c('div',{staticClass:\"bg-circle circle-3\"})])\n},function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"auth-header\"},[_c('h1',{staticClass:\"auth-title\"},[_vm._v(\"重置密码\")]),_c('p',{staticClass:\"auth-subtitle\"},[_vm._v(\"通过邮箱验证码重置您的密码\")])])\n}]\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"checkout-page\"},[_c('h1',{staticClass:\"page-title\"},[_vm._v(\"订单结算\")]),(_vm.loading)?_c('div',{staticClass:\"loading\"},[_c('el-loading-spinner'),_vm._v(\" 加载中... \")],1):(_vm.cartItems.length === 0)?_c('div',{staticClass:\"empty-cart\"},[_c('div',{staticClass:\"empty-icon\"},[_vm._v(\"🛒\")]),_c('h2',[_vm._v(\"购物车是空的\")]),_c('p',[_vm._v(\"请先添加商品到购物车\")]),_c('router-link',{staticClass:\"shop-now-btn\",attrs:{\"to\":\"/productList\"}},[_vm._v(\" 去购物 \")])],1):_c('div',{staticClass:\"checkout-content\"},[_c('div',{staticClass:\"order-summary\"},[_c('h2',{staticClass:\"section-title\"},[_vm._v(\"订单摘要\")]),_c('div',{staticClass:\"order-items\"},_vm._l((_vm.cartItems),function(item){return _c('div',{key:item.id,staticClass:\"order-item\"},[_c('div',{staticClass:\"item-image\"},[_c('img',{attrs:{\"src\":item.image,\"alt\":item.title}})]),_c('div',{staticClass:\"item-info\"},[_c('h3',{staticClass:\"item-title\"},[_vm._v(_vm._s(item.title))]),_c('div',{staticClass:\"item-price\"},[_vm._v(\"¥\"+_vm._s(item.price))])]),_c('div',{staticClass:\"item-quantity\"},[_c('span',{staticClass:\"quantity-label\"},[_vm._v(\"数量:\")]),_c('span',{staticClass:\"quantity-value\"},[_vm._v(_vm._s(item.quantity))])]),_c('div',{staticClass:\"item-total\"},[_c('span',{staticClass:\"total-label\"},[_vm._v(\"小计:\")]),_c('span',{staticClass:\"total-price\"},[_vm._v(\"¥\"+_vm._s((item.price * item.quantity).toFixed(2)))])])])}),0),_c('div',{staticClass:\"order-total\"},[_c('div',{staticClass:\"total-row\"},[_c('span',[_vm._v(\"商品总数:\")]),_c('span',[_vm._v(_vm._s(_vm.summary.totalQuantity)+\" 件\")])]),_c('div',{staticClass:\"total-row\"},[_c('span',[_vm._v(\"商品种类:\")]),_c('span',[_vm._v(_vm._s(_vm.cartItems.length)+\" 种\")])]),_c('div',{staticClass:\"total-row final-total\"},[_c('span',[_vm._v(\"订单总计:\")]),_c('span',{staticClass:\"final-amount\"},[_vm._v(\"¥\"+_vm._s(_vm.summary.totalPrice.toFixed(2)))])])])]),_c('div',{staticClass:\"checkout-form\"},[_c('h2',{staticClass:\"section-title\"},[_vm._v(\"收货信息\")]),_c('form',{staticClass:\"form\",on:{\"submit\":function($event){$event.preventDefault();return _vm.handleSubmit.apply(null, arguments)}}},[_c('div',{staticClass:\"form-row\"},[_c('div',{staticClass:\"form-group\"},[_c('label',{staticClass:\"form-label\",attrs:{\"for\":\"name\"}},[_vm._v(\"收货人姓名 *\")]),_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.form.name),expression:\"form.name\"}],staticClass:\"form-input\",attrs:{\"id\":\"name\",\"type\":\"text\",\"required\":\"\",\"placeholder\":\"请输入收货人姓名\",\"aria-describedby\":\"name-error\"},domProps:{\"value\":(_vm.form.name)},on:{\"input\":function($event){if($event.target.composing)return;_vm.$set(_vm.form, \"name\", $event.target.value)}}}),(_vm.errors.name)?_c('div',{staticClass:\"error-message\",attrs:{\"id\":\"name-error\"}},[_vm._v(\" \"+_vm._s(_vm.errors.name)+\" \")]):_vm._e()]),_c('div',{staticClass:\"form-group\"},[_c('label',{staticClass:\"form-label\",attrs:{\"for\":\"phone\"}},[_vm._v(\"联系电话 *\")]),_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.form.phone),expression:\"form.phone\"}],staticClass:\"form-input\",attrs:{\"id\":\"phone\",\"type\":\"tel\",\"required\":\"\",\"placeholder\":\"请输入联系电话\",\"aria-describedby\":\"phone-error\"},domProps:{\"value\":(_vm.form.phone)},on:{\"input\":function($event){if($event.target.composing)return;_vm.$set(_vm.form, \"phone\", $event.target.value)}}}),(_vm.errors.phone)?_c('div',{staticClass:\"error-message\",attrs:{\"id\":\"phone-error\"}},[_vm._v(\" \"+_vm._s(_vm.errors.phone)+\" \")]):_vm._e()])]),_c('div',{staticClass:\"form-group\"},[_c('label',{staticClass:\"form-label\",attrs:{\"for\":\"address\"}},[_vm._v(\"收货地址 *\")]),_c('textarea',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.form.address),expression:\"form.address\"}],staticClass:\"form-textarea\",attrs:{\"id\":\"address\",\"rows\":\"3\",\"required\":\"\",\"placeholder\":\"请输入详细收货地址\",\"aria-describedby\":\"address-error\"},domProps:{\"value\":(_vm.form.address)},on:{\"input\":function($event){if($event.target.composing)return;_vm.$set(_vm.form, \"address\", $event.target.value)}}}),(_vm.errors.address)?_c('div',{staticClass:\"error-message\",attrs:{\"id\":\"address-error\"}},[_vm._v(\" \"+_vm._s(_vm.errors.address)+\" \")]):_vm._e()]),_c('div',{staticClass:\"form-group\"},[_c('label',{staticClass:\"form-label\",attrs:{\"for\":\"note\"}},[_vm._v(\"备注\")]),_c('textarea',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.form.note),expression:\"form.note\"}],staticClass:\"form-textarea\",attrs:{\"id\":\"note\",\"rows\":\"2\",\"placeholder\":\"可选:订单备注信息\"},domProps:{\"value\":(_vm.form.note)},on:{\"input\":function($event){if($event.target.composing)return;_vm.$set(_vm.form, \"note\", $event.target.value)}}})]),_c('div',{staticClass:\"form-actions\"},[_c('router-link',{staticClass:\"back-btn\",attrs:{\"to\":\"/cart\"}},[_vm._v(\" 返回购物车 \")]),_c('button',{staticClass:\"submit-btn\",attrs:{\"type\":\"submit\",\"disabled\":_vm.submitting,\"aria-label\":\"提交订单\"}},[(_vm.submitting)?_c('span',[_vm._v(\"提交中...\")]):_c('span',[_vm._v(\"提交订单\")])])],1)])])])])\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"receipt-page\"},[_c('div',{staticClass:\"card\",attrs:{\"aria-label\":\"提现记录\",\"tabindex\":\"0\"}},[_vm._m(0),(_vm.loading)?_c('div',{staticClass:\"loading\"},[_c('i',{staticClass:\"el-icon-loading\",attrs:{\"aria-label\":\"加载中\",\"role\":\"img\"}}),_vm._v(\" 加载中... \")]):_c('div',[_c('div',{staticClass:\"table-wrap\"},[_c('el-table',{staticClass:\"withdraw-table\",attrs:{\"data\":_vm.rows,\"border\":\"\",\"stripe\":\"\",\"size\":\"small\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"label\":\"申请时间\",\"width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatFullTime(scope.row.createTime)))]}}])}),_c('el-table-column',{attrs:{\"label\":\"提现金额\",\"width\":\"70\",\"show-overflow-tooltip\":\"\",\"align\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"amount-red\"},[(_vm.formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').truncated)?_c('el-tooltip',{attrs:{\"content\":`-${_vm.formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').full}`,\"placement\":\"top\"}},[_c('span',[_vm._v(\" -\"+_vm._s(_vm.formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" -\"+_vm._s(_vm.formatAmount(scope.row.amount, scope.row.coin || scope.row.toSymbol || 'USDT').text)+\" \")])],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"手续费\",\"width\":\"70\",\"show-overflow-tooltip\":\"\",\"align\":\"right\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"mono\"},[_vm._v(_vm._s(_vm.formatAmount(scope.row.serviceCharge, scope.row.coin || scope.row.toSymbol || 'USDT').text))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"提现链\",\"width\":\"100\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatChain(scope.row.toChain || scope.row.chain)))]}}])}),_c('el-table-column',{attrs:{\"label\":\"币种\",\"width\":\"80\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(String(scope.row.coin || scope.row.toSymbol || '').toUpperCase()))]}}])}),_c('el-table-column',{attrs:{\"label\":\"收款地址\",\"min-width\":\"320\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tooltip',{attrs:{\"content\":scope.row.toAddress,\"placement\":\"top\"}},[_c('span',{staticClass:\"mono-ellipsis\"},[_vm._v(_vm._s(scope.row.toAddress))])]),_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.copy(scope.row.toAddress)}}},[_vm._v(\"复制\")])]}}])}),_c('el-table-column',{attrs:{\"label\":\"交易HASH\",\"width\":\"300\",\"show-overflow-tooltip\":\"\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tooltip',{attrs:{\"content\":scope.row.txHash,\"placement\":\"top\"}},[_c('span',{staticClass:\"mono-ellipsis\"},[_vm._v(_vm._s(scope.row.txHash))])]),(scope.row.txHash)?_c('el-button',{attrs:{\"type\":\"text\",\"size\":\"mini\"},on:{\"click\":function($event){$event.stopPropagation();return _vm.copy(scope.row.txHash)}}},[_vm._v(\"复制\")]):_vm._e()]}}])}),_c('el-table-column',{attrs:{\"label\":\"状态\",\"width\":\"90\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":_vm.getStatusType(scope.row.status),\"size\":\"small\"}},[_vm._v(_vm._s(_vm.getStatusText(scope.row.status)))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"状态更新时间\",\"width\":\"140\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(_vm.formatFullTime(scope.row.updateTime)))]}}])})],1)],1),(!_vm.rows.length)?_c('div',{staticClass:\"empty\"},[_c('div',{staticClass:\"empty-icon\"},[_vm._v(\"🏧\")]),_c('div',{staticClass:\"empty-text\"},[_vm._v(\"暂无提现记录\")])]):_vm._e(),_c('div',{staticClass:\"pagination\"},[_c('el-pagination',{attrs:{\"background\":\"\",\"layout\":\"prev, pager, next, jumper\",\"current-page\":_vm.pageNum,\"page-size\":_vm.pageSize,\"total\":_vm.total},on:{\"update:currentPage\":function($event){_vm.pageNum=$event},\"update:current-page\":function($event){_vm.pageNum=$event},\"current-change\":_vm.fetchList}})],1)])])])\n}\nvar staticRenderFns = [function (){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"card-header\"},[_c('h3',{staticClass:\"card-title\"},[_vm._v(\"提现记录\")])])\n}]\n\nexport { render, staticRenderFns }","\n\n\n\n\n\n\n","import request from '../utils/request'\n\n//商品列表\nexport function getList(data) {\n return request({\n url: `/lease/product/getList`,\n method: 'get',\n data\n })\n}\n\n//创建商品 新增商品\nexport function createProduct(data) {\n return request({\n url: `/lease/product/add`,\n method: 'post',\n data\n })\n}\n\n//获取商品列表\nexport function getProductList(data) {\n return request({\n url: `/lease/product/getList`,\n method: 'post',\n data\n })\n}\n\n// 更新商品\nexport function updateProduct(data) {\n return request({\n url: `/lease/product/update`,\n method: 'post',\n data\n })\n}\n\n// 删除商品\nexport function deleteProduct(id) {\n return request({\n url: `/lease/product/delete`,\n method: 'post',\n data: { id }\n })\n}\n\n\n\n// 查询单个商品详情\nexport function getMachineInfo(data) {\n return request({\n url: `/lease/product/getMachineInfo`,\n method: 'post', \n data\n })\n}\n\n\n// 已购商品\nexport function getOwnedList(data) {\n return request({\n url: `/lease/product/getOwnedList`,\n method: 'post', \n data\n })\n}\n\n\n\n// 已购商品详情\nexport function getOwnedById(data) {\n return request({\n url: `/lease/product/getOwnedById`,\n method: 'post', \n data\n })\n}\n\n// 查商品详情里面的商品信息\nexport function getMachineInfoById(data) {\n return request({\n url: `/lease/product/getMachineInfoById`,\n method: 'post', \n data\n })\n}\n\n\n// 查获取商城商品支持的支付方式\nexport function getPayTypes(data) {\n return request({\n url: `/lease/product/getPayTypes`,\n method: 'post', \n data\n })\n}\n\n\n// 卖家页面---矿机列表\nexport function getShopMachineListForSeller(data) {\n return request({\n url: `/lease/v2/product/machine/getShopMachineListForSeller`,\n method: 'post', \n data\n })\n}\n\n\n// 更新设置GPU商品列表的信息\nexport function updateGpuMachine(data) {\n return request({\n url: `/lease/v2/product/machine/updateGpuMachine`,\n method: 'post', \n data\n })\n}\n\n\n// 修改商品列表ASIC商品信息\nexport function updateAsicMachine(data) {\n return request({\n url: `/lease/v2/product/machine/updateAsicMachine`,\n method: 'post', \n data\n })\n}\n\n\n\n// 删除ASIC 或者GPU\nexport function deleteMachine(data) {\n return request({\n url: `/lease/v2/product/machine/deleteMachine`,\n method: 'post', \n data\n })\n}\n\n\n\n// 获取商场页面的店铺列表\nexport function getShopList(data) {\n return request({\n url: `/lease/v2/product/machine/getShopList`,\n method: 'post', \n data\n })\n}\n\n\n// 获取店铺详情\nexport function getShopMachineList(data) {\n return request({\n url: `/lease/v2/product/machine/getShopMachineList`,\n method: 'post', \n data\n })\n}\n\n\n\n// 获取店铺详情\nexport function addGoodsV2(data) {\n return request({\n url: `/lease/v2/shopping/cart/addGoodsV2`,\n method: 'post', \n data\n })\n}\n\n\n\n\n\n\n\n\n\n","\n\n\n\n\n ","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{directives:[{name:\"loading\",rawName:\"v-loading\",value:(_vm.loading),expression:\"loading\"}],staticClass:\"cart-page\"},[_c('h1',{staticClass:\"page-title\"},[_vm._v(\"购物车\")]),(_vm.loading)?_c('div',{staticClass:\"loading\"},[_c('i',{staticClass:\"el-icon-loading\",attrs:{\"aria-label\":\"加载中\",\"role\":\"img\"}}),_vm._v(\" 加载中... \")]):(_vm.isCartEmpty)?_c('div',{staticClass:\"empty-cart\"},[_c('div',{staticClass:\"empty-icon\"},[_vm._v(\"🛒\")]),_c('h2',[_vm._v(\"购物车是空的\")]),_c('p',[_vm._v(\"快去添加一些商品吧!\")]),_c('router-link',{staticClass:\"shop-now-btn\",attrs:{\"to\":\"/productList\"}},[_vm._v(\" 去购物 \")])],1):_c('div',{staticClass:\"cart-content\"},[_c('p',{staticStyle:{\"color\":\"#9E44F1\",\"font-size\":\"14px\",\"margin-bottom\":\"10px\"}},[_vm._v(\"注意:各店铺支持多种支付方式,请选择店铺支付方式后提交订单结算\")]),_c('el-table',{ref:\"shopTable\",staticStyle:{\"width\":\"100%\"},attrs:{\"data\":_vm.shops,\"border\":\"\",\"row-key\":'id',\"expand-row-keys\":_vm.expandedShopKeys,\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }},on:{\"expand-change\":_vm.handleShopExpandChange}},[_c('el-table-column',{attrs:{\"type\":\"expand\",\"width\":\"46\",\"expandable\":() => false},scopedSlots:_vm._u([{key:\"default\",fn:function(shopScope){return [_c('el-table',{ref:'innerTable-' + shopScope.row.id,staticStyle:{\"width\":\"100%\"},attrs:{\"data\":shopScope.row.productMachineDtoList || [],\"size\":\"small\",\"border\":\"\",\"row-key\":'id',\"reserve-selection\":\"\",\"row-class-name\":_vm.getMachineRowClassName,\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }},on:{\"selection-change\":sels => _vm.handleShopInnerSelectionChange(shopScope.row, sels)}},[_c('el-table-column',{attrs:{\"type\":\"selection\",\"width\":\"46\",\"selectable\":row => _vm.isRowSelectableByShop(shopScope.row, row)}}),_c('el-table-column',{attrs:{\"prop\":\"name\",\"label\":\"商品名称\"}}),_c('el-table-column',{attrs:{\"prop\":\"type\",\"label\":\"矿机种类\",\"width\":\"80\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{class:['type-tag', _vm.typeClass(scope.row.type)],attrs:{\"disable-transitions\":\"\"}},[_vm._v(\" \"+_vm._s(_vm.formatMachineType(scope.row.type))+\" \")])]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"机器ID\",\"width\":\"80\"}}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"最大收益算法\"}}),_c('el-table-column',{attrs:{\"label\":\"可售数量\",\"min-width\":\"40\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(\" \"+_vm._s(Number(scope.row.canSaleNumbers || 0))+\" \")]}}],null,true)}),_c('el-table-column',{attrs:{\"label\":\"购买数量\",\"min-width\":\"80\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input-number',{attrs:{\"min\":1,\"max\":_vm.getRowMaxPurchaseForCart(scope.row),\"precision\":0,\"step\":1,\"size\":\"mini\",\"controls\":false,\"disabled\":Number(scope.row.type) === 1},on:{\"change\":val => _vm.handleNumbersChange(scope.row, val)},model:{value:(scope.row.numbers),callback:function ($$v) {_vm.$set(scope.row, \"numbers\", $$v)},expression:\"scope.row.numbers\"}})]}}],null,true)}),_c('el-table-column',{attrs:{\"label\":\"最大可租(天)\",\"min-width\":\"50\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_vm._v(_vm._s(scope.row.maxLeaseDays != null ? scope.row.maxLeaseDays : ''))]}}],null,true)}),_c('el-table-column',{attrs:{\"label\":\"租赁天数\",\"width\":\"145\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input-number',{attrs:{\"min\":1,\"max\":_vm.getRowMaxLeaseDaysLocal(scope.row),\"precision\":0,\"step\":1,\"size\":\"mini\",\"controls-position\":\"right\"},on:{\"change\":function($event){return _vm.handleLeaseTimeChange(scope.row)},\"input\":function($event){return _vm.handleLeaseTimeInput(scope.row, $event)}},model:{value:(scope.row.leaseTime),callback:function ($$v) {_vm.$set(scope.row, \"leaseTime\", $$v)},expression:\"scope.row.leaseTime\"}})]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"price\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_vm._v(\"单价(\"+_vm._s(_vm.getSelectedCoinSymbolForShop(shopScope.row) || 'USDT')+\")\")]},proxy:true},{key:\"default\",fn:function(scope){return [(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row) != null)?[_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), _vm.getSelectedCoinSymbolForShop(shopScope.row)).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), _vm.getSelectedCoinSymbolForShop(shopScope.row)).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), _vm.getSelectedCoinSymbolForShop(shopScope.row)).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), _vm.getSelectedCoinSymbolForShop(shopScope.row)).text)+\" \")])],1)]:[_vm._v(\"-\")]]}}],null,true)}),_c('el-table-column',{attrs:{\"label\":\"机器状态\",\"width\":\"110\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{attrs:{\"type\":(Number(scope.row.del) === 1 || Number(scope.row.state) === 1) ? 'info' : 'success'}},[_vm._v(\" \"+_vm._s((Number(scope.row.del) === 1 || Number(scope.row.state) === 1) ? '下架' : '上架')+\" \")])]}}],null,true)}),_c('el-table-column',{attrs:{\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_vm._v(\"机器总价(\"+_vm._s(_vm.getSelectedCoinSymbolForShop(shopScope.row) || 'USDT')+\")\")]},proxy:true},{key:\"default\",fn:function(scope){return [(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row) != null)?[_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(_vm.calculateMachineTotal(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), scope.row.leaseTime, scope.row.numbers), _vm.getSelectedCoinSymbolForShop(shopScope.row)).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.calculateMachineTotal(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), scope.row.leaseTime, scope.row.numbers), _vm.getSelectedCoinSymbolForShop(shopScope.row)).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.calculateMachineTotal(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), scope.row.leaseTime, scope.row.numbers), _vm.getSelectedCoinSymbolForShop(shopScope.row)).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.calculateMachineTotal(_vm.getMachineUnitPriceBySelection(shopScope.row, scope.row), scope.row.leaseTime, scope.row.numbers), _vm.getSelectedCoinSymbolForShop(shopScope.row)).text)+\" \")])],1)]:[_vm._v(\"-\")]]}}],null,true)})],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"店铺名称\",\"min-width\":\"150\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(scope.row.name || scope.row.shopName || scope.row.shop?.name || '-'))])]}}])}),_c('el-table-column',{attrs:{\"label\":\"机器总数\",\"width\":\"100\",\"align\":\"center\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('span',[_vm._v(_vm._s(_vm.countMachines(scope.row)))])]}}])}),_c('el-table-column',{attrs:{\"min-width\":\"150\",\"align\":\"right\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_c('span',[_vm._v(\"总价(\"+_vm._s(_vm.getSelectedCoinSymbolForShopHeader())+\")\")])]},proxy:true},{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(_vm.displayShopTotalBySelection(scope.row), _vm.getSelectedCoinSymbolForShop(scope.row)).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(_vm.displayShopTotalBySelection(scope.row), _vm.getSelectedCoinSymbolForShop(scope.row)).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.displayShopTotalBySelection(scope.row), _vm.getSelectedCoinSymbolForShop(scope.row)).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(_vm.displayShopTotalBySelection(scope.row), _vm.getSelectedCoinSymbolForShop(scope.row)).text)+\" \")])],1)]}}])}),_c('el-table-column',{attrs:{\"label\":\"支付方式\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-select',{staticStyle:{\"min-width\":\"180px\"},attrs:{\"placeholder\":\"请选择\",\"size\":\"mini\"},on:{\"change\":val => _vm.handleShopPayChange(scope.row, val)},scopedSlots:_vm._u([{key:\"prefix\",fn:function(){return [(_vm.getSelectedPayIcon(scope.row))?_c('img',{staticStyle:{\"width\":\"16px\",\"height\":\"16px\",\"margin-right\":\"6px\",\"border-radius\":\"3px\"},attrs:{\"src\":_vm.getSelectedPayIcon(scope.row),\"alt\":_vm.getSelectedCoinSymbolForShop(scope.row)}}):_vm._e()]},proxy:true}],null,true),model:{value:(_vm.paySelectionMap[scope.row.id]),callback:function ($$v) {_vm.$set(_vm.paySelectionMap, scope.row.id, $$v)},expression:\"paySelectionMap[scope.row.id]\"}},_vm._l((_vm.getShopPayOptions(scope.row)),function(opt,idx){return _c('el-option',{key:idx,attrs:{\"value\":opt.value,\"label\":opt.label}},[_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"8px\"}},[_c('img',{staticStyle:{\"width\":\"18px\",\"height\":\"18px\",\"border-radius\":\"3px\"},attrs:{\"src\":opt.icon,\"alt\":opt.label}}),_c('span',[_vm._v(_vm._s(opt.label))])])])}),1)]}}])})],1),_c('div',{staticClass:\"summary-actions\",staticStyle:{\"margin-top\":\"16px\",\"display\":\"flex\",\"gap\":\"12px\",\"justify-content\":\"flex-end\"}},[_c('div',{staticClass:\"summary-inline\",staticStyle:{\"color\":\"#666\"}},[_vm._v(\" 已选机器:\"),_c('b',[_vm._v(_vm._s(_vm.selectedMachineCount))]),_vm._v(\" 台 \"),_c('span',{staticStyle:{\"margin-left\":\"12px\"}},[_vm._v(\"金额合计:\")]),(Object.keys(_vm.selectedTotalByCoin || {}).length)?_vm._l((_vm.selectedTotalByCoin),function(amt,coin){return _c('span',{key:coin,staticStyle:{\"margin-left\":\"8px\"}},[_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(amt, coin).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(amt, coin).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(coin)+\": \"+_vm._s(_vm.formatAmount(amt, coin).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(coin)+\": \"+_vm._s(_vm.formatAmount(amt, coin).text))])],1)])}):[_c('span',{staticClass:\"price-strong\"},[_vm._v(\"-\")])]],2),_c('div',{staticClass:\"actions-inline\",staticStyle:{\"display\":\"flex\",\"gap\":\"12px\"}},[_c('el-button',{attrs:{\"type\":\"danger\",\"disabled\":!_vm.selectedMachineCount},on:{\"click\":_vm.handleRemoveSelectedMachines}},[_vm._v(\"删除所选机器\")]),_c('el-button',{attrs:{\"type\":\"warning\",\"plain\":\"\",\"loading\":_vm.clearOffLoading},on:{\"click\":_vm.handleClearOffShelf}},[_vm._v(\"清除已下架商品\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"disabled\":!_vm.selectedMachineCount},on:{\"click\":_vm.handleCheckoutSelected}},[_vm._v(\"结算选中机器\")])],1)]),_c('el-dialog',{attrs:{\"visible\":_vm.confirmDialog.visible,\"width\":\"80vw\",\"close-on-click-modal\":false,\"title\":`确认结算(共 ${_vm.confirmDialog.count} 台机器)`},on:{\"update:visible\":function($event){return _vm.$set(_vm.confirmDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{on:{\"click\":_vm.handleConfirmDialogPrev}},[_vm._v(\"上一步\")]),_c('el-button',{on:{\"click\":function($event){_vm.confirmDialog.visible=false}}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.confirmPay}},[_vm._v(\"确认结算\")])]},proxy:true}])},[_c('div',[_vm._l((_vm.confirmDialog.shops),function(grp){return _c('div',{key:grp.shopId,staticStyle:{\"margin-bottom\":\"18px\"}},[_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"justify-content\":\"space-between\",\"margin\":\"8px 0 6px 0\"}},[_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\"}},[_vm._v(\" 店铺:\"+_vm._s(grp.shopName || grp.shopId)+\" \"),_c('span',{staticStyle:{\"margin-left\":\"12px\",\"color\":\"#666\",\"font-weight\":\"400\"}},[_vm._v(\"支付方式:\"+_vm._s(grp.payLabel))])]),_c('div',[(grp.coinSymbol)?[(grp.enough)?_c('span',{staticStyle:{\"color\":\"#16a34a\",\"font-weight\":\"600\"}},[_vm._v(\" 已满足起付额 \"+_vm._s(_vm.formatAmount(grp.deductibleAmount || 0, grp.coinSymbol).text)+\" \")]):_c('span',{staticStyle:{\"color\":\"#ef4444\",\"font-weight\":\"600\"}},[_vm._v(\" 金额不足最低起付额 \"+_vm._s(_vm.formatAmount(grp.deductibleAmount || 0, grp.coinSymbol).text)+\" ,收取手续费 \"+_vm._s(_vm.formatAmount(grp.fee || 0, grp.coinSymbol).text)+\" \")])]:_vm._e()],2)]),_c('el-table',{attrs:{\"data\":grp.items,\"max-height\":\"260\",\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left' },\"cell-style\":{ textAlign: 'left' }}},[_c('el-table-column',{attrs:{\"label\":\"矿机种类\",\"min-width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{class:['type-tag', _vm.typeClass(scope.row.type)],staticStyle:{\"font-size\":\"14px\"},attrs:{\"disable-transitions\":\"\"}},[_vm._v(\" \"+_vm._s(_vm.formatMachineType(scope.row.type))+\" \")])]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"机器ID\",\"min-width\":\"160\"}}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"最大收益算法\",\"min-width\":\"140\"}}),_c('el-table-column',{attrs:{\"prop\":\"unitPrice\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_vm._v(\"单价(\"+_vm._s(grp.coinSymbol || 'USDT')+\")\")]},proxy:true},{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(scope.row.unitPrice, grp.coinSymbol).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(scope.row.unitPrice, grp.coinSymbol).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(scope.row.unitPrice, grp.coinSymbol).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(scope.row.unitPrice, grp.coinSymbol).text))])],1)]}}],null,true)}),_c('el-table-column',{attrs:{\"prop\":\"leaseTime\",\"label\":\"租赁天数\",\"min-width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"numbers\",\"label\":\"购买数量\",\"min-width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"subtotal\",\"min-width\":\"140\"},scopedSlots:_vm._u([{key:\"header\",fn:function(){return [_vm._v(\"小计(\"+_vm._s(grp.coinSymbol || 'USDT')+\")\")]},proxy:true},{key:\"default\",fn:function(scope){return [_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(scope.row.subtotal, grp.coinSymbol).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(scope.row.subtotal, grp.coinSymbol).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(scope.row.subtotal, grp.coinSymbol).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(scope.row.subtotal, grp.coinSymbol).text))])],1)]}}],null,true)})],1)],1)}),_c('div',{staticStyle:{\"margin-top\":\"12px\",\"text-align\":\"right\"}},[_c('span',{staticStyle:{\"margin-right\":\"8px\"}},[_vm._v(\"总金额:\")]),(Object.keys(_vm.confirmDialog.totalsByCoin || {}).length)?_vm._l((_vm.confirmDialog.totalsByCoin),function(amt,coin){return _c('span',{key:coin,staticStyle:{\"margin-left\":\"12px\"}},[_vm._v(\" \"+_vm._s(coin)+\": \"),_c('span',{staticClass:\"price-strong\"},[(_vm.formatAmount(amt, coin).truncated)?_c('el-tooltip',{attrs:{\"content\":_vm.formatAmount(amt, coin).full,\"placement\":\"top\"}},[_c('span',[_vm._v(\" \"+_vm._s(_vm.formatAmount(amt, coin).text)+\" \"),_c('i',{staticClass:\"el-icon-more amount-more\"})])]):_c('span',[_vm._v(_vm._s(_vm.formatAmount(amt, coin).text))])],1)])}):[_vm._v(\"-\")]],2)],2)]),_c('el-dialog',{attrs:{\"visible\":_vm.noticeDialog.visible,\"width\":\"60vw\",\"title\":\"下单须知\",\"show-close\":false,\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){return _vm.$set(_vm.noticeDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{attrs:{\"type\":\"primary\",\"disabled\":_vm.noticeDialog.countdown > 0},on:{\"click\":_vm.handleNoticeAcknowledge}},[_vm._v(\" 同意并下单\"+_vm._s(_vm.noticeDialog.countdown > 0 ? `(${_vm.noticeDialog.countdown}s)` : '')+\" \")])]},proxy:true}])},[_c('div',{staticClass:\"notice-content\"},[_c('p',{staticClass:\"notice-title\"},[_vm._v(\"尊敬的客户,感谢您选择我们的服务。在您下单前,请务必仔细阅读并完全理解以下须知条款。一旦您点击\\\" 同意并下单\\\"或完成支付流程,即视为您已充分阅读、理解并同意接受本须知的全部内容约束。\")]),_c('ol',{staticClass:\"notice-list\"},[_c('li',[_c('b',[_vm._v(\"预授权冻结:\")]),_vm._v(\"为保障订单顺利执行,在下单成功后,系统将立即对您数字钱包或账户中与订单全款总额等值的资金进行预授权冻结。此操作并非即时划转,而是为确保您有足够的资金用于每日支付。\")]),_c('li',[_c('b',[_vm._v(\"每日结算支付:\")]),_vm._v(\"本服务采用\\\"按日结算\\\"模式。冻结的资金将根据租赁协议约定的每日费用,每日自动划转相应的金额给卖家。划转操作通常在每个UTC日结束时自动执行。\")]),_c('li',[_c('b',[_vm._v(\"资金解冻:\")]),_vm._v(\"当租赁服务到期或因其他原因终止后,系统中剩余的、未被划转的冻结资金将立即解除冻结,并返还至您的可用余额中。\")]),_c('li',[_c('b',[_vm._v(\"订单生效:\")]),_vm._v(\" 您的订单在支付流程完成且资金成功冻结后立即生效。系统将开始为您配置相应的矿机或算力资源。\")]),_c('li',[_c('b',[_vm._v(\"不可取消政策:\")]),_vm._v(\" 鉴于算力服务一经提供即无法退回的特性,所有订单一旦生效,即不可取消、不可退款、不可转让。您无法在租赁期内单方面中止服务或要求退还已冻结及已支付的费用。\")]),_c('li',[_c('b',[_vm._v(\"免责声明:\")]),_vm._v(\"因不可抗力(如自然灾害、政策变动等)导致订单延迟或无法履行,我们不承担相应责任。\")]),_c('li',[_c('b',[_vm._v(\"算力波动:\")]),_vm._v(\"您所租赁的算力产生的收益取决于区块链网络难度、全球总算力、币价波动、矿池运气等多种外部因素。我们仅提供稳定的算力输出,不对您的最终收益做出任何承诺或保证。\")])]),_c('p',{staticClass:\"notice-title\"},[_vm._v(\"再次提醒:数字资产挖矿存在较高市场风险,收益波动巨大,过去业绩不代表未来表现。请根据自身的风险承受能力谨慎决策。您下单的行为即代表您已充分了解并自愿承担所有相关风险。\")]),_c('div',{staticClass:\"notice-ack\"},[_c('el-checkbox',{staticStyle:{\"color\":\"#e74c3c\"},model:{value:(_vm.noticeDialog.checked),callback:function ($$v) {_vm.$set(_vm.noticeDialog, \"checked\", $$v)},expression:\"noticeDialog.checked\"}},[_vm._v(\"我已阅读并同意上述注意事项\")])],1)])]),_c('el-dialog',{attrs:{\"visible\":_vm.configDialog.visible,\"width\":\"80vw\",\"title\":\"矿机配置\",\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){return _vm.$set(_vm.configDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{on:{\"click\":_vm.handleConfigPrev}},[_vm._v(\"上一步\")]),_c('el-button',{on:{\"click\":_vm.handleConfigCancel}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleConfigConfirm}},[_vm._v(\" \"+_vm._s(_vm.unconfiguredMachinesList.length > 0 ? '确认配置' : '下一步')+\" \")])]},proxy:true}])},[_c('div',[(_vm.configDialog.selectedMachines && _vm.configDialog.selectedMachines.length > 0)?_c('div',[(_vm.unconfiguredMachinesList.length > 0)?_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"12px\",\"margin-bottom\":\"12px\"}},[_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\"}},[_vm._v(\"选择币种/算法\")]),_c('el-cascader',{staticStyle:{\"min-width\":\"320px\"},attrs:{\"options\":_vm.configDialog.coinAlgoOptions,\"props\":{ checkStrictly: false },\"clearable\":\"\",\"placeholder\":\"请选择币种与算法\",\"size\":\"small\"},on:{\"change\":_vm.handleCoinAlgoChange},model:{value:(_vm.configDialog.coinAlgoValue),callback:function ($$v) {_vm.$set(_vm.configDialog, \"coinAlgoValue\", $$v)},expression:\"configDialog.coinAlgoValue\"}}),_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\",\"white-space\":\"nowrap\"}},[_vm._v(\"选择矿池/模型\")]),_c('el-cascader',{staticStyle:{\"width\":\"240px\"},attrs:{\"options\":_vm.configDialog.poolOptions,\"props\":{ checkStrictly: false },\"clearable\":\"\",\"placeholder\":\"请选择矿池与模型\",\"size\":\"small\",\"disabled\":!_vm.configDialog.coinAlgoValue || _vm.configDialog.coinAlgoValue.length !== 2},on:{\"change\":_vm.handlePoolValueChange},model:{value:(_vm.configDialog.poolValue),callback:function ($$v) {_vm.$set(_vm.configDialog, \"poolValue\", $$v)},expression:\"configDialog.poolValue\"}})],1):_vm._e(),(_vm.unconfiguredMachinesList.length > 0)?_c('div',[_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\",\"margin-bottom\":\"8px\",\"font-size\":\"14px\"}},[(!_vm.configDialog.coinAlgoValue || _vm.configDialog.coinAlgoValue.length !== 2)?[_vm._v(\" 待配置机器(共 \"+_vm._s(_vm.unconfiguredMachinesList.length)+\" 台) \")]:[_vm._v(\" 支持该币种/算法的机器(共 \"+_vm._s(_vm.unconfiguredMachinesList.length)+\" 台) \")]],2),_c('el-table',{ref:\"configTable\",attrs:{\"data\":_vm.unconfiguredMachinesList,\"max-height\":\"300\",\"border\":\"\",\"stripe\":\"\",\"row-key\":\"id\",\"reserve-selection\":\"\",\"header-cell-style\":{ textAlign: 'left', fontSize: '14px' },\"cell-style\":{ textAlign: 'left', fontSize: '14px' }},on:{\"selection-change\":_vm.handleConfigSelectionChange}},[_c('el-table-column',{attrs:{\"type\":\"selection\",\"width\":\"46\"}}),_c('el-table-column',{attrs:{\"label\":\"矿机种类\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{class:['type-tag', _vm.typeClass(scope.row.type)],staticStyle:{\"font-size\":\"14px\"},attrs:{\"disable-transitions\":\"\"}},[_vm._v(\" \"+_vm._s(_vm.formatMachineType(scope.row.type))+\" \")])]}}],null,false,2555332731)}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"机器ID\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"最大收益算法\",\"min-width\":\"140\"}}),(_vm.getCurrentWalletMining() !== null)?_c('el-table-column',{attrs:{\"label\":\"矿工号\",\"min-width\":\"160\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-input',{attrs:{\"placeholder\":\"矿工号\",\"size\":\"mini\",\"clearable\":\"\",\"maxlength\":\"40\"},on:{\"input\":val => _vm.handleMachineWorkerIdInput(scope.row, val)},model:{value:(scope.row._workerId),callback:function ($$v) {_vm.$set(scope.row, \"_workerId\", $$v)},expression:\"scope.row._workerId\"}})]}}],null,false,46571769)}):_vm._e()],1)],1):_vm._e(),(_vm.getCurrentWalletMining() !== null)?_c('div',{staticStyle:{\"margin-top\":\"16px\"}},[(_vm.getCurrentWalletMining() === true)?_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"12px\"}},[_c('label',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\",\"min-width\":\"100px\"}},[_vm._v(\"钱包地址:\")]),_c('el-input',{staticStyle:{\"flex\":\"1\",\"max-width\":\"500px\"},attrs:{\"placeholder\":\"请输入钱包地址\",\"clearable\":\"\",\"maxlength\":\"95\"},on:{\"input\":_vm.handleWalletAddressInput},model:{value:(_vm.configDialog.walletAddress),callback:function ($$v) {_vm.$set(_vm.configDialog, \"walletAddress\", $$v)},expression:\"configDialog.walletAddress\"}})],1):_vm._e(),(_vm.getCurrentWalletMining() === false)?_c('div',{staticStyle:{\"display\":\"flex\",\"align-items\":\"center\",\"gap\":\"12px\"}},[_c('label',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\",\"min-width\":\"100px\"}},[_vm._v(\"挖矿账户:\")]),_c('el-input',{staticStyle:{\"flex\":\"1\",\"max-width\":\"500px\"},attrs:{\"placeholder\":\"请输入挖矿账户\",\"clearable\":\"\",\"maxlength\":\"40\"},on:{\"input\":_vm.handleMiningAccountInput},model:{value:(_vm.configDialog.miningAccount),callback:function ($$v) {_vm.$set(_vm.configDialog, \"miningAccount\", $$v)},expression:\"configDialog.miningAccount\"}})],1):_vm._e()]):(_vm.configDialog.coinAlgoValue && _vm.configDialog.coinAlgoValue.length === 2 && _vm.getCurrentWalletMining() === null)?_c('div',{staticStyle:{\"margin-top\":\"16px\",\"color\":\"#909399\",\"font-size\":\"14px\"}},[_vm._v(\" 请先选择矿池/模型 \")]):(_vm.configDialog.coinAlgoValue && _vm.configDialog.coinAlgoValue.length === 2 && _vm.unconfiguredMachinesList.length === 0)?_c('div',{staticStyle:{\"margin-bottom\":\"12px\",\"color\":\"#909399\",\"font-size\":\"14px\"}},[_vm._v(\" 当前选择的币种/算法下没有可配置的机器 \")]):_vm._e(),(_vm.unsupportedMachinesList.length > 0)?_c('div',{staticStyle:{\"margin-top\":\"16px\"}},[_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#f56c6c\",\"margin-bottom\":\"8px\",\"font-size\":\"14px\"}},[_vm._v(\" 不支持该币种/算法的机器(共 \"+_vm._s(_vm.unsupportedMachinesList.length)+\" 台) \")]),_c('el-table',{attrs:{\"data\":_vm.unsupportedMachinesList,\"max-height\":\"200\",\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left', fontSize: '14px' },\"cell-style\":{ textAlign: 'left', fontSize: '14px' }}},[_c('el-table-column',{attrs:{\"label\":\"矿机种类\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{class:['type-tag', _vm.typeClass(scope.row.type)],staticStyle:{\"font-size\":\"14px\"},attrs:{\"disable-transitions\":\"\"}},[_vm._v(\" \"+_vm._s(_vm.formatMachineType(scope.row.type))+\" \")])]}}],null,false,2555332731)}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"机器ID\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"最大收益算法\",\"min-width\":\"140\"}})],1)],1):_vm._e()]):_vm._e(),(_vm.configDialog.configuredMachines.length > 0)?_c('div',{staticStyle:{\"margin-top\":\"24px\"}},[_c('div',{staticStyle:{\"font-weight\":\"600\",\"color\":\"#2c3e50\",\"margin-bottom\":\"12px\",\"font-size\":\"16px\"}},[_vm._v(\"已配置机器\")]),_c('el-table',{attrs:{\"data\":_vm.configDialog.configuredMachines,\"max-height\":\"300\",\"border\":\"\",\"stripe\":\"\",\"header-cell-style\":{ textAlign: 'left', fontSize: '14px' },\"cell-style\":{ textAlign: 'left', fontSize: '14px' }}},[_c('el-table-column',{attrs:{\"label\":\"矿机种类\",\"width\":\"120\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [_c('el-tag',{class:['type-tag', _vm.typeClass(scope.row.type)],staticStyle:{\"font-size\":\"14px\"},attrs:{\"disable-transitions\":\"\"}},[_vm._v(\" \"+_vm._s(_vm.formatMachineType(scope.row.type))+\" \")])]}}],null,false,2555332731)}),_c('el-table-column',{attrs:{\"prop\":\"id\",\"label\":\"机器ID\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"coin\",\"label\":\"币种\",\"width\":\"120\"}}),_c('el-table-column',{attrs:{\"prop\":\"algorithm\",\"label\":\"算法\",\"min-width\":\"140\"}}),_c('el-table-column',{attrs:{\"prop\":\"poolName\",\"label\":\"矿池\",\"min-width\":\"140\"}}),_c('el-table-column',{attrs:{\"prop\":\"modelName\",\"label\":\"模型\",\"min-width\":\"140\"}}),_c('el-table-column',{attrs:{\"label\":\"钱包地址\",\"min-width\":\"200\"},scopedSlots:_vm._u([{key:\"default\",fn:function(scope){return [(scope.row.walletAddress)?_c('el-tooltip',{attrs:{\"content\":scope.row.walletAddress,\"placement\":\"top\"}},[_c('span',{staticClass:\"mono-ellipsis\",staticStyle:{\"font-family\":\"monospace\"}},[_vm._v(_vm._s(_vm.formatWalletAddress(scope.row.walletAddress)))])]):_c('span',[_vm._v(\"-\")])]}}],null,false,2449193566)}),(_vm.hasConfiguredMiningAccount)?_c('el-table-column',{attrs:{\"prop\":\"miningAccount\",\"label\":\"挖矿账户\",\"min-width\":\"140\"}}):_vm._e(),(_vm.hasConfiguredWorkerId)?_c('el-table-column',{attrs:{\"prop\":\"workerId\",\"label\":\"矿工号\",\"min-width\":\"140\"}}):_vm._e()],1)],1):_vm._e()])]),_c('el-dialog',{attrs:{\"visible\":_vm.googleCodeDialog.visible,\"width\":\"480px\",\"title\":\"安全验证\",\"show-close\":false,\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){return _vm.$set(_vm.googleCodeDialog, \"visible\", $event)}},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('div',{staticClass:\"dialog-footer\"},[_c('el-button',{on:{\"click\":_vm.handleGoogleCodePrev}},[_vm._v(\"上一步\")]),_c('el-button',{on:{\"click\":_vm.handleGoogleCodeCancel}},[_vm._v(\"取消\")]),_c('el-button',{attrs:{\"type\":\"primary\",\"loading\":_vm.googleCodeDialog.loading,\"disabled\":!_vm.isGoogleCodeValid},on:{\"click\":_vm.handleGoogleCodeSubmit}},[_vm._v(\" \"+_vm._s(_vm.googleCodeDialog.loading ? '验证中...' : '确认验证')+\" \")])],1)]},proxy:true}])},[_c('div',{staticClass:\"google-code-content\"},[_c('div',{staticClass:\"verification-icon\"},[_c('i',{staticClass:\"el-icon-lock\",staticStyle:{\"font-size\":\"48px\",\"color\":\"#409EFF\"}})]),_c('div',{staticClass:\"verification-title\"},[_c('h3',[_vm._v(\"请输入谷歌验证码\")]),_c('p',{staticClass:\"verification-desc\"},[_vm._v(\"为了保障您的账户安全,请输入您的谷歌验证器中的6位验证码\")])]),_c('div',{staticClass:\"code-input-wrapper\"},[_c('el-input',{ref:\"googleCodeInput\",staticClass:\"code-input\",attrs:{\"placeholder\":\"请输入6位验证码\",\"maxlength\":\"6\",\"size\":\"large\"},on:{\"input\":_vm.handleGoogleCodeInput},nativeOn:{\"keyup\":function($event){if(!$event.type.indexOf('key')&&_vm._k($event.keyCode,\"enter\",13,$event.key,\"Enter\"))return null;return _vm.handleGoogleCodeSubmit.apply(null, arguments)}},scopedSlots:_vm._u([{key:\"prepend\",fn:function(){return [_c('i',{staticClass:\"el-icon-key\"})]},proxy:true}]),model:{value:(_vm.googleCodeDialog.code),callback:function ($$v) {_vm.$set(_vm.googleCodeDialog, \"code\", $$v)},expression:\"googleCodeDialog.code\"}})],1),(_vm.googleCodeDialog.error)?_c('div',{staticClass:\"code-error\"},[_c('i',{staticClass:\"el-icon-warning\"}),_c('span',[_vm._v(_vm._s(_vm.googleCodeDialog.error))])]):_vm._e()])])],1),_c('el-dialog',{attrs:{\"visible\":_vm.settlementSuccessfulVisible,\"width\":\"480px\",\"append-to-body\":\"\",\"close-on-click-modal\":false,\"close-on-press-escape\":false},on:{\"update:visible\":function($event){_vm.settlementSuccessfulVisible=$event},\"close\":_vm.handleCloseSuccessDialog},scopedSlots:_vm._u([{key:\"footer\",fn:function(){return [_c('el-button',{attrs:{\"type\":\"primary\"},on:{\"click\":_vm.handleCloseSuccessDialog}},[_vm._v(\"已知晓\")])]},proxy:true}])},[_c('div',{staticStyle:{\"text-align\":\"center\",\"padding\":\"20px 0\"}},[_c('div',{staticStyle:{\"font-size\":\"48px\",\"color\":\"#52c41a\",\"margin-bottom\":\"16px\"}},[_vm._v(\"✓\")]),_c('div',{staticStyle:{\"font-size\":\"18px\",\"color\":\"#333\",\"margin-bottom\":\"12px\"}},[_vm._v(\"请求结算处理成功\")]),_c('div',{staticStyle:{\"color\":\"#666\",\"line-height\":\"1.6\"}},[_vm._v(\" 请在订单列表页面查看结算状态\"),_c('br'),_vm._v(\" 结算成功会自动更新钱包余额 \")])])])],1)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","__webpack_require__.amdO = {};","var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = function(module) {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.p = \"/\";","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t524: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunkpower_leasing\"] = self[\"webpackChunkpower_leasing\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [504], function() { return __webpack_require__(1406); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["component","_coinList","require","_products","exports","name","data","notOnlySpaces","rule","value","callback","trim","length","Error","containsEmoji","text","emojiPattern","test","noEmoji","submitting","form","type","coin","description","image","state","shopId","rules","required","message","trigger","validator","min","max","computed","coinOptions","coinList","label","created","$route","query","Number","methods","fetchAddProduct","params","res","createProduct","code","$message","msg","showClose","$router","push","handleSubmit","valid","$refs","productForm","validate","error","console","handleReset","resetFields","handleCancel","_order","_OrderList","_interopRequireDefault","components","OrderList","active","orders","loading","urlStatus","status","String","savedStatus","localStorage","getItem","initial","fetchOrders","fetchCancelOrder","cancelOrder","handleCancelOrder","orderId","handleTabClick","tab","setItem","e","warn","key","getOrdersByStatus","payload","list","Array","isArray","rows","$set","log","initNoEmojiGuard","window","__noEmojiGuardInitialized","isEditableTarget","el","Element","getAttribute","tag","tagName","toLowerCase","disallow","indexOf","setComposing","composing","__noEmojiComposing","isComposing","sanitizeAndRedispatch","target","before","selectionStart","selectionEnd","after","replace","removed","nextPos","Math","setSelectionRange","evt","Event","bubbles","dispatchEvent","document","addEventListener","_vm","this","_c","_self","staticClass","attrs","class","activeRole","isSecuritySettingsPage","on","$event","handleClickRole","_k","keyCode","preventDefault","_v","_l","displayedLinks","item","to","isActiveLink","_s","_machine","product","ranges","machineList","productId","confirmVisible","stateSnapshot","fieldSnapshot","updateLoading","unitOptions","id","fetchDetail","fetchMachineList","handlePayTypeChange","index","row","sel","_selectedPayIndex","priceList","_priceEditing","price","isRowDisabled","saleState","handleOpenConfirm","warning","getMachineInfoById","productMachineRangeList","getMachineListForUpdate","map","r","first","refreshStateSnapshot","refreshFieldSnapshot","snapshot","i","priceMap","forEach","p","payTypeId","theoryPower","powerDissipation","maxLeaseDays","isCellChanged","snap","pt","pid","cur","ori","current","original","restoreStateSnapshot","currentRow","prevState","updateMachineList","updateMachine","success","deleteMachine","handleTheoryPowerInput","rowItem","v","firstDot","slice","endsWithDot","endsWith","parts","split","intPart","decPart","handleNumericCell","d","handlePriceBlur","raw","pattern","handleMaxLeaseDaysInput","handleMaxLeaseDaysBlur","n","isInteger","handleTheoryPowerBlur","handlePowerDissipationBlur","handleTypeCell","handleStateChange","handleDeleteMachine","$confirm","confirmButtonText","cancelButtonText","handleSubmitMachines","powerPattern","pricePattern","isOnlySpaces","rowLabel","miner","theoryRaw","priceRaw","typeRaw","dissRaw","daysRaw","m","unit","handleBack","back","_m","ref","staticStyle","getRowKey","expandedRowKeys","getRowClassName","textAlign","handleRowClick","handleExpandChange","scopedSlots","_u","fn","scope","formatChain","fromChain","fromSymbol","toUpperCase","fromAddress","stopPropagation","copy","_e","formatFullTime","createTime","formatAmount","realAmount","toSymbol","truncated","full","toChain","toAddress","txHash","getStatusType","getStatusText","updateTime","page","pageSize","total","fetchList","_request","productName","machineCategory","sellCount","coinAndAlgoList","algorithm","cost","costMap","confirmData","saleNumbers","s","validateCoinAlgoRows","str","payTypeDefs","miners","minersLoading","selectedMiner","machineOptions","machinesLoading","selectedMachines","selectedMachineRows","saving","lastCostBaseline","lastCostMapBaseline","lastTypeBaseline","lastMaxLeaseDaysBaseline","lastPowerDissipationBaseline","lastTheoryPowerBaseline","lastUnitBaseline","gpuDialogVisible","clientDownloadUrl","process","VUE_APP_GPU_CLIENT_URL","hasDownloadedClient","algoOptionsMap","loadingCoins","loadingAlgos","walletBindDialogVisible","productMachineURDVos","user","userEmail","initPayTypesFromRoute","validateCost","validateCostMap","getPayTypes","loadSupportCoins","getLeasEmailFromStorage","trimmed","startsWith","parsed","JSON","parse","email","leasEmail","algo","power","getSupportCoin","filter","Boolean","Object","keys","Set","sort","handleCoinChange","loadAlgorithmsForCoin","getSupportAlgo","algorithms","handleCoinRowTheoryInput","handleCoinRowUnitChange","handleAddCoinAlgoRow","last","newIndex","handleRemoveCoinAlgoRow","splice","buildCoinCsvFromRows","set","token","t","add","from","join","buildAlgoCsvFromRows","handleCoinsInput","coinsInput","handleAlgorithmsInput","algorithmsInput","normalizeCsv","input","upper","arr","buildPriceList","defs","priceNum","isFinite","chain","seen","it","payChain","payCoin","has","payCoinImage","nextCostMap","handleGoToWalletBind","handleSellCountInput","$nextTick","machineForm","clearValidate","handleSellCountBlur","handleMachineCategoryChange","val","handleDownloadClient","types","downloadUrl","request","defaults","baseURL","encodeURIComponent","a","createElement","href","click","handleGpuClientStarted","payTypes","decodeURIComponent","Map","values","initCostMap","handleNumeric","syncMaxLeaseDaysToRows","handleCostMapInput","handleTypeInput","syncCostToRows","newCost","oldBaseline","updateMachineType","handleRowPowerDissipationInput","handleRowPowerDissipationBlur","handleRowTheoryPowerInput","handleRowTheoryPowerBlur","handleRowUnitChange","rowNum","handleRowMaxLeaseDaysInput","handleRowMaxLeaseDaysBlur","handleRowPriceInput","handleRowPriceMapInput","handleRowPriceMapBlur","handleRowPriceBlur","handleRowTypeInput","handleRowTypeBlur","handleToggleState","currentState","fetchMiners","getUserMinersList","coinKey","additionalProperties1","handleMinerChange","userMinerVo","getUserMachineList","handleSave","ok","invalidTypeRowIndex","findIndex","coinStr","algoStr","doSubmit","addAsicMachine","duration","addSingleOrBatchMachine","url","method","downloadClient","responseType","activeIndex","buyerLinks","sellerLinks","userInitial","path","mounted","getVal","savedRole","setActiveRoleByRoute","role","stringify","firstPath","qFrom","sessionStorage","buyerPrefixes","sellerPrefixes","shouldBuyer","some","shouldSeller","pathLike","prefixes","watch","immediate","handler","_user","_rsaEncrypt","_password","validateEmail","emailReg","validatePassword","createPasswordValidator","emptyMessage","validateConfirmPassword","registerForm","password","validateAgree","confirmPassword","agree","registerRules","sendingCode","countdown","timer","passwordStrength","pwd","strength","passwordStrengthText","passwordStrengthClass","beforeDestroy","clearInterval","handleEmailChange","goToShop","go","handleSendCode","validateField","sendEmailCode","startCountdown","setInterval","handleRegister","passwordPlain","encryptedPassword","syncEncrypted","rsaEncryptSync","asyncEncrypted","rsaEncrypt","register","_vue","_App","_router","_elementUi","_noEmojiGuard","debug","info","Vue","config","productionTip","use","ElementUI","vm","router","render","h","App","cleanupRequestListeners","$mount","_cartManager","_index","mixins","Index","formatPayType","handleAddToCart","addToCart","title","quantity","_shops","feeRate","hasEmoji","emojiRegex","handleFeeRateInput","fetchAddShop","getAddShop","handleDescriptionInput","substring","handleCreate","hasShop","rateRaw","rateNum","decOk","includes","toString","getBindInfo","bindGoogle","sendOpenGoogleCode","closeStepTwo","sendCloseGoogleCode","getGoogleStatus","openStepTwo","openCreateWallet","walletList","w","walletBalance","balance","displaySymbol","slot","blockedBalance","handleWithdraw","recentTransactions","transaction","time","statusTagType","statusText","amount","amountText","rechargeDialogVisible","resetRechargeForm","WalletData","model","$$v","expression","copyAddress","withdrawDialogVisible","resetWithdrawForm","withdrawForm","withdrawRules","displayWithdrawSymbol","handleAmountInput","totalBalance","availableWithdrawBalance","fee","actualAmount","handleGoogleCodeInput","googleCode","withdrawLoading","confirmWithdraw","createDialogVisible","options","createValue","createLoading","confirmCreateWallet","getOrdersByStatusForSeller","checks","check","_wallet","_amount","recharge","withdraw","consume","rechargeRows","withdrawRows","consumeRows","expandedKeys","pageSizes","currentPage","pagination","pageNum","getStatusByTab","loadList","truncateAmountByCoin","handleTab","pane","clear","tabName","idx","indexPart","stable","__key","isExpanded","toggleExpand","typeKey","getTypeKeyByStatus","transactionRecord","mapped","loadByStatus","getTabByStatus","loadRecharge","loadWithdraw","loadConsume","statusClass","getRechargeStatusType","getRechargeStatusText","getWithdrawStatusType","getWithdrawStatusText","getPayStatusType","getPayStatusText","tron","trx","eth","ethereum","bsc","polygon","matic","Date","toLocaleString","formatTime","formatTrunc","decimals","num","factor","pow","trunc","padded","padEnd","handleSizeChange","handleCurrentChange","handleCopy","navigator","clipboard","writeText","ta","style","position","left","body","appendChild","focus","select","execCommand","removeChild","getLogin","getLogout","sendLoginCode","sendUpdatePwdCode","updatePassword","closeAccount","sendCloseAccount","updatePasswordInCenter","activeTab","pendingRecharges","refreshData","directives","rawName","showDetail","getChainName","formatAddress","address","successRecharges","failedRecharges","detailDialogVisible","closeDetail","selectedItem","_verification","loaded","defaultCover","shop","del","visibleEdit","editForm","gCode","shopConfigs","visibleConfigEdit","configForm","chainLabel","chainValue","payAddress","payCoins","productOptions","editCoinOptionsApi","chainOptions","shopLoading","currentWithdrawRow","withdrawAddressEditable","shopStateText","shopStateTagType","canCreateShop","editCoinOptions","selectedCoinLabels","o","get","withdrawDialogTitle","sym","formatDec6","amountInt","toScaledInt","feeInt","formatDec6FromInt","fetchMyShop","handleEditShopGoogleCodeInput","ensureGoogleStatusEnabledForWalletOp","actionLabel","reason","dangerouslyUseHTMLString","customClass","formatBalance","formatCoin","serviceCharge","charge","validateWithdrawAmount","validateWithdrawToAddress","validateGoogleCode","handleEditAddressClick","withdrawToAddressInput","toAddressPlain","fromAddressPlain","encryptedToAddress","encryptedFromAddress","withdrawBalanceForSeller","fetchShopConfigs","undefined","toFixed","match","amountStr","normalized","re","RegExp","scale","round","decPartRaw","intVal","sign","abs","floor","padStart","amtInt","balanceInt","actualInt","formatFeeRate","fixed","handleEditFeeRateInput","resetShopState","getMyShop","getShopConfigV2","updateShopConfig","deleteShopConfig","handleEditConfig","getChainAndCoin","children","c","preSelected","hasBind","payCoinStr","handleDeleteConfig","$prompt","inputPlaceholder","inputPattern","inputErrorMessage","handleConfigGoogleCodeInput","handleConfigEditClose","submitConfigEdit","addr","encryptedPayAddress","gcode","updateShopConfigV2","removeSelectedCoin","labelUpper","handleOpenEdit","queryShop","submitEdit","updateShop","handleDelete","deleteShop","setTimeout","handleToggleShop","isClosed","confirmMsg","closeShop","handleGoNew","handleAddProduct","handleWalletBind","props","items","default","emptyText","showCheckout","isSeller","showEndTime","onCancel","Function","payLoading","orderDialog","visible","qrContent","dialogVisible","paymentDialog","totalPrice","payAmount","noPayAmount","img","safeItems","buildQrSrc","formatDateTime","formatMachineType","typeNum","handleCheckout","handleGoDetail","then","catch","shouldShowActions","authRoutes","Promise","resolve","_interopRequireWildcard2","meta","requiresAuth","productRoutes","allAuthority","cartRoutes","checkoutRoutes","accountRoutes","redirect","childrenRoutes","mainRoutes","resetForm","resetRules","addOrders","getOrdersByIds","getChainAndListForSeller","getCoinPrice","getMachineSupportCoinAndAlgorithm","getMachineSupportPool","addOrdersV2","getPurchasedItems","getPurchasedInfoV2","range","keyword","withKeys","__rowKey","isOpen","expandedRows","area","handleRangeChange","sellerReceiptList","_productService","_shoppingCart","selectedMap","paymentMethodList","selectedPayKey","filters","minPrice","maxPrice","minPower","maxPower","minPowerDissipation","maxPowerDissipation","powerUnitOptions","sortStates","priceSort","powerSort","powerDissipationSort","activeSortField","payFilterDefaultApplied","confirmAddDialog","cartMachineIdSet","cartCompositeKeySet","cartLoaded","machinesLoaded","productListData","tableData","productDetailLoading","dynamicMeta","dynamicColumns","dynamicRows","dynamicSearch","machineType","savedType","NaN","routeShopId","fetchGetMachineInfo","buildQueryParams","fetchPayTypes","formatDynamicCell","col","pv","getDisplayPrice","pc","getDisplayPriceCoin","nPrice","truncateTo6","coinUnit","colCurrency","currency","ensureDefaultPayFilterFromPrices","firstWithPriceList","find","chainRaw","coinRaw","hit","_truncate","f","isLastHashrateColumn","colIdx","cols","getRenderedColumns","hashrate","others","handleOpenDynamicSearch","handleConfirmDynamicSearch","fetchDynamicTable","kw","baseCols","hitCols","nextCols","handleMachineTypeChange","getRowCoin","getPriceCoinSymbol","formatNum6","ensureDefaultPayFilterSelection","payList","coinSymbol","handleToggleSort","field","k","q","addNum","obj","getShopMachineList","root","columns","saleOutNumbers","leaseTime","purchaseQuantity","_selected","payConfigList","loadProduct","getProductById","fetchAddCart","addCart","fetchGetGoodsList","getGoodsListV2","rawRows","groups","shoppingCartInfoDtoList","flatMap","matched","g","ids","compositeKeys","productMachineDtoList","totalCount","reduce","sum","CustomEvent","detail","count","autoSelectAndDisable","handleSeriesRowClick","lockedIds","opened","handleGetSeriesRowClassName","handleInnerSelectionChange","parentRow","selections","openedSet","isSelectable","isSelectedByParent","handleManualSelect","checked","hasPrice","handleGetInnerRowClass","handleDecreaseVariantQuantity","groupIndex","variantIndex","variants","handleIncreaseVariantQuantity","handleVariantQuantityInput","handleAddVariantToCart","variant","onlyKey","handleAddSelectedToCart","allSelected","flat","handleOpenAddToCartDialog","picked","handleConfirmAddSelectedToCart","numbers","addGoodsV2","clearAllSelections","productMachines","handleDecreaseQuantity","rowIndex","handleIncreaseQuantity","handleQuantityInput","handleQuantityBlur","rowData","date","ENCRYPTION_KEY_SOURCE","str2ab","encoder","TextEncoder","encode","ab2str","buffer","decoder","TextDecoder","decode","arrayBufferToBase64","bytes","Uint8Array","binary","byteLength","fromCharCode","btoa","base64ToArrayBuffer","base64","atob","charCodeAt","async","getDerivedKey","keyMaterial","baseKey","crypto","subtle","importKey","salt","deriveKey","iterations","hash","encrypt","plaintext","iv","getRandomValues","encrypted","combined","decrypt","ciphertext","decrypted","SecureStorage","removeItem","hasItem","secureStorage","currentChain","cascaderProps","multiple","checkStrictly","emitPath","preCheck","prices","rowPrices","getChainAndList","handleRemoveSelectedCoin","coinUpper","next","handleChange","handleItemClick","node","isLeaf","lastChain","expanded","expand","nodes","validateAddressByChain","toUpperOptions","src","FetchAddWalletShopConfig","encryptedParams","addWalletShopConfig","targetChain","filtered","preCheckBeforeBind","getProductListForShopWalletConfig","isSuccess","submitBindWithPrice","coins","handleConfirmBindAfterPreview","collectMachineGroups","pushId","productMachineId","productMachineIdList","machines","machineIds","machineGroups","priceStr","symbol","productMachineForWalletConfigVoList","updateProductListForShopWalletConfig","resetPreCheckPrices","handlePreCheckClose","coinsForBind","canSubmitPreCheck","selectedCoinsDisplay","selectedCoins","formatPayTooltip","getPayImageUrl","handlePayIconKeyDown","handlePayFilterChange","getSelectedPayIcon","proxy","opt","handleMinPriceInput","handleMaxPriceInput","handleSearchFilters","handleResetFilters","handleManualSelectFlat","icon","apply","arguments","getCellClass","getRowMaxLeaseDays","handleLeaseDaysChange","getRowMaxPurchase","handlePurchaseQuantityChange","formatConfirmTotalText","nativeOn","loginForm","loginRules","handleLogin","detailData","poolUser","pool","poolUrl","walletAddress","watchUrl","purchasedMachinesList","workerId","recordTime","startTime","endTime","_receiptRecord","_withdrawRecord","AccountReceiptRecord","AccountWithdrawRecord","activeComponentName","syncTabFromRoute","getMaxDecimalsByCoin","truncateAmountRaw","maxDecimals","isNegative","keep","LoadingManager","constructor","loadingStates","setupListeners","resetAllLoadingStates","setLoading","componentId","stateKey","timestamp","now","getLoading","componentsToUpdate","resetComponentLoadingStates","loadingManager","productListLoading","handleAlgorithmClear","handleAlgorithmSearch","searchAlgorithm","products","handleProductClick","shopName","saleNumber","regexPassword","isEnabled","statusLoading","step1Visible","step2Visible","closeDialogVisible","openDialogVisible","deleteAccountDialogVisible","changePasswordDialogVisible","qrCodeUrl","secretKey","countdownTimer","sendingCloseCode","closeCountdown","closeCountdownTimer","sendingOpenCode","openCountdown","openCountdownTimer","sendingDeleteAccountCode","deleteAccountCountdown","deleteAccountCountdownTimer","deletingAccount","sendingChangePasswordCode","changePasswordCountdown","changePasswordCountdownTimer","changingPassword","closing","opening","verifyForm","emailCode","closeForm","openForm","deleteAccountForm","changePasswordForm","verifyRules","closeRules","openRules","deleteAccountRules","changePasswordRules","googleStatus","getQrCodeSrc","getButtonText","getStatusClass","getButtonType","check2FAStatus","loadUserEmail","ensureGoogleStatusEnabledForSensitiveOp","handleEnable2FA","handleButtonClick","handleDisable2FA","secret","handleSendCloseEmailCode","startCloseCountdown","handleCloseGoogleCodeInput","handleConfirmClose","eCode","handleCloseDialogClose","handleSendOpenEmailCode","startOpenCountdown","handleOpenGoogleCodeInput","handleConfirmOpen","handleOpenDialogClose","handleCopySecret","handleStep1Close","handleNextToStep2","handleBackToStep1","handleStep2Close","handleSendEmailCode","handleConfirm","handleCannotGetCode","handleCannotGetGoogleCode","handleChangePassword","handleSendChangePasswordCode","startChangePasswordCountdown","handleChangePasswordGoogleCodeInput","handleConfirmChangePassword","handleChangePasswordDialogClose","handleDeleteAccount","handleSendDeleteAccountCode","startDeleteAccountCountdown","handleDeleteAccountGoogleCodeInput","handleConfirmDeleteAccount","handleDeleteAccountDialogClose","getShopConfig","addShopConfig","_axios","_errorCode","_loadingManager","_errorNotificationManager","_secureStorage","tokenCache","tokenInitPromise","initTokenCache","encryptedToken","rawToken","upgraded","upgradeError","jsonError","readError","updateToken","encryptError","plainError","clearToken","getToken","waitForInit","parsedToken","finally","pendingRequestMap","getRequestKey","service","axios","create","timeout","RETRY_WINDOW","MAX_CONCURRENT_RETRIES","pendingRequests","activeRetries","lastNetworkStatusTime","online","offline","networkRecoveryInProgress","retryWithConcurrencyLimit","response","handleNetworkOnline","$i18n","pendingPromises","retryPromise","delete","allSettled","commonLoadingProps","prop","handleNetworkOffline","errorNotificationManager","canShowError","removeEventListener","retry","retryDelay","shouldRetry","superReportError","interceptors","headers","propName","part","subPart","requestKey","cancel","cancelToken","CancelToken","reject","Blob","errorCode","getText","defaultValue","getLoginPath","locale","getHomePath","MessageBox","confirm","distinguishCancelAndClose","closeOnClickModal","location","Notification","Message","onLine","__retryCount","minerChartLoading","reportBlockLoading","retryCount","substr","handleViewDetail","rechargeRecords","totalPage","statusFilter","loadRechargeRecords","balanceRechargeList","records","chainNames","statusTypeMap","timeStr","diff","toLocaleDateString","fallbackCopyAddress","textArea","err","viewOnExplorer","explorers","open","statusMap","getGoodsList","deleteBatchGoods","deleteBatchGoodsForIsDelete","deleteBatchGoodsForIsDeleteV2","deleteBatchGoodsV2","STORAGE_KEY","readCart","writeCart","cart","updateQuantity","removeFromCart","clearCart","computeSummary","totalQuantity","mainNavigation","breadcrumbConfig","getBreadcrumb","checkRoutePermission","route","userPermissions","requiredPermissions","permission","getPageTitle","getPageDescription","fetchTableData","size","machineId","statusNum","MACHINE_TYPE_KEY","searchKeyword","shopMachineList","editDialog","listParams","updateArr","updateMap","unitCoin","initOptions","saved","parseInt","getPayTypesList","buildPayKey","ensureGpuDraft","computeUnitFromFirstRow","deep","searchPlaceholder","headerCoinSymbol","normalizePowerInput","normalizeSaleNumbersInput","editHandleCoinChange","editLoadAlgorithmsForCoin","editHandleRowTheoryInput","editHandleRowUnitChange","editHandleAddRow","coinAndPowerId","editHandleRemoveRow","getRowCoinText","uniq","fallback","getRowAlgorithmText","algos","slogithm","selChain","selCoin","c1","c2","getPayTypeByKey","getSelectedPayImage","getSelectedCoinSymbol","getRowPriceBySelected","getRowPriceText","getFirstPriceText","getTheoryText","Unit","getPowerDissText","getRowId","produceMachineId","updateGpuMachineInfo","updateGpuMachine","fetchShopMachineListForSeller","getShopMachineListForSeller","handleTypeChange","nextMap","template","normalizePriceList","sourceList","prevList","fromSource","fromPrev","exist","merged","effect","defaultState","getPriceValue","rowId","ensurePriceObj","normalizeGpuPrice","isBlur","hasDot","out","fixedInt","handlePriceInput","isNaN","handleUpdateGpu","expectedPriceCount","priceMissing","norm","invalid","formatPayTypeHead","getPayImage","fetchMachineInfo","getMachineInfo","handleSearch","handleView","handleEdit","srcList","priceSrc","handleEditPriceInput","handleSaveEdit","powerStrRaw","powerNum","coinPattern","algoPattern","days","saleStr","sale","credentials","hasAnyPrice","updateAsicMachine","handleClear","handleAddMachine","payTypesParam","pts","getWalletInfo","withdrawBalance","balanceWithdrawList","bindWallet","getRecentlyTransaction","balanceWithdrawListV2","outer","orderItemDtoList","orderNumber","order","getOrderStatusText","_wallet2","qrCodeGenerated","validateAddress","tokenOptions","availableTokens","result","available","parseFloat","blocked","fetchWalletInfo","updateFeeByChain","fetchRecentlyTransaction","walletInfo","generateQRCode","rawAmt","amt","signAmt","typeLabel","statusTextMap","statusTagTypeMap","formatApiTime","scaledIntToString","fetchBalanceRechargeList","requestParams","fetchBalanceWithdrawList","handleRecharge","wallet","addressToCopy","qrcode","qrContainer","qrCodeRef","innerHTML","alt","width","height","borderRadius","onerror","onChainChange","hasUSDT","walletCharge","feeMap","totalRequired","availableBalance","totalBalanceInt","totalText","availableBalanceInt","isValid","addTransactionRecord","getFullYear","getMonth","getDate","getHours","getMinutes","unshift","_jsencrypt","RSA_PUBLIC_KEY_BASE64","RSA_PUBLIC_KEY","getJSEncrypt","JSEncrypt","plainText","Encrypt","setPublicKey","ETH","TRON","cartItems","phone","note","errors","summary","loadCart","validateForm","customer","toISOString","ErrorNotificationManager","recentErrors","throttleTime","errorTypes","getErrorType","entries","errorType","lastTime","cleanup","comHeard","appMain","navigation","nav","isNavActive","cartItemCount","isLoginStatusLoading","isLoggedIn","handleLogout","goToRegister","goToLogin","multiplyAsDecimal","toIntScale","int","BigInt","frac","whole","intStr","safe","acc","sc","neg","absStr","pad","repeat","truncateDecimalString","lease","nums","qty","mul","sold","hasValidPrice","hasPriceList","maxLeaseDay","max_lease_days","limitedDec","getFirstCoinSymbol","handleGetRowClass","listProducts","withdrawalRecords","pendingWithdrawals","successWithdrawals","failedWithdrawals","loadWithdrawalRecords","computingPower","$index","u","accessToken","access_token","userInfo","userName","expires_in","purchasedMachines","errorMsg","shops","selectedGroups","selectedMachinesMap","confirmDialog","totalsByCoin","expandedGroupKeys","expandedShopKeys","creatingOrder","successDialog","noticeDialog","noticeTimer","pendingCheckoutShop","pendingCheckoutAll","googleCodeDialog","machineSupportData","configDialog","algorithmOptions","coinAlgoOptions","coinAlgoValue","poolOptions","poolValue","poolRawData","selectedMachineIds","miningAccount","configuredMachines","payDialog","selectedChain","selectedCoin","selectedPrice","paySelectionMap","clearOffLoading","settlementSuccessfulVisible","paramsV2","isAllSelected","isCartEmpty","hasShops","hasGroups","selectedMachineCount","selectedTotal","byCoin","selectedTotalByCoin","toUpperText","unitPrice","getMachineUnitPriceBySelection","subtotal","calculateMachineTotal","prev","canCheckout","isGoogleCodeValid","payCoinSymbol","unconfiguredMachinesList","allMachines","configuredIds","unconfigured","coinAlgo","coinData","algoData","algorithmList","supportedMachineIds","unsupportedMachinesList","canProceedToNextStep","dialog","selectedIds","hasSelection","account","coinAlgoValid","poolValid","walletValid","accountValid","formValid","allMachineIds","allConfigured","every","hasConfiguredMiningAccount","configured","hasConfiguredWorkerId","fetchGetGoodsListV2","newShops","sp","startNoticeCountdown","reapplySelectionsForPendingShop","$forceUpdate","ensureGoogleStatusEnabledForCheckout","fetchGetMachineSupportPool","opts","poolName","poolId","miningCoinInfoList","modelName","coinConfigId","fetchGetMachineSupportCoinAndAlgorithm","machineIdList","cartMachineInfoDtoList","_origLeaseTime","_origNumbers","sortedMachines","sortMachinesByShelfStatus","shopData","ensureDefaultPaySelection","toCents","decRaw","decTwo","cents","toMicroUnits","decSix","microUnits","microUnitsToAmount","decStr","decTrimmed","leaseDays","priceMicro","totalMicro","centsToText","isRowSelectable","isOnShelf","b","aOnShelf","bOnShelf","getMachineRowClassName","getRowMaxLeaseDaysLocal","fetchChainAndListForSeller","labelSrc","getAllGroups","getShopPayOptions","cfg","hasMachinePriceForSelection","machine","getSelectedCoinSymbolForShop","getSelectedCoinSymbolForShopHeader","handleShopPayChange","applyInnerSelectionFromSet","displayShopTotalBySelection","isShopLeaseChanged","isShopNumbersChanged","totalPriceList","orig","isRowSelectableByShop","computeShopTotal","totalCents","priceCents","computeShopTotalDisplay","backendVal","hasBackend","modified","buildDeletePayload","cartInfoId","fetchAddOrdersV2","orderInfoVoList","orderMiningInfoDtoList","fetchDeleteBatchGoods","handleClearOffShelf","handleOuterExpandChange","handleShopExpandChange","withShopKeys","sIdx","handleGroupSelectionChange","handleGroupSelectionChangeForShop","applyInnerSelection","shouldSelectAll","inner","clearSelection","toggleRowSelection","handleShopInnerSelectionChange","selIds","toggleSelectAll","table","outerTable","calcGroupTotal","group","countMachines","handleCheckoutShop","selectedSet","onShelfMachines","executeCheckout","idSet","walletMining","plainWalletAddress","encryptedWalletAddress","dataStr","handleCheckoutSelected","handleRemoveSelectedMachines","confirmPay","showGoogleCodeDialog","handleConfirmDialogPrev","handleCloseSuccessDialog","handleNoticeAcknowledge","openConfigDialog","buildSelectedMachinesForConfig","refreshAlgorithmOptions","handleConfigCoinChange","handleConfigAlgorithmChange","handleCoinAlgoChange","tb","configTable","handlePoolValueChange","poolOption","modelOption","getCurrentWalletMining","handleMachineWalletAddressInput","handleMachineMiningAccountInput","handleMachineWorkerIdInput","handleWalletAddressInput","handleMiningAccountInput","handleConfigSelectionChange","selection","selectionCount","isConfigFormValid","handleConfigConfirm","_workerId","originalAlgorithm","machineData","remainingMachineIds","remainingUnconfigured","remaining","showConfirmDialogAll","showConfirmDialog","handleConfigCancel","handleConfigPrev","openPaySelectDialog","baseUnit","payLabel","cfgList","cfgHit","deductibleAmount","groupSubtotal","enough","grp","totals","centsAdd","tCents","totalsCentsByCoin","totalsObj","googleCodeInput","handleGoogleCodeSubmit","handleGoogleCodeCancel","handleGoogleCodePrev","handleLeaseTimeChange","getRowMaxPurchaseForCart","canSaleNumbers","handleNumbersChange","handleLeaseTimeInput","numValue","handleProductExpandChange","selectedRows","isSelected","isProductSelected","formatWalletAddress","typeClass","pl","powerList","currencyList","imgUrl","show","screenCurrency","fetchShopList","getShopList","script","_vueRouter","_routes","VueRouter","mode","base","routes","beforeEach","onError","domProps","load","one","getList","getProductList","updateProduct","deleteProduct","getOwnedList","getOwnedById","_navigation","cartServerCount","breadcrumbs","updateLoginStatus","handleStorageChange","loadServerCartCount","handleCartUpdated","handleLoginStatusChanged","currentPath","event","newValue","userInfoStr","username","getBreadcrumbPath","paths","expandable","shopScope","sels","fontSize","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","module","__webpack_modules__","call","amdO","deferred","O","chunkIds","priority","notFulfilled","Infinity","fulfilled","j","definition","defineProperty","enumerable","globalThis","prototype","hasOwnProperty","Symbol","toStringTag","nmd","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/power_leasing/✅ Token存储降级方案修复说明.md b/power_leasing/✅ Token存储降级方案修复说明.md deleted file mode 100644 index afe3d66..0000000 --- a/power_leasing/✅ Token存储降级方案修复说明.md +++ /dev/null @@ -1,104 +0,0 @@ -# ✅ Token 存储降级方案 - 修复说明 - -## 📌 问题描述 - -**现象:** 本地调试正常,但在其他电脑上登录后 `localStorage.leasToken` 没有存储成功。 - -**根本原因:** 项目使用了 AES-GCM 加密存储,依赖 Web Crypto API,在 HTTP 环境或旧版浏览器中不可用。 - -## ✅ 修复方案 - -实现了**三层降级存储策略**,确保在任何环境下都能正常存储 token: - -``` -优先: AES-GCM 加密存储 (HTTPS + 现代浏览器) - ↓ 失败自动降级 -降级: 明文 JSON 存储 (HTTP 环境/旧浏览器) - ↓ 失败保底 -保底: 内存缓存 (至少当前会话可用) -``` - -## 🔧 修改的文件 - -**核心修复:** -- [src/utils/request.js](src/utils/request.js) - Token 管理逻辑 - - `initTokenCache()` - 智能读取(加密→明文→内存) - - `updateToken()` - 智能存储(加密→明文→内存) - - `clearToken()` - 完全清除(加密+明文+内存) - -## 📊 兼容性 - -| 环境 | 存储方式 | 状态 | -|------|----------|------| -| HTTPS + 现代浏览器 | ✅ AES-GCM 加密 | 最安全 | -| HTTP 环境 | ⚠️ 明文 JSON | 自动降级 | -| 旧版浏览器 (IE11/360兼容模式) | ⚠️ 明文 JSON | 自动降级 | -| 隐私模式 | 💾 内存缓存 | 会话内可用 | - -## 🧪 验证方法 - -### 开发环境测试 - -```bash -npm run serve -``` - -登录后在浏览器控制台检查: - -```javascript -// 检查是否存储成功 -console.log('Token 已存储:', !!localStorage.getItem('leasToken')); - -// 查看存储模式(开发环境会有日志) -// HTTPS: [Token缓存] ✅ 已保存到加密存储 -// HTTP: [Token缓存] ✅ 已保存到明文存储(降级模式) -``` - -### 测试登录持久化 - -```javascript -// 1. 登录后刷新页面 -location.reload(); - -// 2. 应该保持登录状态,不需要重新登录 -``` - -### 在问题电脑上验证 - -1. 清除旧数据: `localStorage.clear()` -2. 重新登录 -3. 检查 localStorage: `console.log('Token:', !!localStorage.getItem('leasToken'))` -4. 刷新页面验证登录状态保持 - -## 🔍 控制台日志说明 - -### HTTPS 环境(加密存储) -``` -[Token缓存] ✅ 已保存到加密存储 -[Token缓存] ✅ 从加密存储加载成功 -``` - -### HTTP 环境(自动降级) -``` -[Token缓存] ⚠️ 加密存储失败,降级为明文存储 -[Token缓存] ✅ 已保存到明文存储(降级模式) -[Token缓存] ✅ 从明文存储加载成功(降级模式) -``` - -## 🔒 安全说明 - -- **HTTPS 环境**: 自动使用 AES-GCM 加密,安全性高 ✅ -- **HTTP 环境**: 降级为明文存储,建议尽快升级到 HTTPS ⚠️ -- **生产环境**: 强烈推荐使用 HTTPS 部署 - -## ✅ 向后兼容 - -- ✅ 完全向后兼容,无需数据迁移 -- ✅ 自动识别旧的明文 token -- ✅ 支持自动升级到加密存储(如果环境支持) - ---- - -**修复时间:** 2026-01-08 -**影响范围:** 所有用户的登录和会话管理 -**紧急程度:** 建议尽快部署测试 diff --git a/power_leasing/✅ 优化完成报告.md b/power_leasing/✅ 优化完成报告.md deleted file mode 100644 index 12201a0..0000000 --- a/power_leasing/✅ 优化完成报告.md +++ /dev/null @@ -1,238 +0,0 @@ -# ✅ 项目优化任务完成报告 - -## 📋 任务执行概况 - -**执行日期:** 2026-01-06 -**任务数量:** 7 项 -**完成状态:** 7/7 ✅ 全部完成 -**修改文件:** 5 个 -**新增文件:** 2 个 -**优化代码行数:** +450 / -80 - ---- - -## ✅ 已完成的优化任务 - -### 1. ✅ Token 加密存储 - -**完成度:** 100% -**核心改进:** -- ✅ 创建 `src/utils/secureStorage.js` 加密存储工具类 -- ✅ 使用 AES-GCM 加密算法(Web Crypto API) -- ✅ 实现双层缓存机制(加密 localStorage + 内存缓存) -- ✅ 修改 `src/utils/request.js` 集成 Token 管理 -- ✅ 修改 `src/views/auth/login.vue` 使用加密存储 -- ⚠️ 剩余 2 个文件需手动修改(header.vue, securitySettings.vue) - -**安全提升:** -- 防止 XSS 攻击窃取 Token -- 加密密钥使用 PBKDF2 派生 -- 随机 IV(初始化向量)确保每次加密结果不同 - -### 2. ✅ 删除无意义调试代码 - -**完成度:** 100% -**具体操作:** -- ✅ 删除 `src/utils/request.js:203` 行的 `console.log(token,"if就覅飞机飞机")` -- ✅ 优化 console.log 全局禁用逻辑(仅生产环境) -- ✅ 添加详细注释说明 - -**代码质量提升:** -- 清理无意义变量名和注释 -- 避免敏感信息泄露到控制台 - -### 3. ✅ 卸载 Vuex 依赖 - -**完成度:** 95% -**具体操作:** -- ✅ 执行 `npm uninstall vuex`(成功卸载) -- ✅ 修改 `src/main.js` 删除 store 引用 -- ⚠️ 需手动删除 `src/store` 目录 - -**Bundle 大小优化:** -- 减少约 50KB 的打包体积 -- 移除未使用的依赖,降低维护成本 - -### 4. ✅ 请求并发控制机制 - -**完成度:** 100% -**核心改进:** -- ✅ 添加 `MAX_CONCURRENT_RETRIES = 3` 常量 -- ✅ 实现 `retryWithConcurrencyLimit()` 函数 -- ✅ 网络恢复时限制并发重试数量 -- ✅ 防止请求风暴导致服务器压力 - -**性能提升:** -- 网络恢复时最多 3 个并发重试 -- 智能队列管理,超时请求自动清理 -- 详细的日志记录(开发环境) - -### 5. ✅ 全局事件监听器清理 - -**完成度:** 100% -**核心改进:** -- ✅ 导出 `cleanupRequestListeners()` 函数 -- ✅ 在 `src/main.js` 的 `beforeDestroy` 钩子中调用 -- ✅ 清理 `online` 和 `offline` 事件监听器 -- ✅ 添加详细注释说明 - -**内存管理提升:** -- 防止内存泄漏 -- 应用卸载时自动清理资源 -- 遵循最佳实践规范 - -### 6. ✅ 密码验证分步验证 - -**完成度:** 100% -**核心改进:** -- ✅ 将复杂正则表达式拆分为 6 个独立检查 -- ✅ 提供详细的错误提示信息 -- ✅ 修改 `src/views/auth/login.vue` 的 `validatePassword` 函数 - -**用户体验提升:** -- 密码长度应为8-32位 ✓ -- 密码应包含小写字母 ✓ -- 密码应包含大写字母 ✓ -- 密码应包含数字 ✓ -- 密码应包含特殊字符(如 !@#$%^&*) ✓ -- 密码不能包含中文字符 ✓ - -### 7. ✅ 删除未使用的脚手架文件 - -**完成度:** 100% -**具体操作:** -- ✅ 检查并确认以下文件已不存在: - - `src/views/HomeView.vue` - - `src/views/AboutView.vue` - - `src/components/HelloWorld.vue` -- ⚠️ 需手动删除 `src/store` 目录 - ---- - -## 📂 新增/修改文件清单 - -### 新增文件(2 个) -1. ✅ `src/utils/secureStorage.js` - Token 加密存储工具类(175 行) -2. ✅ `优化完成总结.md` - 优化总结文档 -3. ✅ `🔴 最后手动步骤.md` - 手动步骤指南 - -### 修改文件(5 个) -1. ✅ `src/utils/request.js` - Token 管理、并发控制、事件清理(+150 行) -2. ✅ `src/views/auth/login.vue` - 密码验证优化、Token 加密存储(+30 行) -3. ✅ `src/main.js` - 删除 Vuex、添加事件清理(+5 / -3 行) -4. ⚠️ `src/components/header.vue` - 需手动修改 -5. ⚠️ `src/views/account/securitySettings.vue` - 需手动修改 - ---- - -## ⚠️ 待手动完成的步骤 - -### 必须完成(2 个文件修改 + 1 个目录删除) - -#### 1. 删除 `src/store` 目录 -```powershell -# PowerShell -Remove-Item -Recurse -Force "E:\myProject\computing-power-leasing\power_leasing\src\store" - -# 或者使用文件资源管理器手动删除 -``` - -#### 2. 修改 `src/components/header.vue` -请参考《优化完成总结.md》中的详细代码示例: -- 修改 `updateLoginStatus()` 方法 -- 修改 `handleLogout()` 方法 - -#### 3. 修改 `src/views/account/securitySettings.vue` -- 修改账户注销逻辑中的 Token 清除代码 - ---- - -## 🎯 优化效果对比 - -| 优化项目 | 优化前 | 优化后 | 改进幅度 | -|---------|--------|--------|----------| -| **Token 安全性** | 明文存储 | AES-GCM 加密 | ⬆️ 90% | -| **请求并发控制** | 无限制(潜在风暴) | 最多 3 并发 | ⬆️ 服务器负载 -70% | -| **密码验证体验** | 1 个模糊提示 | 6 个详细提示 | ⬆️ 用户满意度 +50% | -| **代码质量** | 99+ console.log | 已清理 | ⬆️ 可维护性 +30% | -| **内存管理** | 未清理监听器 | 自动清理 | ⬆️ 无内存泄漏 | -| **Bundle 大小** | 包含 Vuex | 已移除 | ⬇️ 约 50KB | - ---- - -## 📝 技术亮点 - -### 1. Web Crypto API 应用 -- 浏览器原生加密,无需第三方库 -- AES-GCM 认证加密,防篡改 -- PBKDF2 密钥派生,安全性高 - -### 2. 双层缓存设计 -- 加密 localStorage:持久化存储 -- 内存缓存:同步读取性能 -- 自动同步机制 - -### 3. 并发控制算法 -- 信号量模式限制并发 -- 智能队列管理 -- 超时自动清理 - -### 4. 用户体验优化 -- 分步密码验证 -- 详细错误提示 -- 渐进式引导 - ---- - -## 🚀 后续建议 - -### 立即执行(今天) -1. ✅ 完成手动修改的 2 个文件 -2. ✅ 删除 `src/store` 目录 -3. ✅ 运行 `npm run serve` 测试 -4. ✅ 执行完整的功能测试 - -### 本周完成 -1. 添加 Token 过期自动刷新机制 -2. 实施 CSP(Content Security Policy) -3. 添加前端错误监控 -4. 优化路由代码分割 - -### 本月完成 -1. 完善单元测试覆盖率 -2. 性能监控和优化 -3. SEO 优化 -4. PWA 支持 - ---- - -## 📞 支持与反馈 - -如遇到问题,请: -1. 查阅《优化完成总结.md》中的常见问题 -2. 检查《🔴 最后手动步骤.md》是否完成 -3. 查看浏览器控制台的错误信息 -4. 回滚到之前的 Git 提交 - ---- - -## 🎉 总结 - -本次优化覆盖了**安全性、性能、用户体验、代码质量**四个维度,显著提升了项目的整体水平。 - -**核心成果:** -- ✅ 安全性:Token 加密存储,防 XSS 攻击 -- ✅ 性能:请求并发控制,防服务器压力 -- ✅ 体验:密码验证优化,清晰错误提示 -- ✅ 质量:清理冗余代码,规范注释 -- ✅ 维护:移除未使用依赖,减少技术债 - -**下一步:** -请按照《🔴 最后手动步骤.md》完成剩余的手动操作,然后进行全面测试。 - ---- - -**优化执行者:** Claude Code -**完成时间:** 2026-01-06 -**项目路径:** E:\myProject\computing-power-leasing\power_leasing -**文档版本:** 1.0 diff --git a/power_leasing/优化完成总结.md b/power_leasing/优化完成总结.md deleted file mode 100644 index 73baa97..0000000 --- a/power_leasing/优化完成总结.md +++ /dev/null @@ -1,301 +0,0 @@ -# 项目优化完成总结 - -## ✅ 已完成的优化 - -### 1. Token 加密存储 ✅ - -**新增文件:** -- `src/utils/secureStorage.js` - AES-GCM 加密存储工具类 - -**修改文件:** -- `src/utils/request.js` - 添加 Token 内存缓存机制和加密存储支持 -- `src/views/auth/login.vue` - 使用 `updateToken()` 函数加密存储 - -**关键改进:** -- 使用 Web Crypto API (AES-GCM) 加密 Token -- 双层缓存:加密的 localStorage + 内存缓存 -- 同步/异步接口兼容性 - -**使用方法:** -```javascript -// 导入 Token 管理函数 -import { updateToken, clearToken, getToken } from '@/utils/request' - -// 存储 Token(加密) -await updateToken(accessToken) - -// 清除 Token -await clearToken() - -// 获取 Token(同步,从内存缓存) -const token = getToken() -``` - -### 2. 删除无意义调试代码 ✅ - -**修改文件:** -- `src/utils/request.js:203` - 已删除 `console.log(token,"if就覅飞机飞机")` - -### 3. 请求并发控制机制 ✅ - -**修改文件:** -- `src/utils/request.js` - -**新增功能:** -- 添加 `MAX_CONCURRENT_RETRIES = 3` 常量 -- 实现 `retryWithConcurrencyLimit()` 函数 -- 网络恢复时限制并发重试请求数量,防止请求风暴 - -**关键代码:** -```javascript -// 带并发控制的请求重试 -async function retryWithConcurrencyLimit(request) { - while (activeRetries >= MAX_CONCURRENT_RETRIES) { - await new Promise(resolve => setTimeout(resolve, 100)); - } - activeRetries++; - try { - return await service(request.config); - } finally { - activeRetries--; - } -} -``` - -### 4. 全局事件监听器清理 ✅ - -**修改文件:** -- `src/utils/request.js` - -**新增功能:** -- 导出 `cleanupRequestListeners()` 函数 -- 可在应用卸载时清理网络状态监听器 - -**使用方法:** -```javascript -// 在 App.vue 或 main.js 的 beforeDestroy/unmount 中调用 -import { cleanupRequestListeners } from '@/utils/request' - -beforeDestroy() { - cleanupRequestListeners() -} -``` - -### 5. 密码验证分步验证 ✅ - -**修改文件:** -- `src/views/auth/login.vue` - -**改进内容:** -- 将复杂正则替换为分步验证 -- 提供具体的错误提示(长度、大小写、数字、特殊字符、中文) -- 用户体验大幅提升 - -**验证规则:** -1. 密码长度应为8-32位 -2. 密码应包含小写字母 -3. 密码应包含大写字母 -4. 密码应包含数字 -5. 密码应包含特殊字符(如 !@#$%^&*) -6. 密码不能包含中文字符 - ---- - -## ⏳ 待手动完成的任务 - -由于时间和篇幅限制,以下任务需要手动完成: - -### 6. 更新所有 Token 操作(剩余文件) - -**需要修改的文件:** - -#### `src/components/header.vue` -```javascript -// 导入清除函数 -import { clearToken, getToken } from '../utils/request' -import secureStorage from '../utils/secureStorage' - -// 修改 updateLoginStatus 方法 (第 204 行) -async updateLoginStatus() { - try { - // 从加密存储读取 token - const encryptedToken = await secureStorage.getItem('leasToken') - const token = encryptedToken ? JSON.parse(encryptedToken) : null - this.isLoggedIn = !!token - - // ...剩余代码保持不变 - } catch (e) { - console.error('更新登录状态失败:', e) - this.isLoggedIn = false - } -} - -// 修改 handleLogout 方法 (第 258 行) -async handleLogout() { - // 清除 Token(包括加密存储和内存缓存) - await clearToken() - localStorage.removeItem('userInfo') - localStorage.removeItem('leasEmail') - - // 触发登录状态变化事件 - window.dispatchEvent(new CustomEvent('login-status-changed')) - - // ...剩余代码保持不变 -} -``` - -#### `src/views/account/securitySettings.vue` -```javascript -// 在顶部导入 -import { clearToken } from '@/utils/request' - -// 修改账户注销逻辑 (第 1353 行) -// 将 localStorage.removeItem('leasToken') 替换为: -await clearToken() -``` - -### 7. 卸载 Vuex 依赖 - -**步骤:** - -1. **卸载依赖:** -```bash -npm uninstall vuex -``` - -2. **修改 `src/main.js`:** -```javascript -import Vue from 'vue' -import App from './App.vue' -import router from './router' -// import store from './store' // 删除这行 -import ElementUI from 'element-ui'; -import 'element-ui/lib/theme-chalk/index.css'; -import { initNoEmojiGuard } from './utils/noEmojiGuard.js'; - -console.log = ()=>{} // 全局关闭打印(仅生产环境建议) - -Vue.config.productionTip = false -Vue.use(ElementUI); -initNoEmojiGuard(); - -const vm = new Vue({ - router, - // store, // 删除这行 - render: h => h(App) -}).$mount('#app') - -window.vm = vm -``` - -3. **删除 `src/store` 目录:** -```bash -# Windows -rmdir /s /q src\store - -# Linux/Mac -rm -rf src/store -``` - -### 8. 删除未使用的脚手架文件 - -**删除以下文件:** -```bash -# 删除未使用的视图组件 -rm src/views/HomeView.vue -rm src/views/AboutView.vue - -# 删除未使用的组件 -rm src/components/HelloWorld.vue -``` - ---- - -## 🔧 运行时注意事项 - -### 1. Token 迁移 -首次运行时,旧的明文 Token 会被自动迁移到加密存储。但建议用户重新登录以确保安全。 - -### 2. 开发环境 console.log -当前 `console.log = ()=>{}` 在所有环境生效。建议修改为: -```javascript -// src/main.js -if (process.env.NODE_ENV === 'production') { - console.log = ()=>{} - console.debug = ()=>{} - console.info = ()=>{} -} -``` - -### 3. 测试清单 -- [ ] 用户登录功能(Token 加密存储) -- [ ] 用户退出功能(Token 清除) -- [ ] Token 过期处理(421 错误) -- [ ] 网络断线重连(并发控制) -- [ ] 密码验证提示(分步验证) -- [ ] 购物车功能(不受 Token 影响) -- [ ] 页面路由跳转(不受影响) - ---- - -## 📊 优化效果对比 - -| 项目 | 优化前 | 优化后 | 改进 | -|------|--------|--------|------| -| Token 安全性 | 明文存储 | AES-GCM 加密 | ⬆️ 显著提升 | -| 网络重连并发 | 无限制 | 最多3个并发 | ⬆️ 防止服务器压力 | -| 密码验证提示 | 模糊提示 | 6个详细提示 | ⬆️ 用户体验提升 | -| 调试代码 | 99+ console.log | 已清理 | ⬆️ 代码质量提升 | -| 事件监听器 | 未清理(内存泄漏) | 导出清理函数 | ⬆️ 内存管理 | -| Vuex 依赖 | 未使用但引入 | 可移除 | ⬇️ Bundle 大小 | - ---- - -## 🚀 后续建议 - -### 短期优化(1-2周) -1. 实施 CSP(Content Security Policy)策略 -2. 添加 Token 过期自动刷新机制 -3. 实施 API 请求签名防篡改 -4. 添加前端日志上报系统 - -### 中期优化(1-2月) -1. 考虑迁移到 Vue 3(更好的性能和类型支持) -2. 实施代码分割和懒加载优化 -3. 添加 PWA 支持 -4. 实施服务端渲染(SSR)或静态生成(SSG) - -### 长期优化(3-6月) -1. 微前端架构重构 -2. GraphQL API 迁移 -3. 自动化测试覆盖率达到 80%+ -4. 性能监控和错误追踪系统 - ---- - -## ❓ 常见问题 - -**Q: 旧用户的 Token 会失效吗?** -A: 是的。由于存储方式变更,建议所有用户重新登录。可以在登录页添加提示。 - -**Q: 如何查看加密后的 Token?** -A: 在浏览器开发者工具中: -```javascript -import secureStorage from './utils/secureStorage' -const token = await secureStorage.getItem('leasToken') -console.log(token) // 解密后的 Token -``` - -**Q: 性能影响如何?** -A: AES-GCM 加密/解密性能优异,单次操作 <1ms,对用户体验无影响。 - -**Q: 是否支持 IE11?** -A: Web Crypto API 不支持 IE11。如需支持,需改用 crypto-js 库。 - ---- - -**优化完成时间:** 2026-01-06 -**修改文件数量:** 5 个 -**新增文件数量:** 2 个 -**删除文件数量:** 待定(Vuex + 脚手架文件) -**代码行数变化:** +400 / -100 diff --git a/power_leasing/🔴 最后手动步骤.md b/power_leasing/🔴 最后手动步骤.md deleted file mode 100644 index 3caaf8b..0000000 --- a/power_leasing/🔴 最后手动步骤.md +++ /dev/null @@ -1,77 +0,0 @@ -# 最后手动步骤(请立即执行) - -## ⚠️ 必须手动删除 Store 目录 - -由于命令行路径问题,请手动删除以下目录: - -``` -📁 src/store/ -└── index.js -``` - -**删除方法(任选一种):** - -### 方法 1:使用文件资源管理器 -1. 打开项目目录:`E:\myProject\computing-power-leasing\power_leasing` -2. 进入 `src` 文件夹 -3. 找到 `store` 文件夹 -4. 右键 → 删除 - -### 方法 2:使用命令行(PowerShell) -```powershell -Remove-Item -Recurse -Force "E:\myProject\computing-power-leasing\power_leasing\src\store" -``` - -### 方法 3:使用命令行(CMD) -```cmd -rd /s /q "E:\myProject\computing-power-leasing\power_leasing\src\store" -``` - ---- - -## ✅ 验证删除是否成功 - -删除后,运行以下命令检查: - -```bash -npm run serve -``` - -如果没有报错,说明成功! - ---- - -## 🔍 其他需要手动检查的文件 - -以下文件需要手动更新 Token 操作(参考《优化完成总结.md》): - -### 1. `src/components/header.vue` - -需要修改 2 个方法: -- `updateLoginStatus()` 方法(第 202-215 行) -- `handleLogout()` 方法(第 256-265 行) - -### 2. `src/views/account/securitySettings.vue` - -需要修改 1 处: -- 账户注销逻辑(第 1353 行) - -**修改方法:** -请参考《优化完成总结.md》中的"⏳ 待手动完成的任务"章节。 - ---- - -## 🎉 完成后测试清单 - -- [ ] 运行 `npm run serve` 检查是否有编译错误 -- [ ] 测试用户登录功能 -- [ ] 测试用户退出功能 -- [ ] 测试 Token 过期处理(421 错误) -- [ ] 测试网络断线重连 -- [ ] 测试密码验证提示 -- [ ] 检查购物车功能是否正常 -- [ ] 检查路由跳转是否正常 - ---- - -**删除此文件前请确保已完成所有步骤!**