This commit is contained in:
Mrx
2026-02-14 11:14:52 +08:00
parent b8f0ee65a1
commit ba15295248
11 changed files with 105 additions and 207 deletions

View File

@@ -1,7 +1,7 @@
import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
export default defineManifestConfig({
'name': '天远数据',
'name': '天远助手',
'appid': '__UNI__CC3DA09',
'description': '',
'versionName': '1.0.0',

View File

@@ -9,7 +9,7 @@ export default defineUniPages({
backgroundTextStyle: '@bgTxtStyle',
navigationBarBackgroundColor: '#000000',
navigationBarTextStyle: '@navTxtStyle',
navigationBarTitleText: '天远数据',
navigationBarTitleText: '天远助手',
navigationStyle: 'custom',
},

View File

@@ -3,7 +3,7 @@
* 在页面 setup 中调用 useShare(options) 即可启用右上角菜单的「转发」与「分享到朋友圈」
*/
const DEFAULT_TITLE = '天远数据 - 大数据报告查询'
const DEFAULT_TITLE = '天远助手 - 大数据报告查询'
const DEFAULT_IMAGE_URL = '' // 留空则微信使用页面截图
export interface UseShareOptions {

View File

@@ -4,7 +4,7 @@ import 'uno.css'
import '@/app.scss'
import { setupRouterGuard } from '@/utils/routerGuard'
const DEFAULT_SHARE_TITLE = '天远数据 - 大数据报告查询,即刻赚佣金'
const DEFAULT_SHARE_TITLE = '天远助手 - 大数据报告查询,即刻赚佣金'
// 全局分享:所有页面右上角「转发」「分享到朋友圈」使用统一默认配置
const shareMixin = {

View File

@@ -1,5 +1,5 @@
{
"name": "天远数据",
"name": "天远助手",
"appid": "__UNI__CC3DA09",
"description": "",
"versionName": "1.0.0",

View File

@@ -130,7 +130,7 @@
"backgroundTextStyle": "@bgTxtStyle",
"navigationBarBackgroundColor": "#000000",
"navigationBarTextStyle": "@navTxtStyle",
"navigationBarTitleText": "天远数据",
"navigationBarTitleText": "天远助手",
"navigationStyle": "custom"
},
"tabBar": {

View File

@@ -4,7 +4,7 @@ import { getAgentRevenue } from '@/api/apis'
import GzhQrcode from '@/components/GzhQrcode.vue'
// 分享给好友、分享到朋友圈
useShare({ title: '天远数据 - 资产与收益' })
useShare({ title: '天远助手 - 资产与收益' })
// 日期选项映射
const dateRangeMap = {

View File

@@ -8,7 +8,7 @@
<view class="mb-4 bg-white rounded-lg overflow-hidden px-4 flex items-center justify-between">
<span class="text-blue-600 font-medium text-sm">📝 选择报告</span>
<wd-picker custom-class="flex-1" v-model="selectedReportText" :columns="reportOptions" title="选择报告类型"
<wd-picker custom-class="flex-1" v-model="selectedReportId" :columns="reportOptions" title="选择报告类型"
@confirm="onConfirm" />
</view>
@@ -109,23 +109,27 @@
<script setup>
import { ref, reactive, computed, onMounted, watch } from 'vue'
import { getAgentMembershipUserConfig, saveAgentMembershipUserConfig } from '@/apis/agent'
import { getAgentMembershipUserConfig, saveAgentMembershipUserConfig, getProductConfig } from '@/apis/agent'
// 报告类型选项
const reportOptions = [
{ label: '人事背调', value: 1 },
{ label: '老板企业报告', value: 2 },
// 报告类型选项 - 与 webview 保持一致,支持从后端动态加载
const reportOptions = ref([
{ label: '入职风险', value: 1 },
{ label: '小微企业', value: 2 },
{ label: '家政风险', value: 3 },
{ label: '婚恋风险', value: 4 },
{ label: '贷前背调', value: 5 },
{ label: '贷前风险', value: 5 },
{ label: '租赁风险', value: 6 },
{ label: '个人风险', value: 7 },
]
{ label: '个人大数据', value: 27 },
])
// 状态管理
const showPicker = ref(false)
const selectedReportId = ref(1)
const selectedReportText = ref('人事背调')
const selectedReportText = computed(() => {
const opt = reportOptions.value.find((o) => o.value === selectedReportId.value)
return opt ? opt.label : '请选择'
})
const configData = ref({})
const productConfigData = ref({})
@@ -138,225 +142,132 @@ const increaseError = ref(false)
// 金额输入格式验证:确保最多两位小数
const validateDecimal = (field) => {
console.log(`validateDecimal开始: field=${field}, 值=${configData.value[field]}`)
const value = configData.value[field]
if (value === null || value === undefined) {
console.log(`validateDecimal: ${field}为空,退出验证`)
return
}
if (value === null || value === undefined) return
const numValue = Number(value)
if (isNaN(numValue)) {
console.log(`validateDecimal: ${field}无法转换为数字设置为null`)
configData.value[field] = null
return
}
const fixedValue = parseFloat(numValue.toFixed(2))
console.log(`validateDecimal: ${field}原值=${numValue},处理后=${fixedValue}`)
configData.value[field] = fixedValue
if (field === 'price_increase_amount') {
console.log(`validateDecimal: 检查加价金额上限 ${fixedValue} vs ${priceIncreaseAmountMax.value}`)
if (fixedValue > priceIncreaseAmountMax.value) {
if (priceIncreaseAmountMax.value != null && fixedValue > priceIncreaseAmountMax.value) {
configData.value[field] = priceIncreaseAmountMax.value
console.log(`validateDecimal: 加价金额超过上限,已修正${priceIncreaseAmountMax.value}`)
uni.showToast({
title: `加价金额最大为${priceIncreaseAmountMax.value}`,
icon: 'none'
})
uni.showToast({ title: `加价金额最大${priceIncreaseAmountMax.value}`, icon: 'none' })
increaseError.value = true
setTimeout(() => {
increaseError.value = false
}, 2000)
setTimeout(() => { increaseError.value = false }, 2000)
} else {
increaseError.value = false
}
// 当加价金额改变后,重新验证价格区间
validateRange()
}
console.log(`validateDecimal结束: ${field}最终值=${configData.value[field]}`)
}
// 价格区间验证
const validateRange = () => {
console.log('validateRange开始:',
`最低=${configData.value.price_range_from}`,
`最高=${configData.value.price_range_to}`)
// if (configData.value.price_range_from === null || configData.value.price_range_to === null) {
// console.log('validateRange: 价格区间值为null退出验证')
// rangeError.value = false
// return
// }
if (isNaN(configData.value.price_range_from) || isNaN(configData.value.price_range_to)) {
console.log('validateRange: 价格区间值非数字,退出验证')
return
}
if (!productConfigData.value || priceIncreaseMax.value == null) return
if (isNaN(configData.value.price_range_from) || isNaN(configData.value.price_range_to)) return
const additional = configData.value.price_increase_amount || 0
console.log(`validateRange: 加价金额=${additional}`)
const minAllowed = parseFloat(
(Number(productConfigData.value.cost_price) + Number(additional)).toFixed(2)
) // 使用成本价作为最小值
const maxAllowed = productConfigData.value.price_range_max // 使用产品配置中的最大价格作为最大值
)
const maxAllowed = productConfigData.value.price_range_max
console.log(`validateRange: 最低允许=${minAllowed}, 最高允许=${maxAllowed}`)
// 检查最低金额
if (configData.value.price_range_from < minAllowed) {
console.log(`validateRange: 定价区间最低金额(${configData.value.price_range_from})小于允许最低值(${minAllowed}),进行修正`)
configData.value.price_range_from = minAllowed
uni.showToast({
title: `定价区间最低金额不能低于成本价 ${minAllowed}`,
icon: 'none'
})
uni.showToast({ title: `定价区间最低金额不能低于成本价 ${minAllowed}`, icon: 'none' })
rangeError.value = true
closeRangeError()
configData.value.price_range_to = parseFloat(
(Number(configData.value.price_range_from) + Number(priceIncreaseMax.value)).toFixed(2)
)
console.log(`validateRange: 已调整最高金额为 ${configData.value.price_range_to}`)
return
}
// 检查最高金额是否小于最低金额
if (configData.value.price_range_to < configData.value.price_range_from) {
console.log(`validateRange: 定价区间最高金额(${configData.value.price_range_to})小于最低金额(${configData.value.price_range_from}),进行修正`)
uni.showToast({
title: '定价区间最高金额不能低于定价区间最低金额',
icon: 'none'
})
if (configData.value.price_range_from + priceIncreaseMax.value > maxAllowed) {
configData.value.price_range_to = maxAllowed
console.log(`validateRange: 最高值已修正为最大允许值 ${maxAllowed}`)
} else {
configData.value.price_range_to = configData.value.price_range_from + priceIncreaseMax.value
console.log(`validateRange: 最高值已修正为最低金额+最大增加值 ${configData.value.price_range_to}`)
}
uni.showToast({ title: '定价区间最高金额不能低于定价区间最低金额', icon: 'none' })
configData.value.price_range_to = configData.value.price_range_from + priceIncreaseMax.value > maxAllowed
? maxAllowed
: configData.value.price_range_from + priceIncreaseMax.value
rangeError.value = true
closeRangeError()
return
}
// 检查差值
const diff = parseFloat(
(configData.value.price_range_to - configData.value.price_range_from).toFixed(2)
)
console.log(`validateRange: 价格区间差值=${diff}, 最大允许差值=${priceIncreaseMax.value}`)
if (diff > priceIncreaseMax.value) {
console.log(`validateRange: 价格区间差值超过最大允许值,进行修正`)
uni.showToast({
title: `价格区间最大差值为${priceIncreaseMax.value}`,
icon: 'none'
})
uni.showToast({ title: `价格区间最大差值为${priceIncreaseMax.value}`, icon: 'none' })
configData.value.price_range_to = parseFloat(
(Number(configData.value.price_range_from) + Number(priceIncreaseMax.value)).toFixed(2)
)
console.log(`validateRange: 已调整最高金额为 ${configData.value.price_range_to}`)
closeRangeError()
return
}
// 检查最高金额是否超过上限
if (configData.value.price_range_to > maxAllowed) {
console.log(`validateRange: 定价区间最高金额(${configData.value.price_range_to})超过上限(${maxAllowed}),进行修正`)
configData.value.price_range_to = maxAllowed
uni.showToast({
title: `定价区间最高金额不能超过 ${maxAllowed}`,
icon: 'none'
})
uni.showToast({ title: `定价区间最高金额不能超过 ${maxAllowed}`, icon: 'none' })
closeRangeError()
}
if (!rangeError.value) {
rangeError.value = false
}
console.log('validateRange结束:',
`最终最低=${configData.value.price_range_from}`,
`最终最高=${configData.value.price_range_to}`)
rangeError.value = false
}
// 收取比例验证(修改为保留两位小数,不再四舍五入取整
// 收取比例验证(保留两位小数)
const validateRatio = () => {
console.log(`validateRatio开始: 值=${configData.value.price_ratio}`)
let value = configData.value.price_ratio
if (value === null || value === undefined) {
console.log('validateRatio: 值为空,退出验证')
return
}
if (value === null || value === undefined) return
const numValue = Number(value)
if (isNaN(numValue)) {
console.log('validateRatio: 值无法转换为数字设置为null')
configData.value.price_ratio = null
ratioError.value = true
return
}
console.log(`validateRatio: 检查比例范围 ${numValue} vs 最大值${priceRatioMax.value}`)
if (numValue > priceRatioMax.value) {
console.log(`validateRatio: 比例超过最大值,已修正为${priceRatioMax.value}`)
if (priceRatioMax.value != null && numValue > priceRatioMax.value) {
configData.value.price_ratio = priceRatioMax.value
uni.showToast({
title: `收取比例最大为${priceRatioMax.value}%`,
icon: 'none'
})
uni.showToast({ title: `收取比例最大为${priceRatioMax.value}%`, icon: 'none' })
ratioError.value = true
setTimeout(() => {
ratioError.value = false
}, 1000)
setTimeout(() => { ratioError.value = false }, 1000)
} else if (numValue < 0) {
console.log('validateRatio: 比例小于0已修正为0')
configData.value.price_ratio = 0
ratioError.value = true
} else {
configData.value.price_ratio = parseFloat(numValue.toFixed(2))
ratioError.value = false
}
console.log(`validateRatio结束: 最终值=${configData.value.price_ratio}`)
}
// 获取配置
const getConfig = async () => {
try {
console.log(`getConfig开始: 获取产品ID=${selectedReportId.value}的配置`)
const res = await getAgentMembershipUserConfig({ product_id: selectedReportId.value })
if (res.code === 200) {
const respConfigData = res.data.agent_membership_user_config
console.log("respConfigData", respConfigData)
configData.value = {
id: respConfigData.product_id,
price_range_from: respConfigData.price_range_from || null,
price_range_to: respConfigData.price_range_to || null,
price_ratio: respConfigData.price_ratio * 100 || null, // 转换为百分比
price_ratio: respConfigData.price_ratio != null ? respConfigData.price_ratio * 100 : null,
price_increase_amount: respConfigData.price_increase_amount || null,
}
productConfigData.value = res.data.product_config
// 设置动态限制值
priceIncreaseMax.value = res.data.price_increase_max
priceIncreaseAmountMax.value = res.data.price_increase_amount
priceRatioMax.value = res.data.price_ratio * 100
console.log('getConfig: 配置加载成功',
`最大差值=${priceIncreaseMax.value}`,
`最大加价=${priceIncreaseAmountMax.value}`,
`最大比例=${priceRatioMax.value}%`)
console.log('getConfig: 当前配置', configData.value)
priceRatioMax.value = res.data.price_ratio != null ? res.data.price_ratio * 100 : null
}
} catch (error) {
console.error("getConfig错误:", error)
uni.showToast({
title: '配置加载失败',
icon: 'none'
})
console.error('getConfig错误:', error)
uni.showToast({ title: '配置加载失败', icon: 'none' })
}
}
@@ -377,92 +288,61 @@ const handleSubmit = async () => {
const res = await saveAgentMembershipUserConfig(submitData)
if (res.code === 200) {
uni.showToast({
title: '保存成功',
icon: 'success'
})
uni.showToast({ title: '保存成功', icon: 'success' })
getConfig()
} else {
uni.showToast({ title: res.msg || '保存失败', icon: 'none' })
}
} catch (error) {
console.log("handleSubmit错误:", error)
uni.showToast({
title: '保存失败,请稍后重试',
icon: 'none'
})
uni.showToast({ title: error?.data?.msg || '保存失败,请稍后重试', icon: 'none' })
}
}
// 最终验证函数
const finalValidation = () => {
// 校验最低金额不能为空且大于0
if (!configData.value.price_range_from || configData.value.price_range_from <= 0) {
uni.showToast({
title: "定价区间最低金额不能为空",
icon: 'none'
})
uni.showToast({ title: '定价区间最低金额不能为空', icon: 'none' })
return false
}
// 校验最高金额不能为空且大于0
if (!configData.value.price_range_to || configData.value.price_range_to <= 0) {
uni.showToast({
title: "定价区间最高金额不能为空",
icon: 'none'
})
uni.showToast({ title: '定价区间最高金额不能为空', icon: 'none' })
return false
}
// 校验收取比例不能为空且大于0
if (!configData.value.price_ratio || configData.value.price_ratio <= 0) {
uni.showToast({
title: "收取比例不能为空",
icon: 'none'
})
uni.showToast({ title: '收取比例不能为空', icon: 'none' })
return false
}
// 验证最低金额必须小于最高金额
if (configData.value.price_range_from >= configData.value.price_range_to) {
uni.showToast({
title: "定价区间最低金额必须小于定价区间最高金额",
icon: 'none'
})
uni.showToast({ title: '定价区间最低金额必须小于定价区间最高金额', icon: 'none' })
return false
}
// 验证价格区间差值不能超过最大允许差值
const finalDiff = parseFloat(
(configData.value.price_range_to - configData.value.price_range_from).toFixed(2)
)
if (finalDiff > priceIncreaseMax.value) {
uni.showToast({
title: `价格区间最大差值为${priceIncreaseMax.value}`,
icon: 'none'
})
if (priceIncreaseMax.value != null && finalDiff > priceIncreaseMax.value) {
uni.showToast({ title: `价格区间最大差值为${priceIncreaseMax.value}`, icon: 'none' })
return false
}
// 验证最高金额不能超过产品配置中设定的上限
if (configData.value.price_range_to > productConfigData.value.price_range_max) {
uni.showToast({
title: `定价区间最高金额不能超过${productConfigData.value.price_range_max}`,
icon: 'none'
})
if (productConfigData.value?.price_range_max != null && configData.value.price_range_to > productConfigData.value.price_range_max) {
uni.showToast({ title: `定价区间最高金额不能超过${productConfigData.value.price_range_max}`, icon: 'none' })
return false
}
// 验证最低金额不能低于成本价+加价金额(加价金额允许为空)
const additional = configData.value.price_increase_amount || 0
if (configData.value.price_range_from < productConfigData.value.cost_price + additional) {
uni.showToast({
title: `定价区间最低金额不能低于成本价${productConfigData.value.cost_price + additional}`,
icon: 'none'
})
const minAllowed = (productConfigData.value?.cost_price ?? 0) + additional
if (configData.value.price_range_from < minAllowed) {
uni.showToast({ title: `定价区间最低金额不能低于成本价${minAllowed}`, icon: 'none' })
return false
}
return true
}
// 选择器确认
// 选择器确认 - wd-picker 单列时 selectedItems 为选中项对象
const onConfirm = (e) => {
const { selectedItems } = e
selectedReportId.value = selectedItems.value
selectedReportText.value = selectedItems.label
showPicker.value = false
const { value, selectedItems } = e
const item = Array.isArray(selectedItems) ? selectedItems[0] : selectedItems
if (item) {
selectedReportId.value = item.value ?? value
}
// 重置错误状态
rangeError.value = false
@@ -478,7 +358,38 @@ const closeRangeError = () => {
}, 2000)
}
onMounted(() => {
// 从后端加载可选报告列表(可选,若失败则使用默认列表)
const loadReportOptions = async () => {
try {
const res = await getProductConfig()
if (res.code !== 200 || !res.data) return
const list = res.data.agent_product_config || res.data.AgentProductConfig || []
if (list.length) {
const productNameMap = {
1: '入职风险',
2: '小微企业',
3: '家政风险',
4: '婚恋风险',
5: '贷前风险',
6: '租赁风险',
7: '个人风险',
27: '个人大数据',
}
reportOptions.value = list.map((p) => ({
label: productNameMap[p.product_id] || `报告${p.product_id}`,
value: p.product_id,
}))
if (!reportOptions.value.find((o) => o.value === selectedReportId.value)) {
selectedReportId.value = reportOptions.value[0].value
}
}
} catch (err) {
console.warn('加载报告列表失败,使用默认列表')
}
}
onMounted(async () => {
await loadReportOptions()
getConfig()
})
</script>

View File

@@ -6,7 +6,7 @@ import iconCard1 from '/static/image/icon_2.png'
import iconCard2 from '/static/image/icon_1.png'
// 分享给好友、分享到朋友圈
useShare({ title: '天远数据 - 大数据报告查询,即刻赚佣金' })
useShare({ title: '天远助手 - 大数据报告查询,即刻赚佣金' })
// 从缓存中获取代理状态
const isAgent = ref(false)
@@ -102,8 +102,8 @@ function getPhoneNumber(e) {
<view class="text-gray-800 text-sm">邀请下级页面引导</view>
<view class="text-xs bg-blue-100 text-blue-600 px-2 py-0.5 rounded">引导指南</view>
</view>
<view class="flex items-center py-3 px-2 justify-between" @click="toHelpDetail('如何成为天远数据代理')">
<view class="text-gray-800 text-sm">如何成为天远数据代理</view>
<view class="flex items-center py-3 px-2 justify-between" @click="toHelpDetail('如何成为天远助手代理')">
<view class="text-gray-800 text-sm">如何成为天远助手代理</view>
</view>
</view>
</view> -->
@@ -126,7 +126,7 @@ function getPhoneNumber(e) {
show-menu-by-longpress
/>
<view class="text-gray-600 text-sm text-center mb-2">长按识别保存或者扫码</view>
<view class="text-gray-400 text-xs">关注天远数据公众号</view>
<view class="text-gray-400 text-xs">关注天远助手公众号</view>
<view
class="mt-4 text-blue-500 text-sm"
@click="toggleQrcodePopup"

View File

@@ -147,7 +147,7 @@ onUnmounted(() => {
<view class="mb-8 pt-8 text-left">
<view class="flex flex-col items-center">
<image class="h-18 w-18 rounded-full shadow" src="/static/image/logo.png" mode="scaleToFill" />
<view class="mt-4 text-3xl font-bold text-gray-800">天远数据</view>
<view class="mt-4 text-3xl font-bold text-gray-800">天远助手</view>
</view>
</view>
<view class="space-y-5">

View File

@@ -33,6 +33,7 @@
</view>
</view>
</view>
<VipBanner v-if="isLoggedIn && !isVipOrSvip" />
<!-- 功能菜单 -->
<view class="features-section space-y-3">
@@ -53,12 +54,6 @@
</button>
</template>
<!-- 升级/开通代理会员登录后显示非代理申请普通代理升级 -->
<button
v-if="isLoggedIn && !isVipOrSvip"
class="flex items-center p-3 rounded-xl bg-gradient-to-r from-amber-200/80 to-orange-200/80 text-amber-700 font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 scale-98" @click="toAgentUpgrade">
<text class="mr-2"></text> {{ isAgent ? '升级代理会员' : '开通代理会员' }}
</button>
<button
class=" flex items-center text-gray-600 p-3 rounded-xl bg-white font-medium shadow-sm transition-all active:shadow-md"
hover-class="opacity-80 bg-blue-50" @click="toUserAgreement">
@@ -95,7 +90,7 @@ import { ref, computed, onBeforeMount } from 'vue'
import { maskName, formatExpiryTime } from '@/utils/format'
// 分享给好友、分享到朋友圈
useShare({ title: '天远数据 - 大数据报告查询' })
useShare({ title: '天远助手 - 大数据报告查询' })
// 用户数据
const userName = ref('')
@@ -220,14 +215,6 @@ function toVipRenewal() {
uni.navigateTo({ url: '/pages/agentVipApply' })
}
function toAgentUpgrade() {
if (isAgent.value) {
uni.navigateTo({ url: '/pages/agentVipApply' })
} else {
uni.navigateTo({ url: '/pages/invitationAgentApply' })
}
}
function toBindPhone() {
uni.navigateTo({
url: '/pages/login'