feat: member detail

pull/119/head
xingyu4j 2025-05-29 00:40:19 +08:00
parent 2583d14455
commit 8ad0bbc427
4 changed files with 331 additions and 0 deletions

View File

@ -0,0 +1,82 @@
<script setup lang="ts">
import type { MemberUserApi } from '#/api/member/user';
import type { PayWalletApi } from '#/api/pay/wallet/balance';
import { Card } from 'ant-design-vue';
import { useDescription } from '#/components/description';
import { fenToYuan } from '#/utils';
withDefaults(
defineProps<{
mode?: 'kefu' | 'member';
user: MemberUserApi.User;
wallet: PayWalletApi.WalletVO;
}>(),
{
mode: 'member',
},
);
const [Description] = useDescription({
componentProps: {
bordered: false,
class: 'mx-4',
},
schema: [
{
field: 'levelName',
label: '等级',
content: (data) => data.levelName || '无',
},
{
field: 'experience',
label: '成长值',
content: (data) => data.experience || 0,
},
{
field: 'point',
label: '当前积分',
content: (data) => data.point || 0,
},
{
field: 'totalPoint',
label: '总积分',
content: (data) => data.totalPoint || 0,
},
{
field: 'balance',
label: '当前余额',
content: (data) => fenToYuan(data.balance || 0),
},
{
field: 'totalExpense',
label: '支出金额',
content: (data) => fenToYuan(data.totalExpense || 0),
},
{
field: 'totalRecharge',
label: '充值金额',
content: (data) => fenToYuan(data.totalRecharge || 0),
},
],
});
</script>
<template>
<Card>
<template #title>
<slot name="title"></slot>
</template>
<template #extra>
<slot name="extra"></slot>
</template>
<Description
:column="mode === 'member' ? 2 : 1"
:data="{
...user,
...wallet,
}"
/>
</Card>
</template>

View File

@ -0,0 +1,96 @@
<script setup lang="ts">
import type { MemberUserApi } from '#/api/member/user';
import { h } from 'vue';
import { formatDate } from '@vben/utils';
import { Avatar, Card, Col, Row } from 'ant-design-vue';
import { useDescription } from '#/components/description';
import { DictTag } from '#/components/dict-tag';
import { DICT_TYPE } from '#/utils';
withDefaults(
defineProps<{ mode?: 'kefu' | 'member'; user: MemberUserApi.User }>(),
{
mode: 'member',
},
);
const [Description] = useDescription({
componentProps: {
bordered: false,
class: 'mx-4',
},
schema: [
{
field: 'name',
label: '用户名',
},
{
field: 'nickname',
label: '昵称',
},
{
field: 'mobile',
label: '手机号',
},
{
field: 'sex',
label: '性别',
content: (data) =>
h(DictTag, {
type: DICT_TYPE.SYSTEM_USER_SEX,
value: data.sex,
}),
},
{
field: 'areaName',
label: '所在地',
},
{
field: 'registerIp',
label: '注册 IP',
},
{
field: 'birthday',
label: '生日',
content: (data) => formatDate(data.birthday)?.toString() || '空',
},
{
field: 'createTime',
label: '注册时间',
content: (data) => formatDate(data.createTime)?.toString() || '空',
},
{
field: 'loginDate',
label: '最后登录时间',
content: (data) => formatDate(data.loginDate)?.toString() || '空',
},
],
});
</script>
<template>
<Card>
<template #title>
<slot name="title"></slot>
</template>
<template #extra>
<slot name="extra"></slot>
</template>
<Row v-if="mode === 'member'" :gutter="24">
<Col :span="4">
<Avatar :size="140" shape="square" :src="user.avatar" />
</Col>
<Col :span="20">
<Description :column="2" :data="user" />
</Col>
</Row>
<template v-else-if="mode === 'kefu'">
<Avatar :size="140" shape="square" :src="user.avatar" />
<Description :column="1" :data="user" />
</template>
</Card>
</template>

View File

@ -0,0 +1,81 @@
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MemberPointRecordApi } from '#/api/member/point/record';
import { Tag } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getRecordPage } from '#/api/member/point/record';
import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils';
import { useGridColumns } from '#/views/member/point/record/data';
const props = defineProps<{
userId: number;
}>();
const [Grid] = useVbenVxeGrid({
formOptions: {
schema: [
{
fieldName: 'bizType',
label: '业务类型',
component: 'Select',
componentProps: {
allowClear: true,
options: getDictOptions(DICT_TYPE.MEMBER_POINT_BIZ_TYPE, 'number'),
},
},
{
fieldName: 'title',
label: '积分标题',
component: 'Input',
},
{
fieldName: 'createDate',
label: '获得时间',
component: 'RangePicker',
componentProps: {
...getRangePickerDefaultProps(),
allowClear: true,
},
},
],
},
gridOptions: {
columns: useGridColumns(),
keepSource: true,
pagerConfig: {
pageSize: 10,
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getRecordPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
userId: props.userId,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
toolbarConfig: {
refresh: { code: 'query' },
search: true,
},
} as VxeTableGridOptions<MemberPointRecordApi.Record>,
});
</script>
<template>
<Grid>
<template #point="{ row }">
<Tag :color="row.point > 0 ? '#108ee9' : '#f50'">
{{ row.point > 0 ? `+${row.point}` : row.point }}
</Tag>
</template>
</Grid>
</template>

View File

@ -0,0 +1,72 @@
<script lang="ts" setup>
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { MemberSignInRecordApi } from '#/api/member/signin/record';
import { Tag } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getSignInRecordPage } from '#/api/member/signin/record';
import { getRangePickerDefaultProps } from '#/utils';
import { useGridColumns } from '#/views/member/signin/record/data';
const props = defineProps<{
userId: number;
}>();
const [Grid] = useVbenVxeGrid({
formOptions: {
schema: [
{
fieldName: 'day',
label: '签到天数',
component: 'Input',
},
{
fieldName: 'createTime',
label: '签到时间',
component: 'RangePicker',
componentProps: {
...getRangePickerDefaultProps(),
allowClear: true,
},
},
],
},
gridOptions: {
columns: useGridColumns(),
keepSource: true,
pagerConfig: {
pageSize: 10,
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
return await getSignInRecordPage({
pageNo: page.currentPage,
pageSize: page.pageSize,
userId: props.userId,
...formValues,
});
},
},
},
rowConfig: {
keyField: 'id',
},
toolbarConfig: {
refresh: { code: 'query' },
search: true,
},
} as VxeTableGridOptions<MemberSignInRecordApi.SignInRecord>,
});
</script>
<template>
<Grid>
<template #point="{ row }">
<Tag :color="row.point > 0 ? '#108ee9' : '#f50'">
{{ row.point > 0 ? `+${row.point}` : row.point }}
</Tag>
</template>
</Grid>
</template>