From 59cf72ab9c6778008613878bd35c2cbba90a3166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=83=E8=B4=A7?= <252048765@qq.com> Date: Sat, 5 Jul 2025 07:50:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E4=BC=9A=E5=91=98?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E6=A8=A1=E5=9D=97=EF=BC=8C=E5=8C=85=E6=8B=AC?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E3=80=81=E7=AD=89=E7=BA=A7=E3=80=81=E6=A0=87?= =?UTF-8?q?=E7=AD=BE=E3=80=81=E7=AD=BE=E5=88=B0=E9=85=8D=E7=BD=AE=E7=AD=89?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/table-action/table-action.vue | 2 +- .../src/router/routes/modules/member.ts | 16 + apps/web-ele/src/router/routes/modules/pay.ts | 16 + .../web-ele/src/views/member/config/index.vue | 114 +++++ apps/web-ele/src/views/member/group/data.ts | 88 ++++ apps/web-ele/src/views/member/group/index.vue | 126 +++++ .../src/views/member/group/modules/form.vue | 82 ++++ apps/web-ele/src/views/member/level/data.ts | 152 ++++++ apps/web-ele/src/views/member/level/index.vue | 126 +++++ .../src/views/member/level/modules/form.vue | 82 ++++ .../src/views/member/point/record/data.ts | 101 ++++ .../src/views/member/point/record/index.vue | 46 ++ .../src/views/member/signin/config/data.ts | 101 ++++ .../src/views/member/signin/config/index.vue | 124 +++++ .../member/signin/config/modules/form.vue | 89 ++++ .../src/views/member/signin/record/data.ts | 73 +++ .../src/views/member/signin/record/index.vue | 46 ++ apps/web-ele/src/views/member/tag/data.ts | 68 +++ apps/web-ele/src/views/member/tag/index.vue | 131 +++++ .../src/views/member/tag/modules/form.vue | 88 ++++ .../user/components/user-account-info.vue | 87 ++++ .../user/components/user-address-list.vue | 87 ++++ .../user/components/user-balance-list.vue | 68 +++ .../user/components/user-basic-info.vue | 100 ++++ .../user-experience-record-list.vue | 131 +++++ .../user/components/user-point-list.vue | 74 +++ .../member/user/components/user-sign-list.vue | 65 +++ apps/web-ele/src/views/member/user/data.ts | 449 ++++++++++++++++++ apps/web-ele/src/views/member/user/index.vue | 200 ++++++++ .../member/user/modules/balance-form.vue | 93 ++++ .../src/views/member/user/modules/detail.vue | 136 ++++++ .../src/views/member/user/modules/form.vue | 77 +++ .../views/member/user/modules/leavel-form.vue | 77 +++ .../views/member/user/modules/point-form.vue | 77 +++ apps/web-ele/vite.config.mts | 2 +- 35 files changed, 3392 insertions(+), 2 deletions(-) create mode 100644 apps/web-ele/src/router/routes/modules/member.ts create mode 100644 apps/web-ele/src/router/routes/modules/pay.ts create mode 100644 apps/web-ele/src/views/member/config/index.vue create mode 100644 apps/web-ele/src/views/member/group/data.ts create mode 100644 apps/web-ele/src/views/member/group/index.vue create mode 100644 apps/web-ele/src/views/member/group/modules/form.vue create mode 100644 apps/web-ele/src/views/member/level/data.ts create mode 100644 apps/web-ele/src/views/member/level/index.vue create mode 100644 apps/web-ele/src/views/member/level/modules/form.vue create mode 100644 apps/web-ele/src/views/member/point/record/data.ts create mode 100644 apps/web-ele/src/views/member/point/record/index.vue create mode 100644 apps/web-ele/src/views/member/signin/config/data.ts create mode 100644 apps/web-ele/src/views/member/signin/config/index.vue create mode 100644 apps/web-ele/src/views/member/signin/config/modules/form.vue create mode 100644 apps/web-ele/src/views/member/signin/record/data.ts create mode 100644 apps/web-ele/src/views/member/signin/record/index.vue create mode 100644 apps/web-ele/src/views/member/tag/data.ts create mode 100644 apps/web-ele/src/views/member/tag/index.vue create mode 100644 apps/web-ele/src/views/member/tag/modules/form.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-account-info.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-address-list.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-balance-list.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-basic-info.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-experience-record-list.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-point-list.vue create mode 100644 apps/web-ele/src/views/member/user/components/user-sign-list.vue create mode 100644 apps/web-ele/src/views/member/user/data.ts create mode 100644 apps/web-ele/src/views/member/user/index.vue create mode 100644 apps/web-ele/src/views/member/user/modules/balance-form.vue create mode 100644 apps/web-ele/src/views/member/user/modules/detail.vue create mode 100644 apps/web-ele/src/views/member/user/modules/form.vue create mode 100644 apps/web-ele/src/views/member/user/modules/leavel-form.vue create mode 100644 apps/web-ele/src/views/member/user/modules/point-form.vue diff --git a/apps/web-ele/src/components/table-action/table-action.vue b/apps/web-ele/src/components/table-action/table-action.vue index 895a66d44..7e127ef5e 100644 --- a/apps/web-ele/src/components/table-action/table-action.vue +++ b/apps/web-ele/src/components/table-action/table-action.vue @@ -210,7 +210,7 @@ function handleMenuClick(command: any) { - + {{ $t('page.action.more') }} diff --git a/apps/web-ele/src/router/routes/modules/member.ts b/apps/web-ele/src/router/routes/modules/member.ts new file mode 100644 index 000000000..4f4e81723 --- /dev/null +++ b/apps/web-ele/src/router/routes/modules/member.ts @@ -0,0 +1,16 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/member/user/detail', + component: () => import('#/views/member/user/modules/detail.vue'), + name: 'MemberUserDetail', + meta: { + title: '会员详情', + icon: 'lucide:user', + hideInMenu: true, + }, + }, +]; + +export default routes; diff --git a/apps/web-ele/src/router/routes/modules/pay.ts b/apps/web-ele/src/router/routes/modules/pay.ts new file mode 100644 index 000000000..f7711fcdf --- /dev/null +++ b/apps/web-ele/src/router/routes/modules/pay.ts @@ -0,0 +1,16 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routes: RouteRecordRaw[] = [ + { + path: '/pay/cashier', + component: () => import('#/views/pay/cashier/index.vue'), + name: 'PayCashier', + meta: { + title: '收银台', + icon: 'lucide:badge-japanese-yen', + hideInMenu: true, + }, + }, +]; + +export default routes; diff --git a/apps/web-ele/src/views/member/config/index.vue b/apps/web-ele/src/views/member/config/index.vue new file mode 100644 index 000000000..cd102234f --- /dev/null +++ b/apps/web-ele/src/views/member/config/index.vue @@ -0,0 +1,114 @@ + + + diff --git a/apps/web-ele/src/views/member/group/data.ts b/apps/web-ele/src/views/member/group/data.ts new file mode 100644 index 000000000..e7466bd3e --- /dev/null +++ b/apps/web-ele/src/views/member/group/data.ts @@ -0,0 +1,88 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '#/adapter/form'; +import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '分组名称', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '分组名称', + component: 'Input', + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'name', + title: '分组名称', + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/group/index.vue b/apps/web-ele/src/views/member/group/index.vue new file mode 100644 index 000000000..590faa9e4 --- /dev/null +++ b/apps/web-ele/src/views/member/group/index.vue @@ -0,0 +1,126 @@ + + + diff --git a/apps/web-ele/src/views/member/group/modules/form.vue b/apps/web-ele/src/views/member/group/modules/form.vue new file mode 100644 index 000000000..b25a6cbc9 --- /dev/null +++ b/apps/web-ele/src/views/member/group/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/member/level/data.ts b/apps/web-ele/src/views/member/level/data.ts new file mode 100644 index 000000000..d60a180dc --- /dev/null +++ b/apps/web-ele/src/views/member/level/data.ts @@ -0,0 +1,152 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '#/adapter/form'; +import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '等级名称', + }, + { + component: 'InputNumber', + fieldName: 'level', + label: '等级', + componentProps: { + min: 0, + precision: 0, + }, + }, + { + fieldName: 'experience', + label: '升级经验', + component: 'InputNumber', + componentProps: { + min: 0, + precision: 0, + }, + }, + { + fieldName: 'discountPercent', + label: '享受折扣(%)', + component: 'InputNumber', + componentProps: { + min: 0, + max: 100, + precision: 0, + }, + }, + { + component: 'ImageUpload', + fieldName: 'icon', + label: '等级图标', + }, + { + component: 'ImageUpload', + fieldName: 'backgroundUrl', + label: '等级背景图', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '等级名称', + component: 'Input', + }, + { + fieldName: 'status', + label: '状态', + component: 'Select', + componentProps: { + allowClear: true, + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'icon', + title: '等级图标', + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'backgroundUrl', + title: '等级背景图', + cellRender: { + name: 'CellImage', + }, + }, + { + field: 'name', + title: '等级名称', + }, + { + field: 'level', + title: '等级', + }, + { + field: 'experience', + title: '升级经验', + }, + { + field: 'discountPercent', + title: '享受折扣(%)', + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/level/index.vue b/apps/web-ele/src/views/member/level/index.vue new file mode 100644 index 000000000..b45701cd5 --- /dev/null +++ b/apps/web-ele/src/views/member/level/index.vue @@ -0,0 +1,126 @@ + + + diff --git a/apps/web-ele/src/views/member/level/modules/form.vue b/apps/web-ele/src/views/member/level/modules/form.vue new file mode 100644 index 000000000..95a693b3c --- /dev/null +++ b/apps/web-ele/src/views/member/level/modules/form.vue @@ -0,0 +1,82 @@ + + + diff --git a/apps/web-ele/src/views/member/point/record/data.ts b/apps/web-ele/src/views/member/point/record/data.ts new file mode 100644 index 000000000..df373c375 --- /dev/null +++ b/apps/web-ele/src/views/member/point/record/data.ts @@ -0,0 +1,101 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { ElTag } from 'element-plus'; + +import { DICT_TYPE, getDictOptions, getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '用户', + component: 'Input', + }, + { + 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, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'createTime', + title: '获得时间', + formatter: 'formatDateTime', + }, + { + field: 'nickname', + title: '用户', + }, + { + field: 'point', + title: '获得积分', + slots: { + default: ({ row }) => { + return h( + ElTag, + { + class: 'mr-1', + color: row.point > 0 ? 'blue' : 'red', + }, + () => (row.point > 0 ? `+${row.point}` : row.point), + ); + }, + }, + }, + { + field: 'totalPoint', + title: '总积分', + }, + { + field: 'title', + title: '标题', + }, + { + field: 'description', + title: '描述', + }, + { + field: 'bizId', + title: '业务编码', + }, + { + field: 'bizType', + title: '业务类型', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.MEMBER_POINT_BIZ_TYPE }, + }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/point/record/index.vue b/apps/web-ele/src/views/member/point/record/index.vue new file mode 100644 index 000000000..2a29563a2 --- /dev/null +++ b/apps/web-ele/src/views/member/point/record/index.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/config/data.ts b/apps/web-ele/src/views/member/signin/config/data.ts new file mode 100644 index 000000000..be1d8e272 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/data.ts @@ -0,0 +1,101 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { z } from '#/adapter/form'; +import { CommonStatusEnum, DICT_TYPE, getDictOptions } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'InputNumber', + fieldName: 'day', + label: '签到天数', + help: '只允许设置 1-7,默认签到 7 天为一个周期', + componentProps: { + min: 1, + max: 7, + precision: 0, + }, + }, + { + component: 'InputNumber', + fieldName: 'point', + label: '获得积分', + componentProps: { + min: 0, + precision: 0, + }, + }, + { + component: 'InputNumber', + fieldName: 'experience', + label: '奖励经验', + componentProps: { + min: 0, + precision: 0, + }, + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE), + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'day', + title: '签到天数', + formatter: ({ cellValue }) => ['第', cellValue, '天'].join(' '), + }, + { + field: 'point', + title: '获得积分', + }, + { + field: 'experience', + title: '奖励经验', + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 130, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/signin/config/index.vue b/apps/web-ele/src/views/member/signin/config/index.vue new file mode 100644 index 000000000..a3b946c5c --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/index.vue @@ -0,0 +1,124 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/config/modules/form.vue b/apps/web-ele/src/views/member/signin/config/modules/form.vue new file mode 100644 index 000000000..f24c6bd12 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/config/modules/form.vue @@ -0,0 +1,89 @@ + + + diff --git a/apps/web-ele/src/views/member/signin/record/data.ts b/apps/web-ele/src/views/member/signin/record/data.ts new file mode 100644 index 000000000..b361a55a5 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/record/data.ts @@ -0,0 +1,73 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { ElTag } from 'element-plus'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '签到用户', + component: 'Input', + }, + { + fieldName: 'day', + label: '签到天数', + component: 'Input', + }, + { + fieldName: 'createTime', + label: '签到时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + allowClear: true, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'nickname', + title: '签到用户', + }, + { + field: 'day', + title: '签到天数', + formatter: ({ cellValue }) => ['第', cellValue, '天'].join(' '), + }, + { + field: 'point', + title: '获得积分', + slots: { + default: ({ row }) => { + return h( + ElTag, + { + class: 'mr-5px', + color: row.point > 0 ? 'blue' : 'red', + }, + () => (row.point > 0 ? `+${row.point}` : row.point), + ); + }, + }, + }, + { + field: 'createTime', + title: '签到时间', + formatter: 'formatDateTime', + }, + ]; +} diff --git a/apps/web-ele/src/views/member/signin/record/index.vue b/apps/web-ele/src/views/member/signin/record/index.vue new file mode 100644 index 000000000..f129dc098 --- /dev/null +++ b/apps/web-ele/src/views/member/signin/record/index.vue @@ -0,0 +1,46 @@ + + + diff --git a/apps/web-ele/src/views/member/tag/data.ts b/apps/web-ele/src/views/member/tag/data.ts new file mode 100644 index 000000000..c0da8541e --- /dev/null +++ b/apps/web-ele/src/views/member/tag/data.ts @@ -0,0 +1,68 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { getRangePickerDefaultProps } from '#/utils'; + +/** 新增/修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'name', + label: '标签名称', + rules: 'required', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'name', + label: '标签名称', + component: 'Input', + }, + { + fieldName: 'createTime', + label: '创建时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + field: 'id', + title: '编号', + }, + { + field: 'name', + title: '标签名称', + }, + { + field: 'createTime', + title: '创建时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 150, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} diff --git a/apps/web-ele/src/views/member/tag/index.vue b/apps/web-ele/src/views/member/tag/index.vue new file mode 100644 index 000000000..ac336af8c --- /dev/null +++ b/apps/web-ele/src/views/member/tag/index.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-ele/src/views/member/tag/modules/form.vue b/apps/web-ele/src/views/member/tag/modules/form.vue new file mode 100644 index 000000000..0517412d2 --- /dev/null +++ b/apps/web-ele/src/views/member/tag/modules/form.vue @@ -0,0 +1,88 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-account-info.vue b/apps/web-ele/src/views/member/user/components/user-account-info.vue new file mode 100644 index 000000000..16a282989 --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-account-info.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-address-list.vue b/apps/web-ele/src/views/member/user/components/user-address-list.vue new file mode 100644 index 000000000..760cf2bc6 --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-address-list.vue @@ -0,0 +1,87 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-balance-list.vue b/apps/web-ele/src/views/member/user/components/user-balance-list.vue new file mode 100644 index 000000000..295e7bfbd --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-balance-list.vue @@ -0,0 +1,68 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-basic-info.vue b/apps/web-ele/src/views/member/user/components/user-basic-info.vue new file mode 100644 index 000000000..5bf91d7d6 --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-basic-info.vue @@ -0,0 +1,100 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-experience-record-list.vue b/apps/web-ele/src/views/member/user/components/user-experience-record-list.vue new file mode 100644 index 000000000..e9d3fa0cf --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-experience-record-list.vue @@ -0,0 +1,131 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-point-list.vue b/apps/web-ele/src/views/member/user/components/user-point-list.vue new file mode 100644 index 000000000..cc7dddd75 --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-point-list.vue @@ -0,0 +1,74 @@ + + + diff --git a/apps/web-ele/src/views/member/user/components/user-sign-list.vue b/apps/web-ele/src/views/member/user/components/user-sign-list.vue new file mode 100644 index 000000000..77ef261e7 --- /dev/null +++ b/apps/web-ele/src/views/member/user/components/user-sign-list.vue @@ -0,0 +1,65 @@ + + + diff --git a/apps/web-ele/src/views/member/user/data.ts b/apps/web-ele/src/views/member/user/data.ts new file mode 100644 index 000000000..12c5353aa --- /dev/null +++ b/apps/web-ele/src/views/member/user/data.ts @@ -0,0 +1,449 @@ +import type { VbenFormSchema } from '#/adapter/form'; +import type { VxeTableGridOptions } from '#/adapter/vxe-table'; + +import { h } from 'vue'; + +import { convertToInteger, formatToFraction } from '@vben/utils'; + +import { ElTag } from 'element-plus'; + +import { z } from '#/adapter/form'; +import { getSimpleGroupList } from '#/api/member/group'; +import { getSimpleLevelList } from '#/api/member/level'; +import { getSimpleTagList } from '#/api/member/tag'; +import { getAreaTree } from '#/api/system/area'; +import { + CommonStatusEnum, + DICT_TYPE, + getDictOptions, + getRangePickerDefaultProps, +} from '#/utils'; + +/** 修改的表单 */ +export function useFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + dependencies: { + triggerFields: [''], + show: () => false, + }, + }, + { + component: 'Input', + fieldName: 'mobile', + label: '手机号', + rules: 'required', + }, + { + fieldName: 'status', + label: '状态', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.COMMON_STATUS, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + rules: z.number().default(CommonStatusEnum.ENABLE).optional(), + }, + { + component: 'Input', + fieldName: 'nickname', + label: '用户昵称', + }, + { + component: 'ImageUpload', + fieldName: 'avatar', + label: '头像', + }, + { + component: 'Input', + fieldName: 'name', + label: '真实名字', + }, + { + fieldName: 'sex', + label: '用户性别', + component: 'RadioGroup', + componentProps: { + options: getDictOptions(DICT_TYPE.SYSTEM_USER_SEX, 'number'), + buttonStyle: 'solid', + optionType: 'button', + }, + }, + { + component: 'DatePicker', + fieldName: 'birthday', + label: '出生日期', + componentProps: { + format: 'YYYY-MM-DD', + }, + }, + { + component: 'ApiTreeSelect', + fieldName: 'areaId', + label: '所在地', + componentProps: { + api: () => getAreaTree(), + fieldNames: { label: 'name', value: 'id', children: 'children' }, + }, + }, + { + component: 'ApiSelect', + fieldName: 'tagIds', + label: '用户标签', + componentProps: { + api: () => getSimpleTagList(), + fieldNames: { label: 'name', value: 'id' }, + mode: 'multiple', + }, + }, + { + component: 'ApiSelect', + fieldName: 'groupId', + label: '用户分组', + componentProps: { + api: () => getSimpleGroupList(), + fieldNames: { label: 'name', value: 'id' }, + }, + }, + { + component: 'Textarea', + fieldName: 'mark', + label: '会员备注', + }, + ]; +} + +/** 列表的搜索表单 */ +export function useGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'nickname', + label: '用户昵称', + component: 'Input', + }, + { + fieldName: 'mobile', + label: '手机号', + component: 'Input', + }, + { + fieldName: 'loginDate', + label: '登录时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + }, + { + fieldName: 'createTime', + label: '注册时间', + component: 'RangePicker', + componentProps: { + ...getRangePickerDefaultProps(), + }, + }, + { + fieldName: 'tagIds', + label: '用户标签', + component: 'ApiSelect', + componentProps: { + api: () => getSimpleTagList(), + fieldNames: { label: 'name', value: 'id' }, + mode: 'multiple', + }, + }, + { + fieldName: 'levelId', + label: '用户等级', + component: 'ApiSelect', + componentProps: { + api: () => getSimpleLevelList(), + fieldNames: { label: 'name', value: 'id' }, + }, + }, + { + fieldName: 'groupId', + label: '用户分组', + component: 'ApiSelect', + componentProps: { + api: () => getSimpleGroupList(), + fieldNames: { label: 'name', value: 'id' }, + }, + }, + ]; +} + +/** 列表的字段 */ +export function useGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + }, + { + field: 'id', + title: '用户编号', + }, + { + field: 'avatar', + title: '头像', + slots: { + default: ({ row }) => { + return h('img', { + src: row.avatar, + style: { width: '40px' }, + }); + }, + }, + }, + { + field: 'mobile', + title: '手机号', + }, + { + field: 'nickname', + title: '昵称', + }, + { + field: 'levelName', + title: '等级', + }, + { + field: 'groupName', + title: '分组', + }, + { + field: 'tagNames', + title: '用户标签', + slots: { + default: ({ row }) => { + return row.tagNames?.map((tagName: string, index: number) => { + return h( + ElTag, + { + key: index, + class: 'mr-1', + color: 'blue', + }, + () => tagName, + ); + }); + }, + }, + }, + { + field: 'point', + title: '积分', + }, + { + field: 'status', + title: '状态', + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.COMMON_STATUS }, + }, + }, + { + field: 'loginDate', + title: '登录时间', + formatter: 'formatDateTime', + }, + { + field: 'createTime', + title: '注册时间', + formatter: 'formatDateTime', + }, + { + title: '操作', + width: 200, + fixed: 'right', + slots: { default: 'actions' }, + }, + ]; +} + +/** 修改用户等级 */ +export function useLeavelFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + label: '用户编号', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'nickname', + label: '用户昵称', + componentProps: { + disabled: true, + }, + }, + { + fieldName: 'point', + label: '用户等级', + component: 'ApiSelect', + componentProps: { + api: () => getSimpleLevelList(), + fieldNames: { label: 'name', value: 'id' }, + }, + }, + { + component: 'Textarea', + fieldName: 'reason', + label: '修改原因', + rules: 'required', + }, + ]; +} + +/** 修改用户余额 */ +export function useBalanceFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + label: '用户编号', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'nickname', + label: '用户昵称', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'balance', + label: '变动前余额(元)', + componentProps: { + disabled: true, + }, + }, + { + component: 'RadioGroup', + fieldName: 'changeType', + label: '变动类型', + componentProps: { + options: [ + { label: '增加', value: 1 }, + { label: '减少', value: -1 }, + ], + buttonStyle: 'solid', + optionType: 'button', + }, + defaultValue: 1, + }, + { + component: 'InputNumber', + fieldName: 'changeBalance', + label: '变动余额(元)', + rules: 'required', + componentProps: { + min: 0, + precision: 2, + step: 0.1, + }, + defaultValue: 0, + }, + { + component: 'Input', + fieldName: 'balanceResult', + label: '变动后余额(元)', + dependencies: { + triggerFields: ['changeBalance', 'changeType'], + disabled: true, + trigger(values, form) { + form.setFieldValue( + 'balanceResult', + formatToFraction( + convertToInteger(values.balance) + + convertToInteger(values.changeBalance) * values.changeType, + ), + ); + }, + }, + }, + ]; +} + +/** 修改用户积分 */ +export function usePointFormSchema(): VbenFormSchema[] { + return [ + { + component: 'Input', + fieldName: 'id', + label: '用户编号', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'nickname', + label: '用户昵称', + componentProps: { + disabled: true, + }, + }, + { + component: 'Input', + fieldName: 'point', + label: '变动前积分', + componentProps: { + disabled: true, + }, + }, + { + component: 'RadioGroup', + fieldName: 'changeType', + label: '变动类型', + componentProps: { + options: [ + { label: '增加', value: 1 }, + { label: '减少', value: -1 }, + ], + buttonStyle: 'solid', + optionType: 'button', + }, + defaultValue: 1, + }, + { + component: 'InputNumber', + fieldName: 'changePoint', + label: '变动积分', + rules: 'required', + componentProps: { + min: 0, + precision: 0, + }, + defaultValue: 0, + }, + { + component: 'Input', + fieldName: 'pointResult', + label: '变动后积分', + dependencies: { + triggerFields: ['changePoint', 'changeType'], + disabled: true, + trigger(values, form) { + form.setFieldValue( + 'pointResult', + values.point + values.changePoint * values.changeType || + values.point, + ); + }, + }, + rules: z.number().min(0), + }, + ]; +} diff --git a/apps/web-ele/src/views/member/user/index.vue b/apps/web-ele/src/views/member/user/index.vue new file mode 100644 index 000000000..9f34a64ad --- /dev/null +++ b/apps/web-ele/src/views/member/user/index.vue @@ -0,0 +1,200 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/balance-form.vue b/apps/web-ele/src/views/member/user/modules/balance-form.vue new file mode 100644 index 000000000..e9b13e503 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/balance-form.vue @@ -0,0 +1,93 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/detail.vue b/apps/web-ele/src/views/member/user/modules/detail.vue new file mode 100644 index 000000000..083d5f7a4 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/detail.vue @@ -0,0 +1,136 @@ + + diff --git a/apps/web-ele/src/views/member/user/modules/form.vue b/apps/web-ele/src/views/member/user/modules/form.vue new file mode 100644 index 000000000..cb15a59c3 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/form.vue @@ -0,0 +1,77 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/leavel-form.vue b/apps/web-ele/src/views/member/user/modules/leavel-form.vue new file mode 100644 index 000000000..faf56f7c0 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/leavel-form.vue @@ -0,0 +1,77 @@ + + + diff --git a/apps/web-ele/src/views/member/user/modules/point-form.vue b/apps/web-ele/src/views/member/user/modules/point-form.vue new file mode 100644 index 000000000..48fe0d3d2 --- /dev/null +++ b/apps/web-ele/src/views/member/user/modules/point-form.vue @@ -0,0 +1,77 @@ + + + diff --git a/apps/web-ele/vite.config.mts b/apps/web-ele/vite.config.mts index 8a36bcb78..1cfbccf76 100644 --- a/apps/web-ele/vite.config.mts +++ b/apps/web-ele/vite.config.mts @@ -17,7 +17,7 @@ export default defineConfig(async () => { changeOrigin: true, rewrite: (path) => path.replace(/^\/admin-api/, ''), // mock代理目标地址 - target: 'http://localhost:48080/admin-api', + target: 'http://localhost:48081/admin-api', ws: true, }, },