Files
tydata-webview-v2/src/views/Promote.vue
2026-02-28 12:00:02 +08:00

271 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="min-h-screen p-4 promote">
<div class="mb-4 card !bg-gradient-to-b from-orange-200 to-orange-200/80">
<div class="">
<div class="text-lg font-bold text-orange-500">直推用户查询</div>
<div class="font-bold text-orange-400 mt-1">
自定义价格赚取差价
</div>
</div>
<div class="mt-6">
<div class="mt-2 text-gray-600 bg-orange-100 rounded-xl px-4 py-2">
在下方 自定义价格 处选择报告类型设置客户查询价即可立即推广
</div>
</div>
</div>
<VipBanner />
<!-- 判断是否是代理 -->
<div>
<div class="card mb-4">
<div class="">
<h2 class="text-xl font-semibold mb-2">生成推广码</h2>
<van-cell-group inset>
<!-- 报告类型 -->
<van-field v-model="pickerFieldText" is-link readonly label="报告类型" placeholder="请选择报告类型"
@click="showTypePicker = true" />
<van-popup v-model:show="showTypePicker" destroy-on-close round position="bottom">
<van-picker :model-value="selectedReportType" :columns="reportTypes"
@cancel="showTypePicker = false" @confirm="onConfirmType" />
</van-popup>
<!-- 定价 -->
<van-field v-model="clientPrice" is-link readonly label="客户查询价" placeholder="请输入价格"
@click="showPricePicker = true" />
<PriceInputPopup v-model:show="showPricePicker" :default-price="clientPrice"
:product-config="pickerProductConfig" @change="onPriceChange" />
<div class="flex items-center justify-between my-2">
<div class="text-sm text-gray-500">推广收益为 <span class="text-orange-500">{{ promotionRevenue
}}</span> </div>
<div class="text-sm text-gray-500">我的成本为 <span class="text-orange-500">{{ costPrice
}}</span> </div>
</div>
</van-cell-group>
</div>
<div class="mt-6">
<van-button type="primary" class="w-full" @click="generatePromotionCode">点击立即推广</van-button>
</div>
</div>
</div>
<!-- 如果不是代理展示根据status显示不同内容 -->
<!-- <div>
<div v-if="status === 0" class="card mt-6">
<div class="font-semibold text-lg text-gray-700">申请审核中</div>
<div class="text-sm text-gray-500 mt-4 mb-8">
您的申请正在审核中请耐心等待
</div>
</div>
<div v-else-if="status === 2" class="card mt-6">
<div class="font-semibold text-lg text-gray-700">申请未通过</div>
<div class="text-sm text-gray-500 mt-4 mb-8">
很抱歉您的代理申请未通过请检查您的信息或重新申请
</div>
<van-button type="primary" round class="w-full" @click="showApplyPopup = true">
申请成为代理
</van-button>
</div>
<div v-else-if="status === 3" class="card mt-6">
<div class="font-semibold text-lg text-gray-700">未申请成为代理</div>
<div class="text-sm text-gray-500 mt-4 mb-8">
您还没有申请成为代理立即申请即可开始推广
</div>
<van-button type="primary" round class="w-full" @click="showApplyPopup = true">
申请成为代理
</van-button>
</div>
</div>
<AgentApplicationForm v-model:show="showApplyPopup" @submit="submitApplication"
@close="showApplyPopup = false" /> -->
<QRcode v-model:show="showQRcode" :linkIdentifier="linkIdentifier" />
</div>
</template>
<script setup>
import PriceInputPopup from '@/components/PriceInputPopup.vue';
import VipBanner from '@/components/VipBanner.vue';
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: 'rentalrisk', id: 6 },
];
const showTypePicker = ref(false);
const showApplyPopup = ref(false); // 用来控制申请代理弹窗的显示
const showPricePicker = ref(false);
const pickerFieldText = ref('')
const pickerFieldVal = ref(null)
const pickerProductConfig = ref(null)
const selectedReportType = ref([]);
const clientPrice = ref(null);
const productConfig = ref(null);
const linkIdentifier = ref("")
// const costPrice = computed(() => {
// if (!pickerProductConfig.value) return 0.00
// // 平台定价成本
// let platformPricing = 0
// if (clientPrice.value > pickerProductConfig.value.p_pricing_standard) {
// platformPricing = (clientPrice.value - pickerProductConfig.value.p_pricing_standard) * pickerProductConfig.value.p_overpricing_ratio
// }
// return (pickerProductConfig.value.cost_price + platformPricing).toFixed(2)
// })
const costPrice = computed(() => {
if (!pickerProductConfig.value) return 0.00
// 平台定价成本
let platformPricing = 0
platformPricing += pickerProductConfig.value.cost_price
if (clientPrice.value > pickerProductConfig.value.p_pricing_standard) {
platformPricing += (clientPrice.value - pickerProductConfig.value.p_pricing_standard) * pickerProductConfig.value.p_overpricing_ratio
}
if (pickerProductConfig.value.a_pricing_standard > platformPricing && pickerProductConfig.value.a_pricing_end > platformPricing && pickerProductConfig.value.a_overpricing_ratio > 0) {
if (clientPrice.value > pickerProductConfig.value.a_pricing_standard) {
if (clientPrice.value > pickerProductConfig.value.a_pricing_end) {
platformPricing += (pickerProductConfig.value.a_pricing_end - pickerProductConfig.value.a_pricing_standard) * pickerProductConfig.value.a_overpricing_ratio
} else {
platformPricing += (clientPrice.value - pickerProductConfig.value.a_pricing_standard) * pickerProductConfig.value.a_overpricing_ratio
}
}
}
return safeTruncate(platformPricing)
})
const promotionRevenue = computed(() => {
return safeTruncate(clientPrice.value - costPrice.value)
});
const showQRcode = ref(false);
function safeTruncate(num, decimals = 2) {
if (isNaN(num) || !isFinite(num)) return "0.00";
const factor = 10 ** decimals;
const scaled = Math.trunc(num * factor);
const truncated = scaled / factor;
return truncated.toFixed(decimals);
}
const generatePromotionCode = async () => {
if (selectedReportType.value.length === 0) {
showToast({ message: '请选择报告类型' });
return;
}
if (!clientPrice.value) {
showToast({ message: '请输入查询价格' });
return;
}
const { data, error } = await useApiFetch("/agent/generating_link")
.post({ product: pickerFieldVal.value, price: clientPrice.value })
.json()
if (data.value && !error.value) {
if (data.value.code === 200) {
linkIdentifier.value = data.value.data.link_identifier
} else {
console.log("Error fetching agent info", data.value);
}
}
if (!linkIdentifier.value) return
showQRcode.value = true;
};
onMounted(() => {
getPromoteConfig();
// getAgentInfo();
});
const SelectTypePicker = (reportType) => {
selectedReportType.value = [reportType];
pickerFieldText.value = reportType.text;
pickerFieldVal.value = reportType.value;
for (let i of productConfig.value) {
if (i.product_id === reportType.id) {
pickerProductConfig.value = i
clientPrice.value = i.cost_price
}
}
};
const getPromoteConfig = async () => {
const { data, error } = await useApiFetch("/agent/product_config")
.get()
.json()
if (data.value && !error.value) {
if (data.value.code === 200) {
productConfig.value = data.value.data.AgentProductConfig;
SelectTypePicker(reportTypes[0])
} else {
console.log("Error fetching agent info", data.value);
}
}
}
const onPriceChange = (price) => {
clientPrice.value = price
}
// const getAgentInfo = async () => {
// const { data, error } = await useApiFetch("/agent/info")
// .get()
// .json()
// if (data.value && !error.value) {
// if (data.value.code === 200) {
// isAgent.value = data.value.data.is_agent; // 判断是否是代理
// status.value = data.value.data.status; // 获取代理状态
// agentID.value = data.value.data.agent_id
// } else {
// console.log("Error fetching agent info", data.value);
// }
// }
// };
const onConfirmType = ({ selectedValues, selectedOptions }) => {
SelectTypePicker(selectedOptions[0])
showTypePicker.value = false;
};
const submitApplication = async (formData) => {
// 提交代理申请的数据
const { region, mobile, wechat_id, code } = formData;
const { data, error } = await useApiFetch("/agent/apply")
.post({ region, mobile, wechat_id, code })
.json();
if (data.value && !error.value) {
if (data.value.code === 200) {
showApplyPopup.value = false;
// 这里可以提示成功,或者刷新代理状态
showToast({ message: "已提交申请" });
} else {
console.log('申请失败', data.value);
}
}
};
</script>
<style scoped>
/* .promote {
background-color: #ffeee0;
background-image: linear-gradient(45deg,
rgba(255, 235, 205, 0.3) 25%,
transparent 25%,
transparent 50%,
rgba(255, 235, 205, 0.3) 50%,
rgba(255, 235, 205, 0.3) 75%,
transparent 75%,
transparent);
background-size: 40px 40px;
min-height: 100vh;
}
*/
</style>