1
This commit is contained in:
@@ -0,0 +1,744 @@
|
||||
<template>
|
||||
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button @click="openBatchModal()">
|
||||
<template #icon>
|
||||
<ThunderboltOutlined />
|
||||
</template>
|
||||
批量生成
|
||||
</a-button>
|
||||
<a-button type="primary" @click="openGenerateModal()">
|
||||
<template #icon>
|
||||
<PlusOutlined />
|
||||
</template>
|
||||
生成兑换码
|
||||
</a-button>
|
||||
<a-button @click="reload()">
|
||||
<template #icon>
|
||||
<ReloadOutlined />
|
||||
</template>
|
||||
刷新
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
<a-card :bordered="false" :body-style="{ padding: '16px' }">
|
||||
<!-- Tab 切换 -->
|
||||
<a-tabs v-model:activeKey="activeTab" @change="handleTabChange">
|
||||
<a-tab-pane key="codes" tab="兑换码管理">
|
||||
<!-- 搜索区域 -->
|
||||
<div class="search-container">
|
||||
<a-form layout="inline" :model="searchForm" class="search-form">
|
||||
<a-form-item label="兑换码">
|
||||
<a-input
|
||||
v-model:value="searchForm.code"
|
||||
placeholder="请输入兑换码"
|
||||
allow-clear
|
||||
style="width: 200px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="状态">
|
||||
<a-select
|
||||
v-model:value="searchForm.status"
|
||||
placeholder="请选择状态"
|
||||
allow-clear
|
||||
style="width: 120px"
|
||||
>
|
||||
<a-select-option :value="0">未使用</a-select-option>
|
||||
<a-select-option :value="1">已使用</a-select-option>
|
||||
<a-select-option :value="2">已过期</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="批次号">
|
||||
<a-input
|
||||
v-model:value="searchForm.batchNo"
|
||||
placeholder="请输入批次号"
|
||||
allow-clear
|
||||
style="width: 200px"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="handleSearch">
|
||||
<template #icon>
|
||||
<SearchOutlined />
|
||||
</template>
|
||||
搜索
|
||||
</a-button>
|
||||
<a-button @click="handleReset">
|
||||
<template #icon>
|
||||
<ClearOutlined />
|
||||
</template>
|
||||
重置
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
|
||||
<!-- 统计卡片 -->
|
||||
<a-row :gutter="16" style="margin-bottom: 16px">
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="总兑换码数量"
|
||||
:value="statistics.total"
|
||||
:value-style="{ color: '#1890ff' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="未使用"
|
||||
:value="statistics.unused"
|
||||
:value-style="{ color: '#52c41a' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="已使用"
|
||||
:value="statistics.used"
|
||||
:value-style="{ color: '#faad14' }"
|
||||
/>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-statistic
|
||||
title="已过期"
|
||||
:value="statistics.expired"
|
||||
:value-style="{ color: '#ff4d4f' }"
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
|
||||
<!-- 表格 -->
|
||||
<ele-pro-table
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:scroll="{ x: 1400 }"
|
||||
tool-class="ele-toolbar-form"
|
||||
>
|
||||
<template #bodyCell="{ column, record }">
|
||||
<!-- 兑换码信息 -->
|
||||
<template v-if="column.key === 'code'">
|
||||
<div class="code-info">
|
||||
<a-typography-text strong copyable>{{ record.code }}</a-typography-text>
|
||||
<div class="batch-no" v-if="record.batchNo">
|
||||
批次: {{ record.batchNo }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 金额 -->
|
||||
<template v-if="column.key === 'amount'">
|
||||
<span class="amount-value">¥{{ formatAmount(record.amount) }}</span>
|
||||
</template>
|
||||
|
||||
<!-- 状态 -->
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag :color="getStatusColor(record.status)">
|
||||
{{ getStatusText(record.status) }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 生成方式 -->
|
||||
<template v-if="column.key === 'generateType'">
|
||||
<a-tag :color="record.generateType === 1 ? 'blue' : 'purple'">
|
||||
{{ record.generateType === 1 ? '管理员生成' : '批量生成' }}
|
||||
</a-tag>
|
||||
</template>
|
||||
|
||||
<!-- 过期时间 -->
|
||||
<template v-if="column.key === 'expireTime'">
|
||||
<span v-if="record.expireTime">{{ formatDate(record.expireTime) }}</span>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<!-- 使用信息 -->
|
||||
<template v-if="column.key === 'usedInfo'">
|
||||
<template v-if="record.status === 1 && record.usedAt">
|
||||
<div>使用时间: {{ formatDate(record.usedAt) }}</div>
|
||||
<div class="balance-change">
|
||||
<span class="balance-before">{{ formatAmount(record.balanceBefore) }}</span>
|
||||
<ArrowRightOutlined />
|
||||
<span class="balance-after">{{ formatAmount(record.balanceAfter) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
|
||||
<!-- 创建时间 -->
|
||||
<template v-if="column.key === 'createTime'">
|
||||
{{ formatDate(record.createTime) }}
|
||||
</template>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<template v-if="column.key === 'action'">
|
||||
<a-space>
|
||||
<a-tooltip title="查看详情">
|
||||
<a-button size="small" type="link" @click="viewDetail(record)">
|
||||
<template #icon><EyeOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-tooltip title="复制兑换码">
|
||||
<a-button size="small" type="link" @click="copyCode(record.code)">
|
||||
<template #icon><CopyOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
<a-popconfirm
|
||||
title="确定要删除此兑换码吗?"
|
||||
@confirm="handleDelete(record.id)"
|
||||
>
|
||||
<a-tooltip title="删除">
|
||||
<a-button size="small" type="link" danger>
|
||||
<template #icon><DeleteOutlined /></template>
|
||||
</a-button>
|
||||
</a-tooltip>
|
||||
</a-popconfirm>
|
||||
</a-space>
|
||||
</template>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</a-tab-pane>
|
||||
|
||||
<a-tab-pane key="records" tab="兑换记录">
|
||||
<RechargeRecord />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
</a-card>
|
||||
</a-page-header>
|
||||
|
||||
<!-- 生成兑换码弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="generateModalVisible"
|
||||
title="生成兑换码"
|
||||
:width="500"
|
||||
@ok="handleGenerate"
|
||||
@cancel="generateModalVisible = false"
|
||||
:confirm-loading="generateLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="generateFormRef"
|
||||
:model="generateForm"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
>
|
||||
<a-form-item
|
||||
label="充值金额"
|
||||
name="amount"
|
||||
:rules="[{ required: true, message: '请输入充值金额' }, { type: 'number', min: 0.01, message: '金额必须大于0' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="generateForm.amount"
|
||||
:min="0.01"
|
||||
:precision="2"
|
||||
style="width: 100%"
|
||||
placeholder="请输入充值金额"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="生成数量"
|
||||
name="quantity"
|
||||
:rules="[{ required: true, message: '请输入生成数量' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="generateForm.quantity"
|
||||
:min="1"
|
||||
:max="100"
|
||||
style="width: 100%"
|
||||
placeholder="请输入生成数量"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="有效期"
|
||||
name="expireDays"
|
||||
:rules="[{ required: true, message: '请输入有效期天数' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="generateForm.expireDays"
|
||||
:min="1"
|
||||
:max="365"
|
||||
style="width: 100%"
|
||||
addon-after="天"
|
||||
placeholder="请输入有效期天数"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 批量生成弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="batchModalVisible"
|
||||
title="批量生成兑换码"
|
||||
:width="600"
|
||||
@ok="handleBatchGenerate"
|
||||
@cancel="batchModalVisible = false"
|
||||
:confirm-loading="batchLoading"
|
||||
>
|
||||
<a-form
|
||||
ref="batchFormRef"
|
||||
:model="batchForm"
|
||||
:label-col="{ span: 6 }"
|
||||
:wrapper-col="{ span: 16 }"
|
||||
>
|
||||
<a-form-item label="预设金额">
|
||||
<a-select
|
||||
v-model:value="batchForm.presetAmounts"
|
||||
mode="tags"
|
||||
placeholder="输入预设金额后按回车"
|
||||
style="width: 100%"
|
||||
:token-separators="[',']"
|
||||
>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="每个金额数量"
|
||||
name="quantityPerAmount"
|
||||
:rules="[{ required: true, message: '请输入数量' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="batchForm.quantityPerAmount"
|
||||
:min="1"
|
||||
:max="50"
|
||||
style="width: 100%"
|
||||
placeholder="每个预设金额生成的数量"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="有效期"
|
||||
name="expireDays"
|
||||
:rules="[{ required: true, message: '请输入有效期天数' }]"
|
||||
>
|
||||
<a-input-number
|
||||
v-model:value="batchForm.expireDays"
|
||||
:min="1"
|
||||
:max="365"
|
||||
style="width: 100%"
|
||||
addon-after="天"
|
||||
placeholder="请输入有效期天数"
|
||||
/>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
|
||||
<!-- 生成的兑换码列表弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="codesModalVisible"
|
||||
title="生成的兑换码"
|
||||
:width="700"
|
||||
:footer="null"
|
||||
>
|
||||
<a-alert
|
||||
:message="`共生成 ${generatedCodes.length} 个兑换码`"
|
||||
type="success"
|
||||
style="margin-bottom: 16px"
|
||||
/>
|
||||
<a-list
|
||||
:data-source="generatedCodes"
|
||||
size="small"
|
||||
bordered
|
||||
:max-height="400"
|
||||
style="overflow-y: auto"
|
||||
>
|
||||
<template #renderItem="{ item }">
|
||||
<a-list-item>
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<a-typography-text strong copyable>{{ item.code }}</a-typography-text>
|
||||
</template>
|
||||
<template #description>
|
||||
金额: ¥{{ formatAmount(item.amount) }} |
|
||||
有效期至: {{ formatDate(item.expireTime) }}
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</template>
|
||||
</a-list>
|
||||
<div style="margin-top: 16px; text-align: center">
|
||||
<a-button type="primary" @click="copyAllCodes">复制全部兑换码</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
||||
<!-- 兑换码详情弹窗 -->
|
||||
<a-modal
|
||||
v-model:open="detailModalVisible"
|
||||
title="兑换码详情"
|
||||
:width="500"
|
||||
:footer="null"
|
||||
>
|
||||
<a-descriptions :column="1" bordered v-if="currentRecord">
|
||||
<a-descriptions-item label="兑换码">
|
||||
<a-typography-text copyable strong>{{ currentRecord.code }}</a-typography-text>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="充值金额">
|
||||
<span style="color: #f5222d; font-weight: bold">¥{{ formatAmount(currentRecord.amount) }}</span>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="状态">
|
||||
<a-tag :color="getStatusColor(currentRecord.status)">
|
||||
{{ getStatusText(currentRecord.status) }}
|
||||
</a-tag>
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="生成方式">
|
||||
{{ currentRecord.generateType === 1 ? '管理员生成' : '批量生成' }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="批次号">{{ currentRecord.batchNo || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="过期时间">{{ formatDate(currentRecord.expireTime) || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="使用时间">{{ formatDate(currentRecord.usedAt) || '-' }}</a-descriptions-item>
|
||||
<a-descriptions-item label="使用前余额">
|
||||
¥{{ formatAmount(currentRecord.balanceBefore) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="使用后余额">
|
||||
¥{{ formatAmount(currentRecord.balanceAfter) }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="创建时间">{{ formatDate(currentRecord.createTime) }}</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, computed, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import {
|
||||
PlusOutlined,
|
||||
ReloadOutlined,
|
||||
SearchOutlined,
|
||||
ClearOutlined,
|
||||
EyeOutlined,
|
||||
CopyOutlined,
|
||||
DeleteOutlined,
|
||||
ArrowRightOutlined,
|
||||
ThunderboltOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { toDateString } from 'ele-admin-pro';
|
||||
import { pageRechargeCode, generateRechargeCode, batchGenerateRechargeCode, removeRechargeCode } from '@/api/shop/shopRechargeCode';
|
||||
import type { ShopRechargeCode } from '@/api/shop/shopRechargeCode/model';
|
||||
import RechargeRecord from '@/views/shop/shopRechargeRecord/index.vue';
|
||||
|
||||
const TABLE_COLUMN_COLORS = {
|
||||
unused: '#52c41a',
|
||||
used: '#faad14',
|
||||
expired: '#ff4d4f'
|
||||
};
|
||||
|
||||
// Tab切换
|
||||
const activeTab = ref('codes');
|
||||
const loadedTabs = ref<Set<string>>(new Set(['codes']));
|
||||
|
||||
function handleTabChange(tab: string) {
|
||||
if (!loadedTabs.value.has(tab)) {
|
||||
loadedTabs.value.add(tab);
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索表单
|
||||
const searchForm = reactive({
|
||||
code: '',
|
||||
status: undefined as number | undefined,
|
||||
batchNo: ''
|
||||
});
|
||||
|
||||
// 表格引用
|
||||
const tableRef = ref(null);
|
||||
|
||||
// 生成弹窗相关
|
||||
const generateModalVisible = ref(false);
|
||||
const generateFormRef = ref(null);
|
||||
const generateForm = reactive({
|
||||
amount: 10,
|
||||
quantity: 1,
|
||||
expireDays: 30
|
||||
});
|
||||
const generateLoading = ref(false);
|
||||
|
||||
// 批量生成弹窗相关
|
||||
const batchModalVisible = ref(false);
|
||||
const batchFormRef = ref(null);
|
||||
const batchForm = reactive({
|
||||
presetAmounts: [] as number[],
|
||||
quantityPerAmount: 1,
|
||||
expireDays: 30
|
||||
});
|
||||
const batchLoading = ref(false);
|
||||
|
||||
// 生成的兑换码列表弹窗
|
||||
const codesModalVisible = ref(false);
|
||||
const generatedCodes = ref<ShopRechargeCode[]>([]);
|
||||
|
||||
// 详情弹窗
|
||||
const detailModalVisible = ref(false);
|
||||
const currentRecord = ref<ShopRechargeCode | null>(null);
|
||||
|
||||
// 统计数据
|
||||
const statistics = reactive({
|
||||
total: 0,
|
||||
unused: 0,
|
||||
used: 0,
|
||||
expired: 0
|
||||
});
|
||||
|
||||
// 表格列配置
|
||||
const columns = ref([
|
||||
{
|
||||
title: '兑换码信息',
|
||||
key: 'code',
|
||||
width: 250,
|
||||
fixed: 'left'
|
||||
},
|
||||
{
|
||||
title: '充值金额',
|
||||
key: 'amount',
|
||||
width: 120,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 100,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '生成方式',
|
||||
key: 'generateType',
|
||||
width: 120,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '过期时间',
|
||||
key: 'expireTime',
|
||||
width: 160,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '使用信息',
|
||||
key: 'usedInfo',
|
||||
width: 200,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
title: '创建时间',
|
||||
key: 'createTime',
|
||||
width: 160,
|
||||
align: 'center',
|
||||
sorter: true
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 150,
|
||||
fixed: 'right',
|
||||
align: 'center'
|
||||
}
|
||||
]);
|
||||
|
||||
// 数据源
|
||||
const datasource = ({ page, limit, where, orders }) => {
|
||||
const params = {
|
||||
...where,
|
||||
...searchForm,
|
||||
...orders,
|
||||
page,
|
||||
limit
|
||||
};
|
||||
return pageRechargeCode(params).then((res) => {
|
||||
// 更新统计数据
|
||||
if (res.list && res.list.length > 0) {
|
||||
updateStatistics(res.list);
|
||||
}
|
||||
return res;
|
||||
});
|
||||
};
|
||||
|
||||
// 更新统计数据
|
||||
const updateStatistics = (list: ShopRechargeCode[]) => {
|
||||
statistics.total = list.length;
|
||||
statistics.unused = list.filter((item) => item.status === 0).length;
|
||||
statistics.used = list.filter((item) => item.status === 1).length;
|
||||
statistics.expired = list.filter((item) => item.status === 2).length;
|
||||
};
|
||||
|
||||
// 格式化金额
|
||||
const formatAmount = (amount: string | number | undefined) => {
|
||||
if (amount === null || amount === undefined) return '0.00';
|
||||
return Number(amount).toFixed(2);
|
||||
};
|
||||
|
||||
// 格式化日期
|
||||
const formatDate = (dateStr: string | undefined) => {
|
||||
if (!dateStr) return '-';
|
||||
return toDateString(dateStr, 'yyyy-MM-dd HH:mm');
|
||||
};
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: number) => {
|
||||
const map: Record<number, string> = { 0: '未使用', 1: '已使用', 2: '已过期' };
|
||||
return map[status] || '未知';
|
||||
};
|
||||
|
||||
// 获取状态颜色
|
||||
const getStatusColor = (status: number) => {
|
||||
const map: Record<number, string> = { 0: 'green', 1: 'orange', 2: 'red' };
|
||||
return map[status] || 'default';
|
||||
};
|
||||
|
||||
// 搜索
|
||||
const handleSearch = () => {
|
||||
tableRef.value?.reload();
|
||||
};
|
||||
|
||||
// 重置
|
||||
const handleReset = () => {
|
||||
searchForm.code = '';
|
||||
searchForm.status = undefined;
|
||||
searchForm.batchNo = '';
|
||||
tableRef.value?.reload();
|
||||
};
|
||||
|
||||
// 刷新
|
||||
const reload = () => {
|
||||
tableRef.value?.reload();
|
||||
};
|
||||
|
||||
// 打开生成弹窗
|
||||
const openGenerateModal = () => {
|
||||
generateForm.amount = 10;
|
||||
generateForm.quantity = 1;
|
||||
generateForm.expireDays = 30;
|
||||
generateModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 打开批量生成弹窗
|
||||
const openBatchModal = () => {
|
||||
batchForm.presetAmounts = [];
|
||||
batchForm.quantityPerAmount = 1;
|
||||
batchForm.expireDays = 30;
|
||||
batchModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 生成兑换码
|
||||
const handleGenerate = async () => {
|
||||
try {
|
||||
await generateFormRef.value.validate();
|
||||
generateLoading.value = true;
|
||||
const res = await generateRechargeCode(
|
||||
generateForm.amount,
|
||||
generateForm.quantity,
|
||||
generateForm.expireDays
|
||||
);
|
||||
generatedCodes.value = res || [];
|
||||
generateModalVisible.value = false;
|
||||
codesModalVisible.value = true;
|
||||
message.success(`成功生成 ${generatedCodes.value.length} 个兑换码`);
|
||||
tableRef.value?.reload();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
generateLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 批量生成兑换码
|
||||
const handleBatchGenerate = async () => {
|
||||
try {
|
||||
if (!batchForm.presetAmounts || batchForm.presetAmounts.length === 0) {
|
||||
message.warning('请输入至少一个预设金额');
|
||||
return;
|
||||
}
|
||||
batchLoading.value = true;
|
||||
const res = await batchGenerateRechargeCode({
|
||||
presetAmounts: batchForm.presetAmounts.map(Number),
|
||||
quantityPerAmount: batchForm.quantityPerAmount,
|
||||
expireDays: batchForm.expireDays
|
||||
});
|
||||
generatedCodes.value = res?.codes || [];
|
||||
batchModalVisible.value = false;
|
||||
codesModalVisible.value = true;
|
||||
message.success(`成功生成 ${generatedCodes.value.length} 个兑换码`);
|
||||
tableRef.value?.reload();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
batchLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 复制兑换码
|
||||
const copyCode = (code: string) => {
|
||||
navigator.clipboard.writeText(code).then(() => {
|
||||
message.success('兑换码已复制');
|
||||
});
|
||||
};
|
||||
|
||||
// 复制所有兑换码
|
||||
const copyAllCodes = () => {
|
||||
const codes = generatedCodes.value.map((item) => item.code).join('\n');
|
||||
navigator.clipboard.writeText(codes).then(() => {
|
||||
message.success('所有兑换码已复制');
|
||||
});
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const viewDetail = (record: ShopRechargeCode) => {
|
||||
currentRecord.value = record;
|
||||
detailModalVisible.value = true;
|
||||
};
|
||||
|
||||
// 删除
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
await removeRechargeCode(id);
|
||||
message.success('删除成功');
|
||||
tableRef.value?.reload();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
// 获取页面标题
|
||||
const getPageTitle = () => {
|
||||
return '充值兑换码管理';
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// 初始加载
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.search-container {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.code-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.batch-no {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.amount-value {
|
||||
font-weight: bold;
|
||||
color: #f5222d;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.balance-change {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.balance-before {
|
||||
color: #999;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.balance-after {
|
||||
color: #52c41a;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user