feat: 添加推广管理功能,包含推广配置页面及相关表单
This commit is contained in:
@@ -235,7 +235,8 @@ const local: App.I18n.Schema = {
|
|||||||
withdraw: 'Withdraw',
|
withdraw: 'Withdraw',
|
||||||
wallet: 'Wallet',
|
wallet: 'Wallet',
|
||||||
kyc: 'KYC',
|
kyc: 'KYC',
|
||||||
check: 'CheckIn'
|
check: 'CheckIn',
|
||||||
|
referral: 'Referral'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
|||||||
@@ -231,7 +231,8 @@ const local: App.I18n.Schema = {
|
|||||||
withdraw: '提现管理',
|
withdraw: '提现管理',
|
||||||
wallet: '钱包管理',
|
wallet: '钱包管理',
|
||||||
kyc: '实名管理',
|
kyc: '实名管理',
|
||||||
check: '签到管理'
|
check: '签到管理',
|
||||||
|
referral: '推广管理'
|
||||||
},
|
},
|
||||||
page: {
|
page: {
|
||||||
login: {
|
login: {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export const views: Record<LastLevelRouteKey, RouteComponent | (() => Promise<Ro
|
|||||||
kyc: () => import("@/views/kyc/index.vue"),
|
kyc: () => import("@/views/kyc/index.vue"),
|
||||||
news: () => import("@/views/news/index.vue"),
|
news: () => import("@/views/news/index.vue"),
|
||||||
product: () => import("@/views/product/index.vue"),
|
product: () => import("@/views/product/index.vue"),
|
||||||
|
referral: () => import("@/views/referral/index.vue"),
|
||||||
user: () => import("@/views/user/index.vue"),
|
user: () => import("@/views/user/index.vue"),
|
||||||
wallet: () => import("@/views/wallet/index.vue"),
|
wallet: () => import("@/views/wallet/index.vue"),
|
||||||
withdraw: () => import("@/views/withdraw/index.vue"),
|
withdraw: () => import("@/views/withdraw/index.vue"),
|
||||||
|
|||||||
@@ -109,6 +109,15 @@ export const generatedRoutes: GeneratedRoute[] = [
|
|||||||
i18nKey: 'route.product'
|
i18nKey: 'route.product'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'referral',
|
||||||
|
path: '/referral',
|
||||||
|
component: 'layout.base$view.referral',
|
||||||
|
meta: {
|
||||||
|
title: 'referral',
|
||||||
|
i18nKey: 'route.referral'
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'user',
|
name: 'user',
|
||||||
path: '/user',
|
path: '/user',
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ const routeMap: RouteMap = {
|
|||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?",
|
||||||
"news": "/news",
|
"news": "/news",
|
||||||
"product": "/product",
|
"product": "/product",
|
||||||
|
"referral": "/referral",
|
||||||
"user": "/user",
|
"user": "/user",
|
||||||
"wallet": "/wallet",
|
"wallet": "/wallet",
|
||||||
"withdraw": "/withdraw"
|
"withdraw": "/withdraw"
|
||||||
|
|||||||
3
src/typings/elegant-router.d.ts
vendored
3
src/typings/elegant-router.d.ts
vendored
@@ -27,6 +27,7 @@ declare module "@elegant-router/types" {
|
|||||||
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
"login": "/login/:module(pwd-login|code-login|register|reset-pwd|bind-wechat)?";
|
||||||
"news": "/news";
|
"news": "/news";
|
||||||
"product": "/product";
|
"product": "/product";
|
||||||
|
"referral": "/referral";
|
||||||
"user": "/user";
|
"user": "/user";
|
||||||
"wallet": "/wallet";
|
"wallet": "/wallet";
|
||||||
"withdraw": "/withdraw";
|
"withdraw": "/withdraw";
|
||||||
@@ -71,6 +72,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "login"
|
| "login"
|
||||||
| "news"
|
| "news"
|
||||||
| "product"
|
| "product"
|
||||||
|
| "referral"
|
||||||
| "user"
|
| "user"
|
||||||
| "wallet"
|
| "wallet"
|
||||||
| "withdraw"
|
| "withdraw"
|
||||||
@@ -100,6 +102,7 @@ declare module "@elegant-router/types" {
|
|||||||
| "kyc"
|
| "kyc"
|
||||||
| "news"
|
| "news"
|
||||||
| "product"
|
| "product"
|
||||||
|
| "referral"
|
||||||
| "user"
|
| "user"
|
||||||
| "wallet"
|
| "wallet"
|
||||||
| "withdraw"
|
| "withdraw"
|
||||||
|
|||||||
95
src/views/referral/components/edit.vue
Normal file
95
src/views/referral/components/edit.vue
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import type { FormInst, FormRules } from 'naive-ui';
|
||||||
|
import { client, safeClient } from '@/service/api';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ReferralEdit'
|
||||||
|
});
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
data: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: 'close'): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
interface ReferralForm {
|
||||||
|
depth: number;
|
||||||
|
commissionRate: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const formRef = ref<FormInst | null>(null);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const formModel = ref<ReferralForm>({
|
||||||
|
depth: 1,
|
||||||
|
commissionRate: 0
|
||||||
|
});
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
depth: [{ required: true, type: 'number', message: '请输入团队层级', trigger: 'blur' }],
|
||||||
|
commissionRate: [{ required: true, type: 'number', message: '请输入佣金比例', trigger: 'blur' }]
|
||||||
|
};
|
||||||
|
|
||||||
|
async function handleSubmit() {
|
||||||
|
await formRef.value?.validate();
|
||||||
|
loading.value = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await safeClient(() =>
|
||||||
|
client.api.admin.referrals['depth-configs']({ id: props.data.id }).patch({
|
||||||
|
depth: formModel.value.depth,
|
||||||
|
commissionRate: String(formModel.value.commissionRate / 100)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
if (result.data) {
|
||||||
|
window.$message?.success('更新成功');
|
||||||
|
emit('close');
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
formModel.value = {
|
||||||
|
depth: props.data.depth || 1,
|
||||||
|
commissionRate: (Number(props.data.commissionRate) || 0) * 100
|
||||||
|
};
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<NForm ref="formRef" :model="formModel" :rules="rules" label-placement="left" :label-width="100">
|
||||||
|
<NFormItem label="团队层级" path="depth">
|
||||||
|
<NInputNumber v-model:value="formModel.depth" placeholder="请输入团队层级" class="w-full" :min="1" disabled />
|
||||||
|
</NFormItem>
|
||||||
|
|
||||||
|
<NFormItem label="佣金比例" path="commissionRate">
|
||||||
|
<NInputNumber
|
||||||
|
v-model:value="formModel.commissionRate"
|
||||||
|
placeholder="请输入佣金比例"
|
||||||
|
class="w-full"
|
||||||
|
:min="0"
|
||||||
|
:max="100"
|
||||||
|
:step="0.01"
|
||||||
|
>
|
||||||
|
<template #suffix>%</template>
|
||||||
|
</NInputNumber>
|
||||||
|
</NFormItem>
|
||||||
|
</NForm>
|
||||||
|
|
||||||
|
<div class="mt-16px flex justify-end gap-12px">
|
||||||
|
<NButton @click="emit('close')">取消</NButton>
|
||||||
|
<NButton type="primary" :loading="loading" @click="handleSubmit">确定</NButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
85
src/views/referral/index.vue
Normal file
85
src/views/referral/index.vue
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { h, useTemplateRef } from 'vue';
|
||||||
|
import { useDialog } from 'naive-ui';
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
import { client, safeClient } from '@/service/api';
|
||||||
|
import type { TableBaseColumns, TableFetchData, TableInst } from '@/components/table';
|
||||||
|
import Edit from './components/edit.vue';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'ReferralPage'
|
||||||
|
});
|
||||||
|
|
||||||
|
const dialog = useDialog();
|
||||||
|
|
||||||
|
const tableInst = useTemplateRef<TableInst>('tableInst');
|
||||||
|
|
||||||
|
const fetchData: TableFetchData = ({ pagination, filter }) => {
|
||||||
|
return safeClient(() => client.api.admin.referrals['depth-configs'].get({ query: { ...pagination, ...filter } }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: TableBaseColumns = [
|
||||||
|
{
|
||||||
|
key: 'depth',
|
||||||
|
title: '团队层级'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'commissionRate',
|
||||||
|
title: '佣金比例(%)',
|
||||||
|
render: (row: any) => {
|
||||||
|
// 1 => 100%
|
||||||
|
return `${Number(row.commissionRate) * 100} %`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'createdAt',
|
||||||
|
title: '创建时间',
|
||||||
|
render: (row: any) => {
|
||||||
|
return dayjs(row.createdAt).format('YYYY-MM-DD HH:mm');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'operations',
|
||||||
|
title: '操作',
|
||||||
|
width: 150,
|
||||||
|
fixed: 'right',
|
||||||
|
operations: (row: any) => [
|
||||||
|
{
|
||||||
|
contentText: '编辑',
|
||||||
|
size: 'small',
|
||||||
|
onClick: () => {
|
||||||
|
handleEdit(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleEdit(row: any) {
|
||||||
|
const d = dialog.create({
|
||||||
|
title: '编辑推广配置',
|
||||||
|
showIcon: false,
|
||||||
|
style: { width: '600px' },
|
||||||
|
content: () =>
|
||||||
|
h(Edit, {
|
||||||
|
data: row,
|
||||||
|
onClose: () => {
|
||||||
|
d.destroy();
|
||||||
|
tableInst.value?.reload();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TableBase
|
||||||
|
ref="tableInst"
|
||||||
|
:fetch-data="fetchData"
|
||||||
|
:columns="columns"
|
||||||
|
:scroll-x="800"
|
||||||
|
:show-header-operation="false"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="css" scoped></style>
|
||||||
Reference in New Issue
Block a user