234 lines
7.5 KiB
Vue
234 lines
7.5 KiB
Vue
<script setup>
|
||
import PriceInputPopup from '@/components/PriceInputPopup.vue'
|
||
import VipBanner from '@/components/VipBanner.vue'
|
||
import { calculatePromotionPricing, safeTruncate } from '@/utils/promotionPricing'
|
||
|
||
definePage({ layout: 'default' })
|
||
|
||
const showPricePicker = ref(false)
|
||
const pickerProductConfig = ref(null)
|
||
const productConfig = ref(null)
|
||
const linkIdentifier = ref('')
|
||
const showQRcode = ref(false)
|
||
const promotionForm = ref(null)
|
||
const loadingConfig = ref(false)
|
||
const generating = ref(false)
|
||
|
||
const formData = ref({
|
||
productType: '',
|
||
clientPrice: null,
|
||
})
|
||
|
||
/** 从首页报告卡片带入的 product_en,配置加载后预选 */
|
||
const initialFeature = ref('')
|
||
|
||
const availableReportTypes = computed(() => {
|
||
if (!productConfig.value?.length)
|
||
return []
|
||
return [...productConfig.value]
|
||
.sort((a, b) => Number(a.product_id) - Number(b.product_id))
|
||
.map(item => ({
|
||
id: item.product_id,
|
||
label: item.product_name || `产品${item.product_id}`,
|
||
value: item.product_en || '',
|
||
}))
|
||
.filter(item => !!item.value)
|
||
})
|
||
|
||
const pricingResult = computed(() => {
|
||
return calculatePromotionPricing(formData.value.clientPrice, pickerProductConfig.value)
|
||
})
|
||
|
||
const costPrice = computed(() => pricingResult.value.costPrice)
|
||
const promotionRevenue = computed(() => pricingResult.value.promotionRevenue)
|
||
|
||
function selectProductType(reportTypeValue) {
|
||
const reportType = availableReportTypes.value.find(item => item.id === reportTypeValue || item.value === reportTypeValue)
|
||
if (!reportType)
|
||
return
|
||
|
||
formData.value.productType = reportType.value
|
||
|
||
const matchedConfig = productConfig.value?.find(item => item.product_id === reportType.id)
|
||
if (!matchedConfig) {
|
||
pickerProductConfig.value = null
|
||
formData.value.clientPrice = null
|
||
uni.showToast({ title: '该报告暂不可推广', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
pickerProductConfig.value = matchedConfig
|
||
formData.value.clientPrice = matchedConfig.cost_price
|
||
}
|
||
|
||
function onConfirmType(e) {
|
||
// 单列 wd-picker 的 e.value 为标量;多列时为数组。不能用 e.value[0] 取标量,否则字符串会变成首字符。
|
||
const raw = e?.value
|
||
const nextValue = Array.isArray(raw) ? raw[0] : raw
|
||
const fromItem = e?.selectedItems
|
||
const resolved = nextValue ?? (Array.isArray(fromItem) ? fromItem[0]?.value : fromItem?.value)
|
||
if (resolved != null && resolved !== '')
|
||
selectProductType(resolved)
|
||
}
|
||
|
||
function onPriceChange(price) {
|
||
formData.value.clientPrice = price
|
||
}
|
||
|
||
function getPricePayload() {
|
||
return safeTruncate(Number(formData.value.clientPrice))
|
||
}
|
||
|
||
function openPricePicker() {
|
||
if (!pickerProductConfig.value) {
|
||
uni.showToast({ title: '请先选择报告类型', icon: 'none' })
|
||
return
|
||
}
|
||
showPricePicker.value = true
|
||
}
|
||
|
||
function toExampleReport() {
|
||
const feature = formData.value.productType
|
||
if (!feature) {
|
||
uni.showToast({ title: '请先选择报告类型', icon: 'none' })
|
||
return
|
||
}
|
||
uni.navigateTo({
|
||
url: `/pages/report-example-webview?feature=${encodeURIComponent(feature)}`,
|
||
})
|
||
}
|
||
|
||
async function getPromoteConfig() {
|
||
loadingConfig.value = true
|
||
try {
|
||
const { data, error } = await useApiFetch('/agent/product_config', { silent: true }).get().json()
|
||
if (data.value && !error.value && data.value.code === 200) {
|
||
const list = data.value.data.AgentProductConfig || []
|
||
productConfig.value = list
|
||
const preset = initialFeature.value
|
||
? availableReportTypes.value.find(item => item.value === initialFeature.value)
|
||
: null
|
||
const availableType = preset || availableReportTypes.value[0]
|
||
if (availableType) {
|
||
selectProductType(availableType.value)
|
||
}
|
||
else {
|
||
pickerProductConfig.value = null
|
||
formData.value.productType = ''
|
||
formData.value.clientPrice = null
|
||
uni.showToast({ title: '暂无可推广产品', icon: 'none' })
|
||
}
|
||
return
|
||
}
|
||
uni.showToast({ title: data.value?.msg || '获取配置失败', icon: 'none' })
|
||
}
|
||
catch {
|
||
uni.showToast({ title: '获取配置失败', icon: 'none' })
|
||
}
|
||
finally {
|
||
loadingConfig.value = false
|
||
}
|
||
}
|
||
|
||
async function generatePromotionCode() {
|
||
if (generating.value)
|
||
return
|
||
try {
|
||
await promotionForm.value.validate()
|
||
}
|
||
catch {
|
||
return
|
||
}
|
||
generating.value = true
|
||
try {
|
||
const { data, error } = await useApiFetch('/agent/generating_link')
|
||
.post({ product: formData.value.productType, price: getPricePayload() })
|
||
.json()
|
||
if (data.value && !error.value && data.value.code === 200) {
|
||
linkIdentifier.value = data.value.data.link_identifier
|
||
showQRcode.value = true
|
||
}
|
||
else {
|
||
uni.showToast({ title: data.value?.msg || '生成推广码失败', icon: 'none' })
|
||
}
|
||
}
|
||
catch {
|
||
uni.showToast({ title: '生成推广码失败', icon: 'none' })
|
||
}
|
||
finally {
|
||
generating.value = false
|
||
}
|
||
}
|
||
|
||
onLoad((options) => {
|
||
const feature = options?.feature
|
||
if (feature)
|
||
initialFeature.value = decodeURIComponent(String(feature))
|
||
})
|
||
|
||
onMounted(() => {
|
||
getPromoteConfig()
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view class="promote min-h-screen p-4">
|
||
<view class="card mb-4 from-orange-200 to-orange-200/80 !bg-gradient-to-b">
|
||
<view class="text-lg text-orange-500 font-bold">
|
||
直推用户查询
|
||
</view>
|
||
<view class="mt-1 text-orange-400 font-bold">
|
||
自定义价格,赚取差价
|
||
</view>
|
||
<view class="mt-6 rounded-xl bg-orange-100 px-4 py-2 text-gray-600">
|
||
在下方 “自定义价格” 处选择报告类型,设置客户查询价(元)即可立即推广。
|
||
</view>
|
||
</view>
|
||
<VipBanner />
|
||
|
||
<view class="card mb-4 relative">
|
||
<text
|
||
class="absolute right-4 top-4 z-10 text-sm text-blue-600 active:opacity-70"
|
||
@click="toExampleReport"
|
||
>
|
||
示例报告
|
||
</text>
|
||
<view class="mb-2 pr-20 text-xl font-semibold">
|
||
生成推广码
|
||
</view>
|
||
<wd-form ref="promotionForm" :model="formData">
|
||
<wd-cell-group border>
|
||
<wd-picker v-model="formData.productType" label="报告类型" label-width="100px" title="选择报告类型"
|
||
:columns="[availableReportTypes]" prop="productType" placeholder="请选择报告类型"
|
||
:rules="[{ required: true, message: '请选择报告类型' }]" @confirm="onConfirmType" />
|
||
<wd-input v-model="formData.clientPrice" label="客户查询价" label-width="100px" placeholder="请输入价格"
|
||
prop="clientPrice" clickable readonly suffix-icon="arrow-right"
|
||
:rules="[{ required: true, message: '请输入客户查询价' }]" @click="openPricePicker" />
|
||
</wd-cell-group>
|
||
<view class="my-2 flex items-center justify-between text-sm text-gray-500">
|
||
<view>
|
||
推广收益为 <text class="text-orange-500">
|
||
{{ promotionRevenue }}
|
||
</text> 元
|
||
</view>
|
||
<view>
|
||
我的成本为 <text class="text-orange-500">
|
||
{{ costPrice }}
|
||
</text> 元
|
||
</view>
|
||
</view>
|
||
</wd-form>
|
||
<wd-button type="primary" block :loading="generating || loadingConfig"
|
||
:disabled="loadingConfig || !pickerProductConfig" @click="generatePromotionCode">
|
||
点击立即推广
|
||
</wd-button>
|
||
</view>
|
||
|
||
<PriceInputPopup v-model:show="showPricePicker" :default-price="formData.clientPrice"
|
||
:product-config="pickerProductConfig" @change="onPriceChange" />
|
||
<QRcode v-model:show="showQRcode" :link-identifier="linkIdentifier" />
|
||
</view>
|
||
</template>
|
||
|
||
<style scoped></style>
|