428 lines
13 KiB
Vue
428 lines
13 KiB
Vue
<template>
|
||
<!-- 板块标题 -->
|
||
<view class="rate-title" @click="rateHeightHandle" v-if="vdata.isShowRate">
|
||
<view style="font-size: 28rpx; font-weight: 700;">{{ props.title }}</view>
|
||
<text class="svg" :class="{trans:(rateheight != '0px')}"></text>
|
||
</view>
|
||
|
||
<!-- 父元素 ,用于展开和收起 -->
|
||
<view class="rate-list" ref="rateListRef" :style="{height: rateheight}" v-if="vdata.isShowRate">
|
||
<!-- 一键全开全关 -->
|
||
<JeePayForm :start="false" text="全部开启" backColor="#fff" border="bottom-border">
|
||
<switch @change="allOnHandle" :checked="vdata.allOn" class="name" />
|
||
</JeePayForm>
|
||
|
||
<view class="list-item" v-for="(item, index) in paramsList" :key="index">
|
||
|
||
<view class="title">
|
||
<view class="name">{{ item.wayName }} {{ item.wayCode }}</view>
|
||
<switch :checked="item.state == 1" @change="switchHandle($event, index)" class="name" />
|
||
</view>
|
||
|
||
<!-- 是否为银联模式 有bug 待后台优化 -->
|
||
<!-- <view class="title" v-if="item.feeType == 'LEVEL'">
|
||
<view class="name">银联模式</view>
|
||
<switch :checked="item.creditCardPaywayFee" @change="isUpMode($event, index)" class="name" />
|
||
</view> -->
|
||
|
||
<view class="line" v-if="item.feeType == 'SINGLE'">单笔费率: <input type="text" v-model="item.feeRate" /> %</view>
|
||
|
||
<view v-if="item.feeType == 'LEVEL'">
|
||
|
||
<template v-if="item.creditCardPaywayFee">
|
||
<view>借记卡(储蓄卡):</view>
|
||
<view class="line">保底费用:<input type="text" v-model="item.minFee" /> 元,</view>
|
||
<view class="line">封顶费用:<input type="text" v-model="item.maxFee" />元</view>
|
||
|
||
<template v-for="(levelItem, i) in item.levelList" :key="i">
|
||
<view style="margin: 10rpx 0;"></view>
|
||
{{ levelItem.minFee }} 元 ~ {{ levelItem.maxFee }}元,
|
||
<view class="line">费率:<input type="text" v-model='levelItem.feeRate' /> %</view>
|
||
</template>
|
||
|
||
<view style="margin-top: 20rpx">贷记卡(信用卡):</view>
|
||
<view class="line">保底费用:<input type="text" v-model="item.creditCardPaywayFee.minFee" /> 元,</view>
|
||
<view class="line">封顶费用:<input type="text" v-model="item.creditCardPaywayFee.maxFee" />元</view>
|
||
|
||
<template v-for="(levelItem, i) in item.creditCardPaywayFee.levelList" :key="i">
|
||
<view style="margin: 10rpx 0;"></view>
|
||
{{ levelItem.minFee }} 元 ~ {{ levelItem.maxFee }}元,
|
||
<view class="line">费率:<input type="text" v-model='levelItem.feeRate' /> %</view>
|
||
</template>
|
||
|
||
</template>
|
||
|
||
<template v-else>
|
||
阶梯费率:
|
||
<view class="line">保底费用:<input type="text" v-model="item.minFee" /> 元,</view>
|
||
<view class="line">封顶费用:<input type="text" v-model="item.maxFee" />元</view>
|
||
|
||
<template v-for="(levelItem, i) in item.levelList" :key="i">
|
||
<view style="margin: 10rpx 0;"></view>
|
||
{{ levelItem.minFee }} 元 ~ {{ levelItem.maxFee }}元,
|
||
<view class="line">费率:<input type="text" v-model='levelItem.feeRate' /> %</view>
|
||
</template>
|
||
</template>
|
||
|
||
</view>
|
||
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, inject, reactive } from 'vue'
|
||
import {$getRateConfigPayways, $getRateConfigSavedMapData} from '@/http/apiManager.js'
|
||
import JeePayForm from "@/components/applyComponents/JeePayForm.vue"; // 通用左右结构布局
|
||
|
||
/*
|
||
* 核心逻辑
|
||
* 1. 从可配置接口中,获取费率列表 (payways 接口)
|
||
* 2. 从已配置接口中,获取具体的费率值 (savedMapData接口)
|
||
MCHRATE 进件时自己配置的费率,如果存在进件信息,费率值和状态以此为准
|
||
READONLYPARENTDEFRATE 代理商给商户配置的费率,不存在进件信息以此为准,费率组件展示几条数据,以此为准
|
||
READONLYPARENTAGENT 代理商自己配置的费率,只读即可,目前用不到
|
||
* 3. 将上面两个接口中的相关字段存入一个新数组
|
||
* 4. 切换与修改费率值时,都在修改这个新数组
|
||
* 5. 点击提交按钮后,父组件调用子组件的方法,将该数组传递至父组件,提交前删除渠道名字段(wayName)
|
||
* 6. 遍历该数组,将状态为1(开通)的费率对象保存至用于提交的参数数组中
|
||
* 7. 获取费率时要整乘100,提交前费率要整除100
|
||
* 8. 针对'支付宝产品和微信产品'的费率值,要确保所有的费率值一致
|
||
* 9. 针对微信进件'渠道',选择参与费率活动时,才展开费率板块
|
||
*/
|
||
|
||
const props = defineProps({
|
||
// 是否对费率值进行校验 all:全部校验 separate:支付宝 微信分开校验 默认不校验
|
||
// 目前只有微信 支付宝 和 富友会进行校验
|
||
isCheck: {type: String, default: ''},
|
||
title: {type: String, default: '签约产品费率'},
|
||
isUtmpay: {type: Boolean, default: false },
|
||
})
|
||
|
||
const emits = defineEmits(['autoPos'])
|
||
|
||
const channelInfo = inject('channelInfo')
|
||
|
||
let rateheight = ref('0px') // 费率板块的高度
|
||
|
||
// 如果是银联前置渠道 则rateheight的高度 变为auto 让其自动展开
|
||
if (props.isUtmpay) rateheight.value = 'auto'
|
||
|
||
function rateHeightHandle () {
|
||
rateheight.value == '0px' ? rateheight.value = 'auto' : rateheight.value = '0px'
|
||
}
|
||
|
||
let rateListRef = ref(null)
|
||
|
||
let infoId = `_${channelInfo.mchNo}` // 用于传参
|
||
|
||
const vdata = reactive({
|
||
isShowRate: true, // 是否展示签约产品费率列表,READONLYPARENTDEFRATE为空不展示
|
||
allOn: false, // 是否全部展开
|
||
})
|
||
|
||
// 存在进件信息时,存入以下信息
|
||
if (channelInfo.applyId) {
|
||
infoId = `${channelInfo.applyId}_${channelInfo.mchNo}`
|
||
}
|
||
|
||
let paramsList = ref([]) // 用于传值
|
||
|
||
// 可配置费率列表
|
||
$getRateConfigPayways(infoId,'agentApplyment', channelInfo.code).then( ({bizData}) => {
|
||
|
||
bizData.records.forEach(item => {
|
||
|
||
// 从可配置列表中,获取并保存以下信息
|
||
paramsList.value.push({
|
||
wayCode: item.wayCode, // 渠道code
|
||
wayName: item.wayName // 渠道名
|
||
})
|
||
})
|
||
|
||
// 请求已配置费率列表
|
||
return $getRateConfigSavedMapData(infoId, 'agentApplyment', channelInfo.code)
|
||
}).then(({bizData}) => {
|
||
|
||
// 如果可配置列表中内容为空,则不可进选择费率
|
||
if (Object.keys(paramsList.value).length === 0) {
|
||
vdata.isShowRate = false
|
||
return false
|
||
}
|
||
|
||
// 从此处获取 费率类型 费率值等信息,以READONLYPARENTDEFRATE为准,READONLYPARENTAGENT 只读, 并且将其状态设置为 未开启 0
|
||
Object.keys(bizData.READONLYPARENTAGENT).forEach(item => {
|
||
bizData.READONLYPARENTAGENT[item].state = 0
|
||
})
|
||
|
||
let rateConfigList = Object.assign(bizData.READONLYPARENTAGENT, bizData.READONLYPARENTDEFRATE)
|
||
|
||
// 组装数据(rateConfigList,paramsList), 用于渲染与传参
|
||
Object.keys(rateConfigList).forEach(item => {
|
||
for (let i = 0; i < paramsList.value.length; i++) {
|
||
if (item === paramsList.value[i].wayCode) {
|
||
Object.assign(paramsList.value[i], rateConfigList[item])
|
||
break
|
||
}
|
||
}
|
||
|
||
})
|
||
paramsList.value.forEach(item => {
|
||
// 如果某一项没有 费率类型,则代表未匹配到费率, 未其添加默认值
|
||
if (!item.feeType) {
|
||
item['state'] = '0'
|
||
item['feeType'] = 'SINGLE'
|
||
item['feeRate'] = '0'
|
||
}
|
||
})
|
||
|
||
// 判断是否存在进件信息,若存在则用进件信息的费率再匹配一次
|
||
if (channelInfo.applyId) {
|
||
Object.keys(bizData.MCHRATE).forEach(item => {
|
||
for (let i = 0; i < paramsList.value.length; i++) {
|
||
if (item === paramsList.value[i].wayCode) {
|
||
Object.assign(paramsList.value[i], bizData.MCHRATE[item])
|
||
break
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// 合并之后调用遍历数据方法,费率百分比值 乘100 金额分转元 除100
|
||
rateEach(paramsList.value)
|
||
|
||
})
|
||
|
||
// 遍历费率的方法
|
||
const rateEach = data => {
|
||
|
||
data.forEach(item => {
|
||
// 如果某一项的state为0,则代表未全部开启费率
|
||
if(item.state == 0) vdata.allOn = false
|
||
|
||
if (item['feeRate']) item['feeRate'] = (item['feeRate'] * 100).toFixed(2)
|
||
if (item['levelList']) {
|
||
for (let i = 0; i< item['levelList'].length; i++) {
|
||
item['levelList'][i].feeRate = (item['levelList'][i].feeRate * 100).toFixed(2)
|
||
}
|
||
}
|
||
if (item['creditCardPaywayFee']) {
|
||
item['creditCardPaywayFee'].maxFee = (item['creditCardPaywayFee'].maxFee / 100).toFixed(2)
|
||
item['creditCardPaywayFee'].minFee = (item['creditCardPaywayFee'].minFee / 100).toFixed(2)
|
||
for (let i = 0; i< item['creditCardPaywayFee']['levelList'].length; i++) {
|
||
item['creditCardPaywayFee']['levelList'][i].feeRate = (item['creditCardPaywayFee']['levelList'][i].feeRate * 100).toFixed(2)
|
||
}
|
||
}
|
||
if (item['maxFee']) item['maxFee'] = (item['maxFee'] / 100).toFixed(2)
|
||
if (item['minFee']) item['minFee'] = (item['minFee'] / 100).toFixed(2)
|
||
})
|
||
}
|
||
|
||
// 全部开启的开关
|
||
const allOnHandle = e => {
|
||
let flag = e.detail.value
|
||
flag ? paramsList.value.forEach(item => item.state = 1)
|
||
: paramsList.value.forEach(item => item.state = 0)
|
||
}
|
||
|
||
// 切换事件
|
||
const switchHandle = (e, index) => {
|
||
let flag = e.detail.value
|
||
flag ? paramsList.value[index].state = 1
|
||
: paramsList.value[index].state = 0
|
||
for (let i = 0; i < paramsList.value.length; i++) {
|
||
if (paramsList.value[i].state == 0) {
|
||
vdata.allOn = false
|
||
} else {
|
||
vdata.allOn = true
|
||
}
|
||
}
|
||
|
||
// 如果开启了 auto-pos 则向父组件传递信息
|
||
if (paramsList.value[index].wayCode === 'AUTO_POS') {
|
||
emits('autoPos', e.detail.value)
|
||
}
|
||
|
||
}
|
||
|
||
// 银联模式切换事件
|
||
const isUpMode = (e, index) => {
|
||
// 打开银联模式
|
||
if (e.detail.value) {
|
||
paramsList.value[index].creditCardPaywayFee = {
|
||
levelList: [{
|
||
maxFee: 0,
|
||
feeRate: 0,
|
||
minFee: 0
|
||
}, {
|
||
maxFee: 0,
|
||
feeRate: 0,
|
||
minFee: 0
|
||
}],
|
||
maxFee: 0,
|
||
minFee: 0
|
||
}
|
||
} else {
|
||
delete paramsList.value[index].creditCardPaywayFee
|
||
}
|
||
}
|
||
|
||
// 父组件调用此方法,传值回去
|
||
const getList = isTempData => {
|
||
|
||
// 深拷贝,因为要整除100,防止页面中的值受到影响
|
||
let data = JSON.parse(JSON.stringify(paramsList.value)),
|
||
rateList = [], // 传给父组件的费率信息
|
||
errInfo = '' // 错误信息
|
||
// 费率值校验,判断是否相等 全部判断模式 适用于 支付宝官方和微信官方
|
||
if ((props.isCheck == 'all') && !isTempData) {
|
||
for(let i = 0; i < data.length; i++) {
|
||
if (data[i].state != 1) continue
|
||
if (data[0].feeRate != data[i].feeRate) {
|
||
errInfo = '设置了不同的费率值,请确保一致'
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// 支付宝和微信分开 验证 适用于 富友进件
|
||
if ((props.isCheck == 'separate') && !isTempData) {
|
||
let wxList = []
|
||
let aliList = []
|
||
|
||
data.forEach(item => {
|
||
if ((item.wayCode.indexOf('ALI') != -1) && item.state == 1) aliList.push(item)
|
||
if ((item.wayCode.indexOf('WX') != -1) && item.state == 1) wxList.push(item)
|
||
})
|
||
|
||
for (let j = 0; j < aliList.length; j++) {
|
||
if (aliList[0].feeRate != aliList[j].feeRate) {
|
||
errInfo = '支付宝费率设置了不同的费率值,请确保一致'
|
||
break
|
||
}
|
||
}
|
||
|
||
for (let i = 0; i < wxList.length; i++) {
|
||
if (wxList[0].feeRate != wxList[i].feeRate) {
|
||
errInfo = '微信费率设置了不同的费率值,请确保一致'
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
// 如果存在保存信息往下不执行
|
||
if (errInfo) return errInfo
|
||
|
||
// 要把费率都除100
|
||
data.forEach(item => {
|
||
delete item.wayName // 删除渠道名字
|
||
|
||
// 金额元转分
|
||
if (item.feeType === 'SINGLE' ) {
|
||
item.feeRate = (item.feeRate / 100).toFixed(4)
|
||
} else {
|
||
item.levelList.forEach(item => item.feeRate = (item.feeRate / 100).toFixed(4))
|
||
item.maxFee *= 100
|
||
item.minFee *= 100
|
||
if (item.creditCardPaywayFee) {
|
||
item.creditCardPaywayFee.levelList.forEach(item => item.feeRate = (item.feeRate / 100).toFixed(4))
|
||
item.creditCardPaywayFee.maxFee *= 100
|
||
item.creditCardPaywayFee.minFee *= 100
|
||
}
|
||
}
|
||
|
||
// 传值时只传已开通的
|
||
if(item.state == 1) {
|
||
rateList.push(item)
|
||
}
|
||
})
|
||
|
||
return rateList
|
||
}
|
||
|
||
// 向父元素导出方法
|
||
defineExpose({ getList })
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.rate-title {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 30rpx;
|
||
color:#000;
|
||
font-weight: 550;
|
||
border-bottom: 1px solid #ebeef5;
|
||
image {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
}
|
||
.svg {
|
||
font-family: uniicons;
|
||
text-decoration: none;
|
||
text-align: center;
|
||
color: rgb(187, 187, 187);
|
||
font-size: 14px;
|
||
&::before {
|
||
content: "\e6b8";
|
||
}
|
||
}
|
||
}
|
||
.trans{
|
||
transform: rotate(180deg);
|
||
}
|
||
.rate-list {
|
||
// height: 600rpx;
|
||
overflow: hidden;
|
||
display: flex;
|
||
flex-direction: column;
|
||
.list-item {
|
||
border-bottom: 1px solid #ebeef5;
|
||
padding: 35rpx 30rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
font-size: 28rpx;
|
||
|
||
input {
|
||
border: 1px solid #ebeef5;
|
||
display: inline-block;
|
||
width: 180rpx;
|
||
margin: 0 10rpx;
|
||
padding: 0 10rpx;
|
||
}
|
||
|
||
.title {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
}
|
||
}
|
||
// 不存咋费率值时设置的属性
|
||
.none {
|
||
padding: 0 !important;
|
||
border: none !important;
|
||
height: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.line {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.submit{
|
||
display: flex;
|
||
justify-content: center;
|
||
margin: 0 auto ;
|
||
width: 380rpx;
|
||
height: 90rpx;
|
||
line-height: 90rpx;
|
||
border-radius: 10rpx;
|
||
background: #3981FF;
|
||
font-weight: 500;
|
||
font-size: 30rpx;
|
||
color: #fff;
|
||
}
|
||
</style> |