351 lines
15 KiB
Vue
351 lines
15 KiB
Vue
<template>
|
||
<div v-loading="payLoading">
|
||
<div v-if="!safeItems.length" class="empty">{{ emptyText }}</div>
|
||
<el-table v-else :data="safeItems" border :header-cell-style="{ textAlign: 'left' }" :cell-style="{ textAlign: 'left' }">
|
||
<el-table-column type="expand" width="46">
|
||
<template #default="outer">
|
||
<el-table :data="outer.row.orderItemDtoList || []" size="small" border :header-cell-style="{ textAlign: 'left' }" :cell-style="{ textAlign: 'left' }" row-key="productMachineId">
|
||
<el-table-column prop="productMachineId" label="机器ID" min-width="120" />
|
||
<el-table-column prop="name" label="名称" min-width="160" />
|
||
<el-table-column prop="payCoin" label="币种" min-width="100" />
|
||
<el-table-column prop="address" label="收款地址" min-width="240" />
|
||
<el-table-column prop="leaseTime" label="租赁天数" min-width="100" />
|
||
<el-table-column prop="price" label="售价(USDT)" min-width="240">
|
||
<template #default="scope">
|
||
<span class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(scope.row.price, scope.row.payCoin || 'USDT').truncated"
|
||
:content="formatAmount(scope.row.price, scope.row.payCoin || 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(scope.row.price, scope.row.payCoin || 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(scope.row.price, scope.row.payCoin || 'USDT').text }}</span>
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</template>
|
||
</el-table-column>
|
||
|
||
<el-table-column label="订单号" min-width="220">
|
||
<template #default="scope"><span class="value mono">{{ scope.row && scope.row.orderNumber || '—' }}</span></template>
|
||
</el-table-column>
|
||
|
||
<el-table-column label="创建时间" min-width="180">
|
||
<template #default="scope">{{ formatDateTime(scope.row && scope.row.createTime) }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="商品数" min-width="100">
|
||
<template #default="scope">{{ Array.isArray(scope.row && scope.row.orderItemDtoList) ? scope.row.orderItemDtoList.length : 0 }}</template>
|
||
</el-table-column>
|
||
<el-table-column label="总金额(USDT)" min-width="140">
|
||
<template #default="scope">
|
||
<span class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(scope.row && scope.row.totalPrice, 'USDT').truncated"
|
||
:content="formatAmount(scope.row && scope.row.totalPrice, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(scope.row && scope.row.totalPrice, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(scope.row && scope.row.totalPrice, 'USDT').text }}</span>
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column min-width="180">
|
||
<template #header>
|
||
<el-tooltip placement="top" effect="dark">
|
||
<div slot="content">
|
||
实际支付金额/理论支付金额:<br/>
|
||
1. 实际支付金额是按照矿机实际算力计算支付金额<br/>
|
||
2. 理论支付金额是卖家定义出售价格
|
||
</div>
|
||
<span style="display:inline-flex;align-items:center;gap:6px;">
|
||
<i class="el-icon-question" style="color:#909399;" aria-label="说明" role="img"></i>
|
||
已支付金额(USDT)
|
||
</span>
|
||
</el-tooltip>
|
||
</template>
|
||
<template #default="scope">
|
||
<span class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(scope.row && scope.row.payAmount, 'USDT').truncated"
|
||
:content="formatAmount(scope.row && scope.row.payAmount, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(scope.row && scope.row.payAmount, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(scope.row && scope.row.payAmount, 'USDT').text }}</span>
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="待支付金额(USDT)" min-width="140">
|
||
<template #default="scope">
|
||
<span class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(scope.row && scope.row.noPayAmount, 'USDT').truncated"
|
||
:content="formatAmount(scope.row && scope.row.noPayAmount, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(scope.row && scope.row.noPayAmount, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(scope.row && scope.row.noPayAmount, 'USDT').text }}</span>
|
||
</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column label="操作" min-width="280" fixed="right">
|
||
<template #default="scope">
|
||
<el-button size="mini" @click="handleGoDetail(scope.row)" style="margin-right:8px;">详情</el-button>
|
||
<template v-if="shouldShowActions(scope.row)">
|
||
<el-button type="primary" size="mini" @click="handleCheckout(scope.row)">去结算</el-button>
|
||
<!-- <el-button type="danger" size="mini" style="margin-left:8px;" @click="handleCancel(scope.row)">取消订单</el-button> -->
|
||
</template>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<!-- 修改功能之前 跟购物车弹窗一样
|
||
<el-dialog :visible.sync="orderDialog.visible" width="520px" title="请扫码支付">
|
||
<div style="text-align:left; margin-bottom:12px; color:#666;">
|
||
<div style="margin-bottom:6px;">支付币种:<b>{{ orderDialog.coin }}</b></div>
|
||
<div style="margin-bottom:6px;">支付金额(USDT):<b class="value strong">{{ orderDialog.amount }}</b></div>
|
||
<div style="word-break:break-all;">收款地址:<code>{{ orderDialog.address }}</code></div>
|
||
</div>
|
||
<div style="text-align:left;">
|
||
<img v-if="orderDialog.qrContent" :src="orderDialog.qrContent" alt="支付二维码" style="width:240px;height:240px;" />
|
||
<div v-else style="color:#666;">未返回支付二维码</div>
|
||
</div>
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="orderDialog.visible=false">关闭</el-button>
|
||
</span>
|
||
</el-dialog> -->
|
||
|
||
|
||
|
||
<el-dialog :visible.sync="dialogVisible" width="520px" title="请扫码支付">
|
||
<div style="text-align:left; margin-bottom:12px; color:#666;">
|
||
<div style="margin-bottom:6px;">总金额(USDT):
|
||
<b>
|
||
<el-tooltip
|
||
v-if="formatAmount(paymentDialog.totalPrice, 'USDT').truncated"
|
||
:content="formatAmount(paymentDialog.totalPrice, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(paymentDialog.totalPrice, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(paymentDialog.totalPrice, 'USDT').text }}</span>
|
||
</b>
|
||
</div>
|
||
<div style="margin-bottom:6px;display:flex;align-items:center;gap:6px;">
|
||
<el-tooltip placement="top" effect="dark">
|
||
<div slot="content">
|
||
实际支付金额/理论支付金额:<br/>
|
||
1. 实际支付金额是按照矿机实际算力计算支付金额<br/>
|
||
2. 理论支付金额是卖家定义出售价格
|
||
</div>
|
||
<i class="el-icon-question" style="color:#909399;" aria-label="说明" role="img"></i>
|
||
</el-tooltip>
|
||
<span>已支付金额(USDT):</span>
|
||
<b class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(paymentDialog.payAmount, 'USDT').truncated"
|
||
:content="formatAmount(paymentDialog.payAmount, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(paymentDialog.payAmount, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(paymentDialog.payAmount, 'USDT').text }}</span>
|
||
</b>
|
||
</div>
|
||
<div style="margin-bottom:6px;">待支付金额(USDT):
|
||
<b class="value strong">
|
||
<el-tooltip
|
||
v-if="formatAmount(paymentDialog.noPayAmount, 'USDT').truncated"
|
||
:content="formatAmount(paymentDialog.noPayAmount, 'USDT').full"
|
||
placement="top"
|
||
>
|
||
<span>
|
||
{{ formatAmount(paymentDialog.noPayAmount, 'USDT').text }}
|
||
<i class="el-icon-more amount-more"></i>
|
||
</span>
|
||
</el-tooltip>
|
||
<span v-else>{{ formatAmount(paymentDialog.noPayAmount, 'USDT').text }}</span>
|
||
</b>
|
||
</div>
|
||
<!-- <div style="word-break:break-all;">收款地址:<code>{{ orderDialog.address }}</code></div> -->
|
||
</div>
|
||
<div style="text-align:center;">
|
||
<img v-if="paymentDialog.img" :src="paymentDialog.img" alt="支付二维码" style="width:180px;height:180px;margin-top: 18px;" />
|
||
<div v-else style="color:#666;">未返回支付二维码</div>
|
||
</div>
|
||
<p style="margin-bottom:6px;color:red;text-align:left">注意:如果已经支付对应金额,不要在重复支付,待系统确认后会自动更新订单状态。因个人原因重复支付导致无法退款,平台不承担任何责任。</p>
|
||
|
||
<span slot="footer" class="dialog-footer">
|
||
<el-button @click="dialogVisible=false">关闭</el-button>
|
||
</span>
|
||
</el-dialog>
|
||
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import { addOrders } from '../../api/order'
|
||
import { truncateAmountByCoin } from '../../utils/amount'
|
||
export default {
|
||
name: 'OrderList',
|
||
props: {
|
||
items: { type: Array, default: () => [] },
|
||
emptyText: { type: String, default: '暂无数据' },
|
||
showCheckout: { type: Boolean, default: false },
|
||
onCancel: { type: Function, default: null }
|
||
},
|
||
data() {
|
||
return {
|
||
payLoading: false,
|
||
orderDialog: { visible: false, qrContent: '', coin: '', amount: '', address: '' },
|
||
dialogVisible: false,
|
||
paymentDialog: { totalPrice: "", payAmount: '', noPayAmount: '', img: '', }
|
||
}
|
||
},
|
||
computed: {
|
||
safeItems() {
|
||
return Array.isArray(this.items) ? this.items : []
|
||
}
|
||
},
|
||
methods: {
|
||
formatAmount(value, coin) {
|
||
return truncateAmountByCoin(value, coin)
|
||
},
|
||
buildQrSrc(img) {
|
||
if (!img) return ''
|
||
try { const s = String(img).trim(); return s.startsWith('data:') ? s : `data:image/png;base64,${s}` } catch (e) { return '' }
|
||
},
|
||
formatDateTime(value) {
|
||
if (!value) return '—'
|
||
try { const str = String(value); return str.includes('T') ? str.replace('T', ' ') : str } catch (e) { return String(value) }
|
||
},
|
||
async handleCheckout(row) {
|
||
if (!row) return
|
||
try {
|
||
this.payLoading = true
|
||
this.paymentDialog={
|
||
totalPrice: row.totalPrice,
|
||
payAmount: row.payAmount,
|
||
noPayAmount: row.noPayAmount,
|
||
img: row.img
|
||
}
|
||
|
||
if (this.paymentDialog.img) {
|
||
this.paymentDialog.img = this.buildQrSrc(this.paymentDialog.img)
|
||
this.dialogVisible=true
|
||
}else{
|
||
this.$message({
|
||
message: '未返回支付二维码',
|
||
type: 'error',
|
||
showClose: true
|
||
});
|
||
|
||
}
|
||
// this.dialogVisible=true
|
||
// const list = Array.isArray(row.orderItemDtoList) ? row.orderItemDtoList : []
|
||
// const payload = list.map(m => {
|
||
// const base = {
|
||
// leaseTime: Number(m.leaseTime || 1),
|
||
// machineId: m.productMachineId != null ? m.productMachineId : (m.machineId != null ? m.machineId : m.id),
|
||
// productId: m.productId,
|
||
// shopId: m.shopId
|
||
// }
|
||
// // 尝试从子项或订单行上获取店铺ID并附加
|
||
// const sid = m.shopId != null ? m.shopId : (row && (row.shopId != null ? row.shopId : row.shopID))
|
||
// return sid != null ? { ...base, shopId: sid } : base
|
||
// }).filter(p => p.machineId != null && p.productId != null)
|
||
// if (!payload.length) { this.$message.warning('该订单没有可支付的机器项'); return }
|
||
// const res = await addOrders(payload)
|
||
// if (!res || Number(res.code) !== 200) {
|
||
// // 全局拦截器已弹错误,这里只记录并中断,避免重复弹窗
|
||
// console.warn('创建支付订单失败:', res)
|
||
// return
|
||
// }
|
||
// const first = Array.isArray(res.data) && res.data.length ? res.data[0] : null
|
||
// if (!first || !first.img) { this.$message.error('未返回支付二维码'); return }
|
||
// this.orderDialog.coin = first.payCoin || ''
|
||
// this.orderDialog.amount = first.amount != null ? String(first.amount) : ''
|
||
// this.orderDialog.address = first.payAddress || ''
|
||
// this.orderDialog.qrContent = this.buildQrSrc(first.img)
|
||
// this.orderDialog.visible = true
|
||
} catch (e) {
|
||
console.log(e,'创建支付订单失败');
|
||
} finally { this.payLoading = false }
|
||
},
|
||
handleGoDetail(row) {
|
||
const id = row && (row.id != null ? row.id : row.orderId)
|
||
if (id == null) {
|
||
this.$message({
|
||
message: '订单ID缺失',
|
||
type: 'error',
|
||
showClose: true
|
||
});
|
||
return
|
||
}
|
||
try { this.$router.push(`/account/order-detail/${id}`) } catch (e) {
|
||
this.$message({
|
||
message: '无法跳转到详情页',
|
||
type: 'error',
|
||
showClose: true
|
||
})
|
||
}
|
||
},
|
||
handleCancel(row) {
|
||
if (!row || !this.onCancel) return
|
||
const id = row.id
|
||
if (id == null) {
|
||
this.$message({
|
||
message: '订单ID缺失',
|
||
type: 'error',
|
||
showClose: true
|
||
});
|
||
return
|
||
}
|
||
this.$confirm('确认取消该订单吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' })
|
||
.then(() => { try { this.onCancel({ orderId: id }) } catch (e) { void 0 } })
|
||
.catch(() => { return null })
|
||
},
|
||
shouldShowActions(row) {
|
||
console.log(row,'飞机飞机覅附件s');
|
||
if (!this.showCheckout) return false
|
||
const s = Number(row && row.status)
|
||
console.log(s,'飞机飞机覅附件s');
|
||
|
||
// 支持在 待支付(0) 与 支付中(6) 部分已支付(10) 三个状态显示按钮
|
||
return s === 0 || s === 6 || s === 10
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.empty { color: #888; padding: 24px; text-align: center; }
|
||
.value.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; word-break: break-all; }
|
||
.value.strong { font-weight: 700; color: #e74c3c; }
|
||
.amount-more { font-size: 12px; color: #94a3b8; margin-left: 4px; }
|
||
</style>
|
||
|
||
|