chore(config): 添加项目配置文件和隐私协议

- 添加 .editorconfig 文件统一代码风格
- 添加 .env.development 和 .env.example 环境配置文件
- 添加 .eslintignore 和 .eslintrc.js 代码检查配置
- 添加 .gitignore 版本控制忽略文件配置
- 添加 .prettierignore 格式化忽略配置
- 添加隐私协议HTML文件
- 添加API密钥管理组件基础结构
This commit is contained in:
2026-01-26 14:05:01 +08:00
commit 482e2a2718
1192 changed files with 238401 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
<!-- 搜索表单 -->
<template>
<a-space :size="10" style="flex-wrap: wrap">
<a-button type="primary" class="ele-btn-icon" @click="add">
<template #icon>
<PlusOutlined />
</template>
<span>添加</span>
</a-button>
</a-space>
</template>
<script lang="ts" setup>
import { PlusOutlined } from '@ant-design/icons-vue';
import type { GradeParam } from '@/api/user/grade/model';
import { watch } from 'vue';
const props = withDefaults(
defineProps<{
// 选中的角色
selection?: [];
}>(),
{}
);
const emit = defineEmits<{
(e: 'search', where?: GradeParam): void;
(e: 'add'): void;
(e: 'remove'): void;
(e: 'batchMove'): void;
}>();
// 新增
const add = () => {
emit('add');
};
watch(
() => props.selection,
() => {}
);
</script>

View File

@@ -0,0 +1,744 @@
<!-- 编辑弹窗 -->
<template>
<ele-modal
:width="1000"
:visible="visible"
:maskClosable="false"
:maxable="maxable"
:title="isUpdate ? '编辑分销商设置' : '新增分销商设置'"
:body-style="{ paddingBottom: '28px' }"
@update:visible="updateVisible"
@ok="save"
>
<a-form
ref="formRef"
:model="form"
:rules="rules"
:label-col="{ span: 4 }"
:wrapper-col="{ span: 20 }"
>
<!-- 基本信息 -->
<a-divider orientation="left">
<span style="color: #1890ff; font-weight: 600;">基本信息</span>
</a-divider>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="设置标识" name="key">
<a-select
v-model:value="form.key"
placeholder="请选择设置标识"
@change="onSettingKeyChange"
>
<a-select-option value="commission_rate">
<div class="setting-option">
<a-tag color="blue">佣金比例</a-tag>
<span>分销佣金比例设置</span>
</div>
</a-select-option>
<a-select-option value="withdraw_config">
<div class="setting-option">
<a-tag color="green">提现配置</a-tag>
<span>提现相关参数设置</span>
</div>
</a-select-option>
<a-select-option value="level_config">
<div class="setting-option">
<a-tag color="orange">等级配置</a-tag>
<span>分销商等级设置</span>
</div>
</a-select-option>
<a-select-option value="reward_config">
<div class="setting-option">
<a-tag color="purple">奖励配置</a-tag>
<span>推广奖励设置</span>
</div>
</a-select-option>
<a-select-option value="other">
<div class="setting-option">
<a-tag color="default">其他设置</a-tag>
<span>自定义设置项</span>
</div>
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="设置描述" name="describe">
<a-input
placeholder="请输入设置项描述"
v-model:value="form.describe"
/>
</a-form-item>
</a-col>
</a-row>
<!-- 设置内容 -->
<a-divider orientation="left">
<span style="color: #1890ff; font-weight: 600;">设置内容</span>
</a-divider>
<!-- 预设配置模板 -->
<div v-if="form.key && form.key !== 'other'" class="config-template">
<a-alert
:message="getTemplateTitle()"
:description="getTemplateDescription()"
type="info"
show-icon
style="margin-bottom: 16px"
/>
<!-- 佣金比例配置 -->
<div v-if="form.key === 'commission_rate'" class="commission-config">
<a-row :gutter="16">
<a-col :span="8">
<a-form-item label="一级佣金比例">
<a-input-number
v-model:value="configData.firstRate"
:min="0"
:max="100"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter>%</template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="二级佣金比例">
<a-input-number
v-model:value="configData.secondRate"
:min="0"
:max="100"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter>%</template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="三级佣金比例">
<a-input-number
v-model:value="configData.thirdRate"
:min="0"
:max="100"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter>%</template>
</a-input-number>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 提现配置 -->
<div v-if="form.key === 'withdraw_config'" class="withdraw-config">
<a-row :gutter="16">
<a-col :span="8">
<a-form-item label="最小提现金额">
<a-input-number
v-model:value="configData.minAmount"
:min="0"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter></template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="手续费比例">
<a-input-number
v-model:value="configData.feeRate"
:min="0"
:max="100"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter>%</template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="审核方式">
<a-select v-model:value="configData.auditType" style="width: 100%">
<a-select-option :value="1">自动审核</a-select-option>
<a-select-option :value="2">人工审核</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 等级配置 -->
<div v-if="form.key === 'level_config'" class="level-config">
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="升级条件">
<a-select v-model:value="configData.upgradeType" style="width: 100%">
<a-select-option :value="1">按推广人数</a-select-option>
<a-select-option :value="2">按累计佣金</a-select-option>
<a-select-option :value="3">按订单数量</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="升级阈值">
<a-input-number
v-model:value="configData.upgradeThreshold"
:min="0"
placeholder="0"
style="width: 100%"
/>
</a-form-item>
</a-col>
</a-row>
</div>
<!-- 奖励配置 -->
<div v-if="form.key === 'reward_config'" class="reward-config">
<a-row :gutter="16">
<a-col :span="8">
<a-form-item label="推广奖励">
<a-input-number
v-model:value="configData.promotionReward"
:min="0"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter></template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="首单奖励">
<a-input-number
v-model:value="configData.firstOrderReward"
:min="0"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter></template>
</a-input-number>
</a-form-item>
</a-col>
<a-col :span="8">
<a-form-item label="月度奖励">
<a-input-number
v-model:value="configData.monthlyReward"
:min="0"
:precision="2"
placeholder="0.00"
style="width: 100%"
>
<template #addonAfter></template>
</a-input-number>
</a-form-item>
</a-col>
</a-row>
</div>
</div>
<!-- JSON 编辑器 -->
<a-form-item label="配置内容" name="values">
<div class="json-editor-container">
<div class="json-editor-header">
<span>JSON 配置</span>
<a-space>
<a-button size="small" @click="formatJson">
<template #icon>
<FormatPainterOutlined />
</template>
格式化
</a-button>
<a-button size="small" @click="validateJson">
<template #icon>
<CheckCircleOutlined />
</template>
验证
</a-button>
<a-button size="small" @click="resetToTemplate" v-if="form.key && form.key !== 'other'">
<template #icon>
<ReloadOutlined />
</template>
重置为模板
</a-button>
</a-space>
</div>
<a-textarea
v-model:value="form.values"
placeholder="请输入JSON格式的配置内容"
:rows="12"
class="json-editor"
@blur="onJsonBlur"
/>
<div class="json-status" v-if="jsonStatus">
<a-alert
:type="jsonStatus.type"
:message="jsonStatus.message"
show-icon
:closable="false"
/>
</div>
</div>
</a-form-item>
</a-form>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, reactive, watch } from 'vue';
import { Form, message } from 'ant-design-vue';
import {
FormatPainterOutlined,
CheckCircleOutlined,
ReloadOutlined
} from '@ant-design/icons-vue';
import { assignObject } from 'ele-admin-pro';
import { addShopDealerSetting, updateShopDealerSetting } from '@/api/shop/shopDealerSetting';
import { ShopDealerSetting } from '@/api/shop/shopDealerSetting/model';
import { FormInstance } from 'ant-design-vue/es/form';
// 是否是修改
const isUpdate = ref(false);
const useForm = Form.useForm;
const props = defineProps<{
// 弹窗是否打开
visible: boolean;
// 修改回显的数据
data?: ShopDealerSetting | null;
}>();
const emit = defineEmits<{
(e: 'done'): void;
(e: 'update:visible', visible: boolean): void;
}>();
// 提交状态
const loading = ref(false);
// 是否显示最大化切换按钮
const maxable = ref(true);
// 表格选中数据
const formRef = ref<FormInstance | null>(null);
// 表单数据
const form = reactive<ShopDealerSetting>({
key: undefined,
describe: '',
values: '',
tenantId: undefined,
updateTime: undefined
});
// 配置数据(用于模板配置)
const configData = reactive<any>({
// 佣金比例配置
firstRate: 0,
secondRate: 0,
thirdRate: 0,
// 提现配置
minAmount: 0,
feeRate: 0,
auditType: 1,
// 等级配置
upgradeType: 1,
upgradeThreshold: 0,
// 奖励配置
promotionReward: 0,
firstOrderReward: 0,
monthlyReward: 0
});
// JSON状态
const jsonStatus = ref<any>(null);
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
// 表单验证规则
const rules = reactive({
key: [
{
required: true,
message: '请选择设置标识',
trigger: 'change'
}
],
describe: [
{
required: true,
message: '请输入设置描述',
trigger: 'blur'
},
{
min: 2,
max: 100,
message: '描述长度应在2-100个字符之间',
trigger: 'blur'
}
],
values: [
{
required: true,
message: '请输入配置内容',
trigger: 'blur'
},
{
validator: (rule: any, value: any) => {
if (value) {
try {
JSON.parse(value);
return Promise.resolve();
} catch (e) {
return Promise.reject('配置内容必须是有效的JSON格式');
}
}
return Promise.resolve();
},
trigger: 'blur'
}
]
});
/* 获取模板标题 */
const getTemplateTitle = () => {
const titleMap = {
commission_rate: '佣金比例配置模板',
withdraw_config: '提现配置模板',
level_config: '等级配置模板',
reward_config: '奖励配置模板'
};
return titleMap[form.key] || '配置模板';
};
/* 获取模板描述 */
const getTemplateDescription = () => {
const descMap = {
commission_rate: '设置一级、二级、三级分销商的佣金比例,支持小数点后两位',
withdraw_config: '配置提现的最小金额、手续费比例和审核方式',
level_config: '设置分销商等级升级的条件和阈值',
reward_config: '配置推广奖励、首单奖励和月度奖励金额'
};
return descMap[form.key] || '请根据业务需求配置相关参数';
};
/* 设置标识改变时的处理 */
const onSettingKeyChange = (value: string) => {
// 重置配置数据
Object.keys(configData).forEach(key => {
configData[key] = typeof configData[key] === 'number' ? 0 : '';
});
// 设置默认描述
const descMap = {
commission_rate: '分销佣金比例设置',
withdraw_config: '提现相关参数配置',
level_config: '分销商等级配置',
reward_config: '推广奖励配置',
other: '自定义设置项'
};
if (!form.describe) {
form.describe = descMap[value] || '';
}
// 生成默认JSON
resetToTemplate();
};
/* 重置为模板 */
const resetToTemplate = () => {
if (!form.key || form.key === 'other') {
form.values = '{}';
return;
}
let template = {};
switch (form.key) {
case 'commission_rate':
template = {
firstRate: configData.firstRate || 10,
secondRate: configData.secondRate || 5,
thirdRate: configData.thirdRate || 2,
description: '分销佣金比例配置'
};
break;
case 'withdraw_config':
template = {
minAmount: configData.minAmount || 100,
feeRate: configData.feeRate || 1,
auditType: configData.auditType || 1,
description: '提现配置参数'
};
break;
case 'level_config':
template = {
upgradeType: configData.upgradeType || 1,
upgradeThreshold: configData.upgradeThreshold || 10,
description: '分销商等级配置'
};
break;
case 'reward_config':
template = {
promotionReward: configData.promotionReward || 10,
firstOrderReward: configData.firstOrderReward || 5,
monthlyReward: configData.monthlyReward || 50,
description: '推广奖励配置'
};
break;
}
form.values = JSON.stringify(template, null, 2);
validateJson();
};
/* 格式化JSON */
const formatJson = () => {
try {
const parsed = JSON.parse(form.values);
form.values = JSON.stringify(parsed, null, 2);
jsonStatus.value = {
type: 'success',
message: 'JSON格式化成功'
};
} catch (e) {
jsonStatus.value = {
type: 'error',
message: 'JSON格式错误无法格式化'
};
}
};
/* 验证JSON */
const validateJson = () => {
try {
JSON.parse(form.values);
jsonStatus.value = {
type: 'success',
message: 'JSON格式正确'
};
} catch (e) {
jsonStatus.value = {
type: 'error',
message: `JSON格式错误: ${e.message}`
};
}
};
/* JSON失焦时验证 */
const onJsonBlur = () => {
if (form.values) {
validateJson();
}
};
const { resetFields } = useForm(form, rules);
/* 保存编辑 */
const save = () => {
if (!formRef.value) {
return;
}
// 先验证JSON格式
if (form.values) {
try {
JSON.parse(form.values);
} catch (e) {
message.error('配置内容JSON格式错误请检查后重试');
return;
}
}
formRef.value
.validate()
.then(() => {
loading.value = true;
const formData = {
...form,
updateTime: Date.now()
};
const saveOrUpdate = isUpdate.value ? updateShopDealerSetting : addShopDealerSetting;
saveOrUpdate(formData)
.then((msg) => {
loading.value = false;
message.success(msg);
updateVisible(false);
emit('done');
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
})
.catch(() => {});
};
watch(
() => props.visible,
(visible) => {
if (visible) {
jsonStatus.value = null;
if (props.data) {
assignObject(form, props.data);
// 解析配置数据到模板
if (props.data.values) {
try {
const parsed = JSON.parse(props.data.values);
Object.keys(configData).forEach(key => {
if (parsed[key] !== undefined) {
configData[key] = parsed[key];
}
});
} catch (e) {
console.warn('解析配置数据失败:', e);
}
}
isUpdate.value = true;
} else {
// 重置为默认值
Object.assign(form, {
key: undefined,
describe: '',
values: '{}',
tenantId: undefined,
updateTime: undefined
});
// 重置配置数据
Object.keys(configData).forEach(key => {
configData[key] = typeof configData[key] === 'number' ? 0 : '';
});
isUpdate.value = false;
}
} else {
resetFields();
}
},
{ immediate: true }
);
// 监听配置数据变化自动更新JSON
watch(
() => configData,
() => {
if (form.key && form.key !== 'other') {
resetToTemplate();
}
},
{ deep: true }
);
</script>
<style lang="less" scoped>
.setting-option {
display: flex;
align-items: center;
.ant-tag {
margin-right: 8px;
}
span {
color: #666;
font-size: 12px;
}
}
.config-template {
background: #fafafa;
padding: 16px;
border-radius: 6px;
margin-bottom: 16px;
.commission-config,
.withdraw-config,
.level-config,
.reward-config {
margin-top: 16px;
}
}
.json-editor-container {
border: 1px solid #d9d9d9;
border-radius: 6px;
overflow: hidden;
.json-editor-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 12px;
background: #fafafa;
border-bottom: 1px solid #d9d9d9;
span {
font-weight: 600;
color: #333;
}
}
.json-editor {
border: none;
border-radius: 0;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
font-size: 12px;
line-height: 1.5;
&:focus {
box-shadow: none;
}
}
.json-status {
padding: 8px 12px;
border-top: 1px solid #d9d9d9;
background: #fff;
}
}
:deep(.ant-divider-horizontal.ant-divider-with-text-left) {
margin: 24px 0 16px 0;
.ant-divider-inner-text {
padding: 0 16px 0 0;
}
}
:deep(.ant-form-item) {
margin-bottom: 16px;
}
:deep(.ant-select-selection-item) {
display: flex;
align-items: center;
}
:deep(.ant-input-number) {
width: 100%;
}
:deep(.ant-alert) {
.ant-alert-message {
font-weight: 600;
}
}
</style>
</script>

View File

@@ -0,0 +1,415 @@
<template>
<a-page-header :title="getPageTitle()" @back="() => $router.go(-1)">
<a-card :bordered="false" :body-style="{ padding: '24px' }">
<!-- 设置标签页 -->
<a-tabs v-model:activeKey="activeTab" type="card" class="setting-tabs">
<a-tab-pane key="basic" tab="基础设置">
<a-form
:model="basicSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 是否开启分销功能 -->
<a-form-item label="是否开启分销功能">
<a-radio-group v-model:value="basicSettings.enableDistribution">
<a-radio :value="true">开启</a-radio>
<a-radio :value="false">关闭</a-radio>
</a-radio-group>
<div class="setting-desc">开启后用户可以申请成为分销商</div>
</a-form-item>
<!-- 分销层级 -->
<a-form-item label="分销层级">
<a-radio-group v-model:value="basicSettings.distributionLevel">
<a-radio :value="1">一级</a-radio>
<a-radio :value="2">二级</a-radio>
<a-radio :value="3">三级</a-radio>
</a-radio-group>
<div class="setting-desc">设置分销商推荐层级关系</div>
</a-form-item>
<!-- 分销商内购 -->
<a-form-item label="分销商内购">
<a-radio-group v-model:value="basicSettings.dealerSelfBuy">
<a-radio :value="true">开启</a-radio>
<a-radio :value="false">关闭</a-radio>
</a-radio-group>
<div class="setting-desc"
>分销商自己购买是否获得佣金开启一般佣金</div
>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="commission" tab="分销条件">
<a-form
:model="commissionSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 申请方式 -->
<a-form-item label="申请方式">
<a-radio-group v-model:value="commissionSettings.applyType">
<a-radio :value="10">需后台审核</a-radio>
<a-radio :value="20">无需审核</a-radio>
</a-radio-group>
<div class="setting-desc">设置用户申请分销商的审核方式</div>
</a-form-item>
<!-- 佣金结算 -->
<a-form-item label="佣金结算">
<a-radio-group v-model:value="commissionSettings.settlementType">
<a-radio :value="10">订单完成</a-radio>
<a-radio :value="20">订单确认收货</a-radio>
</a-radio-group>
<div class="setting-desc">设置佣金何时结算到分销商账户</div>
</a-form-item>
<!-- 最低提现金额 -->
<a-form-item label="最低提现金额">
<a-input-number
v-model:value="commissionSettings.minWithdrawAmount"
:min="0"
:precision="2"
style="width: 200px"
>
<template #addonAfter></template>
</a-input-number>
<div class="setting-desc">分销商申请提现的最低金额限制</div>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="withdraw" tab="提现设置">
<a-form
:model="withdrawSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 提现方式 -->
<a-form-item label="提现方式">
<a-checkbox-group
v-model:value="withdrawSettings.withdrawMethods"
>
<a-checkbox :value="10">微信</a-checkbox>
<a-checkbox :value="20">支付宝</a-checkbox>
<a-checkbox :value="30">银行卡</a-checkbox>
</a-checkbox-group>
<div class="setting-desc">设置支持的提现方式</div>
</a-form-item>
<!-- 提现手续费 -->
<a-form-item label="提现手续费">
<a-input-number
v-model:value="withdrawSettings.withdrawFeeRate"
:min="0"
:max="100"
:precision="2"
style="width: 200px"
>
<template #addonAfter>%</template>
</a-input-number>
<div class="setting-desc">提现时收取的手续费比例</div>
</a-form-item>
<!-- 提现审核 -->
<a-form-item label="提现审核">
<a-radio-group v-model:value="withdrawSettings.withdrawAudit">
<a-radio :value="true">需要审核</a-radio>
<a-radio :value="false">无需审核</a-radio>
</a-radio-group>
<div class="setting-desc">设置提现申请是否需要人工审核</div>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="agreement" tab="协议">
<a-form
:model="agreementSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 分销商协议 -->
<a-form-item label="分销商协议">
<a-textarea
v-model:value="agreementSettings.dealerAgreement"
:rows="10"
placeholder="请输入分销商协议内容..."
/>
<div class="setting-desc">用户申请分销商时需要同意的协议内容</div>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="notification" tab="自定义文字">
<a-form
:model="notificationSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 申请成功提示 -->
<a-form-item label="申请成功提示">
<a-textarea
v-model:value="notificationSettings.applySuccessText"
:rows="3"
placeholder="请输入申请成功后的提示文字..."
/>
</a-form-item>
<!-- 申请失败提示 -->
<a-form-item label="申请失败提示">
<a-textarea
v-model:value="notificationSettings.applyFailText"
:rows="3"
placeholder="请输入申请失败后的提示文字..."
/>
</a-form-item>
<!-- 提现成功提示 -->
<a-form-item label="提现成功提示">
<a-textarea
v-model:value="notificationSettings.withdrawSuccessText"
:rows="3"
placeholder="请输入提现成功后的提示文字..."
/>
</a-form-item>
</a-form>
</a-tab-pane>
<a-tab-pane key="page" tab="页面设置">
<a-form
:model="pageSettings"
:label-col="{ span: 6 }"
:wrapper-col="{ span: 18 }"
layout="horizontal"
>
<!-- 分销中心标题 -->
<a-form-item label="分销中心标题">
<a-input
v-model:value="pageSettings.centerTitle"
placeholder="请输入分销中心页面标题"
/>
</a-form-item>
<!-- 分销中心背景图 -->
<a-form-item label="分销中心背景图">
<a-upload
v-model:file-list="pageSettings.backgroundImages"
list-type="picture-card"
:max-count="1"
@preview="handlePreview"
>
<div v-if="pageSettings.backgroundImages.length < 1">
<PlusOutlined />
<div style="margin-top: 8px">上传</div>
</div>
</a-upload>
</a-form-item>
</a-form>
</a-tab-pane>
</a-tabs>
<!-- 保存按钮 -->
<div class="setting-footer">
<a-button
type="primary"
size="large"
@click="saveSettings"
:loading="saving"
>
保存设置
</a-button>
</div>
</a-card>
</a-page-header>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue';
import { message } from 'ant-design-vue';
import { PlusOutlined } from '@ant-design/icons-vue';
import { getPageTitle } from '@/utils/common';
import {
updateShopDealerSetting,
getShopDealerSetting
} from '@/api/shop/shopDealerSetting';
// 当前激活的标签页
const activeTab = ref('basic');
// 保存状态
const saving = ref(false);
// 基础设置
const basicSettings = reactive({
enableDistribution: true,
distributionLevel: 3,
dealerSelfBuy: false
});
// 分销条件设置
const commissionSettings = reactive({
applyType: 10,
settlementType: 10,
minWithdrawAmount: 100
});
// 提现设置
const withdrawSettings = reactive({
withdrawMethods: [10, 20, 30],
withdrawFeeRate: 0,
withdrawAudit: true
});
// 协议设置
const agreementSettings = reactive({
dealerAgreement: '分销商协议内容...'
});
// 通知设置
const notificationSettings = reactive({
applySuccessText: '恭喜您成功成为分销商!',
applyFailText: '很抱歉,您的申请未通过审核。',
withdrawSuccessText: '提现申请已提交,请耐心等待处理。'
});
// 页面设置
const pageSettings = reactive({
centerTitle: '分销中心',
backgroundImages: []
});
/* 图片预览 */
const handlePreview = (file: any) => {
console.log('预览图片:', file);
};
/* 加载设置 */
const loadSettings = async () => {
try {
// 这里应该调用API获取设置数据
// const settings = await getShopDealerSetting();
// 然后将数据分配到各个设置对象中
console.log('加载设置数据');
} catch (error) {
console.error('加载设置失败:', error);
message.error('加载设置失败');
}
};
/* 保存设置 */
const saveSettings = async () => {
saving.value = true;
try {
// 收集所有设置数据
const allSettings = {
basic: basicSettings,
commission: commissionSettings,
withdraw: withdrawSettings,
agreement: agreementSettings,
notification: notificationSettings,
page: pageSettings
};
console.log('保存设置:', allSettings);
// 这里应该调用API保存设置
// await updateShopDealerSetting(allSettings);
// 模拟保存
await new Promise((resolve) => setTimeout(resolve, 1000));
message.success('设置保存成功');
} catch (error) {
console.error('保存设置失败:', error);
message.error('保存设置失败');
} finally {
saving.value = false;
}
};
// 页面加载时获取设置数据
onMounted(() => {
loadSettings();
});
</script>
<script lang="ts">
export default {
name: 'ShopDealerSetting'
};
</script>
<style lang="less" scoped>
.dealer-setting-container {
max-width: 1200px;
margin: 0 auto;
}
.setting-tabs {
:deep(.ant-tabs-card > .ant-tabs-nav .ant-tabs-tab) {
border-radius: 6px 6px 0 0;
background: #fafafa;
border: 1px solid #d9d9d9;
margin-right: 8px;
&.ant-tabs-tab-active {
background: #fff;
border-bottom-color: #fff;
}
}
:deep(.ant-tabs-content-holder) {
background: #fff;
border: 1px solid #d9d9d9;
border-radius: 0 6px 6px 6px;
padding: 24px;
min-height: 500px;
}
}
.setting-desc {
color: #999;
font-size: 12px;
margin-top: 4px;
line-height: 1.4;
}
.setting-footer {
text-align: center;
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid #f0f0f0;
}
:deep(.ant-form-item-label > label) {
font-weight: 500;
}
:deep(.ant-radio-group) {
.ant-radio-wrapper {
margin-right: 16px;
}
}
:deep(.ant-checkbox-group) {
.ant-checkbox-wrapper {
margin-right: 16px;
margin-bottom: 8px;
}
}
:deep(.ant-upload-select-picture-card) {
width: 120px;
height: 120px;
}
:deep(.ant-upload-list-picture-card .ant-upload-list-item) {
width: 120px;
height: 120px;
}
</style>