feat:【mall 商城】分销用户的 update 迁移(antd 50%)

This commit is contained in:
YunaiV
2025-10-09 22:18:57 +08:00
parent db38eb23da
commit 94d0550ecc
5 changed files with 164 additions and 305 deletions

View File

@@ -168,3 +168,15 @@ export function useCreateFormSchema(): VbenFormSchema[] {
},
];
}
/** 修改分销用户表单配置 */
export function useUpdateFormSchema(): VbenFormSchema[] {
return [
{
fieldName: 'bindUserId',
label: '上级推广员编号',
component: 'InputSearch',
rules: 'required',
},
];
}

View File

@@ -17,8 +17,8 @@ import {
import { useGridColumns, useGridFormSchema } from './data';
import CreateForm from './modules/create-form.vue';
import BrokerageOrderListModal from './modules/order-list-modal.vue';
import UpdateForm from './modules/update-form.vue';
import BrokerageUserListModal from './modules/user-list-modal.vue';
import BrokerageUserUpdateForm from './modules/user-update-form.vue';
defineOptions({ name: 'TradeBrokerageUser' });
@@ -27,8 +27,8 @@ const [CreateFormModal, createFormModalApi] = useVbenModal({
destroyOnClose: true,
});
const [UserUpdateModal, userUpdateModalApi] = useVbenModal({
connectedComponent: BrokerageUserUpdateForm,
const [UpdateFormModal, updateModalApi] = useVbenModal({
connectedComponent: UpdateForm,
destroyOnClose: true,
});
@@ -53,8 +53,8 @@ function handleCreate() {
}
/** 修改分销员 */
function handleOpenUpdateForm(row: MallBrokerageUserApi.BrokerageUser) {
userUpdateModalApi.setData(row).open();
function handleUpdateForm(row: MallBrokerageUserApi.BrokerageUser) {
updateModalApi.setData(row).open();
}
/** 打开推广人列表 */
@@ -156,7 +156,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
<!-- 创建分销员 -->
<CreateFormModal @success="handleRefresh" />
<!-- 修改分销员 -->
<UserUpdateModal @success="handleRefresh" />
<UpdateFormModal @success="handleRefresh" />
<!-- 推广人列表 -->
<UserListModal />
<!-- 推广订单列表 -->
@@ -194,7 +194,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
label: '修改上级推广人',
type: 'link',
auth: ['trade:brokerage-user:update-bind-user'],
onClick: handleOpenUpdateForm.bind(null, row),
onClick: handleUpdateForm.bind(null, row),
},
{
label: '清除上级推广人',

View File

@@ -0,0 +1,145 @@
<script lang="ts" setup>
import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { formatDate, isEmpty } from '@vben/utils';
import {
Avatar,
Descriptions,
DescriptionsItem,
Divider,
InputSearch,
message,
Tag,
} from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import {
getBrokerageUser,
updateBindUser,
} from '#/api/mall/trade/brokerage/user';
import { useUpdateFormSchema } from '../data';
defineOptions({ name: 'BrokerageUserUpdateForm' });
const emit = defineEmits(['success']);
const formData = ref<any>({
id: undefined,
bindUserId: undefined,
});
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
formItemClass: 'col-span-2',
labelWidth: 120,
},
layout: 'horizontal',
schema: useUpdateFormSchema(),
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
await formApi.setValues(formData.value);
const { valid } = await formApi.validate();
if (!valid) {
return;
}
modalApi.lock();
try {
await updateBindUser(formData.value);
// 关闭并提示
await modalApi.close();
emit('success');
message.success($t('ui.actionMessage.operationSuccess'));
} finally {
modalApi.unlock();
}
},
onOpenChange: async (isOpen: boolean) => {
if (!isOpen) {
return;
}
const data = modalApi.getData<MallBrokerageUserApi.BrokerageUser>();
if (!data || !data.id) {
return;
}
modalApi.lock();
try {
formData.value = {
id: data.id,
bindUserId: data.bindUserId,
};
await formApi.setValues(formData.value);
if (data.bindUserId) {
await handleSearchUser(data.bindUserId, '上级分销员');
}
} finally {
modalApi.unlock();
}
},
});
/** 绑定用户信息 */
const bindUser = ref<MallBrokerageUserApi.BrokerageUser | undefined>();
/** 查询分销员 */
async function handleSearchUser(id: number, userType: string) {
if (isEmpty(id)) {
message.warning(`请先输入${userType}编号后重试!!!`);
return;
}
if (formData.value?.bindUserId === formData.value?.id) {
message.error('不能绑定自己为推广人');
return;
}
const userData = await getBrokerageUser(id);
if (!userData) {
message.warning(`${userType}不存在`);
return;
}
bindUser.value = userData as MallBrokerageUserApi.BrokerageUser;
}
</script>
<template>
<Modal title="修改上级推广人" class="w-1/3">
<Form>
<template #bindUserId>
<InputSearch
v-model:value="formData.bindUserId"
placeholder="请输入上级分销员编号"
@search="handleSearchUser(formData.bindUserId, '上级分销员')"
/>
</template>
</Form>
<!-- 上级推广员信息展示 -->
<Divider v-if="bindUser" />
<Descriptions v-if="bindUser" title="上级推广员信息" :column="1" bordered>
<DescriptionsItem label="头像">
<Avatar :src="bindUser?.avatar" />
</DescriptionsItem>
<DescriptionsItem label="昵称">
{{ bindUser?.nickname }}
</DescriptionsItem>
<DescriptionsItem label="分销资格">
<Tag v-if="bindUser?.brokerageEnabled" color="success"> </Tag>
<Tag v-else></Tag>
</DescriptionsItem>
<DescriptionsItem label="成为分销员的时间">
{{ formatDate(bindUser?.brokerageTime) }}
</DescriptionsItem>
</Descriptions>
</Modal>
</template>

View File

@@ -1,167 +0,0 @@
<script lang="ts" setup>
import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user';
import { reactive, ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { formatDate, isEmpty } from '@vben/utils';
import {
Avatar,
Descriptions,
DescriptionsItem,
InputSearch,
message,
Tag,
} from 'ant-design-vue';
import {
createBrokerageUser,
getBrokerageUser,
} from '#/api/mall/trade/brokerage/user';
import { getUser } from '#/api/member/user';
defineOptions({ name: 'BrokerageUserCreateForm' });
const emit = defineEmits(['success']);
const formData = ref<any>({
userId: undefined,
bindUserId: undefined,
});
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
if (!formData.value) {
return;
}
modalApi.lock();
// 提交表单
try {
await createBrokerageUser(formData.value);
// 关闭并提示
await modalApi.close();
emit('success');
message.success($t('ui.actionMessage.operationSuccess'));
} finally {
modalApi.unlock();
}
},
onOpenChange: async (isOpen: boolean) => {
if (!isOpen) {
return;
}
formData.value = {
userId: undefined,
bindUserId: undefined,
};
},
});
/** 用户信息 */
const userInfo = reactive<{
bindUser: MallBrokerageUserApi.BrokerageUser | undefined;
user: MallBrokerageUserApi.BrokerageUser | undefined;
}>({
bindUser: undefined,
user: undefined,
});
/** 查询推广员和分销员 */
async function handleGetUser(id: any, userType: string) {
if (isEmpty(id)) {
message.warning(`请先输入${userType}编号后重试!!!`);
return;
}
if (
userType === '推广员' &&
formData.value?.bindUserId === formData.value?.userId
) {
message.error('不能绑定自己为推广人');
return;
}
try {
const user =
userType === '推广员' ? await getBrokerageUser(id) : await getUser(id);
if (userType === '推广员') {
userInfo.bindUser = user as MallBrokerageUserApi.BrokerageUser;
} else {
userInfo.user = user as MallBrokerageUserApi.BrokerageUser;
}
if (!user) {
message.warning(`${userType}不存在`);
}
} catch {
message.warning(`${userType}不存在`);
}
}
</script>
<template>
<Modal title="创建分销员" class="w-2/5">
<!-- TODO @宽度不够label 会折行 -->
<div class="mr-2 flex items-center">
分销员编号
<InputSearch
v-model:value="formData.userId"
placeholder="请输入推广员编号"
enter-button
class="mx-2 w-52"
@search="handleGetUser(formData?.userId, '分销员')"
/>
上级推广人编号
<InputSearch
v-model:value="formData.bindUserId"
placeholder="请输入推广员编号"
enter-button
class="mx-2 w-52"
@search="handleGetUser(formData?.bindUserId, '推广员')"
/>
</div>
<div class="mt-4">
<!-- 展示分销员的信息 -->
<Descriptions
title="分销员信息"
class="mt-4"
v-if="userInfo.user"
:column="1"
bordered
>
<DescriptionsItem label="头像">
<Avatar :src="userInfo.user?.avatar" />
</DescriptionsItem>
<DescriptionsItem label="昵称">
{{ userInfo.user?.nickname }}
</DescriptionsItem>
</Descriptions>
<!-- 展示上级推广人的信息 -->
<Descriptions
title="上级推广人信息"
class="mt-4"
v-if="userInfo.bindUser"
:column="1"
bordered
>
<DescriptionsItem label="头像">
<Avatar :src="userInfo.bindUser?.avatar" />
</DescriptionsItem>
<DescriptionsItem label="昵称">
{{ userInfo.bindUser?.nickname }}
</DescriptionsItem>
<DescriptionsItem label="推广资格">
<Tag v-if="userInfo.bindUser?.brokerageEnabled" color="success">
</Tag>
<Tag v-else></Tag>
</DescriptionsItem>
<DescriptionsItem label="成为推广员的时间">
{{ formatDate(userInfo.bindUser?.brokerageTime) }}
</DescriptionsItem>
</Descriptions>
</div>
</Modal>
</template>

View File

@@ -1,131 +0,0 @@
<script lang="ts" setup>
import type { MallBrokerageUserApi } from '#/api/mall/trade/brokerage/user';
import { ref } from 'vue';
import { useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { formatDate } from '@vben/utils';
import {
Avatar,
Descriptions,
DescriptionsItem,
InputSearch,
message,
Tag,
} from 'ant-design-vue';
import {
getBrokerageUser,
updateBindUser,
} from '#/api/mall/trade/brokerage/user';
/** 修改分销用户 */
defineOptions({ name: 'BrokerageUserUpdateForm' });
const emit = defineEmits(['success']);
const formData = ref<any>();
const [Modal, modalApi] = useVbenModal({
async onConfirm() {
if (!formData.value) {
return;
}
// 未查找到合适的上级
if (!bindUser.value) {
message.error('请先查询并确认推广人');
return;
}
modalApi.lock();
try {
await updateBindUser(formData.value);
// 关闭并提示
await modalApi.close();
emit('success');
message.success($t('ui.actionMessage.operationSuccess'));
} finally {
modalApi.unlock();
}
},
onOpenChange: async (isOpen: boolean) => {
if (!isOpen) {
formData.value = {
id: 0,
bindUserId: 0,
};
return;
}
const data = modalApi.getData<MallBrokerageUserApi.BrokerageUser>();
if (!data || !data.id) {
return;
}
modalApi.lock();
try {
formData.value = {
id: data.id,
bindUserId: data.bindUserId,
};
if (data.bindUserId) {
await handleGetUser();
}
} finally {
modalApi.unlock();
}
},
});
const bindUser = ref<MallBrokerageUserApi.BrokerageUser>();
/** 查询推广员 */
async function handleGetUser() {
if (!formData.value) {
return;
}
if (formData.value.bindUserId === formData.value.id) {
message.error('不能绑定自己为推广人');
return;
}
try {
bindUser.value = await getBrokerageUser(formData.value.bindUserId);
if (!bindUser.value) {
message.warning('推广员不存在');
}
} catch {
message.warning('推广员不存在');
}
}
</script>
<template>
<Modal title="修改上级推广人" class="w-2/5">
<div class="mr-2 flex items-center">
推广员编号
<InputSearch
v-model:value="formData.bindUserId"
placeholder="请输入推广员编号"
enter-button
class="mx-2 w-52"
@search="handleGetUser"
/>
</div>
<!-- 展示上级推广人的信息 -->
<Descriptions class="mt-4" v-if="bindUser" :column="1" bordered>
<DescriptionsItem label="头像">
<Avatar :src="bindUser.avatar" />
</DescriptionsItem>
<DescriptionsItem label="昵称">
{{ bindUser.nickname }}
</DescriptionsItem>
<DescriptionsItem label="推广资格">
<Tag v-if="bindUser.brokerageEnabled" color="success"></Tag>
<Tag v-else></Tag>
</DescriptionsItem>
<DescriptionsItem label="成为推广员的时间">
{{ formatDate(bindUser.brokerageTime) }}
</DescriptionsItem>
</Descriptions>
</Modal>
</template>