feat: member detail
							parent
							
								
									2583d14455
								
							
						
					
					
						commit
						8ad0bbc427
					
				|  | @ -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> | ||||||
|  | @ -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> | ||||||
|  | @ -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> | ||||||
|  | @ -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> | ||||||
		Loading…
	
		Reference in New Issue
	
	 xingyu4j
						xingyu4j