f
Some checks failed
CI / Test (ubuntu-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Lint (ubuntu-latest) (push) Has been cancelled
CI / Lint (windows-latest) (push) Has been cancelled
CI / Check (ubuntu-latest) (push) Has been cancelled
CI / Check (windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Website on push / Deploy Push Playground Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Docs Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Antd Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Element Ftp (push) Has been cancelled
Deploy Website on push / Deploy Push Naive Ftp (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
CI / CI OK (push) Has been cancelled
Deploy Website on push / Rerun on failure (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Issue Close Require / close-issues (push) Has been cancelled
Close stale issues / stale (push) Has been cancelled

This commit is contained in:
2025-11-27 19:08:41 +08:00
commit 0668eea99b
1450 changed files with 125078 additions and 0 deletions

View File

@@ -0,0 +1,254 @@
import type { VbenFormSchema } from '#/adapter/form';
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
// 会员等级选项
export const levelNameOptions = [
{ label: '普通会员', value: 'normal' },
{ label: 'VIP会员', value: 'VIP' },
{ label: 'SVIP会员', value: 'SVIP' },
];
// 代理会员配置列表列配置
export function useColumns(): VxeTableGridOptions['columns'] {
return [
{ field: 'id', title: 'ID', width: 80 },
{
field: 'level_name',
title: '会员等级',
formatter: ({ cellValue }) => {
const option = levelNameOptions.find(
(item) => item.value === cellValue,
);
return option?.label || cellValue;
},
},
{
field: 'price',
title: '会员年费',
formatter: ({ cellValue }) =>
cellValue !== null && cellValue !== undefined
? `¥${cellValue.toFixed(2)}`
: '-',
},
{
field: 'report_commission',
title: '直推报告收益',
formatter: ({ cellValue }) =>
cellValue !== null && cellValue !== undefined
? `¥${cellValue.toFixed(2)}`
: '-',
},
{
field: 'lower_activity_reward',
title: '下级活跃奖励',
formatter: ({ cellValue }) =>
cellValue !== null && cellValue !== undefined
? `¥${cellValue.toFixed(2)}`
: '-',
},
{
field: 'new_activity_reward',
title: '新增活跃奖励',
formatter: ({ cellValue }) =>
cellValue !== null && cellValue !== undefined
? `¥${cellValue.toFixed(2)}`
: '-',
},
{
field: 'lower_standard_count',
title: '活跃下级达标数',
formatter: ({ cellValue }) => cellValue ?? '-',
},
{
field: 'new_lower_standard_count',
title: '新增活跃下级达标数',
formatter: ({ cellValue }) => cellValue ?? '-',
},
{
field: 'lower_withdraw_reward_ratio',
title: '下级提现奖励比例',
formatter: ({ cellValue }) =>
cellValue !== null && cellValue !== undefined
? `${(cellValue * 100).toFixed(2)}%`
: '-',
},
{
field: 'create_time',
title: '创建时间',
width: 180,
},
{
align: 'center',
slots: { default: 'operation' },
field: 'operation',
fixed: 'right',
title: '操作',
width: 120,
},
] as const;
}
// 代理会员配置搜索表单配置
export function useGridFormSchema(): VbenFormSchema[] {
return [
{
component: 'Select',
fieldName: 'level_name',
label: '会员等级',
componentProps: {
placeholder: '请选择会员等级',
options: levelNameOptions,
},
},
];
}
// 代理会员配置编辑表单配置
export function useFormSchema(): VbenFormSchema[] {
return [
{
component: 'Select',
fieldName: 'level_name',
label: '会员等级',
rules: 'required',
componentProps: {
options: levelNameOptions,
},
},
{
component: 'InputNumber',
fieldName: 'price',
label: '会员年费',
rules: 'required',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'report_commission',
label: '直推报告收益',
rules: 'required',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'lower_activity_reward',
label: '下级活跃奖励',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'new_activity_reward',
label: '新增活跃奖励',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'lower_standard_count',
label: '活跃下级达标数',
componentProps: {
min: 0,
precision: 0,
},
},
{
component: 'InputNumber',
fieldName: 'new_lower_standard_count',
label: '新增活跃下级达标数',
componentProps: {
min: 0,
precision: 0,
},
},
{
component: 'InputNumber',
fieldName: 'lower_withdraw_reward_ratio',
label: '下级提现奖励比例',
componentProps: {
min: 0,
max: 100,
precision: 2,
step: 0.01,
addonAfter: '%',
},
},
{
component: 'InputNumber',
fieldName: 'lower_convert_vip_reward',
label: '下级转化VIP奖励',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'lower_convert_svip_reward',
label: '下级转化SVIP奖励',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'exemption_amount',
label: '免责金额',
rules: 'required',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'price_increase_max',
label: '提价最高金额',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
{
component: 'InputNumber',
fieldName: 'price_ratio',
label: '提价区间收取比例',
componentProps: {
min: 0,
max: 100,
precision: 2,
step: 0.01,
addonAfter: '%',
},
},
{
component: 'InputNumber',
fieldName: 'price_increase_amount',
label: '加价金额',
componentProps: {
min: 0,
precision: 2,
step: 0.01,
},
},
];
}

View File

@@ -0,0 +1,105 @@
<script lang="ts" setup>
import type {
OnActionClickParams,
VxeGridListeners,
VxeTableGridOptions,
} from '#/adapter/vxe-table';
import type { AgentApi } from '#/api/agent';
import { Page, useVbenDrawer } from '@vben/common-ui';
import { Button, Space } from 'ant-design-vue';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { getAgentMembershipConfigList } from '#/api/agent';
import { useColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
// 表单抽屉
const [FormDrawer, formDrawerApi] = useVbenDrawer({
connectedComponent: Form,
destroyOnClose: true,
});
// 表格配置
const [Grid, gridApi] = useVbenVxeGrid({
formOptions: {
schema: useGridFormSchema(),
submitOnChange: true,
},
gridEvents: {
sortChange: () => {
gridApi.query();
},
} as VxeGridListeners<AgentApi.AgentMembershipConfigListItem>,
gridOptions: {
columns: useColumns(),
height: 'auto',
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
const res = await getAgentMembershipConfigList({
page: page.currentPage,
pageSize: page.pageSize,
level_name: formValues.level_name,
});
return res;
},
},
props: {
result: 'items',
total: 'total',
},
},
rowConfig: {
keyField: 'id',
},
toolbarConfig: {
custom: true,
export: false,
refresh: { code: 'query' },
search: true,
zoom: true,
},
} as VxeTableGridOptions<AgentApi.AgentMembershipConfigListItem>,
});
// 操作处理函数
function onActionClick(
e: OnActionClickParams<AgentApi.AgentMembershipConfigListItem>,
) {
switch (e.code) {
case 'edit': {
onEdit(e.row);
break;
}
}
}
// 编辑处理
function onEdit(row: AgentApi.AgentMembershipConfigListItem) {
formDrawerApi.setData(row).open();
}
// 刷新处理
function onRefresh() {
gridApi.query();
}
</script>
<template>
<Page auto-content-height>
<FormDrawer @success="onRefresh" />
<Grid table-title="代理会员配置列表">
<template #operation="{ row }">
<Space>
<Button type="link" @click="onActionClick({ code: 'edit', row })">
配置
</Button>
</Space>
</template>
</Grid>
</Page>
</template>

View File

@@ -0,0 +1,88 @@
<script lang="ts" setup>
import type { AgentApi } from '#/api/agent';
import { ref } from 'vue';
import { useVbenDrawer, useVbenForm } from '@vben/common-ui';
import { updateAgentMembershipConfig } from '#/api/agent';
import { useFormSchema } from '../data';
const emit = defineEmits(['success']);
const formData = ref<AgentApi.AgentMembershipConfigListItem>();
const id = ref<number>();
const [Form, formApi] = useVbenForm({
schema: useFormSchema(),
showDefaultActions: false,
});
const drawerTitle = ref('会员配置');
const [Drawer, drawerApi] = useVbenDrawer({
title: drawerTitle.value,
destroyOnClose: true,
async onConfirm() {
const valid = await formApi.validate();
if (!valid || !id.value) return;
const values = await formApi.getValues();
const params: AgentApi.UpdateAgentMembershipConfigParams = {
id: id.value,
level_name: values.level_name,
price: values.price,
report_commission: values.report_commission,
lower_activity_reward: values.lower_activity_reward ?? null,
new_activity_reward: values.new_activity_reward ?? null,
lower_standard_count: values.lower_standard_count ?? null,
new_lower_standard_count: values.new_lower_standard_count ?? null,
lower_withdraw_reward_ratio:
values.lower_withdraw_reward_ratio !== null &&
values.lower_withdraw_reward_ratio !== undefined
? values.lower_withdraw_reward_ratio / 100
: null,
lower_convert_vip_reward: values.lower_convert_vip_reward ?? null,
lower_convert_svip_reward: values.lower_convert_svip_reward ?? null,
exemption_amount: values.exemption_amount ?? null,
price_increase_max: values.price_increase_max ?? null,
price_ratio:
values.price_ratio !== null && values.price_ratio !== undefined
? values.price_ratio / 100
: null,
price_increase_amount: values.price_increase_amount ?? null,
};
await updateAgentMembershipConfig(params);
emit('success');
drawerApi.close();
},
onOpenChange(isOpen) {
if (isOpen) {
const data = drawerApi.getData<AgentApi.AgentMembershipConfigListItem>();
formApi.resetForm();
if (data) {
formData.value = data;
id.value = data.id;
formApi.setValues({
...data,
lower_withdraw_reward_ratio: data.lower_withdraw_reward_ratio
? data.lower_withdraw_reward_ratio * 100
: null,
price_ratio: data.price_ratio ? data.price_ratio * 100 : null,
});
} else {
id.value = undefined;
}
}
},
});
</script>
<template>
<Drawer :title="drawerTitle">
<Form />
</Drawer>
</template>