Commit d836b97a by Sweet Zhang

对接产品佣金

parent a7784bac
...@@ -439,6 +439,9 @@ export default { ...@@ -439,6 +439,9 @@ export default {
// 数据字典查询 // 数据字典查询
metaQuery(params){ metaQuery(params){
return request(`${apiURL}/metadata/dropOptionsQuery`,'POST',params) return request(`${apiURL}/metadata/dropOptionsQuery`,'POST',params)
},
// 持牌人佣金查询
queryRate(params){
return request(`${apiURL}/insurance_product/query/rate?planBizId=${params.planBizId}&userId=${params.userId}`, "GET")
} }
} }
...@@ -49,7 +49,7 @@ const config = { ...@@ -49,7 +49,7 @@ const config = {
stage, stage,
prod prod
} }
let env = 'prod'; let env = 'dev';
let baseURL = config[env].base_url; let baseURL = config[env].base_url;
let apiURL = config[env].api_url; let apiURL = config[env].api_url;
......
<template>
<view class="container">
<!-- 水印容器 -->
<view class="watermark-container">
<view class="watermark" v-for="i in 24" :key="i">
<text class="watermark-text">{{ userId }}</text>
</view>
</view>
<!-- 费率详情 -->
<!-- 费率详情 -->
<view class="info-card" v-if="rateData && rateData.length > 0">
<view class="info-title">费率详情</view>
<view class="contract-detail">
<!-- 表格 -->
<view class="detail-table">
<!-- 保险公司 -->
<view class="table-row">
<view class="table-cell first-column">
<text class="cell-text">保险公司</text>
</view>
<view class="table-cell" v-for="(plan, index) in rateData" :key="index">
<text class="cell-text">{{ plan.companyName }}</text>
</view>
</view>
<!-- 产品名称 -->
<view class="table-row">
<view class="table-cell first-column">
<text class="cell-text">产品名称</text>
</view>
<view class="table-cell" v-for="(plan, index) in rateData" :key="index">
<text class="cell-text">{{ plan.planName }}</text>
</view>
</view>
<!-- 条件 -->
<view class="table-row">
<view class="table-cell first-column">
<text class="cell-text">条件</text>
</view>
<view class="table-cell" v-for="(plan, index) in rateData" :key="index">
<text class="cell-text">供款年期 = {{ plan.term }} </text>
</view>
</view>
<!-- 各年保费 -->
<view class="table-row" v-for="year in maxYears" :key="year">
<view class="table-cell first-column">
<text class="cell-text">保费(第{{ year }}年)</text>
</view>
<view class="table-cell" v-for="(plan, index) in rateData" :key="index">
<text class="cell-text commission-value">
{{ getCommissionRate(plan, year) }}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 加载状态 -->
<view class="loading" v-if="loading">
<text>加载中...</text>
</view>
<!-- 错误状态 -->
<view class="error" v-if="error">
<text>{{ error }}</text>
</view>
</view>
</template>
<script setup>
import { ref, onMounted,computed } from 'vue'
import { useRouter, useRoute } from 'vue-router';
import api from '@/api/api';
// 计算最大年份数
const maxYears = ref(7)
// 获取指定年份的佣金率
const getCommissionRate = (plan, year) => {
const rate = plan.termRateResponseList.find(item => item.issueNumber === year)
return rate ? `${rate.calculateRate}%` : '0%'
}
// 路由实例
const router = useRouter();
const route = useRoute();
// 响应式数据
const rateData = ref([])
const userId = ref('')
const loading = ref(false)
const error = ref(null)
// 获取页面参数
const planBizId = ref(route.query.planBizId || '')
const planName = ref(decodeURIComponent(route.query.planName || ''))
// 获取费率数据
const fetchRateData = async () => {
if (!planBizId.value) return
loading.value = true
error.value = null
try {
const params = {
planBizId:planBizId.value,
userId:localStorage.getItem('cffp_userId')
}
const response = await api.queryRate(params)
// 模拟API延迟
await new Promise(resolve => setTimeout(resolve, 800))
if (response.success) {
rateData.value = response.data
}
} catch (err) {
error.value = '获取费率数据失败'
console.error('API调用失败:', err)
} finally {
loading.value = false
}
}
// 生命周期
onMounted(() => {
userId.value = localStorage.getItem('cffp_userId') || ''
fetchRateData()
})
</script>
<style scoped>
.container {
padding: 20px;
background-color: #f5f7fa;
min-height: 100vh;
position: relative;
}
.watermark-text {
font-size: 24px;
color: #007AFF;
font-weight: bold;
white-space: nowrap;
}
/* 水印样式 - 铺满屏幕版本 */
.watermark-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 99;
overflow: hidden;
}
.watermark {
position: absolute;
opacity: 0.06;
transform: rotate(-30deg);
font-size: 16px;
color: #666;
font-weight: 500;
white-space: nowrap;
}
/* 4列6行的规律网格布局,铺满整个屏幕 */
.watermark:nth-child(1) { top: 8%; left: 5%; }
.watermark:nth-child(2) { top: 8%; left: 30%; }
.watermark:nth-child(3) { top: 8%; left: 55%; }
.watermark:nth-child(4) { top: 8%; left: 80%; }
.watermark:nth-child(5) { top: 25%; left: 2%; }
.watermark:nth-child(6) { top: 25%; left: 27%; }
.watermark:nth-child(7) { top: 25%; left: 52%; }
.watermark:nth-child(8) { top: 25%; left: 77%; }
.watermark:nth-child(9) { top: 42%; left: 8%; }
.watermark:nth-child(10) { top: 42%; left: 33%; }
.watermark:nth-child(11) { top: 42%; left: 58%; }
.watermark:nth-child(12) { top: 42%; left: 83%; }
.watermark:nth-child(13) { top: 59%; left: 2%; }
.watermark:nth-child(14) { top: 59%; left: 27%; }
.watermark:nth-child(15) { top: 59%; left: 52%; }
.watermark:nth-child(16) { top: 59%; left: 77%; }
.watermark:nth-child(17) { top: 76%; left: 8%; }
.watermark:nth-child(18) { top: 76%; left: 33%; }
.watermark:nth-child(19) { top: 76%; left: 58%; }
.watermark:nth-child(20) { top: 76%; left: 83%; }
.watermark:nth-child(21) { top: 93%; left: 2%; }
.watermark:nth-child(22) { top: 93%; left: 27%; }
.watermark:nth-child(23) { top: 93%; left: 52%; }
.watermark:nth-child(24) { top: 93%; left: 77%; }
.loading, .error {
text-align: center;
padding: 20px;
color: #666;
position: relative;
z-index: 10;
}
.error {
color: #FF6B6B;
}
.contract-detail {
border: 1px solid #dcdfe6;
border-radius: 4px;
overflow: hidden;
margin-top: 10px;
}
.contract-title {
background: #f5f7fa;
padding: 12px 15px;
border-bottom: 1px solid #dcdfe6;
}
.contract-name {
font-size: 14px;
font-weight: 600;
color: #303133;
}
.detail-table {
background: white;
overflow-x: auto;
}
.table-row {
display: flex;
min-width: 600px;
border-bottom: 1px solid #ebeef5;
}
.table-row:last-child {
border-bottom: none;
}
.table-row.header-row {
background: #fafafa;
font-weight: 600;
}
.table-cell {
flex: 1;
padding: 12px 15px;
min-height: 44px;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
border-right: 1px solid #ebeef5;
}
.table-cell:last-child {
border-right: none;
}
.table-cell.first-column {
background: #fafafa;
width: 60px;
flex: none;
justify-content: flex-start;
}
.cell-text {
font-size: 14px;
color: #606266;
line-height: 1.4;
}
.header-row .cell-text {
color: #303133;
font-weight: 600;
}
.commission-value {
color: #007AFF;
font-weight: 600;
}
/* 其他样式保持不变 */
.info-card {
background-color: white;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
position: relative;
z-index: 10;
}
.info-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
color: #333;
}
</style>
\ No newline at end of file
<template>
<view class="container">
<!-- 头部 -->
<view class="header">
<view class="title">产品查询</view>
</view>
<!-- 搜索区域 -->
<view class="search-box">
<input
class="search-input"
type="text"
placeholder="请输入产品名称"
v-model="searchKeyword"
@input="handleSearch"
/>
<view class="search-icon">🔍</view>
</view>
<!-- 产品列表 -->
<view class="product-list" v-if="!loading && filteredProducts.length > 0">
<view
class="product-item"
v-for="product in filteredProducts"
:key="product.planBizId"
@click="goToCommissionDetail(product)"
>
<view class="product-header">
<view class="product-name">{{ product.planName }}</view>
<view class="product-term">{{ product.term }}</view>
</view>
<view class="product-info">
<view class="info-item">
<text class="info-label">保险公司:</text>
<text class="info-value">{{ product.companyName }}</text>
</view>
<view class="info-item">
<text class="info-label">险种类别:</text>
<text class="info-value">{{ getCategoryName(product.category) }}</text>
</view>
<view class="info-item">
<text class="info-label">适用年龄:</text>
<text class="info-value">{{ product.minAge }} - {{ product.maxAge }}</text>
</view>
</view>
<view class="arrow"></view>
</view>
</view>
<!-- 加载状态 -->
<view class="loading" v-if="loading">
<text>加载中...</text>
</view>
<!-- 空状态 -->
<view class="empty" v-if="!loading && filteredProducts.length === 0">
<text>暂无产品数据</text>
</view>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
// 响应式数据
const searchKeyword = ref('')
const products = ref([])
const loading = ref(false)
// 模拟产品数据 - 实际应从API获取
const mockProducts = [
{
"planBizId": "1387023335996522496",
"planName": "環宇盈活儲蓄保險計劃",
"category": "SAV",
"companyName": "友邦保險(國際)有限公司",
"term": 3,
"minAge": 0,
"maxAge": 60
},
{
"planBizId": "1387023335996522496",
"planName": "環宇盈活儲蓄保險計劃",
"category": "SAV",
"companyName": "友邦保險(國際)有限公司",
"term": 5,
"minAge": 0,
"maxAge": 65
},
{
"planBizId": "1387023335996522497",
"planName": "卓越醫療保障計劃",
"category": "MED",
"companyName": "保誠保險有限公司",
"term": 10,
"minAge": 18,
"maxAge": 55
},
{
"planBizId": "1387023335996522498",
"planName": "豐盛退休年金",
"category": "RET",
"companyName": "宏利人壽保險公司",
"term": 20,
"minAge": 30,
"maxAge": 50
}
]
// 计算属性 - 筛选后的产品列表
const filteredProducts = computed(() => {
if (!searchKeyword.value) {
return products.value
}
return products.value.filter(product =>
product.planName.toLowerCase().includes(searchKeyword.value.toLowerCase()) ||
product.companyName.toLowerCase().includes(searchKeyword.value.toLowerCase())
)
})
// 方法
const handleSearch = () => {
// 实际项目中可以添加防抖
}
const goToCommissionDetail = (product) => {
uni.navigateTo({
url: `/myPackageA/product-list/commission-detail?planBizId=${product.planBizId}`
})
}
const getCategoryName = (category) => {
const categoryMap = {
'SAV': '储蓄保险',
'MED': '医疗保险',
'RET': '退休年金',
'LIF': '人寿保险'
}
return categoryMap[category] || category
}
// 获取产品数据
const fetchProducts = async () => {
loading.value = true
try {
// 实际API调用
// const response = await uni.request({
// url: '/insurance_product/list',
// method: 'GET'
// })
// 模拟API延迟
await new Promise(resolve => setTimeout(resolve, 1000))
products.value = mockProducts
} catch (err) {
console.error('获取产品列表失败:', err)
// 使用模拟数据
products.value = mockProducts
} finally {
loading.value = false
}
}
// 生命周期
onMounted(() => {
fetchProducts()
})
</script>
<style scoped>
.container {
padding: 20px;
background-color: #f5f7fa;
min-height: 100vh;
}
.header {
text-align: center;
margin-bottom: 20px;
}
.title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.search-box {
position: relative;
background-color: white;
border-radius: 8px;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.search-input {
width: 100%;
padding: 12px 40px 12px 15px;
border: 1px solid #e0e0e0;
border-radius: 8px;
font-size: 14px;
}
.search-icon {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
color: #999;
}
.product-list {
margin-bottom: 15px;
}
.product-item {
background-color: white;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
position: relative;
}
.product-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
}
.product-name {
font-size: 16px;
font-weight: bold;
color: #333;
flex: 1;
}
.product-term {
font-size: 14px;
color: #007AFF;
background-color: #f0f7ff;
padding: 2px 8px;
border-radius: 4px;
}
.product-info {
margin-bottom: 5px;
}
.info-item {
margin-bottom: 5px;
}
.info-label {
color: #666;
font-size: 12px;
}
.info-value {
color: #333;
font-size: 12px;
font-weight: 500;
}
.arrow {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
color: #999;
font-size: 18px;
}
.loading, .empty {
text-align: center;
padding: 40px 20px;
color: #666;
}
</style>
\ No newline at end of file
<template> <template>
<scroll-view @scroll="handleScroll" scroll-y="true" class="scroll-Y"> <scroll-view @scroll="handleScroll" scroll-y="true" class="scroll-Y">
<view class="product-list-page"> <view class="product-list-page">
<!-- 顶部搜索和筛选 --> <!-- 顶部搜索和筛选 -->
<view class="search-bar"> <view class="search-bar">
......
...@@ -585,6 +585,17 @@ ...@@ -585,6 +585,17 @@
"style": { "style": {
"navigationBarTitleText": "产品对比" "navigationBarTitleText": "产品对比"
} }
},{
"path": "product-list/product-commission",
"style": {
"navigationBarTitleText": "持牌人佣金"
}
},
{
"path": "product-list/commission-detail",
"style": {
"navigationBarTitleText": "佣金详情"
}
} }
] ]
......
...@@ -224,6 +224,7 @@ ...@@ -224,6 +224,7 @@
{key:'policies',title:'制度',icon:'icon-xiaoshoue',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:4}, {key:'policies',title:'制度',icon:'icon-xiaoshoue',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:4},
{key:'products',title:'产品分析',icon:'icon-shujufenxi',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:3}, {key:'products',title:'产品分析',icon:'icon-shujufenxi',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:3},
{key:'cases',title:'案例分享',icon:'icon-shiyongjiaocheng',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:2}, {key:'cases',title:'案例分享',icon:'icon-shiyongjiaocheng',link:'/pages/personalCenter/detail',isOpen:true,isShow:false,identity: true,type:2},
{key:'commission',title:'持牌人佣金',icon:'icon-shiyongjiaocheng',link:'/myPackageA/product-list/product-commission',isOpen:true,isShow:false,identity: true},
], ],
},{id:'04',categoryName:'海外资产配置', },{id:'04',categoryName:'海外资产配置',
children:[ children:[
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment