更新号池界面

This commit is contained in:
李志强 2026-04-13 10:09:18 +08:00
parent 449a7deac5
commit aabf7e56d4
3 changed files with 189 additions and 145 deletions

View File

@ -38,7 +38,7 @@ const selectedRows = ref([]);
const detailRow = ref(null); const detailRow = ref(null);
const pagination = reactive({ const pagination = reactive({
page: 1, page: 1,
pageSize: 30, pageSize: 20,
}); });
const pagedList = computed(() => tableData.value); const pagedList = computed(() => tableData.value);
@ -196,6 +196,11 @@ function typeText(type) {
return 'Token'; return 'Token';
} }
const tooltipOpts = {
popperClass: 'pool-tooltip',
popperStyle: { maxWidth: '600px', wordBreak: 'break-all', whiteSpace: 'pre-wrap' },
};
const PLATFORM_MAP = { const PLATFORM_MAP = {
local: { label: '本地', type: 'info' }, local: { label: '本地', type: 'info' },
xianyu: { label: '闲鱼', type: 'warning' }, xianyu: { label: '闲鱼', type: 'warning' },
@ -219,17 +224,31 @@ function normalizeRow(raw) {
} }
return ''; return '';
}; };
// null
const pickNullable = (...keys) => {
for (const key of keys) {
if (raw?.[key] !== undefined) return raw[key] ?? null;
}
return null;
};
const formatTime = (val) => {
if (!val) return '';
const d = new Date(val);
if (isNaN(d)) return val;
const p = (v) => String(v).padStart(2, '0');
return `${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
};
return { return {
id: pick('id', 'Id'), id: pick('id', 'Id', 'ID'),
type: pick('data_type', 'dataType', 'type'), type: pick('data_type', 'dataType', 'type'),
account: pick('account', 'Account'), account: pick('account', 'Account'),
password: pick('password', 'Password'), password: pick('password', 'Password'),
token: pick('token', 'Token'), token: pick('token', 'Token'),
remark: pick('remark', 'Remark'), remark: pick('remark', 'Remark'),
extracted: Number(pick('is_extracted', 'isExtracted')) === 1 || !!pick('extracted'), extracted: Number(pick('is_extracted', 'isExtracted', 'IsExtracted')) === 1,
extractedAt: pick('extracted_time', 'extracted_at', 'extractedAt'), extractedAt: formatTime(pickNullable('extracted_time', 'extractedAt')),
extractedPlatform: pick('extracted_platform', 'extractedPlatform'), extractedPlatform: pickNullable('extracted_platform', 'extractedPlatform'),
createdAt: pick('create_time', 'created_at', 'createdAt'), createdAt: formatTime(pick('create_time', 'createdAt')),
}; };
} }
@ -289,38 +308,14 @@ const examples = [
{ label: '抖音 · 提取 Krio Token', url: `${BASE_URL}/api/getcard?type=douyin&module=krio&data_type=tk` }, { label: '抖音 · 提取 Krio Token', url: `${BASE_URL}/api/getcard?type=douyin&module=krio&data_type=tk` },
]; ];
const successResp = `// 账号密码类型data_type=account const successResp = `// 纯 Token 类型data_type=tk
{ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"code": 200,
"msg": "success", // data_type=account
"data": { 账号user@example.com / 密码your_password
"type": "account",
"account": "user@example.com",
"password": "your_password"
}
}
// +Token data_type=account_tk // +Token data_type=account_tk
{ 账号user@example.com / 密码your_password / TokeneyJhbGciOiJIUzI1NiIs...`;
"code": 200,
"msg": "success",
"data": {
"type": "account_tk",
"account": "user@example.com",
"password": "your_password",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}
// Token data_type=tk
{
"code": 200,
"msg": "success",
"data": {
"type": "tk",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}`;
const errorResp = `// 无可用卡密 const errorResp = `// 无可用卡密
{ "code": 404, "msg": "暂无可用卡密" } { "code": 404, "msg": "暂无可用卡密" }
@ -333,6 +328,17 @@ function copyText(text) {
ElMessage.success('已复制'); ElMessage.success('已复制');
}); });
} }
function copyCardInfo(row) {
const parts = [];
if (row.account) parts.push(row.account);
if (row.password) parts.push(row.password);
if (row.token) parts.push(row.token);
if (!parts.length) { ElMessage.warning('无可复制内容'); return; }
navigator.clipboard.writeText(parts.join('\n')).then(() => {
ElMessage.success('已复制');
});
}
</script> </script>
<template> <template>
@ -390,15 +396,14 @@ function copyText(text) {
<el-tag>{{ typeText(row.type) }}</el-tag> <el-tag>{{ typeText(row.type) }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip /> <el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="密码/Token" min-width="240" show-overflow-tooltip> <el-table-column prop="password" label="密码" min-width="160" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }"> <template #default="{ row }">{{ row.password || '-' }}</template>
<span v-if="row.type === 'account'">{{ row.password || '-' }}</span>
<span v-else-if="row.type === 'account_tk'">{{ `${row.password || '-'} / ${row.token || '-'}` }}</span>
<span v-else>{{ row.token || '-' }}</span>
</template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip /> <el-table-column label="Token" min-width="200" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }">{{ row.token || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="提取状态" width="100"> <el-table-column label="提取状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.extracted ? 'success' : 'info'"> <el-tag :type="row.extracted ? 'success' : 'info'">
@ -415,17 +420,11 @@ function copyText(text) {
<span v-else>-</span> <span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="180" fixed="right" align="center"> <el-table-column label="操作" width="220" fixed="right" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" @click="openDetail(row)">详情</el-button> <el-button link type="primary" @click="openDetail(row)">详情</el-button>
<el-button <el-button link type="warning" :disabled="row.extracted" @click="openExtractByRow(row)">提取</el-button>
link <el-button v-if="row.extracted" link type="success" @click="copyCardInfo(row)">复制</el-button>
type="warning"
:disabled="row.extracted"
@click="openExtractByRow(row)"
>
提取
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -436,7 +435,7 @@ function copyText(text) {
v-model:page-size="pagination.pageSize" v-model:page-size="pagination.pageSize"
background background
layout="total, prev, pager, next, jumper" layout="total, prev, pager, next, jumper"
:page-sizes="[30, 50, 100]" :page-sizes="[20, 50, 100]"
:total="total" :total="total"
/> />
</div> </div>
@ -457,7 +456,7 @@ function copyText(text) {
{{ detailRow.password || '-' }} {{ detailRow.password || '-' }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="Token"> <el-descriptions-item label="Token">
{{ detailRow.token || '-' }} <span class="token-text">{{ detailRow.token || '-' }}</span>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="提取状态"> <el-descriptions-item label="提取状态">
{{ detailRow.extracted ? '已提取' : '未提取' }} {{ detailRow.extracted ? '已提取' : '未提取' }}
@ -689,4 +688,21 @@ function copyText(text) {
word-break: break-all; word-break: break-all;
margin: 0; margin: 0;
} }
.token-text {
word-break: break-all;
white-space: pre-wrap;
line-height: 1.6;
}
</style>
<style>
.pool-tooltip.el-popper {
max-width: 600px !important;
white-space: pre-wrap !important;
word-break: break-all !important;
}
.pool-tooltip .el-popper__arrow {
display: block;
}
</style> </style>

View File

@ -123,6 +123,11 @@ function typeText(type) {
return 'Token'; return 'Token';
} }
const tooltipOpts = {
popperClass: 'pool-tooltip',
popperStyle: { maxWidth: '600px', wordBreak: 'break-all', whiteSpace: 'pre-wrap' },
};
const PLATFORM_MAP = { const PLATFORM_MAP = {
local: { label: '本地', type: 'info' }, local: { label: '本地', type: 'info' },
xianyu: { label: '闲鱼', type: 'warning' }, xianyu: { label: '闲鱼', type: 'warning' },
@ -141,17 +146,30 @@ function normalizeRow(raw) {
} }
return ''; return '';
}; };
const pickNullable = (...keys) => {
for (const key of keys) {
if (raw?.[key] !== undefined) return raw[key] ?? null;
}
return null;
};
const formatTime = (val) => {
if (!val) return '';
const d = new Date(val);
if (isNaN(d)) return val;
const p = (v) => String(v).padStart(2, '0');
return `${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
};
return { return {
id: pick('id', 'Id'), id: pick('id', 'Id', 'ID'),
type: pick('data_type', 'dataType', 'type'), type: pick('data_type', 'dataType', 'type'),
account: pick('account', 'Account'), account: pick('account', 'Account'),
password: pick('password', 'Password'), password: pick('password', 'Password'),
token: pick('token', 'Token'), token: pick('token', 'Token'),
remark: pick('remark', 'Remark'), remark: pick('remark', 'Remark'),
extracted: Number(pick('is_extracted', 'isExtracted')) === 1 || !!pick('extracted'), extracted: Number(pick('is_extracted', 'isExtracted', 'IsExtracted')) === 1,
extractedAt: pick('extracted_time', 'extracted_at', 'extractedAt'), extractedAt: formatTime(pickNullable('extracted_time', 'extractedAt')),
extractedPlatform: pick('extracted_platform', 'extractedPlatform'), extractedPlatform: pickNullable('extracted_platform', 'extractedPlatform'),
createdAt: pick('create_time', 'created_at', 'createdAt'), createdAt: formatTime(pick('create_time', 'createdAt')),
}; };
} }
@ -203,38 +221,14 @@ const examples = [
{ label: '抖音 · 提取 Windsurf Token', url: `${BASE_URL}/api/getcard?type=douyin&module=windsurf&data_type=tk` }, { label: '抖音 · 提取 Windsurf Token', url: `${BASE_URL}/api/getcard?type=douyin&module=windsurf&data_type=tk` },
]; ];
const successResp = `// 账号密码类型data_type=account const successResp = `// 纯 Token 类型data_type=tk
{ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"code": 200,
"msg": "success", // data_type=account
"data": { 账号user@example.com / 密码your_password
"type": "account",
"account": "user@example.com",
"password": "your_password"
}
}
// +Token data_type=account_tk // +Token data_type=account_tk
{ 账号user@example.com / 密码your_password / TokeneyJhbGciOiJIUzI1NiIs...`;
"code": 200,
"msg": "success",
"data": {
"type": "account_tk",
"account": "user@example.com",
"password": "your_password",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}
// Token data_type=tk
{
"code": 200,
"msg": "success",
"data": {
"type": "tk",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}`;
const errorResp = `// 无可用卡密 const errorResp = `// 无可用卡密
{ "code": 404, "msg": "暂无可用卡密" } { "code": 404, "msg": "暂无可用卡密" }
@ -245,6 +239,15 @@ const errorResp = `// 无可用卡密
function copyText(text) { function copyText(text) {
navigator.clipboard.writeText(text).then(() => { ElMessage.success('已复制'); }); navigator.clipboard.writeText(text).then(() => { ElMessage.success('已复制'); });
} }
function copyCardInfo(row) {
const parts = [];
if (row.account) parts.push(row.account);
if (row.password) parts.push(row.password);
if (row.token) parts.push(row.token);
if (!parts.length) { ElMessage.warning('无可复制内容'); return; }
navigator.clipboard.writeText(parts.join('\n')).then(() => { ElMessage.success('已复制'); });
}
</script> </script>
<template> <template>
@ -281,15 +284,14 @@ function copyText(text) {
<el-table-column label="账号类型" width="160" align="center"> <el-table-column label="账号类型" width="160" align="center">
<template #default="{ row }"><el-tag>{{ typeText(row.type) }}</el-tag></template> <template #default="{ row }"><el-tag>{{ typeText(row.type) }}</el-tag></template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip /> <el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="密码/Token" min-width="240" show-overflow-tooltip> <el-table-column prop="password" label="密码" min-width="160" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }"> <template #default="{ row }">{{ row.password || '-' }}</template>
<span v-if="row.type === 'account'">{{ row.password || '-' }}</span>
<span v-else-if="row.type === 'account_tk'">{{ `${row.password || '-'} / ${row.token || '-'}` }}</span>
<span v-else>{{ row.token || '-' }}</span>
</template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip /> <el-table-column label="Token" min-width="200" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }">{{ row.token || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="提取状态" width="100"> <el-table-column label="提取状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.extracted ? 'success' : 'info'">{{ row.extracted ? '已提取' : '未提取' }}</el-tag> <el-tag :type="row.extracted ? 'success' : 'info'">{{ row.extracted ? '已提取' : '未提取' }}</el-tag>
@ -304,10 +306,11 @@ function copyText(text) {
<span v-else>-</span> <span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="180" fixed="right" align="center"> <el-table-column label="操作" width="220" fixed="right" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" @click="openDetail(row)">详情</el-button> <el-button link type="primary" @click="openDetail(row)">详情</el-button>
<el-button link type="warning" :disabled="row.extracted" @click="openExtractByRow(row)">提取</el-button> <el-button link type="warning" :disabled="row.extracted" @click="openExtractByRow(row)">提取</el-button>
<el-button v-if="row.extracted" link type="success" @click="copyCardInfo(row)">复制</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -332,7 +335,9 @@ function copyText(text) {
<el-descriptions-item label="账号类型">{{ typeText(detailRow.type) }}</el-descriptions-item> <el-descriptions-item label="账号类型">{{ typeText(detailRow.type) }}</el-descriptions-item>
<el-descriptions-item label="账号">{{ detailRow.account || '-' }}</el-descriptions-item> <el-descriptions-item label="账号">{{ detailRow.account || '-' }}</el-descriptions-item>
<el-descriptions-item label="密码">{{ detailRow.password || '-' }}</el-descriptions-item> <el-descriptions-item label="密码">{{ detailRow.password || '-' }}</el-descriptions-item>
<el-descriptions-item label="Token">{{ detailRow.token || '-' }}</el-descriptions-item> <el-descriptions-item label="Token">
<span class="token-text">{{ detailRow.token || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="提取状态">{{ detailRow.extracted ? '已提取' : '未提取' }}</el-descriptions-item> <el-descriptions-item label="提取状态">{{ detailRow.extracted ? '已提取' : '未提取' }}</el-descriptions-item>
<el-descriptions-item label="提取时间">{{ detailRow.extractedAt || '-' }}</el-descriptions-item> <el-descriptions-item label="提取时间">{{ detailRow.extractedAt || '-' }}</el-descriptions-item>
<el-descriptions-item label="提取平台"> <el-descriptions-item label="提取平台">
@ -444,4 +449,13 @@ function copyText(text) {
.example-url-wrap { display: flex; align-items: center; gap: 8px; background: #f5f7fa; padding: 6px 10px; border-radius: 4px; } .example-url-wrap { display: flex; align-items: center; gap: 8px; background: #f5f7fa; padding: 6px 10px; border-radius: 4px; }
.example-url { flex: 1; font-size: 12px; color: #409eff; word-break: break-all; } .example-url { flex: 1; font-size: 12px; color: #409eff; word-break: break-all; }
.code-block { background: #1e1e1e; color: #d4d4d4; padding: 12px 16px; border-radius: 6px; font-size: 12px; line-height: 1.6; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 0; } .code-block { background: #1e1e1e; color: #d4d4d4; padding: 12px 16px; border-radius: 6px; font-size: 12px; line-height: 1.6; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 0; }
.token-text { word-break: break-all; white-space: pre-wrap; line-height: 1.6; }
</style> </style>
<style>
.pool-tooltip.el-popper {
max-width: 600px;
white-space: pre-wrap;
word-break: break-all;
}
</style>

View File

@ -123,6 +123,11 @@ function typeText(type) {
return 'Token'; return 'Token';
} }
const tooltipOpts = {
popperClass: 'pool-tooltip',
popperStyle: { maxWidth: '600px', wordBreak: 'break-all', whiteSpace: 'pre-wrap' },
};
const PLATFORM_MAP = { const PLATFORM_MAP = {
local: { label: '本地', type: 'info' }, local: { label: '本地', type: 'info' },
xianyu: { label: '闲鱼', type: 'warning' }, xianyu: { label: '闲鱼', type: 'warning' },
@ -141,17 +146,30 @@ function normalizeRow(raw) {
} }
return ''; return '';
}; };
const pickNullable = (...keys) => {
for (const key of keys) {
if (raw?.[key] !== undefined) return raw[key] ?? null;
}
return null;
};
const formatTime = (val) => {
if (!val) return '';
const d = new Date(val);
if (isNaN(d)) return val;
const p = (v) => String(v).padStart(2, '0');
return `${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
};
return { return {
id: pick('id', 'Id'), id: pick('id', 'Id', 'ID'),
type: pick('data_type', 'dataType', 'type'), type: pick('data_type', 'dataType', 'type'),
account: pick('account', 'Account'), account: pick('account', 'Account'),
password: pick('password', 'Password'), password: pick('password', 'Password'),
token: pick('token', 'Token'), token: pick('token', 'Token'),
remark: pick('remark', 'Remark'), remark: pick('remark', 'Remark'),
extracted: Number(pick('is_extracted', 'isExtracted')) === 1 || !!pick('extracted'), extracted: Number(pick('is_extracted', 'isExtracted', 'IsExtracted')) === 1,
extractedAt: pick('extracted_time', 'extracted_at', 'extractedAt'), extractedAt: formatTime(pickNullable('extracted_time', 'extractedAt')),
extractedPlatform: pick('extracted_platform', 'extractedPlatform'), extractedPlatform: pickNullable('extracted_platform', 'extractedPlatform'),
createdAt: pick('create_time', 'created_at', 'createdAt'), createdAt: formatTime(pick('create_time', 'createdAt')),
}; };
} }
@ -203,38 +221,14 @@ const examples = [
{ label: '抖音 · 提取 Krio Token', url: `${BASE_URL}/api/getcard?type=douyin&module=krio&data_type=tk` }, { label: '抖音 · 提取 Krio Token', url: `${BASE_URL}/api/getcard?type=douyin&module=krio&data_type=tk` },
]; ];
const successResp = `// 账号密码类型data_type=account const successResp = `// 纯 Token 类型data_type=tk
{ eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
"code": 200,
"msg": "success", // data_type=account
"data": { 账号user@example.com / 密码your_password
"type": "account",
"account": "user@example.com",
"password": "your_password"
}
}
// +Token data_type=account_tk // +Token data_type=account_tk
{ 账号user@example.com / 密码your_password / TokeneyJhbGciOiJIUzI1NiIs...`;
"code": 200,
"msg": "success",
"data": {
"type": "account_tk",
"account": "user@example.com",
"password": "your_password",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}
// Token data_type=tk
{
"code": 200,
"msg": "success",
"data": {
"type": "tk",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
}`;
const errorResp = `// 无可用卡密 const errorResp = `// 无可用卡密
{ "code": 404, "msg": "暂无可用卡密" } { "code": 404, "msg": "暂无可用卡密" }
@ -245,6 +239,15 @@ const errorResp = `// 无可用卡密
function copyText(text) { function copyText(text) {
navigator.clipboard.writeText(text).then(() => { ElMessage.success('已复制'); }); navigator.clipboard.writeText(text).then(() => { ElMessage.success('已复制'); });
} }
function copyCardInfo(row) {
const parts = [];
if (row.account) parts.push(row.account);
if (row.password) parts.push(row.password);
if (row.token) parts.push(row.token);
if (!parts.length) { ElMessage.warning('无可复制内容'); return; }
navigator.clipboard.writeText(parts.join('\n')).then(() => { ElMessage.success('已复制'); });
}
</script> </script>
<template> <template>
@ -281,15 +284,14 @@ function copyText(text) {
<el-table-column label="账号类型" width="160" align="center"> <el-table-column label="账号类型" width="160" align="center">
<template #default="{ row }"><el-tag>{{ typeText(row.type) }}</el-tag></template> <template #default="{ row }"><el-tag>{{ typeText(row.type) }}</el-tag></template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip /> <el-table-column prop="account" label="账号" min-width="180" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="密码/Token" min-width="240" show-overflow-tooltip> <el-table-column prop="password" label="密码" min-width="160" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }"> <template #default="{ row }">{{ row.password || '-' }}</template>
<span v-if="row.type === 'account'">{{ row.password || '-' }}</span>
<span v-else-if="row.type === 'account_tk'">{{ `${row.password || '-'} / ${row.token || '-'}` }}</span>
<span v-else>{{ row.token || '-' }}</span>
</template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip /> <el-table-column label="Token" min-width="200" show-overflow-tooltip :tooltip-options="tooltipOpts">
<template #default="{ row }">{{ row.token || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="140" show-overflow-tooltip :tooltip-options="tooltipOpts" />
<el-table-column label="提取状态" width="100"> <el-table-column label="提取状态" width="100">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.extracted ? 'success' : 'info'">{{ row.extracted ? '已提取' : '未提取' }}</el-tag> <el-tag :type="row.extracted ? 'success' : 'info'">{{ row.extracted ? '已提取' : '未提取' }}</el-tag>
@ -304,10 +306,11 @@ function copyText(text) {
<span v-else>-</span> <span v-else>-</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="180" fixed="right" align="center"> <el-table-column label="操作" width="220" fixed="right" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-button link type="primary" @click="openDetail(row)">详情</el-button> <el-button link type="primary" @click="openDetail(row)">详情</el-button>
<el-button link type="warning" :disabled="row.extracted" @click="openExtractByRow(row)">提取</el-button> <el-button link type="warning" :disabled="row.extracted" @click="openExtractByRow(row)">提取</el-button>
<el-button v-if="row.extracted" link type="success" @click="copyCardInfo(row)">复制</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -332,7 +335,9 @@ function copyText(text) {
<el-descriptions-item label="账号类型">{{ typeText(detailRow.type) }}</el-descriptions-item> <el-descriptions-item label="账号类型">{{ typeText(detailRow.type) }}</el-descriptions-item>
<el-descriptions-item label="账号">{{ detailRow.account || '-' }}</el-descriptions-item> <el-descriptions-item label="账号">{{ detailRow.account || '-' }}</el-descriptions-item>
<el-descriptions-item label="密码">{{ detailRow.password || '-' }}</el-descriptions-item> <el-descriptions-item label="密码">{{ detailRow.password || '-' }}</el-descriptions-item>
<el-descriptions-item label="Token">{{ detailRow.token || '-' }}</el-descriptions-item> <el-descriptions-item label="Token">
<span class="token-text">{{ detailRow.token || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="提取状态">{{ detailRow.extracted ? '已提取' : '未提取' }}</el-descriptions-item> <el-descriptions-item label="提取状态">{{ detailRow.extracted ? '已提取' : '未提取' }}</el-descriptions-item>
<el-descriptions-item label="提取时间">{{ detailRow.extractedAt || '-' }}</el-descriptions-item> <el-descriptions-item label="提取时间">{{ detailRow.extractedAt || '-' }}</el-descriptions-item>
<el-descriptions-item label="提取平台"> <el-descriptions-item label="提取平台">
@ -444,4 +449,13 @@ function copyText(text) {
.example-url-wrap { display: flex; align-items: center; gap: 8px; background: #f5f7fa; padding: 6px 10px; border-radius: 4px; } .example-url-wrap { display: flex; align-items: center; gap: 8px; background: #f5f7fa; padding: 6px 10px; border-radius: 4px; }
.example-url { flex: 1; font-size: 12px; color: #409eff; word-break: break-all; } .example-url { flex: 1; font-size: 12px; color: #409eff; word-break: break-all; }
.code-block { background: #1e1e1e; color: #d4d4d4; padding: 12px 16px; border-radius: 6px; font-size: 12px; line-height: 1.6; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 0; } .code-block { background: #1e1e1e; color: #d4d4d4; padding: 12px 16px; border-radius: 6px; font-size: 12px; line-height: 1.6; overflow-x: auto; white-space: pre-wrap; word-break: break-all; margin: 0; }
.token-text { word-break: break-all; white-space: pre-wrap; line-height: 1.6; }
</style> </style>
<style>
.pool-tooltip.el-popper {
max-width: 600px;
white-space: pre-wrap;
word-break: break-all;
}
</style>