设备管理优化

This commit is contained in:
扫地僧 2026-06-16 00:39:26 +08:00
parent fa2dd8548c
commit 0a95690a12
5 changed files with 140 additions and 58 deletions

View File

@ -573,10 +573,7 @@ onUnmounted(() => {
<el-table-column prop="id" label="ID" width="80" /> <el-table-column prop="id" label="ID" width="80" />
<el-table-column label="激活码" min-width="260" show-overflow-tooltip> <el-table-column label="激活码" min-width="260" show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
<div class="code-cell">
<span class="code-text">{{ row.code || '-' }}</span> <span class="code-text">{{ row.code || '-' }}</span>
<el-button v-if="row.code" link type="primary" @click="copyCode(row.code)">复制</el-button>
</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="类型" width="100" align="center"> <el-table-column label="类型" width="100" align="center">
@ -598,7 +595,7 @@ onUnmounted(() => {
<div class="muted">设备{{ row.machineCode || row.bindDeviceId || '-' }}</div> <div class="muted">设备{{ row.machineCode || row.bindDeviceId || '-' }}</div>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ownerUserName" label="归属用户" min-width="130" show-overflow-tooltip /> <!-- <el-table-column prop="ownerUserName" label="归属用户" min-width="130" show-overflow-tooltip /> -->
<el-table-column prop="activatedAt" label="激活时间" width="180"> <el-table-column prop="activatedAt" label="激活时间" width="180">
<template #default="{ row }">{{ row.activatedAt || '-' }}</template> <template #default="{ row }">{{ row.activatedAt || '-' }}</template>
</el-table-column> </el-table-column>
@ -609,9 +606,10 @@ onUnmounted(() => {
<template #default="{ row }">{{ row.createdAt || '-' }}</template> <template #default="{ row }">{{ row.createdAt || '-' }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip /> <el-table-column prop="remark" label="备注" min-width="160" show-overflow-tooltip />
<el-table-column label="操作" width="250" fixed="right" align="center"> <el-table-column label="操作" width="290" 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 v-if="row.code" link type="primary" @click="copyCode(row.code)">复制</el-button>
<el-button link type="warning" @click="openEdit(row)">编辑</el-button> <el-button link type="warning" @click="openEdit(row)">编辑</el-button>
<el-button link :type="Number(row.status) === 3 ? 'success' : 'info'" @click="handleToggleStatus(row)"> <el-button link :type="Number(row.status) === 3 ? 'success' : 'info'" @click="handleToggleStatus(row)">
{{ Number(row.status) === 3 ? '启用' : '禁用' }} {{ Number(row.status) === 3 ? '启用' : '禁用' }}

View File

@ -1,4 +1,6 @@
<script lang="ts" setup> <script lang="ts" setup>
import { ElMessage } from 'element-plus';
defineProps({ defineProps({
modelValue: { modelValue: {
type: Boolean, type: Boolean,
@ -45,6 +47,18 @@ function statusType(status: unknown) {
if (value === 'failed' || value === '0') return 'danger'; if (value === 'failed' || value === '0') return 'danger';
return 'info'; return 'info';
} }
function copyCode(code: unknown) {
const text = String(code || '').trim();
if (!text) {
ElMessage.warning('暂无激活码可复制');
return;
}
navigator.clipboard.writeText(text).then(() => {
ElMessage.success('激活码已复制');
});
}
</script> </script>
<template> <template>
@ -54,7 +68,7 @@ function statusType(status: unknown) {
title="激活记录" title="激活记录"
size="760px" size="760px"
direction="rtl" direction="rtl"
@update:model-value="(v) => emit('update:modelValue', v)" @update:model-value="(v: boolean) => emit('update:modelValue', v)"
@opened="emit('refresh')" @opened="emit('refresh')"
> >
<div class="record-header"> <div class="record-header">
@ -74,10 +88,23 @@ function statusType(status: unknown) {
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="激活账号" min-width="150" show-overflow-tooltip /> <el-table-column label="激活码" min-width="260" show-overflow-tooltip>
<el-table-column prop="ip" label="IP" min-width="130" show-overflow-tooltip /> <template #default="{ row: item }">
<el-table-column prop="clientVersion" label="客户端版本" width="120" /> <span class="code-text">{{ item.activationCode || item.code || '-' }}</span>
<el-table-column prop="createdAt" label="激活时间" width="180" /> <el-button v-if="item.activationCode || item.code" link type="primary" @click="copyCode(item.activationCode || item.code)">
复制
</el-button>
</template>
</el-table-column>
<el-table-column prop="machineCode" label="机器码" min-width="180" show-overflow-tooltip />
<el-table-column prop="deviceInfo" label="设备信息" min-width="160" show-overflow-tooltip />
<el-table-column prop="durationDays" label="有效天数" width="100" align="center" />
<el-table-column prop="activatedAt" label="激活时间" width="180">
<template #default="{ row: item }">{{ item.activatedAt || item.createdAt || '-' }}</template>
</el-table-column>
<el-table-column prop="expiredAt" label="到期时间" width="180">
<template #default="{ row: item }">{{ item.expiredAt || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip /> <el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
</el-table> </el-table>
@ -88,8 +115,8 @@ function statusType(status: unknown) {
background background
layout="total, prev, pager, next, jumper" layout="total, prev, pager, next, jumper"
:total="total" :total="total"
@update:current-page="(v) => emit('update:page', v)" @update:current-page="(v: number) => emit('update:page', v)"
@update:page-size="(v) => emit('update:pageSize', v)" @update:page-size="(v: number) => emit('update:pageSize', v)"
/> />
</div> </div>
</el-drawer> </el-drawer>
@ -121,6 +148,12 @@ function statusType(status: unknown) {
margin-top: 14px; margin-top: 14px;
} }
.code-text {
font-family: Consolas, Monaco, 'Courier New', monospace;
font-weight: 600;
word-break: break-all;
}
@media (max-width: 768px) { @media (max-width: 768px) {
:deep(.equipment-record-drawer) { :deep(.equipment-record-drawer) {
width: 100vw !important; width: 100vw !important;

View File

@ -16,7 +16,7 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue']); const emit = defineEmits(['update:modelValue']);
const statusMap: Record<string, { label: string; type: string }> = { const statusMap: Record<string, { label: string; type: string }> = {
active: { label: '正常', type: 'success' }, active: { label: '已激活', type: 'success' },
inactive: { label: '未激活', type: 'info' }, inactive: { label: '未激活', type: 'info' },
disabled: { label: '禁用', type: 'danger' }, disabled: { label: '禁用', type: 'danger' },
expired: { label: '已过期', type: 'warning' }, expired: { label: '已过期', type: 'warning' },
@ -50,7 +50,7 @@ function copyText(text: unknown, label = '内容') {
:model-value="modelValue" :model-value="modelValue"
title="设备详情" title="设备详情"
width="760px" width="760px"
@update:model-value="(v) => emit('update:modelValue', v)" @update:model-value="(v: boolean) => emit('update:modelValue', v)"
> >
<el-descriptions v-if="row" :column="2" border> <el-descriptions v-if="row" :column="2" border>
<el-descriptions-item label="设备ID"> <el-descriptions-item label="设备ID">
@ -73,7 +73,7 @@ function copyText(text: unknown, label = '内容') {
<el-descriptions-item label="机器码"> <el-descriptions-item label="机器码">
<span class="code-text">{{ display(row.machineCode) }}</span> <span class="code-text">{{ display(row.machineCode) }}</span>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="授权码"> <el-descriptions-item label="绑定激活码">
<span class="code-text">{{ display(row.licenseCode) }}</span> <span class="code-text">{{ display(row.licenseCode) }}</span>
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="系统平台"> <el-descriptions-item label="系统平台">
@ -83,7 +83,7 @@ function copyText(text: unknown, label = '内容') {
{{ display(row.version) }} {{ display(row.version) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="绑定账号"> <el-descriptions-item label="绑定账号">
{{ display(row.account) }} {{ display(row.raw?.bindAccount || row.raw?.bind_account) }}
</el-descriptions-item> </el-descriptions-item>
<el-descriptions-item label="归属用户"> <el-descriptions-item label="归属用户">
{{ display(row.owner) }} {{ display(row.owner) }}

View File

@ -34,28 +34,31 @@ defineProps({
const emit = defineEmits(['update:modelValue', 'update:page', 'update:pageSize', 'refresh']); const emit = defineEmits(['update:modelValue', 'update:page', 'update:pageSize', 'refresh']);
function copyContent(content: unknown) { function copyContent(content: unknown, label = '提取内容') {
const text = String(content || '').trim(); const text = String(content || '').trim();
if (!text) { if (!text) {
ElMessage.warning('暂无提取内容可复制'); ElMessage.warning(`暂无${label}可复制`);
return; return;
} }
navigator.clipboard.writeText(text).then(() => { navigator.clipboard.writeText(text).then(() => {
ElMessage.success('提取内容已复制'); ElMessage.success(`${label}已复制`);
}); });
} }
function statusText(status: unknown) { function statusText(status: unknown) {
const value = String(status || ''); const value = String(status || '');
if (value === 'success' || value === '1') return '成功'; if (value === 'success' || value === '1') return '已提取';
if (value === 'failed' || value === '0') return '失败'; if (value === '2') return '补号';
if (value === '3') return '异常';
if (value === 'failed' || value === '0') return '未提取';
return value || '-'; return value || '-';
} }
function statusType(status: unknown) { function statusType(status: unknown) {
const value = String(status || ''); const value = String(status || '');
if (value === 'success' || value === '1') return 'success'; if (value === 'success' || value === '1') return 'success';
if (value === 'failed' || value === '0') return 'danger'; if (value === '2') return 'warning';
if (value === '3' || value === 'failed') return 'danger';
return 'info'; return 'info';
} }
</script> </script>
@ -67,7 +70,7 @@ function statusType(status: unknown) {
title="提取记录" title="提取记录"
size="860px" size="860px"
direction="rtl" direction="rtl"
@update:model-value="(v) => emit('update:modelValue', v)" @update:model-value="(v: boolean) => emit('update:modelValue', v)"
@opened="emit('refresh')" @opened="emit('refresh')"
> >
<div class="record-header"> <div class="record-header">
@ -87,19 +90,47 @@ function statusType(status: unknown) {
</el-tag> </el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="platform" label="提取平台" width="110" /> <el-table-column prop="platform" label="提取平台" width="110">
<el-table-column prop="type" label="提取类型" width="110" /> <template #default="{ row: item }">{{ item.platform || '-' }}</template>
<el-table-column prop="account" label="提取账号" min-width="150" show-overflow-tooltip /> </el-table-column>
<el-table-column label="提取内容" min-width="220" show-overflow-tooltip> <el-table-column prop="type" label="数据类型" width="110">
<template #default="{ row: item }">{{ item.type || '-' }}</template>
</el-table-column>
<el-table-column label="Cursor账号" min-width="170" show-overflow-tooltip>
<template #default="{ row: item }"> <template #default="{ row: item }">
<span>{{ item.content || '-' }}</span> <span>{{ item.account || '-' }}</span>
<el-button v-if="item.content" link type="primary" @click="copyContent(item.content)"> <el-button v-if="item.account" link type="primary" @click="copyContent(item.account, 'Cursor账号')">
复制 复制
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ip" label="IP" min-width="130" show-overflow-tooltip /> <el-table-column label="密码" min-width="150" show-overflow-tooltip>
<el-table-column prop="createdAt" label="提取时间" width="180" /> <template #default="{ row: item }">
<span>{{ item.password || '-' }}</span>
<el-button v-if="item.password" link type="primary" @click="copyContent(item.password, '密码')">
复制
</el-button>
</template>
</el-table-column>
<el-table-column label="Token" min-width="240" show-overflow-tooltip>
<template #default="{ row: item }">
<span>{{ item.token || '-' }}</span>
<el-button v-if="item.token" link type="primary" @click="copyContent(item.token, 'Token')">
复制
</el-button>
</template>
</el-table-column>
<el-table-column label="提取内容" min-width="260" show-overflow-tooltip>
<template #default="{ row: item }">
<span>{{ item.content || '-' }}</span>
<el-button v-if="item.content" link type="primary" @click="copyContent(item.content, '提取内容')">
复制
</el-button>
</template>
</el-table-column>
<el-table-column prop="extractedAt" label="提取时间" width="180">
<template #default="{ row: item }">{{ item.extractedAt || item.createdAt || '-' }}</template>
</el-table-column>
<el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip /> <el-table-column prop="remark" label="备注" min-width="180" show-overflow-tooltip />
</el-table> </el-table>
@ -110,8 +141,8 @@ function statusType(status: unknown) {
background background
layout="total, prev, pager, next, jumper" layout="total, prev, pager, next, jumper"
:total="total" :total="total"
@update:current-page="(v) => emit('update:page', v)" @update:current-page="(v: number) => emit('update:page', v)"
@update:page-size="(v) => emit('update:pageSize', v)" @update:page-size="(v: number) => emit('update:pageSize', v)"
/> />
</div> </div>
</el-drawer> </el-drawer>

View File

@ -15,7 +15,7 @@ import {
getCursorEquipmentExtractRecords, getCursorEquipmentExtractRecords,
getCursorEquipmentList, getCursorEquipmentList,
updateCursorEquipment, updateCursorEquipment,
} from '@/api/cursorEquipment'; } from '../../../api/cursorEquipment';
type EquipmentRow = Record<string, any>; type EquipmentRow = Record<string, any>;
@ -60,10 +60,10 @@ const extractState = reactive({
}); });
const statusOptions = [ const statusOptions = [
{ label: '未激活', value: 'inactive' }, { label: '未激活', value: 0 },
{ label: '正常', value: 'active' }, { label: '已激活', value: 1 },
{ label: '禁用', value: 'disabled' }, { label: '禁用', value: 3 },
{ label: '已过期', value: 'expired' }, { label: '已过期', value: 2 },
]; ];
const osOptions = [ const osOptions = [
@ -74,7 +74,7 @@ const osOptions = [
]; ];
const statusMap: Record<string, { label: string; type: string }> = { const statusMap: Record<string, { label: string; type: string }> = {
active: { label: '正常', type: 'success' }, active: { label: '已激活', type: 'success' },
inactive: { label: '未激活', type: 'info' }, inactive: { label: '未激活', type: 'info' },
disabled: { label: '禁用', type: 'danger' }, disabled: { label: '禁用', type: 'danger' },
expired: { label: '已过期', type: 'warning' }, expired: { label: '已过期', type: 'warning' },
@ -87,7 +87,7 @@ const summary = computed(() => {
const expired = tableData.value.filter((item) => item.status === 'expired').length; const expired = tableData.value.filter((item) => item.status === 'expired').length;
return [ return [
{ label: '当前页设备', value: tableData.value.length, type: 'primary' }, { label: '当前页设备', value: tableData.value.length, type: 'primary' },
{ label: '正常设备', value: active, type: 'success' }, { label: '已激活设备', value: active, type: 'success' },
{ label: '未激活', value: inactive, type: 'info' }, { label: '未激活', value: inactive, type: 'info' },
{ label: '禁用/过期', value: disabled + expired, type: 'danger' }, { label: '禁用/过期', value: disabled + expired, type: 'danger' },
]; ];
@ -137,24 +137,35 @@ function formatTime(value: any) {
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`; return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())} ${p(d.getHours())}:${p(d.getMinutes())}:${p(d.getSeconds())}`;
} }
function normalizeEquipmentStatus(status: any) {
const value = String(status ?? '').trim();
if (value === '0' || value === 'inactive') return 'inactive';
if (value === '1' || value === 'active' || value === 'normal') return 'active';
if (value === '2' || value === 'expired') return 'expired';
if (value === '3' || value === 'disabled' || value === 'disable') return 'disabled';
return value || 'inactive';
}
function normalizeRow(raw: any): EquipmentRow { function normalizeRow(raw: any): EquipmentRow {
const status = String(pick(raw, 'status', 'Status') || 'inactive'); const status = normalizeEquipmentStatus(pick(raw, 'status', 'Status'));
return { return {
id: pick(raw, 'id', 'ID', 'Id'), id: pick(raw, 'id', 'ID', 'Id'),
name: pick(raw, 'name', 'device_name', 'deviceName', 'Name', 'DeviceName'), name: pick(raw, 'name', 'device_name', 'deviceName', 'Name', 'DeviceName'),
deviceNo: pick(raw, 'device_no', 'deviceNo', 'DeviceNo', 'serial_no', 'serialNo'), deviceNo: pick(raw, 'device_no', 'deviceNo', 'DeviceNo', 'serial_no', 'serialNo'),
machineCode: pick(raw, 'machine_code', 'machineCode', 'MachineCode', 'fingerprint'), machineCode: pick(raw, 'machine_code', 'machineCode', 'MachineCode', 'fingerprint'),
licenseCode: pick(raw, 'license_code', 'licenseCode', 'LicenseCode'), licenseCode: pick(raw, 'bindActivationCode', 'activationCode', 'activation_code', 'code', 'Code', 'license_code', 'licenseCode', 'LicenseCode'),
os: pick(raw, 'os', 'OS', 'platform', 'Platform'), os: pick(raw, 'system', 'System', 'os', 'OS', 'platform', 'Platform'),
version: pick(raw, 'version', 'Version', 'client_version', 'clientVersion'), version: pick(raw, 'version', 'Version', 'client_version', 'clientVersion'),
account: pick(raw, 'account', 'Account', 'email', 'Email'), account: pick(raw, 'bindActivationCode', 'activationCode', 'activation_code', 'code', 'Code', 'license_code', 'licenseCode', 'LicenseCode'),
owner: pick(raw, 'owner', 'Owner', 'user_name', 'userName', 'tenant_name', 'tenantName'), owner: pick(raw, 'owner', 'Owner', 'user_name', 'userName', 'tenant_name', 'tenantName'),
status, status,
activationCount: Number(pick(raw, 'activation_count', 'activationCount', 'ActivationCount') || 0), activationCount: Number(pick(raw, 'activation_count', 'activationCount', 'ActivationCount') || 0),
extractCount: Number(pick(raw, 'extract_count', 'extractCount', 'ExtractCount') || 0), extractCount: Number(pick(raw, 'extract_count', 'extractCount', 'ExtractCount') || 0),
lastActivatedAt: formatTime(pick(raw, 'last_activated_at', 'lastActivatedAt', 'activated_at')), lastActivatedAt: formatTime(pick(raw, 'lastActivatedAt', 'last_activated_at', 'activationTime', 'activation_time', 'activated_at', 'activatedAt')),
lastExtractedAt: formatTime(pick(raw, 'last_extracted_at', 'lastExtractedAt', 'extracted_at')), lastExtractedAt: formatTime(pick(raw, 'last_extracted_at', 'lastExtractedAt', 'extracted_at')),
expiredAt: formatTime(pick(raw, 'expired_at', 'expiredAt', 'expire_time', 'expireTime')), expiredAt: formatTime(pick(raw, 'expiredAt', 'expired_at', 'expireTime', 'expire_time')),
createdAt: formatTime(pick(raw, 'create_time', 'created_at', 'createdAt', 'CreatedAt')), createdAt: formatTime(pick(raw, 'create_time', 'created_at', 'createdAt', 'CreatedAt')),
remark: pick(raw, 'remark', 'Remark'), remark: pick(raw, 'remark', 'Remark'),
raw, raw,
@ -164,14 +175,23 @@ function normalizeRow(raw: any): EquipmentRow {
function normalizeRecord(raw: any): EquipmentRow { function normalizeRecord(raw: any): EquipmentRow {
return { return {
id: pick(raw, 'id', 'ID', 'Id'), id: pick(raw, 'id', 'ID', 'Id'),
status: pick(raw, 'status', 'Status', 'result', 'Result'), status: pick(raw, 'status', 'Status', 'result', 'Result', 'isExtracted', 'is_extracted'),
activationCode: pick(raw, 'activationCode', 'activation_code', 'code', 'Code'),
durationDays: pick(raw, 'durationDays', 'duration_days'),
machineCode: pick(raw, 'machineCode', 'machine_code', 'MachineCode'),
deviceInfo: pick(raw, 'deviceInfo', 'device_info', 'DeviceInfo'),
expiredAt: formatTime(pick(raw, 'expiredAt', 'expired_at', 'expireTime', 'expire_time')),
activatedAt: formatTime(pick(raw, 'activatedAt', 'activated_at', 'activationTime', 'activation_time')),
account: pick(raw, 'account', 'Account', 'email', 'Email'), account: pick(raw, 'account', 'Account', 'email', 'Email'),
platform: pick(raw, 'platform', 'Platform', 'source', 'Source'), password: pick(raw, 'password', 'Password'),
token: pick(raw, 'token', 'Token'),
platform: pick(raw, 'platform', 'Platform', 'source', 'Source', 'extractedPlatform', 'extracted_platform'),
type: pick(raw, 'type', 'Type', 'data_type', 'dataType'), type: pick(raw, 'type', 'Type', 'data_type', 'dataType'),
content: pick(raw, 'content', 'Content', 'extract_content', 'extractContent', 'token', 'Token'), content: pick(raw, 'content', 'Content', 'extract_content', 'extractContent'),
ip: pick(raw, 'ip', 'IP', 'client_ip', 'clientIp'), ip: pick(raw, 'ip', 'IP', 'client_ip', 'clientIp'),
clientVersion: pick(raw, 'client_version', 'clientVersion', 'version', 'Version'), clientVersion: pick(raw, 'client_version', 'clientVersion', 'version', 'Version'),
createdAt: formatTime(pick(raw, 'create_time', 'created_at', 'createdAt', 'CreatedAt')), createdAt: formatTime(pick(raw, 'create_time', 'created_at', 'createdAt', 'CreatedAt')),
extractedAt: formatTime(pick(raw, 'extractedAt', 'extracted_at', 'extracted_time')),
remark: pick(raw, 'remark', 'Remark', 'message', 'Message'), remark: pick(raw, 'remark', 'Remark', 'message', 'Message'),
raw, raw,
}; };
@ -202,7 +222,7 @@ async function fetchList() {
page: pagination.page, page: pagination.page,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
keyword: query.keyword || undefined, keyword: query.keyword || undefined,
status: query.status || undefined, status: query.status === '' ? undefined : query.status,
os: query.os || undefined, os: query.os || undefined,
}); });
if (res?.code !== 200) { if (res?.code !== 200) {
@ -401,7 +421,7 @@ onUnmounted(() => {
<div class="toolbar-left"> <div class="toolbar-left">
<el-input <el-input
v-model="query.keyword" v-model="query.keyword"
placeholder="搜索设备名称 / 编号 / 机器码 / 账号" placeholder="搜索设备名称 / 编号 / 机器码 / 激活码"
clearable clearable
class="w-300" class="w-300"
/> />
@ -450,7 +470,7 @@ onUnmounted(() => {
<el-table-column prop="version" label="版本" width="110" align="center"> <el-table-column prop="version" label="版本" width="110" align="center">
<template #default="{ row }">{{ row.version || '-' }}</template> <template #default="{ row }">{{ row.version || '-' }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="account" label="绑定账号" min-width="160" show-overflow-tooltip /> <el-table-column prop="account" label="绑定激活码" min-width="160" show-overflow-tooltip />
<el-table-column prop="owner" label="归属用户" min-width="130" show-overflow-tooltip /> <el-table-column prop="owner" label="归属用户" min-width="130" show-overflow-tooltip />
<el-table-column label="激活/提取" width="120" align="center"> <el-table-column label="激活/提取" width="120" align="center">
<template #default="{ row }"> <template #default="{ row }">
@ -492,18 +512,18 @@ onUnmounted(() => {
</div> </div>
</el-card> </el-card>
<DetailDialog v-model="detailVisible" :row="currentRow" /> <DetailDialog v-model="detailVisible" :row="currentRow || undefined" />
<EditDialog <EditDialog
v-model="editVisible" v-model="editVisible"
:row="currentRow" :row="currentRow || undefined"
:loading="actionLoading" :loading="actionLoading"
@submit="handleSave" @submit="handleSave"
/> />
<DeleteDialog <DeleteDialog
v-model="deleteVisible" v-model="deleteVisible"
:row="currentRow" :row="currentRow || undefined"
:loading="actionLoading" :loading="actionLoading"
@confirm="handleDelete" @confirm="handleDelete"
/> />
@ -512,7 +532,7 @@ onUnmounted(() => {
v-model="activationVisible" v-model="activationVisible"
v-model:page="activationState.page" v-model:page="activationState.page"
v-model:page-size="activationState.pageSize" v-model:page-size="activationState.pageSize"
:row="currentRow" :row="currentRow || undefined"
:loading="activationState.loading" :loading="activationState.loading"
:records="activationState.records" :records="activationState.records"
:total="activationState.total" :total="activationState.total"
@ -523,7 +543,7 @@ onUnmounted(() => {
v-model="extractVisible" v-model="extractVisible"
v-model:page="extractState.page" v-model:page="extractState.page"
v-model:page-size="extractState.pageSize" v-model:page-size="extractState.pageSize"
:row="currentRow" :row="currentRow || undefined"
:loading="extractState.loading" :loading="extractState.loading"
:records="extractState.records" :records="extractState.records"
:total="extractState.total" :total="extractState.total"