feat: 添加签到页面,整合用户选择和日期选择功能,支持数据过滤

This commit is contained in:
2026-01-20 02:35:54 +07:00
parent 5f128ba4bb
commit 4a5b8c3ab8
11 changed files with 126 additions and 6 deletions

View File

@@ -40,7 +40,7 @@ export type TableFilterColumn = {
key: string;
title: string;
component?: Component | VNode;
componentProps?: Record<string, any>;
componentProps?: Record<string, any> | ((form: Record<string, any>) => Record<string, any>);
};
export type TableFilterColumns = Array<TableFilterColumn>;

View File

@@ -31,6 +31,7 @@ const props = withDefaults(
{
title: '',
showHeaderOperation: true,
filterColumnsCount: 4,
filterColumns: () => [],
headerOperations: () => ({
add: true,

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { NInput } from 'naive-ui';
import type { TableFilterColumns } from '.';
import type { TableFilterColumn, TableFilterColumns } from '.';
const props = defineProps<{
columns?: TableFilterColumns;
@@ -15,8 +15,22 @@ const inlineForm: Record<string, any> = {};
const form = ref<Record<string, any>>({});
function transformProps(col: TableFilterColumn) {
if (typeof col.componentProps === 'object') {
return col.componentProps;
} else if (typeof col.componentProps === 'function') {
return col.componentProps(form.value);
}
}
onMounted(() => {
props.columns?.forEach(col => {
if (col.key.includes(',')) {
col.key.split(',').forEach(k => {
inlineForm[k] = null;
form.value[k] = null;
});
return;
}
inlineForm[col.key] = null;
form.value[col.key] = null;
});
@@ -41,7 +55,7 @@ function handleConfirm() {
<component
:is="col.component || NInput"
:value="form[col.key]"
v-bind="col.componentProps"
v-bind="transformProps(col)"
@update:value="(val: any) => (form[col.key] = val)"
/>
</NFormItem>

View File

@@ -234,7 +234,8 @@ const local: App.I18n.Schema = {
news: 'News',
withdraw: 'Withdraw',
wallet: 'Wallet',
kyc: 'KYC'
kyc: 'KYC',
check: 'CheckIn'
},
page: {
login: {

View File

@@ -230,7 +230,8 @@ const local: App.I18n.Schema = {
news: '新闻管理',
withdraw: '提现管理',
wallet: '钱包管理',
kyc: '实名管理'
kyc: '实名管理',
check: '签到管理'
},
page: {
login: {

View File

@@ -20,6 +20,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
500: () => import("@/views/_builtin/500/index.vue"),
"iframe-page": () => import("@/views/_builtin/iframe-page/[url].vue"),
login: () => import("@/views/_builtin/login/index.vue"),
check: () => import("@/views/check/index.vue"),
home: () => import("@/views/home/index.vue"),
kyc: () => import("@/views/kyc/index.vue"),
news: () => import("@/views/news/index.vue"),

View File

@@ -39,6 +39,15 @@ export const generatedRoutes: GeneratedRoute[] = [
hideInMenu: true
}
},
{
name: 'check',
path: '/check',
component: 'layout.base$view.check',
meta: {
title: 'check',
i18nKey: 'route.check'
}
},
{
name: 'home',
path: '/home',

View File

@@ -166,6 +166,7 @@ const routeMap: RouteMap = {
"403": "/403",
"404": "/404",
"500": "/500",
"check": "/check",
"home": "/home",
"iframe-page": "/iframe-page/:url",
"kyc": "/kyc",

View File

@@ -20,6 +20,7 @@ declare module "@elegant-router/types" {
"403": "/403";
"404": "/404";
"500": "/500";
"check": "/check";
"home": "/home";
"iframe-page": "/iframe-page/:url";
"kyc": "/kyc";
@@ -63,6 +64,7 @@ declare module "@elegant-router/types" {
| "403"
| "404"
| "500"
| "check"
| "home"
| "iframe-page"
| "kyc"
@@ -93,6 +95,7 @@ declare module "@elegant-router/types" {
| "500"
| "iframe-page"
| "login"
| "check"
| "home"
| "kyc"
| "news"

87
src/views/check/index.vue Normal file
View File

@@ -0,0 +1,87 @@
<script lang="ts" setup>
import { useTemplateRef } from 'vue';
import { NDatePicker } from 'naive-ui';
import dayjs from 'dayjs';
import { client, safeClient } from '@/service/api';
import type { TableBaseColumns, TableFetchData, TableFilterColumns, TableInst } from '@/components/table';
import UserSelect from '@/components/common/user-select.vue';
defineOptions({
name: 'CheckInPage'
});
const props = defineProps<{
userId: string;
}>();
const tableInst = useTemplateRef<TableInst>('tableInst');
const fetchData: TableFetchData = ({ pagination, filter }) => {
return safeClient(() => client.api.admin.checkIns.get({ query: { userId: props.userId, ...pagination, ...filter } }));
};
const columns: TableBaseColumns = [
{
key: 'userId',
title: '用户ID'
},
{
key: 'checkInAt',
title: '签到时间',
render: (row: any) => {
return dayjs(row.checkInAt).format('YYYY-MM-DD HH:mm:ss');
}
}
];
const filterColumns: TableFilterColumns = [
{
key: 'userId',
title: '用户',
component: UserSelect
},
{
key: 'startDate',
title: '开始日期',
component: NDatePicker,
componentProps: form => ({
clearable: true,
valueFormat: 'yyyy-MM-dd',
formattedValue: form.startDate,
onUpdateFormattedValue: val => {
form.startDate = val;
}
})
},
{
key: 'endDate',
title: '结束日期',
component: NDatePicker,
componentProps: form => ({
clearable: true,
valueFormat: 'yyyy-MM-dd',
formattedValue: form.endDate,
onUpdateFormattedValue: val => {
form.endDate = val;
}
})
}
];
</script>
<template>
<TableBase
ref="tableInst"
:fetch-data="fetchData"
:columns="columns"
:filter-columns="filterColumns"
:scroll-x="800"
:header-operations="{
add: false,
refresh: true,
columns: true
}"
/>
</template>
<style lang="css" scoped></style>

View File

@@ -13,7 +13,9 @@ const props = defineProps<{
const tableInst = useTemplateRef<TableInst>('tableInst');
const fetchData: TableFetchData = ({ pagination, filter }) => {
return safeClient(() => client.api.admin.wallet.wallets.get({ query: { userId: props.userId } }));
return safeClient(() =>
client.api.admin.wallet.wallets.get({ query: { userId: props.userId, ...pagination, ...filter } })
);
};
const columns: TableBaseColumns = [