提交 7a670497 编写于 作者: Z zhuxiao

运营平台、商户系统新增商户应用及相关支付配置

上级 32ea147e
......@@ -74,6 +74,8 @@ export const API_URL_USER_ROLE_RELA_LIST = '/api/sysUserRoleRelas'
/** 服务商、商户管理 **/
export const API_URL_ISV_LIST = '/api/isvInfo'
export const API_URL_MCH_LIST = '/api/mchInfo'
/** 商户App管理 **/
export const API_URL_MCH_APP = '/api/mchApps'
/** 支付订单管理 **/
export const API_URL_PAY_ORDER_LIST = '/api/payOrder'
/** 退款订单管理 **/
......@@ -185,7 +187,7 @@ export function getIsvPayConfigUnique (infoId, ifCode) {
})
}
export function getMcgPayConfigUnique (infoId, ifCode) {
export function getMchPayConfigUnique (infoId, ifCode) {
return request.request({
url: '/api/mch/payConfigs/' + infoId + '/' + ifCode,
method: 'get'
......
......@@ -18,7 +18,7 @@
<img src="~@/assets/svg/add-icon-hover.svg" alt="add-icon" class="jeepay-card-add-icon-hover">
</div>
<div class="jeepay-card-add-text">
{{ name }}
{{ name }}
</div>
</div>
</a-col>
......
......@@ -28,6 +28,7 @@ export const asyncRouteDefine = {
'IfDefinePage': { defaultPath: '/ifdefines', component: () => import('@/views/payconfig/payIfDefine/List') },
'IsvListPage': { defaultPath: '/isv', component: () => import('@/views/isv/IsvList') }, // 服务商列表
'MchListPage': { defaultPath: '/mch', component: () => import('@/views/mch/MchList') }, // 商户列表
'MchAppPage': { defaultPath: '/apps', component: () => import ('@/views/mchApp/List') }, // 商户应用列表
'PayOrderListPage': { defaultPath: '/payOrder', component: () => import('@/views/order/pay/PayOrderList') }, // 支付订单列表
'RefundOrderListPage': { defaultPath: '/refundOrder', component: () => import('@/views/order/refund/RefundOrderList') }, // 退款订单列表
'MchNotifyListPage': { defaultPath: '/notify', component: () => import('@/views/order/notify/MchNotifyList') }, // 商户通知列表
......
......@@ -58,7 +58,7 @@
<template slot="opSlot" slot-scope="{record}"> <!-- 操作列插槽 -->
<JeepayTableColumns>
<a-button type="link" v-if="$access('ENT_MCH_INFO_EDIT')" @click="editFunc(record.mchNo)">修改</a-button>
<a-button type="link" v-if="$access('ENT_MCH_PAY_CONFIG_LIST')" @click="showPayIfConfigList(record)">支付配置</a-button>
<a-button type="link" v-if="$access('ENT_MCH_APP_CONFIG')" @click="mchAppConfig(record.mchNo)">应用配置</a-button>
<a-button type="link" v-if="$access('ENT_MCH_INFO_DEL')" style="color: red" @click="delFunc(record.mchNo)">删除</a-button>
</JeepayTableColumns>
</template>
......@@ -68,8 +68,6 @@
<InfoAddOrEdit ref="infoAddOrEdit" :callbackFunc="searchFunc"/>
<!-- 新增页面组件 -->
<InfoDetail ref="infoDetail" :callbackFunc="searchFunc"/>
<!-- 支付参数配置页面组件 -->
<MchPayIfConfigList ref="mchPayIfConfigList" />
</page-header-wrapper>
</template>
<script>
......@@ -79,7 +77,6 @@ import JeepayTableColumns from '@/components/JeepayTable/JeepayTableColumns'
import { API_URL_MCH_LIST, req, reqLoad } from '@/api/manage'
import InfoAddOrEdit from './AddOrEdit'
import InfoDetail from './Detail'
import MchPayIfConfigList from './MchPayIfConfigList'
// eslint-disable-next-line no-unused-vars
const tableColumns = [
......@@ -94,7 +91,7 @@ const tableColumns = [
export default {
name: 'MchListPage',
components: { JeepayTable, JeepayTableColumns, InfoAddOrEdit, InfoDetail, MchPayIfConfigList, JeepayTextUp },
components: { JeepayTable, JeepayTableColumns, InfoAddOrEdit, InfoDetail, JeepayTextUp },
data () {
return {
btnLoading: false,
......@@ -136,8 +133,11 @@ export default {
})
})
},
showPayIfConfigList: function (record) { // 支付参数配置
this.$refs.mchPayIfConfigList.show(record.mchNo, record.type)
mchAppConfig: function (recordId) { // 应用配置
this.$router.push({
path: '/apps',
query: { mchNo: recordId }
})
}
}
}
......
<template>
<a-drawer
:visible="visible"
:title=" isAdd ? '新增应用' : '修改应用'"
width="40%"
:maskClosable="false"
@close="onClose">
<a-form-model ref="infoFormModel" :model="saveObject" layout="vertical" :rules="rules">
<a-row :gutter="16">
<a-col :span="12" v-if="!isAdd">
<a-form-model-item label="应用 AppId" prop="appId">
<a-input v-model="saveObject.appId" placeholder="请输入" :disabled="!isAdd" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="商户号" prop="mchNo">
<a-input v-model="saveObject.mchNo" placeholder="请输入" :disabled="!isAdd" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="应用名称" prop="appName">
<a-input v-model="saveObject.appName" placeholder="请输入" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="状态" prop="state">
<a-radio-group v-model="saveObject.state">
<a-radio :value="1">
启用
</a-radio>
<a-radio :value="0">
停用
</a-radio>
</a-radio-group>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="私钥 AppSecret" prop="appSecret" >
<a-input v-model="saveObject.appSecret" placeholder="请输入" type="textarea" />
<a-button type="primary" ghost @click="randomKey(false, 128, 0)"><a-icon type="file-sync" />随机生成私钥</a-button>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="备注" prop="remark">
<a-input v-model="saveObject.remark" placeholder="请输入" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
<div class="drawer-btn-center">
<a-button @click="onClose" icon="close" :style="{ marginRight: '8px' }">取消</a-button>
<a-button type="primary" @click="onSubmit" icon="check" >保存</a-button>
</div>
</a-drawer>
</template>
<script>
import { API_URL_MCH_APP, req } from '@/api/manage'
export default {
props: {
callbackFunc: { type: Function, default: () => () => ({}) }
},
data () {
return {
isAdd: true, // 新增 or 修改
visible: false, // 抽屉开关
appId: '', // 应用AppId
saveObject: {}, // 数据对象
rules: {
mchNo: [{ required: true, message: '请输入商户号', trigger: 'blur' }],
appName: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
appSecret: [{ required: true, message: '请输入私钥或点击随机生成私钥' }]
}
}
},
methods: {
// 抽屉显示
show (mchNo, appId) {
this.isAdd = !appId
// 数据清空
this.saveObject = {
'state': 1,
'appSecret': '',
'mchNo': mchNo
}
if (this.$refs.infoFormModel !== undefined) {
this.$refs.infoFormModel.resetFields()
}
const that = this
if (!this.isAdd) { // 修改信息 延迟展示弹层
that.appId = appId
// 拉取详情
req.getById(API_URL_MCH_APP, appId).then(res => {
that.saveObject = res
if (!that.saveObject.appSecret) { // 解决商户私钥为空无法写入的问题
that.saveObject.appSecret = ''
}
})
this.visible = true
} else {
that.visible = true // 展示弹层信息
}
},
// 表单提交
onSubmit () {
const that = this
this.$refs.infoFormModel.validate(valid => {
if (valid) { // 验证通过
// 请求接口
if (that.isAdd) {
req.add(API_URL_MCH_APP, that.saveObject).then(res => {
that.$message.success('新增成功')
that.visible = false
that.callbackFunc() // 刷新列表
})
} else {
req.updateById(API_URL_MCH_APP, that.appId, that.saveObject).then(res => {
that.$message.success('修改成功')
that.visible = false
that.callbackFunc() // 刷新列表
})
}
}
})
},
randomKey: function (randomFlag, min, max) { // 生成随机128位私钥
let str = ''
let range = min
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
// 随机产生
if (randomFlag) {
range = Math.round(Math.random() * (max - min)) + min
}
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1))
str += arr[ pos ]
}
this.saveObject.appSecret = str
},
onClose () {
this.visible = false
}
}
}
</script>
<style lang="less" scoped>
</style>
<template>
<page-header-wrapper>
<a-card>
<div class="table-page-search-wrapper">
<a-form layout="inline" class="table-head-ground">
<div class="table-layer">
<jeepay-text-up :placeholder="'商户号'" :msg="searchData.mchNo" v-model="searchData.mchNo"/>
<jeepay-text-up :placeholder="'应用AppId'" :msg="searchData.appId" v-model="searchData.appId"/>
<jeepay-text-up :placeholder="'应用名称'" :msg="searchData.appName" v-model="searchData.appName"/>
<a-form-item label="" class="table-head-layout">
<a-select v-model="searchData.state" placeholder="状态" default-value="">
<a-select-option value="">全部</a-select-option>
<a-select-option value="0">禁用</a-select-option>
<a-select-option value="1">启用</a-select-option>
</a-select>
</a-form-item>
<span class="table-page-search-submitButtons" style="flex-grow: 0; flex-shrink: 0;">
<a-button type="primary" icon="search" @click="queryFunc" :loading="btnLoading">查询</a-button>
<a-button style="margin-left: 8px" icon="reload" @click="() => this.searchData = {}">重置</a-button>
</span>
</div>
</a-form>
<div>
<a-button v-if="$access('ENT_MCH_APP_ADD')" type="primary" icon="plus" @click="addFunc" class="mg-b-30">新建</a-button>
</div>
</div>
<!-- 列表渲染 -->
<JeepayTable
@btnLoadClose="btnLoading=false"
ref="infoTable"
:initData="false"
:reqTableDataFunc="reqTableDataFunc"
:tableColumns="tableColumns"
:searchData="searchData"
:scrollX="1200"
rowKey="mchName"
>
<template slot="appIdSlot" slot-scope="{record}">
<b>{{ record.appId }}</b>
</template> <!-- 自定义插槽 -->
<template slot="stateSlot" slot-scope="{record}">
<a-badge :status="record.state === 0?'error':'processing'" :text="record.state === 0?'禁用':'启用'" />
</template>
<template slot="opSlot" slot-scope="{record}"> <!-- 操作列插槽 -->
<JeepayTableColumns>
<a-button type="link" v-if="$access('ENT_MCH_APP_EDIT')" @click="editFunc(record.appId)">修改</a-button>
<a-button type="link" v-if="$access('ENT_MCH_PAY_CONFIG_LIST')" @click="showPayIfConfigList(record.appId)">支付配置</a-button>
<a-button type="link" v-if="$access('ENT_MCH_APP_DEL')" style="color: red" @click="delFunc(record.appId)">删除</a-button>
</JeepayTableColumns>
</template>
</JeepayTable>
</a-card>
<!-- 新增应用 -->
<MchAppAddOrEdit ref="mchAppAddOrEdit" :callbackFunc="searchFunc"/>
<!-- 支付参数配置页面组件 -->
<MchPayIfConfigList ref="mchPayIfConfigList" />
</page-header-wrapper>
</template>
<script>
import JeepayTable from '@/components/JeepayTable/JeepayTable'
import JeepayTextUp from '@/components/JeepayTextUp/JeepayTextUp' // 文字上移组件
import JeepayTableColumns from '@/components/JeepayTable/JeepayTableColumns'
import { API_URL_MCH_APP, req } from '@/api/manage'
import MchAppAddOrEdit from './AddOrEdit'
import MchPayIfConfigList from './MchPayIfConfigList'
// eslint-disable-next-line no-unused-vars
const tableColumns = [
{ key: 'appId', fixed: 'left', width: '320px', title: '应用AppId', scopedSlots: { customRender: 'appIdSlot' } },
{ key: 'appName', title: '应用名称', dataIndex: 'appName' },
{ key: 'mchNo', title: '商户号', dataIndex: 'mchNo' },
{ key: 'state', title: '状态', scopedSlots: { customRender: 'stateSlot' } },
{ key: 'createdAt', dataIndex: 'createdAt', title: '创建日期' },
{ key: 'op', title: '操作', width: '260px', fixed: 'right', align: 'center', scopedSlots: { customRender: 'opSlot' } }
]
export default {
name: 'MchAppPage',
components: { JeepayTable, JeepayTableColumns, JeepayTextUp, MchAppAddOrEdit, MchPayIfConfigList },
data () {
return {
btnLoading: false,
tableColumns: tableColumns,
searchData: { 'mchNo': '' }
}
},
mounted () {
this.searchData.mchNo = this.$route.query.mchNo
this.queryFunc()
},
methods: {
queryFunc () {
this.btnLoading = true
this.$refs.infoTable.refTable(true)
},
// 请求table接口数据
reqTableDataFunc: (params) => {
return req.list(API_URL_MCH_APP, params)
},
searchFunc: function () { // 点击【查询】按钮点击事件
this.$refs.infoTable.refTable(true)
},
addFunc: function () { // 业务通用【新增】 函数
this.$refs.mchAppAddOrEdit.show(this.searchData.mchNo)
},
editFunc: function (recordId) { // 业务通用【修改】 函数
this.$refs.mchAppAddOrEdit.show(this.searchData.mchNo, recordId)
},
delFunc (appId) {
const that = this
this.$infoBox.confirmDanger('确认删除?', '', () => {
req.delById(API_URL_MCH_APP, appId).then(res => {
that.$message.success('删除成功!')
that.searchFunc()
})
})
},
showPayIfConfigList: function (recordId) { // 支付参数配置
this.$refs.mchPayIfConfigList.show(recordId)
}
}
}
</script>
<style lang="less" scoped>
</style>
......@@ -78,7 +78,7 @@
<script>
import JeepayCard from '@/components/JeepayCard/JeepayCard'
import JeepayUpload from '@/components/JeepayUpload/JeepayUpload'
import { API_URL_MCH_PAYCONFIGS_LIST, req, getMcgPayConfigUnique, upload } from '@/api/manage'
import { API_URL_MCH_PAYCONFIGS_LIST, req, getMchPayConfigUnique, upload } from '@/api/manage'
export default {
components: {
JeepayCard,
......@@ -92,7 +92,7 @@ export default {
return {
btnLoading: false,
visible: false, // 抽屉开关
mchNo: null, // 商户号
appId: null, // 商户号
ifCode: null, // 接口代码
mchType: null, // 商户类型:1-普通商户 2-特约商户
action: upload.cert, // 上传文件地址
......@@ -109,26 +109,26 @@ export default {
},
methods: {
// 弹层打开事件
show: function (mchNo, mchType, record) {
this.mchNo = mchNo
show: function (appId, record) {
this.appId = appId
this.ifCode = record.ifCode
this.mchType = mchType
this.mchType = record.mchType
this.saveObject = {} // 要保存的对象
this.ifParams = {} // 参数配置对象
this.mchParams = {} // 支付接口定义描述
this.saveObject.infoId = mchNo
this.saveObject.infoId = appId
this.saveObject.ifCode = record.ifCode
this.saveObject.state = record.ifConfigState === 0 ? 0 : 1
if (this.$refs.mchParamFormModel !== undefined) {
this.$refs.mchParamFormModel.resetFields()
}
this.getMcgPayConfig(record)
this.getMchPayConfig(record)
},
// 支付参数配置
getMcgPayConfig (record) {
getMchPayConfig (record) {
const that = this
// 获取支付参数
getMcgPayConfigUnique(that.saveObject.infoId, that.saveObject.ifCode).then(res => {
getMchPayConfigUnique(that.saveObject.infoId, that.saveObject.ifCode).then(res => {
if (res && res.ifParams) {
that.saveObject = res
that.ifParams = JSON.parse(res.ifParams)
......
......@@ -126,8 +126,7 @@ export default {
return {
currentStep: 0, // 当前步骤条index
btnLoading: false,
mchNo: null, // 商户号
mchType: null, // 商户类型:1-普通商户 2-特约商户
appId: null, // 应用appId
visible: false, // 抽屉开关
jeepayCard: { // 卡片配置
height: 300,
......@@ -139,9 +138,8 @@ export default {
},
methods: {
// 弹层打开事件
show (mchNo, mchType) {
this.mchNo = mchNo
this.mchType = mchType
show (appId) {
this.appId = appId
this.ifCode = null
this.currentStep = 0
this.visible = true
......@@ -153,7 +151,7 @@ export default {
},
// 请求支付接口定义数据
reqCardListFunc () {
return req.list(API_URL_MCH_PAYCONFIGS_LIST, { 'mchNo': this.mchNo })
return req.list(API_URL_MCH_PAYCONFIGS_LIST, { 'appId': this.appId })
},
// 刷新支付接口card列表
refCardList () {
......@@ -162,7 +160,7 @@ export default {
// 请求支付通道数据
reqTableDataFunc (params) {
const that = this
return req.list(API_URL_MCH_PAYPASSAGE_LIST, Object.assign(params, { mchNo: that.mchNo }))
return req.list(API_URL_MCH_PAYPASSAGE_LIST, Object.assign(params, { appId: that.appId }))
},
searchFunc (isToFirst = false) { // 点击【查询】按钮点击事件
this.$refs.infoTable.refTable(isToFirst)
......@@ -175,23 +173,23 @@ export default {
if (record.subMchIsvConfig === 0) {
this.$error({
title: '提示',
content: '当前商户为特约商户,请先配置服务商支付参数!'
content: '当前应用所属商户为特约商户,请先配置服务商支付参数!'
})
return
}
this.$refs.mchPayConfigAddOrEdit.show(this.mchNo, this.mchType, record)
this.$refs.mchPayConfigAddOrEdit.show(this.appId, record)
},
// 支付通道配置
editPayPassageFunc (record) {
const that = this
getAvailablePayInterfaceList(that.mchNo, record.wayCode).then(resData => {
getAvailablePayInterfaceList(that.appId, record.wayCode).then(resData => {
if (!resData || resData.length === 0) {
that.$error({
title: '提示',
content: '暂无可用支付接口配置'
})
} else {
that.$refs.mchPayPassageAddOrEdit.show(that.mchNo, record.wayCode)
that.$refs.mchPayPassageAddOrEdit.show(that.appId, record.wayCode)
}
})
},
......
......@@ -83,7 +83,7 @@ export default {
data () {
return {
cardList: [],
mchNo: null, // 商户号
appId: null, // 应用appId
wayCode: null, // 支付方式代码
visible: false, // 是否显示弹层/抽屉
jeepayCard: {
......@@ -94,8 +94,8 @@ export default {
},
methods: {
// 弹层打开事件
show: function (mchNo, wayCode) {
this.mchNo = mchNo
show: function (appId, wayCode) {
this.appId = appId
this.wayCode = wayCode
this.visible = true
this.cardList = []
......@@ -104,7 +104,7 @@ export default {
// 请求支付接口定义数据
refCardList () {
const that = this
getAvailablePayInterfaceList(this.mchNo, this.wayCode).then(resData => {
getAvailablePayInterfaceList(this.appId, this.wayCode).then(resData => {
if (resData === undefined || resData.length === 0) {
that.cardList = []
return
......@@ -150,7 +150,7 @@ export default {
reqParams.push({
id: item.passageId,
mchNo: that.mchNo,
appId: that.appId,
wayCode: that.wayCode,
ifCode: item.ifCode,
rate: item.rate,
......
......@@ -74,6 +74,8 @@ export const API_URL_USER_ROLE_RELA_LIST = '/api/sysUserRoleRelas'
/** 首页统计 **/
export const API_URL_MAIN_STATISTIC = 'api/mainChart'
/** 商户App管理 **/
export const API_URL_MCH_APP = '/api/mchApps'
/** 支付订单管理 **/
export const API_URL_PAY_ORDER_LIST = '/api/payOrder'
/** 退款订单管理 **/
......@@ -125,17 +127,17 @@ export function getRoleList (parameter) {
}
/** 根据支付接口查询支付参数配置 **/
export function getMcgPayConfigUnique (ifCode) {
export function getMchPayConfigUnique (infoId, ifCode) {
return request.request({
url: '/api/mch/payConfigs/' + ifCode,
url: '/api/mch/payConfigs/' + infoId + '/' + ifCode,
method: 'get'
})
}
/** 根据支付方式查询可用支付接口 **/
export function getAvailablePayInterfaceList (wayCode) {
export function getAvailablePayInterfaceList (appId, wayCode) {
return request.request({
url: '/api/mch/payPassages/availablePayInterface/' + wayCode,
url: '/api/mch/payPassages/availablePayInterface/' + appId + '/' + wayCode,
method: 'GET'
})
}
......
......@@ -15,7 +15,7 @@
<div class="jeepay-card-add" :style="{'height': height + 'px'}">
<img src="~@/assets/svg/add-icon.svg" alt="add-icon" :style="{'width': height/3 + 'px', 'height': height/3 + 'px'}">
<div class="jeepay-card-add-text">
{{ name }}
{{ name }}
</div>
</div>
</a-col>
......
......@@ -24,6 +24,8 @@ export const asyncRouteDefine = {
'SysUserPage': { defaultPath: '/users', component: () => import('@/views/sysuser/SysUserPage') },
'RolePage': { defaultPath: '/roles', component: () => import('@/views/role/RolePage') },
'MchAppPage': { defaultPath: '/apps', component: () => import ('@/views/mchApp/List') }, // 商户应用列表
'PayOrderListPage': { defaultPath: '/payOrder', component: () => import('@/views/order/pay/PayOrderList') }, // 支付订单列表
'RefundOrderListPage': { defaultPath: '/refundOrder', component: () => import('@/views/order/refund/RefundOrderList') }, // 退款订单列表
'PayConfigPage': { defaultPath: '/pay/config', component: () => import('@/views/pay/PayConfigList') }, // 支付参数配置
......
<template>
<a-drawer
:visible="visible"
:title=" isAdd ? '新增应用' : '修改应用'"
width="40%"
:maskClosable="false"
@close="onClose">
<a-form-model ref="infoFormModel" :model="saveObject" layout="vertical" :rules="rules">
<a-row :gutter="16">
<a-col :span="12" v-if="!isAdd">
<a-form-model-item label="应用 AppId" prop="appId">
<a-input v-model="saveObject.appId" placeholder="请输入" :disabled="!isAdd" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="应用名称" prop="appName">
<a-input v-model="saveObject.appName" placeholder="请输入" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="状态" prop="state">
<a-radio-group v-model="saveObject.state">
<a-radio :value="1">
启用
</a-radio>
<a-radio :value="0">
停用
</a-radio>
</a-radio-group>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="私钥 AppSecret" prop="appSecret" >
<a-input v-model="saveObject.appSecret" placeholder="请输入" type="textarea" />
<a-button type="primary" ghost @click="randomKey(false, 128, 0)"><a-icon type="file-sync" />随机生成私钥</a-button>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="备注" prop="remark">
<a-input v-model="saveObject.remark" placeholder="请输入" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
<div class="drawer-btn-center">
<a-button @click="onClose" icon="close" :style="{ marginRight: '8px' }">取消</a-button>
<a-button type="primary" @click="onSubmit" icon="check" >保存</a-button>
</div>
</a-drawer>
</template>
<script>
import { API_URL_MCH_APP, req } from '@/api/manage'
export default {
props: {
callbackFunc: { type: Function, default: () => () => ({}) }
},
data () {
return {
isAdd: true, // 新增 or 修改
visible: false, // 抽屉开关
appId: '', // 应用AppId
saveObject: {}, // 数据对象
rules: {
appName: [{ required: true, message: '请输入应用名称', trigger: 'blur' }],
appSecret: [{ required: true, message: '请输入私钥或点击随机生成私钥' }]
}
}
},
methods: {
// 抽屉显示
show (appId) {
this.isAdd = !appId
// 数据清空
this.saveObject = {
'state': 1,
'appSecret': ''
}
if (this.$refs.infoFormModel !== undefined) {
this.$refs.infoFormModel.resetFields()
}
const that = this
if (!this.isAdd) { // 修改信息 延迟展示弹层
that.appId = appId
// 拉取详情
req.getById(API_URL_MCH_APP, appId).then(res => {
that.saveObject = res
if (!that.saveObject.appSecret) { // 解决商户私钥为空无法写入的问题
that.saveObject.appSecret = ''
}
})
this.visible = true
} else {
that.visible = true // 展示弹层信息
}
},
// 表单提交
onSubmit () {
const that = this
this.$refs.infoFormModel.validate(valid => {
if (valid) { // 验证通过
// 请求接口
if (that.isAdd) {
req.add(API_URL_MCH_APP, that.saveObject).then(res => {
that.$message.success('新增成功')
that.visible = false
that.callbackFunc() // 刷新列表
})
} else {
req.updateById(API_URL_MCH_APP, that.appId, that.saveObject).then(res => {
that.$message.success('修改成功')
that.visible = false
that.callbackFunc() // 刷新列表
})
}
}
})
},
randomKey: function (randomFlag, min, max) { // 生成随机128位私钥
let str = ''
let range = min
const arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
// 随机产生
if (randomFlag) {
range = Math.round(Math.random() * (max - min)) + min
}
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1))
str += arr[ pos ]
}
this.saveObject.appSecret = str
},
onClose () {
this.visible = false
}
}
}
</script>
<style lang="less" scoped>
</style>
<template>
<page-header-wrapper>
<a-card>
<div class="table-page-search-wrapper">
<a-form layout="inline" class="table-head-ground">
<div class="table-layer">
<jeepay-text-up :placeholder="'应用AppId'" :msg="searchData.appId" v-model="searchData.appId"/>
<jeepay-text-up :placeholder="'应用名称'" :msg="searchData.appName" v-model="searchData.appName"/>
<a-form-item label="" class="table-head-layout">
<a-select v-model="searchData.state" placeholder="状态" default-value="">
<a-select-option value="">全部</a-select-option>
<a-select-option value="0">禁用</a-select-option>
<a-select-option value="1">启用</a-select-option>
</a-select>
</a-form-item>
<span class="table-page-search-submitButtons" style="flex-grow: 0; flex-shrink: 0;">
<a-button type="primary" icon="search" @click="queryFunc" :loading="btnLoading">查询</a-button>
<a-button style="margin-left: 8px" icon="reload" @click="() => this.searchData = {}">重置</a-button>
</span>
</div>
</a-form>
<div>
<a-button v-if="$access('ENT_MCH_APP_ADD')" type="primary" icon="plus" @click="addFunc" class="mg-b-30">新建</a-button>
</div>
</div>
<!-- 列表渲染 -->
<JeepayTable
@btnLoadClose="btnLoading=false"
ref="infoTable"
:initData="true"
:reqTableDataFunc="reqTableDataFunc"
:tableColumns="tableColumns"
:searchData="searchData"
:scrollX="1200"
rowKey="mchName"
>
<template slot="appIdSlot" slot-scope="{record}">
<b>{{ record.appId }}</b>
</template> <!-- 自定义插槽 -->
<template slot="stateSlot" slot-scope="{record}">
<a-badge :status="record.state === 0?'error':'processing'" :text="record.state === 0?'禁用':'启用'" />
</template>
<template slot="opSlot" slot-scope="{record}"> <!-- 操作列插槽 -->
<JeepayTableColumns>
<a-button type="link" v-if="$access('ENT_MCH_APP_EDIT')" @click="editFunc(record.appId)">修改</a-button>
<a-button type="link" v-if="$access('ENT_MCH_PAY_CONFIG_LIST')" @click="showPayIfConfigList(record.appId)">支付配置</a-button>
<a-button type="link" v-if="$access('ENT_MCH_APP_DEL')" style="color: red" @click="delFunc(record.appId)">删除</a-button>
</JeepayTableColumns>
</template>
</JeepayTable>
</a-card>
<!-- 新增应用 -->
<MchAppAddOrEdit ref="mchAppAddOrEdit" :callbackFunc="searchFunc"/>
<!-- 支付参数配置页面组件 -->
<MchPayIfConfigList ref="mchPayIfConfigList" />
</page-header-wrapper>
</template>
<script>
import JeepayTable from '@/components/JeepayTable/JeepayTable'
import JeepayTextUp from '@/components/JeepayTextUp/JeepayTextUp' // 文字上移组件
import JeepayTableColumns from '@/components/JeepayTable/JeepayTableColumns'
import { API_URL_MCH_APP, req } from '@/api/manage'
import MchAppAddOrEdit from './AddOrEdit'
import MchPayIfConfigList from './MchPayIfConfigList'
// eslint-disable-next-line no-unused-vars
const tableColumns = [
{ key: 'appId', fixed: 'left', width: '320px', title: '应用AppId', scopedSlots: { customRender: 'appIdSlot' } },
{ key: 'appName', title: '应用名称', dataIndex: 'appName' },
{ key: 'state', title: '状态', scopedSlots: { customRender: 'stateSlot' } },
{ key: 'createdAt', dataIndex: 'createdAt', title: '创建日期' },
{ key: 'op', title: '操作', width: '260px', fixed: 'right', align: 'center', scopedSlots: { customRender: 'opSlot' } }
]
export default {
name: 'MchAppPage',
components: { JeepayTable, JeepayTableColumns, JeepayTextUp, MchAppAddOrEdit, MchPayIfConfigList },
data () {
return {
btnLoading: false,
tableColumns: tableColumns,
searchData: {}
}
},
methods: {
queryFunc () {
this.btnLoading = true
this.$refs.infoTable.refTable(true)
},
// 请求table接口数据
reqTableDataFunc: (params) => {
return req.list(API_URL_MCH_APP, params)
},
searchFunc: function () { // 点击【查询】按钮点击事件
this.$refs.infoTable.refTable(true)
},
addFunc: function () { // 业务通用【新增】 函数
this.$refs.mchAppAddOrEdit.show()
},
editFunc: function (recordId) { // 业务通用【修改】 函数
this.$refs.mchAppAddOrEdit.show(recordId)
},
delFunc (appId) {
const that = this
this.$infoBox.confirmDanger('确认删除?', '', () => {
req.delById(API_URL_MCH_APP, appId).then(res => {
that.$message.success('删除成功!')
that.searchFunc()
})
})
},
showPayIfConfigList: function (recordId) { // 支付参数配置
this.$refs.mchPayIfConfigList.show(recordId)
}
}
}
</script>
<style lang="less" scoped>
</style>
<template>
<a-drawer
title="填写参数"
width="40%"
:closable="true"
:maskClosable="false"
:visible="visible"
:body-style="{ paddingBottom: '80px' }"
@close="onClose"
>
<a-form-model ref="infoFormModel" :model="saveObject" layout="vertical" :rules="rules">
<a-row :gutter="16">
<a-col :span="12">
<a-form-model-item label="支付接口费率" prop="ifRate">
<a-input v-model="saveObject.ifRate" placeholder="请输入" suffix="%" />
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="状态" prop="state">
<a-radio-group v-model="saveObject.state">
<a-radio :value="1">
启用
</a-radio>
<a-radio :value="0">
停用
</a-radio>
</a-radio-group>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="备注" prop="remark">
<a-input v-model="saveObject.remark" placeholder="请输入" type="textarea" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
<a-divider orientation="left">
<a-tag color="#FF4B33">
{{ saveObject.ifCode }} 商户参数配置
</a-tag>
</a-divider>
<a-form-model ref="mchParamFormModel" :model="ifParams" layout="vertical" :rules="ifParamsRules">
<a-row :gutter="16">
<a-col v-for="(item, key) in mchParams" :key="key" :span="item.type === 'text' ? 12 : 24">
<a-form-model-item :label="item.desc" :prop="item.name" v-if="item.type === 'text' || item.type === 'textarea'">
<a-input v-model="ifParams[item.name]" placeholder="请输入" :type="item.type" />
</a-form-model-item>
<a-form-model-item :label="item.desc" :prop="item.name" v-else-if="item.type === 'radio'">
<a-radio-group v-model="ifParams[item.name]">
<a-radio v-for="(radioItem, radioKey) in item.values" :key="radioKey" :value="radioItem.value">
{{ radioItem.title }}
</a-radio>
</a-radio-group>
</a-form-model-item>
<a-form-model-item :label="item.desc" :prop="item.name" v-else-if="item.type === 'file'">
<a-input v-model="ifParams[item.name]" disabled="disabled" />
<JeepayUpload
:action="action"
:fileUrl="ifParams[item.name]"
@uploadSuccess="uploadSuccess($event, item.name)"
>
<template slot="uploadSlot" slot-scope="{loading}">
<a-button style="marginTop:5px;"> <a-icon :type="loading ? 'loading' : 'upload'" /> {{ loading ? '正在上传' : '点击上传' }} </a-button>
</template>
</JeepayUpload>
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
<div class="drawer-btn-center" v-if="$access('ENT_MCH_PAY_CONFIG_ADD')">
<a-button :style="{ marginRight: '8px' }" @click="onClose" icon="close">取消</a-button>
<a-button type="primary" @click="onSubmit" icon="check" :loading="btnLoading">保存</a-button>
</div>
</a-drawer>
</template>
<script>
import JeepayCard from '@/components/JeepayCard/JeepayCard'
import JeepayUpload from '@/components/JeepayUpload/JeepayUpload'
import { API_URL_MCH_PAYCONFIGS_LIST, req, getMchPayConfigUnique, upload } from '@/api/manage'
export default {
components: {
JeepayCard,
JeepayUpload
},
props: {
callbackFunc: { type: Function, default: () => ({}) }
},
data () {
return {
btnLoading: false,
visible: false, // 抽屉开关
appId: null, // 商户号
ifCode: null, // 接口代码
mchType: null, // 商户类型:1-普通商户 2-特约商户
action: upload.cert, // 上传文件地址
mchParams: {}, // 支付接口定义描述
saveObject: {}, // 保存的对象
ifParams: {}, // 参数配置对象
rules: {
infoId: [{ required: true, trigger: 'blur' }],
ifCode: [{ required: true, trigger: 'blur' }],
ifRate: [{ required: false, pattern: /^(([1-9]{1}\d{0,1})|(0{1}))(\.\d{1,4})?$/, message: '请输入0-100之间的数字,最多四位小数', trigger: 'blur' }]
},
ifParamsRules: {}
}
},
methods: {
// 弹层打开事件
show: function (appId, record) {
this.appId = appId
this.ifCode = record.ifCode
this.mchType = record.mchType
this.saveObject = {} // 要保存的对象
this.ifParams = {} // 参数配置对象
this.mchParams = {} // 支付接口定义描述
this.saveObject.infoId = appId
this.saveObject.ifCode = record.ifCode
this.saveObject.state = record.ifConfigState === 0 ? 0 : 1
if (this.$refs.mchParamFormModel !== undefined) {
this.$refs.mchParamFormModel.resetFields()
}
this.getMchPayConfig(record)
},
// 支付参数配置
getMchPayConfig (record) {
const that = this
// 获取支付参数
getMchPayConfigUnique(that.saveObject.infoId, that.saveObject.ifCode).then(res => {
if (res && res.ifParams) {
that.saveObject = res
that.ifParams = JSON.parse(res.ifParams)
}
})
const newItems = [] // 重新加载支付接口配置定义描述json
let radioItems = [] // 存放单选框value title
const mchParams = record.mchParams // 根据商户类型获取接口定义描述
JSON.parse(mchParams).forEach(item => {
radioItems = []
if (item.type === 'radio') {
const valueItems = item.values.split(',')
const titleItems = item.titles.split(',')
for (const i in valueItems) {
radioItems.push({
value: valueItems[i],
title: titleItems[i]
})
}
}
newItems.push({
name: item.name,
desc: item.desc,
type: item.type,
verify: item.verify,
values: radioItems
})
})
that.mchParams = newItems // 重新赋值接口定义描述
that.visible = true // 打开支付参数配置抽屉
that.generoterRules()
},
// 表单提交
onSubmit () {
const that = this
this.$refs.infoFormModel.validate(valid => {
this.$refs.mchParamFormModel.validate(valid2 => {
if (valid && valid2) { // 验证通过
that.btnLoading = true
const reqParams = {}
reqParams.infoId = that.saveObject.infoId
reqParams.ifCode = that.saveObject.ifCode
reqParams.ifRate = that.saveObject.ifRate
reqParams.state = that.saveObject.state
reqParams.remark = that.saveObject.remark
// 支付参数配置不能为空
if (Object.keys(that.ifParams).length === 0) {
this.$message.error('参数不能为空!')
return
}
reqParams.ifParams = JSON.stringify(that.ifParams)
// 请求接口
if (Object.keys(reqParams).length === 0) {
this.$message.error('参数不能为空!')
return
}
req.add(API_URL_MCH_PAYCONFIGS_LIST, reqParams).then(res => {
that.$message.success('保存成功')
that.visible = false
that.btnLoading = false
that.callbackFunc()
})
}
})
})
},
// 上传文件成功回调方法,参数value为文件地址,name是自定义参数
uploadSuccess (value, name) {
this.ifParams[name] = value
this.$forceUpdate()
},
// 动态生成支付参数表单检验规则
generoterRules () {
const rules = {}
let newItems = []
this.mchParams.forEach(item => {
newItems = []
if (item.verify === 'required') {
newItems.push({
required: true,
message: '请输入' + item.desc,
trigger: 'blur'
})
rules[item.name] = newItems
}
})
this.ifParamsRules = rules
},
onClose () {
this.visible = false
}
}
}
</script>
<style lang="less" scoped>
.jeepay-card-content {
width: 100%;
position: relative;
background-color: @jee-card-back;
border-radius: 6px;
overflow:hidden;
}
.jeepay-card-ops {
width: 100%;
height: 50px;
background-color: @jee-card-back;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
border-top: 1px solid @jee-back;
position: absolute;
bottom: 0;
}
.jeepay-card-content-header {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.jeepay-card-content-body {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
}
.title {
font-size: 16px;
font-family: PingFang SC, PingFang SC-Bold;
font-weight: 700;
color: #1a1a1a;
letter-spacing: 1px;
}
</style>
<template>
<a-drawer
:visible="visible"
@close="onClose"
:closable="true"
:body-style="{ paddingBottom: '80px' }"
:drawer-style="{ backgroundColor: '#f0f2f5' }"
width="80%"
>
<template slot="title">
<a-steps :current="currentStep" type="navigation" style="width:80%">
<a-step title="支付参数配置" @click="stepChange(0)" />
<a-step title="支付通道配置" @click="stepChange(1)" />
</a-steps>
</template>
<div v-if="currentStep === 0">
<JeepayCard
ref="infoCard"
:reqCardListFunc="reqCardListFunc"
:span="jeepayCard.span"
:height="jeepayCard.height"
>
<div slot="cardContentSlot" slot-scope="{record}">
<div :style="{'height': jeepayCard.height + 'px'}" class="jeepay-card-content">
<!-- 卡片自定义样式 -->
<div class="jeepay-card-content-header" :style="{backgroundColor: record.bgColor, height: jeepayCard.height/2 + 'px'}">
<img v-if="record.icon" :src="record.icon" :style="{height: jeepayCard.height/5 + 'px'}">
</div>
<div class="jeepay-card-content-body" :style="{height: (jeepayCard.height/2 - 50) + 'px'}">
<div class="title">
{{ record.ifName }}
</div>
<a-badge :status="record.ifConfigState ===1 ? 'processing' : 'error'" :text="record.ifConfigState ===1 ? '启用' : '未开通'" ></a-badge>
</div>
<!-- 卡片底部操作栏 -->
<div class="jeepay-card-ops">
<a v-if="$access('ENT_MCH_PAY_CONFIG_ADD')" @click="editPayIfConfigFunc(record)">填写参数 <a-icon key="right" type="right" style="fontSize: 13px"></a-icon></a>
<a v-else>暂无操作</a>
</div>
</div>
</div>
</JeepayCard>
</div>
<div v-else-if="currentStep === 1">
<a-card>
<div class="table-page-search-wrapper">
<a-form layout="inline">
<a-row :gutter="10">
<a-col :md="4">
<a-form-item label="">
<a-input placeholder="支付方式代码" v-model="searchData2.wayCode"/>
</a-form-item>
</a-col>
<a-col :md="4">
<a-form-item label="">
<a-input placeholder="支付方式名称" v-model="searchData2.wayName"/>
</a-form-item>
</a-col>
<a-col :sm="6">
<span class="table-page-search-submitButtons">
<a-button type="primary" icon="search" @click="searchFunc(true)">查询</a-button>
<a-button style="margin-left: 8px" icon="reload" @click="() => this.searchData2 = {}">重置</a-button>
</span>
</a-col>
</a-row>
</a-form>
</div>
<!-- 列表渲染 -->
<JeepayTable
ref="infoTable"
:initData="true"
:reqTableDataFunc="reqTableDataFunc"
:tableColumns="tableColumns"
:searchData="searchData2"
>
<template slot="stateSlot" slot-scope="{record}">
<a-badge :status="record.passageState === 0?'error':'processing'" :text="record.passageState === 0?'禁用':'启用'" />
</template>
<template slot="opSlot" slot-scope="{record}"> <!-- 操作列插槽 -->
<JeepayTableColumns>
<a-button type="link" v-if="$access('ENT_MCH_PAY_PASSAGE_CONFIG')" @click="editPayPassageFunc(record)">配置</a-button>
</JeepayTableColumns>
</template>
</JeepayTable>
</a-card>
</div>
<div class="drawer-btn-center ">
<a-button :style="{ marginRight: '8px' }" @click="onClose" icon="close">关闭</a-button>
<a-button type="primary" icon="arrow-left" v-if="$access('ENT_MCH_PAY_CONFIG_LIST') && currentStep ===1" @click="stepChange(0)">上一步</a-button>
<a-button type="primary" icon="arrow-right" v-if="$access('ENT_MCH_PAY_PASSAGE_LIST') && currentStep ===0" @click="stepChange(1)">下一步</a-button>
</div>
<!-- 支付参数配置页面组件 -->
<MchPayConfigAddOrEdit ref="mchPayConfigAddOrEdit" :callbackFunc="refCardList" />
<!-- 支付通道配置页面组件 -->
<MchPayPassageAddOrEdit ref="mchPayPassageAddOrEdit" :callbackFunc="searchFunc"/>
</a-drawer>
</template>
<script>
import JeepayCard from '@/components/JeepayCard/JeepayCard'
import JeepayTable from '@/components/JeepayTable/JeepayTable'
import JeepayTableColumns from '@/components/JeepayTable/JeepayTableColumns'
import { API_URL_MCH_PAYCONFIGS_LIST, API_URL_MCH_PAYPASSAGE_LIST, req, getAvailablePayInterfaceList } from '@/api/manage'
import MchPayConfigAddOrEdit from './MchPayConfigAddOrEdit'
import MchPayPassageAddOrEdit from './MchPayPassageAddOrEdit'
// eslint-disable-next-line no-unused-vars
const tableColumns = [
{ key: 'wayCode', title: '支付方式代码', dataIndex: 'wayCode' },
{ key: 'wayName', title: '支付方式名称', dataIndex: 'wayName' },
{ key: 'passageState', title: '状态', scopedSlots: { customRender: 'stateSlot' } },
{ key: 'op', title: '操作', width: '200px', fixed: 'right', align: 'center', scopedSlots: { customRender: 'opSlot' } }
]
export default {
components: {
JeepayCard,
JeepayTable,
JeepayTableColumns,
MchPayConfigAddOrEdit,
MchPayPassageAddOrEdit
},
data () {
return {
currentStep: 0, // 当前步骤条index
btnLoading: false,
appId: null, // 应用appId
visible: false, // 抽屉开关
jeepayCard: { // 卡片配置
height: 300,
span: { xxl: 6, xl: 4, lg: 4, md: 3, sm: 2, xs: 1 }
},
tableColumns: tableColumns,
searchData2: {}
}
},
methods: {
// 弹层打开事件
show (appId) {
this.appId = appId
this.ifCode = null
this.currentStep = 0
this.visible = true
this.refCardList()
},
// 步骤条切换
stepChange (current) {
this.currentStep = current
},
// 请求支付接口定义数据
reqCardListFunc () {
return req.list(API_URL_MCH_PAYCONFIGS_LIST, { 'appId': this.appId })
},
// 刷新支付接口card列表
refCardList () {
this.$refs.infoCard.refCardList()
},
// 请求支付通道数据
reqTableDataFunc (params) {
const that = this
return req.list(API_URL_MCH_PAYPASSAGE_LIST, Object.assign(params, { appId: that.appId }))
},
searchFunc (isToFirst = false) { // 点击【查询】按钮点击事件
this.$refs.infoTable.refTable(isToFirst)
},
// 支付参数配置
editPayIfConfigFunc (record) {
if (!record) {
return
}
if (record.subMchIsvConfig === 0) {
this.$error({
title: '提示',
content: '服务商未配置,请联系服务商配置支付参数!'
})
return
}
this.$refs.mchPayConfigAddOrEdit.show(this.appId, record)
},
// 支付通道配置
editPayPassageFunc (record) {
const that = this
getAvailablePayInterfaceList(that.appId, record.wayCode).then(resData => {
if (!resData || resData.length === 0) {
that.$error({
title: '提示',
content: '暂无可用支付接口配置'
})
} else {
that.$refs.mchPayPassageAddOrEdit.show(that.appId, record.wayCode)
}
})
},
// 抽屉关闭
onClose () {
this.visible = false
}
}
}
</script>
<style lang="less" scoped>
.jeepay-card-content {
width: 100%;
position: relative;
background-color: @jee-card-back;
border-radius: 6px;
overflow:hidden;
}
.jeepay-card-ops {
width: 100%;
height: 50px;
background-color: @jee-card-back;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
border-top: 1px solid @jee-back;
position: absolute;
bottom: 0;
}
.jeepay-card-content-header {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.jeepay-card-content-body {
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.title {
font-size: 16px;
font-family: PingFang SC, PingFang SC-Bold;
font-weight: 700;
color: #1a1a1a;
letter-spacing: 1px;
}
</style>
<template>
<a-drawer
:visible="visible"
title="配置支付通道"
@close="onClose"
:closable="true"
:maskClosable="false"
:body-style="{ paddingBottom: '80px' }"
:drawer-style="{ backgroundColor: '#f0f2f5' }"
width="40%"
>
<a-list :data-source="[]" v-if="cardList.length === 0" />
<div v-else>
<a-row :gutter="[24,24]" style="width:100%">
<a-col
v-for="(record, key) in cardList"
:key="key"
:xxl="24/jeepayCard.span.xxl"
:xl="24/jeepayCard.span.xl"
:lg="24/jeepayCard.span.lg"
:md="24/jeepayCard.span.md"
:sm="24/jeepayCard.span.sm"
:xs="24/jeepayCard.span.xs"
>
<div :style="{'height': jeepayCard.height + 'px'}" class="jeepay-card-content">
<!-- 卡片自定义样式 -->
<div class="jeepay-card-content-header" :style="{backgroundColor: record.bgColor, height: (jeepayCard.height-50)/2 + 'px'}">
<img v-if="record.icon" :src="record.icon" :style="{height: (jeepayCard.height-50)/5 + 'px'}">
</div>
<div class="jeepay-card-content-body" :style="{height: ((jeepayCard.height-50)/2) + 'px'}">
<div class="title" :style="{height: ((jeepayCard.height-50)/4) + 'px', lineHeight: ((jeepayCard.height-50)/4) + 'px'}">
{{ record.ifName }}
</div>
<a-form layout="inline" :labelCol="{span:8}" :wrapperCol="{span:14}">
<a-form-item label="费率:" :validate-status="record.error" :help="record.help">
<a-input v-model="record.rate" :disabled="!record.state && record.passageId != ''" suffix="%" />
</a-form-item>
</a-form>
</div>
<!-- 卡片底部操作栏 -->
<div class="jeepay-card-ops">
<a-switch checked-children="启用" un-checked-children="停用" v-model="record.state"></a-switch>
</div>
</div>
</a-col>
</a-row>
<div
:style="{
position: 'absolute',
right: 0,
bottom: 0,
width: '100%',
borderTop: '1px solid #e9e9e9',
padding: '10px 16px',
background: '#fff',
textAlign: 'center',
zIndex: 1
}"
>
<a-button icon="close" :style="{ marginRight: '8px' }" @click="onClose">
取消
</a-button>
<a-button type="primary" icon="check" v-if="$access('ENT_MCH_PAY_PASSAGE_ADD')" @click="handleOkFunc">
保存
</a-button>
</div>
</div>
</a-drawer>
</template>
<script>
import JeepayCard from '@/components/JeepayCard/JeepayCard'
import { API_URL_MCH_PAYPASSAGE_LIST, req, getAvailablePayInterfaceList } from '@/api/manage'
export default {
components: {
JeepayCard
},
props: {
callbackFunc: { type: Function, default: () => ({}) }
},
data () {
return {
cardList: [],
appId: null, // 应用appId
wayCode: null, // 支付方式代码
visible: false, // 是否显示弹层/抽屉
jeepayCard: {
height: 300,
span: { xxl: 3, xl: 2, lg: 2, md: 1, sm: 1, xs: 1 }
}
}
},
methods: {
// 弹层打开事件
show: function (appId, wayCode) {
this.appId = appId
this.wayCode = wayCode
this.visible = true
this.cardList = []
this.refCardList()
},
// 请求支付接口定义数据
refCardList () {
const that = this
getAvailablePayInterfaceList(this.appId, this.wayCode).then(resData => {
if (resData === undefined || resData.length === 0) {
that.cardList = []
return
}
const newItems = []
resData.forEach(item => {
newItems.push({
passageId: item.passageId ? item.passageId : '',
ifCode: item.ifCode,
ifName: item.ifName,
icon: item.icon,
bgColor: item.bgColor,
rate: item.rate,
state: item.state === 1
})
})
that.cardList = newItems
that.$forceUpdate()
})
},
handleOkFunc: function () { // 点击【确认】按钮事件
const that = this
const reqParams = []
try {
that.cardList.forEach(item => {
item.error = ''
item.help = ''
const reg = /^(([1-9]{1}\d{0,1})|(0{1}))(\.\d{1,4})?$/
// 状态开启则费率必填
if (item.state) {
if (!item.rate) {
item.error = 'error'
item.help = '请输入费率'
throw new Error('error')
}
if (!reg.test(item.rate) || item.rate > 100) {
item.error = 'error'
item.help = '最多四位小数'
throw new Error('error')
}
}
reqParams.push({
id: item.passageId,
appId: that.appId,
wayCode: that.wayCode,
ifCode: item.ifCode,
rate: item.rate,
state: item.state ? 1 : 0
})
})
} catch (e) {
if (e.message === 'error') {
this.$forceUpdate()
return
}
}
// 请求接口
req.add(API_URL_MCH_PAYPASSAGE_LIST, { 'reqParams': JSON.stringify(reqParams) }).then(res => {
that.$message.success('保存成功')
that.visible = false
that.callbackFunc()
})
},
onClose () {
this.visible = false
}
}
}
</script>
<style lang="less" scoped>
.jeepay-card-content {
width: 100%;
position: relative;
background-color: @jee-card-back;
border-radius: 6px;
overflow:hidden;
}
.jeepay-card-ops {
width: 100%;
height: 50px;
background-color: @jee-card-back;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
border-top: 1px solid @jee-back;
position: absolute;
bottom: 0;
}
.jeepay-card-content-header {
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.jeepay-card-content-body {
display: flex;
flex-direction: column;
justify-content: start;
align-items: center;
}
.title {
font-size: 16px;
font-family: PingFang SC, PingFang SC-Bold;
font-weight: 700;
color: #1a1a1a;
letter-spacing: 1px;
}
</style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册