feat: 添加短信验证码发送记录功能

This commit is contained in:
2025-12-23 23:47:39 +08:00
parent a125f15f58
commit 5709255e39
19 changed files with 668 additions and 14 deletions

View File

@@ -33,6 +33,11 @@ const navItems = ref([
icon: 'pi pi-shopping-cart',
command: () => router.push('/orders')
},
{
label: '短信认证',
icon: 'pi pi-comment',
command: () => router.push('/sms-code-sends')
},
{
label: '设置',
icon: 'pi pi-cog',

View File

@@ -0,0 +1,14 @@
import httpClient from './httpClient';
export const smsCodeSendService = {
get({ page = 1, limit = 10, phone = '' } = {}) {
return httpClient.get('/sms-code-sends', {
params: {
page,
limit,
phone: phone.trim()
}
});
}
};

View File

@@ -0,0 +1,115 @@
<script setup>
import { smsCodeSendService } from '@/api/smsCodeSendService';
import { formatDate } from '@/utils/date';
import Column from 'primevue/column';
import DataTable from 'primevue/datatable';
import InputText from 'primevue/inputtext';
import ProgressSpinner from 'primevue/progressspinner';
import Toast from 'primevue/toast';
import { useToast } from 'primevue/usetoast';
import { onMounted, ref } from 'vue';
const toast = useToast();
const phone = ref('');
const loading = ref(false);
const searchTimeout = ref(null);
const records = ref({
items: [],
total: 0,
page: 1,
limit: 10
});
const first = ref(0);
const rows = ref(10);
const fetchRecords = async () => {
loading.value = true;
try {
const currentPage = (first.value / rows.value) + 1;
const resp = await smsCodeSendService.get({
page: currentPage,
limit: rows.value,
phone: phone.value
});
records.value = resp.data;
} catch (error) {
console.error('Failed to fetch sms code sends:', error);
toast.add({ severity: 'error', summary: '错误', detail: '加载短信验证码记录失败', life: 3000 });
} finally {
loading.value = false;
}
};
const onPage = (event) => {
first.value = event.first;
rows.value = event.rows;
fetchRecords();
};
const onSearch = () => {
if (searchTimeout.value) {
clearTimeout(searchTimeout.value);
}
searchTimeout.value = setTimeout(() => {
first.value = 0;
fetchRecords();
}, 300);
};
onMounted(() => {
fetchRecords();
});
</script>
<template>
<Toast />
<div class="w-full">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-semibold text-gray-800">短信认证</h1>
</div>
<div class="card">
<div class="pb-10 flex gap-3 items-center">
<InputText v-model="phone" placeholder="按手机号筛选..." class="flex-1" @input="onSearch" />
</div>
<DataTable :value="records.items" :paginator="true" :rows="rows" :totalRecords="records.total"
:loading="loading" :lazy="true" :first="first" @page="onPage"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
:rowsPerPageOptions="[10, 25, 50]"
currentPageReportTemplate="显示第 {first} 到 {last} 条,共 {totalRecords} 条结果" dataKey="id" stripedRows
removableSort class="p-datatable-sm" responsiveLayout="scroll">
<template #empty>
<div class="text-center p-4">暂无短信验证码记录</div>
</template>
<template #loading>
<div class="flex flex-col items-center justify-center p-4">
<ProgressSpinner style="width:50px;height:50px" />
<span class="mt-2">加载短信验证码记录...</span>
</div>
</template>
<Column field="id" header="ID" sortable></Column>
<Column field="phone" header="手机号" sortable></Column>
<Column field="code" header="验证码" sortable></Column>
<Column field="sent_at" header="发送时间" sortable>
<template #body="{ data }">
{{ formatDate(data.sent_at) }}
</template>
</Column>
<Column field="expires_at" header="过期时间" sortable>
<template #body="{ data }">
{{ formatDate(data.expires_at) }}
</template>
</Column>
</DataTable>
</div>
</div>
</template>

View File

@@ -52,6 +52,11 @@ const routes = [
name: 'Orders',
component: () => import('./pages/OrderPage.vue'),
},
{
path: '/sms-code-sends',
name: 'SmsCodeSends',
component: () => import('./pages/SmsCodeSendPage.vue'),
},
{
path: '/login',
name: 'Login',