Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
CFFP-HB
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chao Sun
CFFP-HB
Commits
969f8366
Commit
969f8366
authored
Oct 30, 2025
by
Sweet Zhang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'sw0826' into sw1029
parents
6d93ee70
eb02ed96
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
667 additions
and
3 deletions
+667
-3
api/api.ts
+4
-1
myPackageA/product-list/commission-detail.vue
+420
-0
myPackageA/product-list/product-commission.vue
+229
-0
myPackageA/product-list/product-list.vue
+1
-1
pages.json
+12
-1
pages/personalCenter/personalCenter.vue
+1
-0
No files found.
api/api.ts
View file @
969f8366
...
...
@@ -439,6 +439,9 @@ export default {
// 数据字典查询
metaQuery
(
params
){
return
request
(
`
${
apiURL
}
/metadata/dropOptionsQuery`
,
'POST'
,
params
)
},
// 持牌人佣金查询
queryRate
(
params
){
return
request
(
`
${
apiURL
}
/insurance_product/query/rate?planBizId=
${
params
.
planBizId
}
&userId=
${
params
.
userId
}
`
,
"GET"
)
}
}
myPackageA/product-list/commission-detail.vue
0 → 100644
View file @
969f8366
<
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=
"contract-title"
>
<text
class=
"contract-name"
>
合约名称:2025年第三季度佣金表
</text>
</view>
<!-- 表格容器 -->
<view
class=
"table-container"
>
<!-- 固定左侧列 -->
<view
class=
"fixed-column"
>
<!-- 表头 -->
<view
class=
"table-row header-row"
>
<view
class=
"table-cell first-column"
>
<text
class=
"cell-text"
>
险种
</text>
</view>
</view>
<!-- 保险公司 -->
<view
class=
"table-row"
>
<view
class=
"table-cell first-column"
>
<text
class=
"cell-text"
>
保险公司
</text>
</view>
</view>
<!-- 产品名称 -->
<view
class=
"table-row"
>
<view
class=
"table-cell first-column"
>
<text
class=
"cell-text"
>
产品名称
</text>
</view>
</view>
<!-- 条件 -->
<view
class=
"table-row"
>
<view
class=
"table-cell first-column"
>
<text
class=
"cell-text"
>
条件
</text>
</view>
</view>
<!-- 各年介绍费 -->
<view
class=
"table-row"
v-for=
"year in maxYears"
:key=
"year"
>
<view
class=
"table-cell first-column"
>
<text
class=
"cell-text"
>
介绍费
</text>
<text
class=
"cell-text"
>
(第
{{
year
}}
年)
</text>
</view>
</view>
</view>
<!-- 可滚动右侧内容 -->
<scroll-view
class=
"scroll-content"
scroll-x=
"true"
>
<view
class=
"scroll-inner"
>
<!-- 表头 -->
<view
class=
"table-row header-row"
>
<view
class=
"table-cell"
v-for=
"(plan, index) in rateData"
:key=
"index"
>
<text
class=
"cell-text"
>
{{
plan
.
categoryName
}}
</text>
</view>
</view>
<!-- 保险公司 -->
<view
class=
"table-row"
>
<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"
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 conditionContainer"
v-for=
"(plan, index) in rateData"
:key=
"index"
>
<view><text
class=
"cell-text"
>
供款年期:
</text><text
class=
"cell-text"
>
{{
plan
.
term
}}
年
</text></view>
<view
v-if=
"plan.ageRange"
><text
class=
"cell-text"
>
年龄:
</text><text
class=
"cell-text"
>
{{
plan
.
ageRange
}}
</text></view>
<view
v-if=
"plan.premiumRange"
><text
class=
"cell-text"
>
保费:
</text><text
class=
"cell-text"
>
{{
plan
.
premiumRange
}}
</text></view>
</view>
</view>
<!-- 各年保费 -->
<view
class=
"table-row"
v-for=
"year in maxYears"
:key=
"year"
>
<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>
</scroll-view>
</view>
</view>
</view>
<!-- 加载状态 -->
<view
class=
"loading"
v-if=
"loading"
>
<text>
加载中...
</text>
</view>
<!-- 错误状态 -->
<view
class=
"error"
v-if=
"error"
>
<text>
{{
error
}}
</text>
</view>
<!-- 无数据 -->
<view
class=
"error"
v-if=
"rateData && rateData.length==0 && !loading"
>
<text>
暂无数据
</text>
</view>
</view>
</
template
>
<
script
setup
>
import
{
ref
,
onMounted
,
computed
}
from
'vue'
import
{
useRouter
,
useRoute
}
from
'vue-router'
;
import
api
from
'@/api/api'
;
// 默认最大年份是5
const
maxYears
=
ref
(
5
)
// 获取指定年份的佣金率
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
)
if
(
response
.
success
)
{
rateData
.
value
=
response
.
data
if
(
rateData
.
value
&&
rateData
.
value
.
length
>
0
){
rateData
.
value
.
forEach
(
item
=>
{
if
(
item
.
termRateResponseList
)
{
item
.
termRateResponseList
.
forEach
(
term
=>
{
if
((
term
.
issueNumber
>
maxYears
.
value
)
&&
term
.
calculateRate
>
0
)
{
maxYears
.
value
=
term
.
issueNumber
;
}
});
}
});
}
console
.
log
(
'maxYears:'
,
maxYears
);
}
}
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
:
10
rpx
;
background-color
:
#f5f7fa
;
min-height
:
100vh
;
position
:
relative
;
}
.watermark-text
{
font-size
:
48
rpx
;
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
:
32
rpx
;
color
:
#333
;
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
:
40
rpx
;
color
:
#333
;
position
:
relative
;
z-index
:
10
;
}
.error
{
color
:
#FF6B6B
;
}
.contract-detail
{
border
:
1px
solid
#dcdfe6
;
border-radius
:
4px
;
overflow
:
hidden
;
margin-top
:
20
rpx
;
}
.contract-title
{
background
:
#f5f7fa
;
padding
:
24
rpx
30
rpx
;
border-bottom
:
1px
solid
#dcdfe6
;
}
.contract-name
{
font-size
:
28
rpx
;
font-weight
:
600
;
color
:
#333
;
}
/* 表格容器 */
.table-container
{
display
:
flex
;
background
:
white
;
position
:
relative
;
}
/* 固定左侧列 */
.fixed-column
{
width
:
160
rpx
;
flex-shrink
:
0
;
z-index
:
10
;
box-shadow
:
2px
0
4px
rgba
(
0
,
0
,
0
,
0.1
);
white-space
:
nowrap
;
}
/* 固定列样式 */
.fixed-column
.table-cell
{
width
:
160
rpx
;
background
:
#fafafa
;
display
:
flex
;
flex-direction
:
column
;
justify-content
:
center
;
align-items
:
center
;
}
/* 可滚动右侧内容 */
.scroll-content
{
flex
:
1
;
overflow-x
:
auto
;
}
.scroll-inner
{
min-width
:
max-content
;
}
/* 表格行通用样式 */
.table-row
{
display
:
flex
;
min-height
:
88
rpx
;
border-bottom
:
1px
solid
#ebeef5
;
}
.table-row
:last-child
{
border-bottom
:
none
;
}
.table-row.header-row
{
background
:
#fafafa
;
font-weight
:
600
;
}
/* 表格单元格通用样式 */
.table-cell
{
min-height
:
88
rpx
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
text-align
:
center
;
border-right
:
1px
solid
#ebeef5
;
padding
:
24
rpx
16
rpx
;
}
.table-cell
:last-child
{
border-right
:
none
;
}
/* 滚动列样式 */
.scroll-inner
.table-cell
{
min-width
:
240
rpx
;
flex
:
1
;
}
.cell-text
{
font-size
:
26
rpx
;
color
:
#333
;
line-height
:
1.4
;
}
.header-row
.cell-text
{
color
:
#333
;
font-weight
:
600
;
}
.commission-value
{
color
:
#007AFF
;
font-weight
:
600
;
}
/* 其他样式保持不变 */
.info-card
{
background-color
:
white
;
border-radius
:
16
rpx
;
padding
:
20
rpx
;
margin-bottom
:
30
rpx
;
box-shadow
:
0
4
rpx
48
rpx
rgba
(
0
,
0
,
0
,
0.05
);
position
:
relative
;
z-index
:
10
;
}
.info-title
{
font-size
:
32
rpx
;
font-weight
:
bold
;
margin-bottom
:
20
rpx
;
color
:
#333
;
}
.conditionContainer
{
display
:
flex
;
flex-direction
:
column
;
}
.conditionContainer
view
{
width
:
100%
;
margin
:
0
auto
;
}
</
style
>
\ No newline at end of file
myPackageA/product-list/product-commission.vue
0 → 100644
View file @
969f8366
<
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"
/>
<view
class=
"search-icon"
@
click=
"fetchProducts(1)"
>
🔍
</view>
</view>
<!-- 产品列表 -->
<view
class=
"product-list"
v-if=
"!loading && products.length > 0"
>
<view
class=
"product-item"
v-for=
"product in products"
: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"
>
{{
product
.
categoryName
}}
</text>
</view>
</view>
<view
class=
"arrow"
>
›
</view>
</view>
</view>
<!-- 加载状态 -->
<view
class=
"loading"
v-if=
"loading"
>
<text>
加载中...
</text>
</view>
<!-- 空状态 -->
<view
class=
"empty"
v-if=
"!loading && products.length === 0"
>
<text>
暂无产品数据
</text>
</view>
</view>
</
template
>
<
script
setup
>
import
{
ref
,
computed
,
onMounted
}
from
'vue'
import
api
from
'@/api/api'
;
// 响应式数据
const
searchKeyword
=
ref
(
''
)
const
products
=
ref
([])
const
loading
=
ref
(
false
)
// 方法
const
handleSearch
=
()
=>
{
// 实际项目中可以添加防抖
}
const
goToCommissionDetail
=
(
product
)
=>
{
uni
.
navigateTo
({
url
:
`/myPackageA/product-list/commission-detail?planBizId=
${
product
.
planBizId
}
`
})
}
// 获取产品数据
const
fetchProducts
=
async
(
type
=
0
)
=>
{
loading
.
value
=
true
try
{
let
params
=
{
name
:
searchKeyword
.
value
}
// 搜索时,默认只查询10条
if
(
type
===
1
){
params
=
{
name
:
searchKeyword
.
value
,
paginationInfo
:{
noLimitFlag
:
''
,
number
:
1
,
size
:
10
}
}
}
// 实际API调用
const
response
=
await
api
.
productSearch
(
params
)
if
(
response
.
success
){
products
.
value
=
response
.
data
.
list
||
[];
}
}
catch
(
err
)
{
console
.
error
(
'获取产品列表失败:'
,
err
)
// 使用模拟数据
products
.
value
=
[]
}
finally
{
loading
.
value
=
false
}
}
// 生命周期
onMounted
(()
=>
{
fetchProducts
()
})
</
script
>
<
style
scoped
>
.container
{
padding
:
20
rpx
;
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
:
24
rpx
80
rpx
24
rpx
30
rpx
;
font-size
:
28
rpx
;
}
.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
:
28
rpx
;
color
:
#007AFF
;
background-color
:
#f0f7ff
;
padding
:
4
rpx
16
rpx
;
border-radius
:
8
rpx
;
}
.product-info
{
margin-bottom
:
10
rpx
;
}
.info-item
{
margin-bottom
:
10
rpx
;
}
.info-label
{
color
:
#666
;
font-size
:
28
rpx
;
}
.info-value
{
color
:
#333
;
font-size
:
28
rpx
;
font-weight
:
500
;
}
.arrow
{
position
:
absolute
;
right
:
30
rpx
;
top
:
50%
;
transform
:
translateY
(
-50%
);
color
:
#999
;
font-size
:
36
rpx
;
}
.loading
,
.empty
{
text-align
:
center
;
padding
:
80
rpx
40
rpx
;
color
:
#666
;
}
</
style
>
\ No newline at end of file
myPackageA/product-list/product-list.vue
View file @
969f8366
<
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=
"search-bar"
>
...
...
pages.json
View file @
969f8366
...
...
@@ -585,7 +585,18 @@
"style"
:
{
"navigationBarTitleText"
:
"产品对比"
}
}
},{
"path"
:
"product-list/product-commission"
,
"style"
:
{
"navigationBarTitleText"
:
"持牌人佣金"
}
},
{
"path"
:
"product-list/commission-detail"
,
"style"
:
{
"navigationBarTitleText"
:
"佣金详情"
}
}
]
},{
...
...
pages/personalCenter/personalCenter.vue
View file @
969f8366
...
...
@@ -224,6 +224,7 @@
{
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
:
'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
:
'海外资产配置'
,
children
:[
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment