feat: 增加用户充值记录查询
This commit is contained in:
@@ -95,8 +95,8 @@ function handleConfirm() {
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="handleClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleConfirm">确定</el-button>
|
||||
<el-button type="primary" @click="handleClose">关闭</el-button>
|
||||
<el-button v-if="false" type="primary" @click="handleConfirm">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { CircleCheck } from '@element-plus/icons-vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { applyApiKey, getApiKey } from '@/api/model/index.ts';
|
||||
import { applyApiKey, getApiKey, getRechargeLog } from '@/api/model/index.ts';
|
||||
import { isUserVip } from '@/utils/user';
|
||||
|
||||
const apiKey = ref('');
|
||||
@@ -20,6 +20,8 @@ const router = useRouter();
|
||||
async function fetchApiKey() {
|
||||
try {
|
||||
const res = await getApiKey();
|
||||
const res2 = await getRechargeLog();
|
||||
console.log('re2', res2);
|
||||
if (res.data?.apiKey) {
|
||||
apiKey.value = res.data.apiKey;
|
||||
displayedKey.value = res.data.apiKey;
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
<script lang="ts" setup>
|
||||
import { List, Refresh, Search } from '@element-plus/icons-vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { getRechargeLog } from '@/api/model/index.ts';
|
||||
|
||||
interface RechargeLog {
|
||||
id: string;
|
||||
content: string;
|
||||
rechargeAmount: number;
|
||||
creationTime: string;
|
||||
expireDateTime: string;
|
||||
contactInfo: string;
|
||||
remark: string;
|
||||
userId: string;
|
||||
}
|
||||
|
||||
const loading = ref(false);
|
||||
const logData = ref<RechargeLog[]>([]);
|
||||
const searchText = ref('');
|
||||
const currentSort = ref({ prop: '', order: '' });
|
||||
const currentPage = ref(1);
|
||||
const pageSize = ref(10);
|
||||
|
||||
// 模拟数据获取
|
||||
async function fetchRechargeLog() {
|
||||
try {
|
||||
loading.value = true;
|
||||
const res = await getRechargeLog();
|
||||
logData.value = res.data || [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error('获取充值记录失败:', error);
|
||||
ElMessage.error('获取充值记录失败');
|
||||
}
|
||||
finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 排序处理
|
||||
function handleSortChange({ prop, order }: { prop: string; order: string }) {
|
||||
currentSort.value = { prop, order };
|
||||
}
|
||||
|
||||
// 搜索处理
|
||||
function handleSearch() {
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
function handleSearchClear() {
|
||||
searchText.value = '';
|
||||
currentPage.value = 1;
|
||||
}
|
||||
|
||||
// 刷新数据
|
||||
function refreshLog() {
|
||||
fetchRechargeLog();
|
||||
currentPage.value = 1;
|
||||
searchText.value = '';
|
||||
currentSort.value = { prop: '', order: '' };
|
||||
}
|
||||
|
||||
// 过滤和排序后的数据
|
||||
const filteredData = computed(() => {
|
||||
let data = [...logData.value];
|
||||
|
||||
// 搜索过滤
|
||||
if (searchText.value) {
|
||||
const search = searchText.value.toLowerCase();
|
||||
data = data.filter(item =>
|
||||
(item.contactInfo && item.contactInfo.toLowerCase().includes(search))
|
||||
|| (item.remark && item.remark.toLowerCase().includes(search)),
|
||||
);
|
||||
}
|
||||
|
||||
// 排序处理
|
||||
if (currentSort.value.prop) {
|
||||
const { prop, order } = currentSort.value;
|
||||
data.sort((a, b) => {
|
||||
// 处理可能为null的值
|
||||
const valA = a[prop as keyof RechargeLog] || '';
|
||||
const valB = b[prop as keyof RechargeLog] || '';
|
||||
|
||||
if (order === 'ascending') {
|
||||
return valA > valB ? 1 : valA < valB ? -1 : 0;
|
||||
}
|
||||
else {
|
||||
return valA < valB ? 1 : valA > valB ? -1 : 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 分页处理
|
||||
// if (showPagination.value) {
|
||||
// const start = (currentPage.value - 1) * pageSize.value;
|
||||
// return data.slice(start, start + pageSize.value);
|
||||
// }
|
||||
|
||||
return data;
|
||||
});
|
||||
|
||||
// 是否显示分页 暂时不需要分页功能
|
||||
const showPagination = computed(() => {
|
||||
// return logData.value.length > 10;
|
||||
return false;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
fetchRechargeLog();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="recharge-log-container">
|
||||
<div class="log-header">
|
||||
<h2 class="log-title">
|
||||
<el-icon><List /></el-icon>
|
||||
充值记录
|
||||
</h2>
|
||||
<div class="header-actions">
|
||||
<el-tooltip content="刷新数据" placement="top">
|
||||
<el-button circle :loading="loading" @click="refreshLog">
|
||||
<el-icon><Refresh /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
<el-input
|
||||
v-model="searchText"
|
||||
placeholder="搜索联系方式/备注"
|
||||
clearable
|
||||
style="width: 200px; margin-left: 10px;"
|
||||
@clear="handleSearchClear"
|
||||
@keyup.enter="handleSearch"
|
||||
>
|
||||
<template #append>
|
||||
<el-button @click="handleSearch">
|
||||
<el-icon><Search /></el-icon>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="filteredData"
|
||||
style="width: 100%"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
@sort-change="handleSortChange"
|
||||
>
|
||||
<el-table-column
|
||||
prop="content"
|
||||
label="套餐类型"
|
||||
width="120"
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="rechargeAmount"
|
||||
label="金额(元)"
|
||||
width="120"
|
||||
align="right"
|
||||
sortable="custom"
|
||||
>
|
||||
<template #default="{ row }">
|
||||
<span class="amount-cell">¥{{ row.rechargeAmount.toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="creationTime"
|
||||
label="充值时间"
|
||||
width="180"
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="expireDateTime"
|
||||
label="到期时间"
|
||||
width="180"
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column prop="contactInfo" width="100" label="联系方式">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip v-if="row.contactInfo && row.contactInfo.length > 8" :content="row.contactInfo" placement="top">
|
||||
<span class="ellipsis-text">{{ row.contactInfo }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ row.contactInfo || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注">
|
||||
<template #default="{ row }">
|
||||
<el-tooltip v-if="row.remark && row.remark.length > 10" :content="row.remark" placement="top">
|
||||
<span class="ellipsis-text">{{ row.remark }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ row.remark || '-' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<div class="log-footer">
|
||||
<div class="summary">
|
||||
共 <span class="highlight">{{ filteredData.length }}</span> 条记录
|
||||
</div>
|
||||
<el-pagination
|
||||
v-if="showPagination"
|
||||
v-model:current-page="currentPage"
|
||||
v-model:page-size="pageSize"
|
||||
:total="filteredData.length"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
background
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.recharge-log-container {
|
||||
padding: 20px;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.log-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.log-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.log-title .el-icon {
|
||||
margin-right: 8px;
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.amount-cell {
|
||||
font-family: 'Arial', sans-serif;
|
||||
font-weight: bold;
|
||||
color: #e74c3c;
|
||||
}
|
||||
|
||||
.ellipsis-text {
|
||||
display: inline-block;
|
||||
max-width: 120px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.log-footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20px;
|
||||
padding-top: 15px;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.summary {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
color: #409eff;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* 表格样式优化 */
|
||||
:deep(.el-table) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
:deep(.el-table th) {
|
||||
background-color: #f8fafc;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.el-table--striped .el-table__body tr.el-table__row--striped td) {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
:deep(.el-table .cell) {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
/* 分页样式优化 */
|
||||
:deep(.el-pagination) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.el-pagination.is-background .el-pager li:not(.is-disabled).is-active) {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
:deep(.el-pagination.is-background .el-pager li:not(.is-disabled):hover) {
|
||||
color: #409eff;
|
||||
}
|
||||
</style>
|
||||
@@ -65,6 +65,7 @@ const navItems = [
|
||||
// { name: 'role', label: '角色管理', icon: 'Avatar' },
|
||||
// { name: 'permission', label: '权限管理', icon: 'Key' },
|
||||
{ name: 'apiKey', label: 'API密钥', icon: 'Key' },
|
||||
{ name: 'rechargeLog', label: '充值记录', icon: 'Document' },
|
||||
];
|
||||
function openDialog() {
|
||||
dialogVisible.value = true;
|
||||
@@ -266,7 +267,7 @@ function openVipGuide() {
|
||||
|
||||
<!-- 角色管理内容 -->
|
||||
<template #role>
|
||||
<!-- <role-management /> -->
|
||||
<!-- < /> -->
|
||||
</template>
|
||||
|
||||
<!-- 权限管理内容 -->
|
||||
@@ -277,6 +278,9 @@ function openVipGuide() {
|
||||
<template #apiKey>
|
||||
<APIKeyManagement />
|
||||
</template>
|
||||
<template #rechargeLog>
|
||||
<recharge-log />
|
||||
</template>
|
||||
</nav-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
4
Yi.Ai.Vue3/types/components.d.ts
vendored
4
Yi.Ai.Vue3/types/components.d.ts
vendored
@@ -19,6 +19,8 @@ declare module 'vue' {
|
||||
ElCollapse: typeof import('element-plus/es')['ElCollapse']
|
||||
ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
|
||||
ElContainer: typeof import('element-plus/es')['ElContainer']
|
||||
ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
|
||||
ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
|
||||
ElDialog: typeof import('element-plus/es')['ElDialog']
|
||||
ElDivider: typeof import('element-plus/es')['ElDivider']
|
||||
ElEmpty: typeof import('element-plus/es')['ElEmpty']
|
||||
@@ -31,6 +33,7 @@ declare module 'vue' {
|
||||
ElMain: typeof import('element-plus/es')['ElMain']
|
||||
ElMenu: typeof import('element-plus/es')['ElMenu']
|
||||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElTable: typeof import('element-plus/es')['ElTable']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
ElTooltip: typeof import('element-plus/es')['ElTooltip']
|
||||
@@ -43,6 +46,7 @@ declare module 'vue' {
|
||||
NavDialog: typeof import('./../src/components/userPersonalCenter/NavDialog.vue')['default']
|
||||
Popover: typeof import('./../src/components/Popover/index.vue')['default']
|
||||
QrCodeLogin: typeof import('./../src/components/LoginDialog/components/QrCodeLogin/index.vue')['default']
|
||||
RechargeLog: typeof import('./../src/components/userPersonalCenter/components/RechargeLog.vue')['default']
|
||||
RegistrationForm: typeof import('./../src/components/LoginDialog/components/FormLogin/RegistrationForm.vue')['default']
|
||||
RouterLink: typeof import('vue-router')['RouterLink']
|
||||
RouterView: typeof import('vue-router')['RouterView']
|
||||
|
||||
Reference in New Issue
Block a user