422 lines
11 KiB
Vue
422 lines
11 KiB
Vue
|
|
<template>
|
|||
|
|
<div class="account-purchased-machine-config">
|
|||
|
|
<div class="toolbar">
|
|||
|
|
<div class="left-area">
|
|||
|
|
<h2 class="page-title">已购矿机配置</h2>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<el-table
|
|||
|
|
:data="tableData"
|
|||
|
|
v-loading="loading"
|
|||
|
|
border
|
|||
|
|
stripe
|
|||
|
|
style="width: 100%"
|
|||
|
|
:header-cell-style="{ textAlign: 'left' }"
|
|||
|
|
:cell-style="{ textAlign: 'left' }"
|
|||
|
|
>
|
|||
|
|
<el-table-column type="expand" width="46">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<div class="expand-content">
|
|||
|
|
<div class="expand-row" v-if="scope.row.walletAddress">
|
|||
|
|
<div class="expand-label">钱包地址:</div>
|
|||
|
|
<div class="expand-value">
|
|||
|
|
<span class="mono-ellipsis" style="font-family: monospace;">{{ scope.row.walletAddress }}</span>
|
|||
|
|
<el-button
|
|||
|
|
type="text"
|
|||
|
|
size="mini"
|
|||
|
|
icon="el-icon-document-copy"
|
|||
|
|
@click="handleCopy(scope.row.walletAddress, '钱包地址')"
|
|||
|
|
class="copy-btn"
|
|||
|
|
>
|
|||
|
|
复制
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="expand-row" v-if="scope.row.poolUrl">
|
|||
|
|
<div class="expand-label">矿池地址:</div>
|
|||
|
|
<div class="expand-value">
|
|||
|
|
<span class="mono-ellipsis">{{ scope.row.poolUrl }}</span>
|
|||
|
|
<el-button
|
|||
|
|
type="text"
|
|||
|
|
size="mini"
|
|||
|
|
icon="el-icon-document-copy"
|
|||
|
|
@click="handleCopy(scope.row.poolUrl, '矿池地址')"
|
|||
|
|
class="copy-btn"
|
|||
|
|
>
|
|||
|
|
复制
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div class="expand-row" v-if="scope.row.watchUrl">
|
|||
|
|
<div class="expand-label">挖矿信息页面地址:</div>
|
|||
|
|
<div class="expand-value">
|
|||
|
|
<span class="mono-ellipsis">{{ scope.row.watchUrl }}</span>
|
|||
|
|
<el-button
|
|||
|
|
type="text"
|
|||
|
|
size="mini"
|
|||
|
|
icon="el-icon-document-copy"
|
|||
|
|
@click="handleCopy(scope.row.watchUrl, '挖矿信息页面地址')"
|
|||
|
|
class="copy-btn"
|
|||
|
|
>
|
|||
|
|
复制
|
|||
|
|
</el-button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
<div v-if="!scope.row.walletAddress && !scope.row.poolUrl && !scope.row.watchUrl" class="expand-empty">
|
|||
|
|
暂无地址信息
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<!-- <el-table-column prop="id" label="ID" width="80" /> -->
|
|||
|
|
|
|||
|
|
<el-table-column prop="coin" label="币种" width="100">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ scope.row.coin || '—' }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="algorithm" label="算法" min-width="120">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ scope.row.algorithm || '—' }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="pool" label="矿池" min-width="140">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ scope.row.pool || '—' }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="poolUser" label="矿池用户" min-width="140">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ scope.row.poolUser || '—' }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
<el-table-column prop="startTime" label="开始时间" min-width="160">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ formatDateTime(scope.row.startTime) }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="endTime" label="结束时间" min-width="160">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<span>{{ formatDateTime(scope.row.endTime) }}</span>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
|
|||
|
|
<el-table-column prop="status" label="状态" width="140">
|
|||
|
|
<template #default="scope">
|
|||
|
|
<el-tag :type="getStatusType(scope.row.status)">
|
|||
|
|
{{ getStatusText(scope.row.status) }}
|
|||
|
|
</el-tag>
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
</el-table>
|
|||
|
|
|
|||
|
|
<div class="pagination">
|
|||
|
|
<el-pagination
|
|||
|
|
background
|
|||
|
|
layout="total, sizes, prev, pager, next, jumper"
|
|||
|
|
:total="total"
|
|||
|
|
:current-page.sync="pagination.pageNum"
|
|||
|
|
:page-sizes="[10, 20, 50, 100]"
|
|||
|
|
:page-size.sync="pagination.pageSize"
|
|||
|
|
@size-change="handleSizeChange"
|
|||
|
|
@current-change="handleCurrentChange"
|
|||
|
|
/>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { getPurchasedItems } from '../../api/order'
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 已购矿机配置页面
|
|||
|
|
* - 展示已购买矿机的配置信息
|
|||
|
|
* - 支持分页查询
|
|||
|
|
*/
|
|||
|
|
export default {
|
|||
|
|
name: 'AccountPurchasedMachineConfig',
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
loading: false,
|
|||
|
|
tableData: [],
|
|||
|
|
pagination: {
|
|||
|
|
pageNum: 1,
|
|||
|
|
pageSize: 10
|
|||
|
|
},
|
|||
|
|
total: 0,
|
|||
|
|
totalPage: 0
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
created() {
|
|||
|
|
this.fetchTableData()
|
|||
|
|
},
|
|||
|
|
methods: {
|
|||
|
|
/**
|
|||
|
|
* 获取已购矿机配置列表
|
|||
|
|
*/
|
|||
|
|
async fetchTableData() {
|
|||
|
|
this.loading = true
|
|||
|
|
try {
|
|||
|
|
const params = {
|
|||
|
|
pageNum: this.pagination.pageNum,
|
|||
|
|
pageSize: this.pagination.pageSize
|
|||
|
|
}
|
|||
|
|
const res = await getPurchasedItems(params)
|
|||
|
|
if (res && (res.code === 0 || res.code === 200)) {
|
|||
|
|
this.tableData = Array.isArray(res.rows) ? res.rows : []
|
|||
|
|
this.total = Number(res.total || 0)
|
|||
|
|
this.totalPage = Number(res.totalPage || 0)
|
|||
|
|
} else {
|
|||
|
|
this.tableData = []
|
|||
|
|
this.total = 0
|
|||
|
|
this.totalPage = 0
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('获取已购矿机配置失败', e)
|
|||
|
|
this.$message({
|
|||
|
|
message: '获取已购矿机配置失败,请重试',
|
|||
|
|
type: 'error',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
this.tableData = []
|
|||
|
|
this.total = 0
|
|||
|
|
this.totalPage = 0
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 处理分页大小变化
|
|||
|
|
* @param {number} size - 新的分页大小
|
|||
|
|
*/
|
|||
|
|
handleSizeChange(size) {
|
|||
|
|
this.pagination.pageSize = size
|
|||
|
|
this.pagination.pageNum = 1
|
|||
|
|
this.fetchTableData()
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 处理当前页变化
|
|||
|
|
* @param {number} page - 新的页码
|
|||
|
|
*/
|
|||
|
|
handleCurrentChange(page) {
|
|||
|
|
this.pagination.pageNum = page
|
|||
|
|
this.fetchTableData()
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 格式化日期时间
|
|||
|
|
* @param {string|number} value - 日期时间值
|
|||
|
|
* @returns {string} 格式化后的日期时间字符串
|
|||
|
|
*/
|
|||
|
|
formatDateTime(value) {
|
|||
|
|
if (!value) return '—'
|
|||
|
|
try {
|
|||
|
|
const str = String(value)
|
|||
|
|
return str.includes('T') ? str.replace('T', ' ') : str
|
|||
|
|
} catch (e) {
|
|||
|
|
return String(value)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 复制文本到剪贴板
|
|||
|
|
* @param {string} text - 需要复制的内容
|
|||
|
|
* @param {string} label - 语义标签,用于提示文案
|
|||
|
|
*/
|
|||
|
|
async handleCopy(text, label = '内容') {
|
|||
|
|
if (!text) {
|
|||
|
|
this.$message({
|
|||
|
|
message: `${label}为空,无法复制`,
|
|||
|
|
type: 'warning',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const value = String(text).trim()
|
|||
|
|
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
|||
|
|
await navigator.clipboard.writeText(value)
|
|||
|
|
this.$message({
|
|||
|
|
message: `${label}已复制到剪贴板`,
|
|||
|
|
type: 'success',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
} else {
|
|||
|
|
// 备用复制方法
|
|||
|
|
const textArea = document.createElement('textarea')
|
|||
|
|
textArea.value = value
|
|||
|
|
textArea.style.position = 'fixed'
|
|||
|
|
textArea.style.left = '-9999px'
|
|||
|
|
document.body.appendChild(textArea)
|
|||
|
|
textArea.focus()
|
|||
|
|
textArea.select()
|
|||
|
|
try {
|
|||
|
|
document.execCommand('copy')
|
|||
|
|
this.$message({
|
|||
|
|
message: `${label}已复制到剪贴板`,
|
|||
|
|
type: 'success',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
} catch (err) {
|
|||
|
|
this.$message({
|
|||
|
|
message: '复制失败,请手动复制',
|
|||
|
|
type: 'error',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
document.body.removeChild(textArea)
|
|||
|
|
}
|
|||
|
|
} catch (e) {
|
|||
|
|
console.error('复制失败', e)
|
|||
|
|
this.$message({
|
|||
|
|
message: '复制失败,请手动复制',
|
|||
|
|
type: 'error',
|
|||
|
|
showClose: true
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 获取状态文本
|
|||
|
|
* @param {number|boolean} status - 状态值
|
|||
|
|
* @returns {string} 状态文本
|
|||
|
|
*/
|
|||
|
|
getStatusText(status) {
|
|||
|
|
const statusNum = Number(status)
|
|||
|
|
if (statusNum === 0) return '租约已到期'
|
|||
|
|
if (statusNum === 1) return '挖矿中'
|
|||
|
|
if (statusNum === 2) return '卖家矿机启动中'
|
|||
|
|
// 兼容旧数据(boolean类型)
|
|||
|
|
if (status === true) return '挖矿中'
|
|||
|
|
return '未知状态'
|
|||
|
|
},
|
|||
|
|
/**
|
|||
|
|
* 获取状态标签类型
|
|||
|
|
* @param {number|boolean} status - 状态值
|
|||
|
|
* @returns {string} el-tag 的类型
|
|||
|
|
*/
|
|||
|
|
getStatusType(status) {
|
|||
|
|
const statusNum = Number(status)
|
|||
|
|
if (statusNum === 0) return 'info' // 租约已到期 - 灰色
|
|||
|
|
if (statusNum === 1) return 'success' // 挖矿中 - 绿色
|
|||
|
|
if (statusNum === 2) return 'warning' // 卖家矿机启动中 - 黄色
|
|||
|
|
// 兼容旧数据(boolean类型)
|
|||
|
|
if (status === true) return 'success'
|
|||
|
|
return 'info'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped>
|
|||
|
|
.account-purchased-machine-config {
|
|||
|
|
padding: 4px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.toolbar {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.left-area {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-title {
|
|||
|
|
margin: 0;
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #2c3e50;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.pagination {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
margin-top: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 展开内容样式 */
|
|||
|
|
.expand-content {
|
|||
|
|
padding: 16px;
|
|||
|
|
background-color: #fafafa;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
padding: 12px;
|
|||
|
|
background-color: #fff;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
border: 1px solid #e4e7ed;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-row:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-label {
|
|||
|
|
min-width: 100px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #606266;
|
|||
|
|
margin-right: 12px;
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-value {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 8px;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-value .mono-ellipsis {
|
|||
|
|
font-family: monospace;
|
|||
|
|
color: #303133;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
word-break: break-all;
|
|||
|
|
flex: 0 1 auto;
|
|||
|
|
margin-right: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.copy-btn {
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
padding: 0 8px;
|
|||
|
|
color: #409eff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.copy-btn:hover {
|
|||
|
|
color: #66b1ff;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.expand-empty {
|
|||
|
|
padding: 20px;
|
|||
|
|
text-align: center;
|
|||
|
|
color: #909399;
|
|||
|
|
font-size: 14px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 钱包地址和URL格式化显示样式 */
|
|||
|
|
.mono-ellipsis {
|
|||
|
|
font-family: monospace;
|
|||
|
|
display: inline-block;
|
|||
|
|
max-width: 100%;
|
|||
|
|
overflow: hidden;
|
|||
|
|
text-overflow: ellipsis;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
vertical-align: middle;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
|