t
This commit is contained in:
@@ -38,9 +38,14 @@
|
||||
|
||||
<!-- 成本和收益信息 -->
|
||||
<div class="bg-gray-50 rounded-lg p-3 space-y-2">
|
||||
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">我的成本</span>
|
||||
<span class="text-sm font-semibold text-orange-500">¥{{ costPrice }}</span>
|
||||
<span class="text-sm text-gray-600">底价成本</span>
|
||||
<span class="text-sm font-semibold text-orange-500">¥{{ baseCost }}</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">提价成本</span>
|
||||
<span class="text-sm font-semibold text-orange-500">¥{{ raiseCost }}</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-gray-600">推广收益</span>
|
||||
@@ -76,7 +81,7 @@
|
||||
:product-config="pickerProductConfig" @change="onPriceChange" />
|
||||
|
||||
<!-- 二维码弹窗 -->
|
||||
<QRcode v-model:show="showQRcode" :linkIdentifier="linkIdentifier" />
|
||||
<QRcode v-model:show="showQRcode" :fullLink="fullLink" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -87,6 +92,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||
import PriceInputPopup from '@/components/PriceInputPopup.vue';
|
||||
import QRcode from '@/components/QRcode.vue';
|
||||
import ReportFeatures from '@/components/ReportFeatures.vue';
|
||||
import { getProductConfig, generateLink } from '@/api/agent';
|
||||
|
||||
// 导入logo图片
|
||||
import personalDataLogo from '@/assets/images/promote/personal_data_logo.png';
|
||||
@@ -100,16 +106,8 @@ import consumerFinanceReportLogo from '@/assets/images/promote/consumer_finance_
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// 报告类型配置(保持原来的数据结构)
|
||||
const reportTypes = [
|
||||
{ text: "小微企业", value: "companyinfo", id: 2 },
|
||||
{ text: "贷前风险", value: "preloanbackgroundcheck", id: 5 },
|
||||
{ text: "个人大数据", value: "personalData", id: 27 },
|
||||
{ text: '入职背调', value: 'backgroundcheck', id: 1 },
|
||||
{ text: '家政风险', value: 'homeservice', id: 3 },
|
||||
{ text: '婚恋风险', value: 'marriage', id: 4 },
|
||||
{ text: "消金报告", value: "consumerFinanceReport", id: 28 },
|
||||
];
|
||||
// 报告类型配置(从接口获取)
|
||||
const reportTypes = ref([]);
|
||||
|
||||
// 从 query 参数获取报告类型(使用 computed 以响应路由变化)
|
||||
const currentFeature = computed(() => route.query.feature || '');
|
||||
@@ -121,13 +119,13 @@ const pickerProductConfig = ref(null);
|
||||
const pickerFieldVal = ref(null); // 保持原来的变量名,用于存储报告类型的 value
|
||||
const clientPrice = ref(null);
|
||||
const productConfig = ref(null);
|
||||
const linkIdentifier = ref("");
|
||||
const fullLink = ref(""); // 完整的推广短链
|
||||
const featureData = ref({});
|
||||
const showQRcode = ref(false);
|
||||
|
||||
// Logo映射
|
||||
const logoMap = {
|
||||
'personalData': personalDataLogo,
|
||||
'riskassessment': personalDataLogo,
|
||||
'companyinfo': companyLogo,
|
||||
'preloanbackgroundcheck': preloanBackgroundCheckLogo,
|
||||
'marriage': marriageRiskLogo,
|
||||
@@ -145,35 +143,41 @@ const currentLogo = computed(() => {
|
||||
const costPrice = computed(() => {
|
||||
if (!pickerProductConfig.value) return 0.00
|
||||
|
||||
// 确保所有金额值都是数字类型
|
||||
const baseCost = Number(pickerProductConfig.value.cost_price) || 0;
|
||||
// 新系统:成本价 = 实际底价(actual_base_price)
|
||||
// actual_base_price = base_price + 等级加成
|
||||
const actualBasePrice = Number(pickerProductConfig.value.actual_base_price) || 0;
|
||||
const clientPriceNum = Number(clientPrice.value) || 0;
|
||||
const pStandard = Number(pickerProductConfig.value.p_pricing_standard) || 0;
|
||||
const pRatio = Number(pickerProductConfig.value.p_overpricing_ratio) || 0;
|
||||
const aStandard = Number(pickerProductConfig.value.a_pricing_standard) || 0;
|
||||
const aEnd = Number(pickerProductConfig.value.a_pricing_end) || 0;
|
||||
const aRatio = Number(pickerProductConfig.value.a_overpricing_ratio) || 0;
|
||||
const priceThreshold = Number(pickerProductConfig.value.price_threshold) || 0;
|
||||
const priceFeeRate = Number(pickerProductConfig.value.price_fee_rate) || 0;
|
||||
|
||||
// 平台定价成本
|
||||
let platformPricing = baseCost;
|
||||
|
||||
// 提价成本计算
|
||||
if (clientPriceNum > pStandard) {
|
||||
platformPricing += (clientPriceNum - pStandard) * pRatio;
|
||||
// 计算提价成本
|
||||
let priceCost = 0;
|
||||
if (clientPriceNum > priceThreshold) {
|
||||
priceCost = (clientPriceNum - priceThreshold) * priceFeeRate;
|
||||
}
|
||||
|
||||
// 代理提价成本计算
|
||||
if (aStandard > platformPricing && aEnd > platformPricing && aRatio > 0) {
|
||||
if (clientPriceNum > aStandard) {
|
||||
if (clientPriceNum > aEnd) {
|
||||
platformPricing += (aEnd - aStandard) * aRatio;
|
||||
} else {
|
||||
platformPricing += (clientPriceNum - aStandard) * aRatio;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 总成本 = 实际底价 + 提价成本
|
||||
const totalCost = actualBasePrice + priceCost;
|
||||
|
||||
return safeTruncate(platformPricing);
|
||||
return safeTruncate(totalCost);
|
||||
});
|
||||
|
||||
const baseCost = computed(() => {
|
||||
if (!pickerProductConfig.value) return "0.00";
|
||||
const actualBasePrice = Number(pickerProductConfig.value.actual_base_price) || 0;
|
||||
return safeTruncate(actualBasePrice);
|
||||
});
|
||||
|
||||
const raiseCost = computed(() => {
|
||||
if (!pickerProductConfig.value) return "0.00";
|
||||
const clientPriceNum = Number(clientPrice.value) || 0;
|
||||
const priceThreshold = Number(pickerProductConfig.value.price_threshold) || 0;
|
||||
const priceFeeRate = Number(pickerProductConfig.value.price_fee_rate) || 0;
|
||||
let priceCost = 0;
|
||||
if (clientPriceNum > priceThreshold) {
|
||||
priceCost = (clientPriceNum - priceThreshold) * priceFeeRate;
|
||||
}
|
||||
return safeTruncate(priceCost);
|
||||
});
|
||||
|
||||
const promotionRevenue = computed(() => {
|
||||
@@ -222,10 +226,10 @@ const getProductInfo = async () => {
|
||||
|
||||
// 根据 feature 找到对应的报告类型(保持原来的数据结构匹配方式)
|
||||
const findReportTypeByFeature = (feature) => {
|
||||
return reportTypes.find(type => type.value === feature);
|
||||
return reportTypes.value.find(type => type.value === feature);
|
||||
};
|
||||
|
||||
// 选择报告类型并设置配置(保持原来的处理逻辑)
|
||||
// 选择报告类型并设置配置
|
||||
const SelectTypePicker = (reportType) => {
|
||||
if (!reportType) return;
|
||||
|
||||
@@ -236,12 +240,12 @@ const SelectTypePicker = (reportType) => {
|
||||
|
||||
// 如果产品配置已加载,则设置配置
|
||||
if (productConfig.value) {
|
||||
// 遍历产品配置,找到匹配的产品
|
||||
// 遍历产品配置,找到匹配的产品(根据 product_en 匹配)
|
||||
for (let i of productConfig.value) {
|
||||
if (i.product_id === reportType.id) {
|
||||
if (i.product_en === reportType.value) {
|
||||
pickerProductConfig.value = i;
|
||||
// 确保初始价格为数字类型
|
||||
clientPrice.value = Number(i.cost_price) || 0;
|
||||
// 新系统:初始价格设置为实际底价(成本价)
|
||||
clientPrice.value = Number(i.actual_base_price) || Number(i.price_range_min) || 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -256,13 +260,25 @@ const SelectTypePicker = (reportType) => {
|
||||
|
||||
// 获取产品配置
|
||||
const getPromoteConfig = async () => {
|
||||
const { data, error } = await useApiFetch("/agent/product_config")
|
||||
.get()
|
||||
.json();
|
||||
const { data, error } = await getProductConfig();
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
productConfig.value = data.value.data.AgentProductConfig;
|
||||
// 新系统数据结构:data.value.data.list 是数组
|
||||
productConfig.value = data.value.data.list || [];
|
||||
|
||||
// 根据接口返回的产品列表,生成报告类型配置
|
||||
const types = [];
|
||||
productConfig.value.forEach(config => {
|
||||
if (config.product_en) {
|
||||
types.push({
|
||||
text: config.product_name,
|
||||
value: config.product_en,
|
||||
id: config.product_id,
|
||||
});
|
||||
}
|
||||
});
|
||||
reportTypes.value = types;
|
||||
|
||||
// 根据当前 feature 找到对应的报告类型,然后设置配置
|
||||
// 如果没有 feature 参数,默认选择第一个报告类型
|
||||
@@ -272,8 +288,8 @@ const getPromoteConfig = async () => {
|
||||
}
|
||||
|
||||
// 如果没有找到匹配的报告类型或没有feature参数,使用第一个报告类型
|
||||
if (!reportType && reportTypes.length > 0) {
|
||||
reportType = reportTypes[0];
|
||||
if (!reportType && reportTypes.value.length > 0) {
|
||||
reportType = reportTypes.value[0];
|
||||
}
|
||||
|
||||
if (reportType) {
|
||||
@@ -286,7 +302,7 @@ const getPromoteConfig = async () => {
|
||||
};
|
||||
|
||||
const generatePromotionCode = async () => {
|
||||
if (!pickerFieldVal.value) {
|
||||
if (!pickerFieldVal.value || !pickerProductConfig.value) {
|
||||
showToast({ message: '请选择报告类型' });
|
||||
return;
|
||||
}
|
||||
@@ -298,23 +314,46 @@ const generatePromotionCode = async () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// 保持原来的接口调用方式,price 参数需要转换为 string 类型
|
||||
// 使用 toFixed(2) 确保精度,避免浮点数精度问题
|
||||
const priceStr = priceNum.toFixed(2);
|
||||
// 验证价格范围
|
||||
const minPrice = Number(pickerProductConfig.value.price_range_min) || 0;
|
||||
const maxPrice = Number(pickerProductConfig.value.price_range_max) || Infinity;
|
||||
|
||||
const { data, error } = await useApiFetch("/agent/generating_link")
|
||||
.post({ product: pickerFieldVal.value, price: priceStr })
|
||||
.json();
|
||||
if (priceNum < minPrice) {
|
||||
showToast({ message: `价格不能低于 ${minPrice.toFixed(2)} 元` });
|
||||
return;
|
||||
}
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
linkIdentifier.value = data.value.data.link_identifier;
|
||||
showQRcode.value = true;
|
||||
if (priceNum > maxPrice) {
|
||||
showToast({ message: `价格不能高于 ${maxPrice.toFixed(2)} 元` });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// 构建目标路径模板:推广报告页面路径(后端会将 linkIdentifier 拼接到路径中)
|
||||
// 注意:后端会在重定向时自动将 linkIdentifier 拼接到 target_path 后面
|
||||
const targetPath = `/agent/promotionInquire/`;
|
||||
|
||||
// 新系统API:使用 product_id、set_price 和 target_path
|
||||
const { data, error } = await generateLink({
|
||||
product_id: pickerProductConfig.value.product_id,
|
||||
set_price: priceNum,
|
||||
target_path: targetPath
|
||||
});
|
||||
|
||||
if (data.value && !error.value) {
|
||||
if (data.value.code === 200) {
|
||||
// 使用后端返回的完整短链
|
||||
fullLink.value = data.value.data.full_link || "";
|
||||
showQRcode.value = true;
|
||||
} else {
|
||||
console.log("Error generating promotion link", data.value);
|
||||
showToast({ message: data.value.msg || '生成推广链接失败,请重试' });
|
||||
}
|
||||
} else {
|
||||
console.log("Error generating promotion link", data.value);
|
||||
showToast({ message: '生成推广链接失败,请重试' });
|
||||
}
|
||||
} else {
|
||||
} catch (err) {
|
||||
console.error('生成推广链接失败:', err);
|
||||
showToast({ message: '生成推广链接失败,请重试' });
|
||||
}
|
||||
};
|
||||
@@ -562,4 +601,4 @@ onMounted(async () => {
|
||||
opacity: 0.4 !important;
|
||||
color: #bdbdbd !important;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user