Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
dae9bc13
authored
Aug 05, 2023
by
芋道源码
Committed by
Gitee
Aug 05, 2023
Browse files
Options
Browse Files
Download
Plain Diff
!188 feat: 支付管理/应用信息
Merge pull request !188 from dhb52/master
parents
945903d6
36268cf8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
889 additions
and
115 deletions
+889
-115
src/api/pay/channel/index.ts
+2
-4
src/utils/constants.ts
+6
-1
src/views/pay/app/components/AppForm.vue
+3
-18
src/views/pay/app/components/alipayChannelForm.vue
+315
-0
src/views/pay/app/components/mockChannelForm.vue
+130
-0
src/views/pay/app/components/weixinChannelForm.vue
+343
-0
src/views/pay/app/index.vue
+89
-91
src/views/pay/order/index.vue
+1
-1
No files found.
src/api/pay/channel/index.ts
View file @
dae9bc13
...
@@ -7,7 +7,6 @@ export interface ChannelVO {
...
@@ -7,7 +7,6 @@ export interface ChannelVO {
status
:
number
status
:
number
remark
:
string
remark
:
string
feeRate
:
number
feeRate
:
number
merchantId
:
number
appId
:
number
appId
:
number
createTime
:
Date
createTime
:
Date
}
}
...
@@ -18,13 +17,12 @@ export const getChannelPage = (params: PageParam) => {
...
@@ -18,13 +17,12 @@ export const getChannelPage = (params: PageParam) => {
}
}
// 查询详情支付渠道
// 查询详情支付渠道
export
const
getChannel
=
(
merchantId
:
number
,
appId
:
string
,
code
:
string
)
=>
{
export
const
getChannel
=
(
appId
:
string
,
code
:
string
)
=>
{
const
params
=
{
const
params
=
{
merchantId
:
merchantId
,
appId
:
appId
,
appId
:
appId
,
code
:
code
code
:
code
}
}
return
request
.
get
({
url
:
'/pay/channel/get
-channel
'
,
params
:
params
})
return
request
.
get
({
url
:
'/pay/channel/get'
,
params
:
params
})
}
}
// 新增支付渠道
// 新增支付渠道
...
...
src/utils/constants.ts
View file @
dae9bc13
...
@@ -118,6 +118,10 @@ export const PayChannelEnum = {
...
@@ -118,6 +118,10 @@ export const PayChannelEnum = {
ALIPAY_BAR
:
{
ALIPAY_BAR
:
{
code
:
'alipay_bar'
,
code
:
'alipay_bar'
,
name
:
'支付宝条码支付'
name
:
'支付宝条码支付'
},
MOCK
:
{
code
:
'mock'
,
name
:
'模拟支付'
}
}
}
}
...
@@ -126,7 +130,8 @@ export const PayChannelEnum = {
...
@@ -126,7 +130,8 @@ export const PayChannelEnum = {
*/
*/
export
const
PayType
=
{
export
const
PayType
=
{
WECHAT
:
'WECHAT'
,
WECHAT
:
'WECHAT'
,
ALIPAY
:
'ALIPAY'
ALIPAY
:
'ALIPAY'
,
MOCK
:
'MOCK'
}
}
/**
/**
...
...
src/views/pay/app/AppForm.vue
→
src/views/pay/app/
components/
AppForm.vue
View file @
dae9bc13
...
@@ -10,16 +10,6 @@
...
@@ -10,16 +10,6 @@
<el-form-item
label=
"应用名"
prop=
"name"
>
<el-form-item
label=
"应用名"
prop=
"name"
>
<el-input
v-model=
"formData.name"
placeholder=
"请输入应用名"
/>
<el-input
v-model=
"formData.name"
placeholder=
"请输入应用名"
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"所属商户"
prop=
"merchantId"
>
<el-select
v-model=
"formData.merchantId"
placeholder=
"请选择所属商户"
>
<el-option
v-for=
"item in merchantList"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"开启状态"
prop=
"status"
>
<el-form-item
label=
"开启状态"
prop=
"status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio
<el-radio
...
@@ -47,10 +37,10 @@
...
@@ -47,10 +37,10 @@
</
template
>
</
template
>
</Dialog>
</Dialog>
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
*
as
AppApi
from
'@/api/pay/app'
import
*
as
AppApi
from
'@/api/pay/app'
import
*
as
MerchantApi
from
'@/api/pay/merchant'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
defineOptions
({
name
:
'PayAppForm'
})
defineOptions
({
name
:
'PayAppForm'
})
...
@@ -77,11 +67,9 @@ const formRules = reactive({
...
@@ -77,11 +67,9 @@ const formRules = reactive({
name
:
[{
required
:
true
,
message
:
'应用名不能为空'
,
trigger
:
'blur'
}],
name
:
[{
required
:
true
,
message
:
'应用名不能为空'
,
trigger
:
'blur'
}],
status
:
[{
required
:
true
,
message
:
'开启状态不能为空'
,
trigger
:
'blur'
}],
status
:
[{
required
:
true
,
message
:
'开启状态不能为空'
,
trigger
:
'blur'
}],
payNotifyUrl
:
[{
required
:
true
,
message
:
'支付结果的回调地址不能为空'
,
trigger
:
'blur'
}],
payNotifyUrl
:
[{
required
:
true
,
message
:
'支付结果的回调地址不能为空'
,
trigger
:
'blur'
}],
refundNotifyUrl
:
[{
required
:
true
,
message
:
'退款结果的回调地址不能为空'
,
trigger
:
'blur'
}],
refundNotifyUrl
:
[{
required
:
true
,
message
:
'退款结果的回调地址不能为空'
,
trigger
:
'blur'
}]
merchantId
:
[{
required
:
true
,
message
:
'商户编号不能为空'
,
trigger
:
'blur'
}]
})
})
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
merchantList
=
ref
([])
// 商户列表
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
const
open
=
async
(
type
:
string
,
id
?:
number
)
=>
{
...
@@ -98,8 +86,6 @@ const open = async (type: string, id?: number) => {
...
@@ -98,8 +86,6 @@ const open = async (type: string, id?: number) => {
formLoading
.
value
=
false
formLoading
.
value
=
false
}
}
}
}
// 加载商户列表
merchantList
.
value
=
await
MerchantApi
.
getMerchantListByName
()
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
...
@@ -137,8 +123,7 @@ const resetForm = () => {
...
@@ -137,8 +123,7 @@ const resetForm = () => {
status
:
CommonStatusEnum
.
ENABLE
,
status
:
CommonStatusEnum
.
ENABLE
,
remark
:
undefined
,
remark
:
undefined
,
payNotifyUrl
:
undefined
,
payNotifyUrl
:
undefined
,
refundNotifyUrl
:
undefined
,
refundNotifyUrl
:
undefined
merchantId
:
undefined
}
}
formRef
.
value
?.
resetFields
()
formRef
.
value
?.
resetFields
()
}
}
...
...
src/views/pay/app/components/alipayChannelForm.vue
0 → 100644
View file @
dae9bc13
<
template
>
<div>
<el-dialog
v-model=
"dialogVisible"
:title=
"title"
@
closed=
"close"
append-to-body
destroy-on-close
width=
"830px"
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"rules"
label-width=
"100px"
v-loading=
"formLoading"
>
<el-form-item
label-width=
"180px"
label=
"渠道费率"
prop=
"feeRate"
>
<el-input
v-model=
"formData.feeRate"
placeholder=
"请输入渠道费率"
clearable
>
<template
#
append
>
%
</
template
>
</el-input>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"开放平台 APPID"
prop=
"config.appId"
>
<el-input
v-model=
"formData.config.appId"
placeholder=
"请输入开放平台 APPID"
clearable
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"渠道状态"
prop=
"status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio
v-for=
"dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key=
"parseInt(dict.value)"
:label=
"parseInt(dict.value)"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"网关地址"
prop=
"config.serverUrl"
>
<el-radio-group
v-model=
"formData.config.serverUrl"
>
<el-radio
label=
"https://openapi.alipay.com/gateway.do"
>
线上环境
</el-radio>
<el-radio
label=
"https://openapi-sandbox.dl.alipaydev.com/gateway.do"
>
沙箱环境
</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"算法类型"
prop=
"config.signType"
>
<el-radio-group
v-model=
"formData.config.signType"
>
<el-radio
key=
"RSA2"
label=
"RSA2"
>
RSA2
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"公钥类型"
prop=
"config.mode"
>
<el-radio-group
v-model=
"formData.config.mode"
>
<el-radio
key=
"公钥模式"
:label=
"1"
>
公钥模式
</el-radio>
<el-radio
key=
"证书模式"
:label=
"2"
>
证书模式
</el-radio>
</el-radio-group>
</el-form-item>
<div
v-if=
"formData.config.mode === 1"
>
<el-form-item
label-width=
"180px"
label=
"应用私钥"
prop=
"config.privateKey"
>
<el-input
type=
"textarea"
:autosize=
"{ minRows: 8, maxRows: 8 }"
v-model=
"formData.config.privateKey"
placeholder=
"请输入应用私钥"
clearable
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"支付宝公钥"
prop=
"config.alipayPublicKey"
>
<el-input
type=
"textarea"
:autosize=
"{ minRows: 8, maxRows: 8 }"
v-model=
"formData.config.alipayPublicKey"
placeholder=
"请输入支付宝公钥"
clearable
:style=
"{ width: '100%' }"
/>
</el-form-item>
</div>
<div
v-if=
"formData.config.mode === 2"
>
<el-form-item
label-width=
"180px"
label=
"商户公钥应用证书"
prop=
"config.appCertContent"
>
<el-input
v-model=
"formData.config.appCertContent"
type=
"textarea"
placeholder=
"请上传商户公钥应用证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
>
<el-upload
action=
""
ref=
"privateKeyContentFile"
:limit=
"1"
:accept=
"fileAccept"
:http-request=
"appCertUpload"
:before-upload=
"fileBeforeUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"支付宝公钥证书"
prop=
"config.alipayPublicCertContent"
>
<el-input
v-model=
"formData.config.alipayPublicCertContent"
type=
"textarea"
placeholder=
"请上传支付宝公钥证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
>
<el-upload
ref=
"privateCertContentFile"
action=
""
:limit=
"1"
:accept=
"fileAccept"
:before-upload=
"fileBeforeUpload"
:http-request=
"alipayPublicCertUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"根证书"
prop=
"config.rootCertContent"
>
<el-input
v-model=
"formData.config.rootCertContent"
type=
"textarea"
placeholder=
"请上传根证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
>
<el-upload
ref=
"privateCertContentFile"
:limit=
"1"
:accept=
"fileAccept"
action=
""
:before-upload=
"fileBeforeUpload"
:http-request=
"rootCertUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
</div>
<el-form-item
label-width=
"180px"
label=
"备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
:style=
"{ width: '100%' }"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"close"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确定
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
lang=
"ts"
setup
name=
"AlipayChannelForm"
>
import
{
createChannel
,
getChannel
,
updateChannel
}
from
'@/api/pay/channel'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
{
DICT_TYPE
,
getDictOptions
}
from
'@/utils/dict'
const
message
=
useMessage
()
// 消息弹窗
const
emit
=
defineEmits
([
'success'
])
const
dialogVisible
=
ref
(
false
)
const
formLoading
=
ref
(
false
)
const
title
=
ref
(
''
)
const
formData
=
ref
<
any
>
({
appId
:
''
,
code
:
''
,
status
:
undefined
,
feeRate
:
undefined
,
remark
:
''
,
config
:
{
appId
:
''
,
serverUrl
:
null
,
signType
:
''
,
mode
:
null
,
privateKey
:
''
,
alipayPublicKey
:
''
,
appCertContent
:
''
,
alipayPublicCertContent
:
''
,
rootCertContent
:
''
}
})
const
rules
=
{
feeRate
:
[{
required
:
true
,
message
:
'请输入渠道费率'
,
trigger
:
'blur'
}],
status
:
[{
required
:
true
,
message
:
'渠道状态不能为空'
,
trigger
:
'blur'
}],
'config.appId'
:
[{
required
:
true
,
message
:
'请输入开放平台上创建的应用的 ID'
,
trigger
:
'blur'
}],
'config.serverUrl'
:
[{
required
:
true
,
message
:
'请传入网关地址'
,
trigger
:
'blur'
}],
'config.signType'
:
[{
required
:
true
,
message
:
'请传入签名算法类型'
,
trigger
:
'blur'
}],
'config.mode'
:
[{
required
:
true
,
message
:
'公钥类型不能为空'
,
trigger
:
'blur'
}],
'config.privateKey'
:
[{
required
:
true
,
message
:
'请输入商户私钥'
,
trigger
:
'blur'
}],
'config.alipayPublicKey'
:
[
{
required
:
true
,
message
:
'请输入支付宝公钥字符串'
,
trigger
:
'blur'
}
],
'config.appCertContent'
:
[{
required
:
true
,
message
:
'请上传商户公钥应用证书'
,
trigger
:
'blur'
}],
'config.alipayPublicCertContent'
:
[
{
required
:
true
,
message
:
'请上传支付宝公钥证书'
,
trigger
:
'blur'
}
],
'config.rootCertContent'
:
[{
required
:
true
,
message
:
'请上传指定根证书'
,
trigger
:
'blur'
}]
}
const
fileAccept
=
'.crt'
const
formRef
=
ref
()
const
open
=
async
(
appId
,
code
)
=>
{
dialogVisible
.
value
=
true
formLoading
.
value
=
true
reset
(
appId
,
code
)
try
{
const
data
=
await
getChannel
(
appId
,
code
)
if
(
data
&&
data
.
id
)
{
formData
.
value
=
data
formData
.
value
.
config
=
JSON
.
parse
(
data
.
config
)
}
title
.
value
=
!
formData
.
value
.
id
?
'创建支付渠道'
:
'编辑支付渠道'
}
finally
{
formLoading
.
value
=
false
}
}
defineExpose
({
open
})
const
close
=
()
=>
{
dialogVisible
.
value
=
false
reset
(
undefined
,
undefined
)
}
const
submitForm
=
async
()
=>
{
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
const
data
:
any
=
{
...
formData
.
value
}
data
.
config
=
JSON
.
stringify
(
formData
.
value
.
config
)
if
(
!
data
.
id
)
{
await
createChannel
(
data
)
message
.
success
(
'新增成功'
)
}
else
{
await
updateChannel
(
data
)
message
.
success
(
'修改成功'
)
}
emit
(
'success'
)
close
()
}
/** 重置表单 */
const
reset
=
(
appId
,
code
)
=>
{
formData
.
value
=
{
appId
:
appId
,
code
:
code
,
status
:
CommonStatusEnum
.
ENABLE
,
remark
:
''
,
feeRate
:
null
,
config
:
{
appId
:
''
,
serverUrl
:
null
,
signType
:
'RSA2'
,
mode
:
null
,
privateKey
:
''
,
alipayPublicKey
:
''
,
appCertContent
:
''
,
alipayPublicCertContent
:
''
,
rootCertContent
:
''
}
}
// formRef.value?.resetFields()
}
const
fileBeforeUpload
=
(
file
)
=>
{
let
format
=
'.'
+
file
.
name
.
split
(
'.'
)[
1
]
if
(
format
!==
fileAccept
)
{
message
.
error
(
`请上传指定格式"
${
fileAccept
}
"文件`
)
return
false
}
let
isRightSize
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isRightSize
)
{
message
.
error
(
'文件大小超过 2MB'
)
}
return
isRightSize
}
const
appCertUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
appCertContent
=
e
.
target
.
result
}
readFile
.
readAsText
(
event
.
file
)
}
const
alipayPublicCertUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
alipayPublicCertContent
=
e
.
target
.
result
}
readFile
.
readAsText
(
event
.
file
)
}
const
rootCertUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
rootCertContent
=
e
.
target
.
result
}
readFile
.
readAsText
(
event
.
file
)
}
</
script
>
src/views/pay/app/components/mockChannelForm.vue
0 → 100644
View file @
dae9bc13
<
template
>
<div>
<el-dialog
v-model:visible=
"dialogVisible"
:title=
"title"
@
closed=
"close"
append-to-body
destroy-on-close
width=
"800px"
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"rules"
label-width=
"100px"
v-loading=
"formLoading"
>
<el-form-item
label-width=
"180px"
label=
"渠道状态"
prop=
"status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio
v-for=
"dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key=
"parseInt(dict.value)"
:label=
"parseInt(dict.value)"
>
{{
dict
.
label
}}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
:style=
"
{ width: '100%' }" />
</el-form-item>
</el-form>
<template
#
footer
>
<el-button
@
click=
"close"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确定
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
lang=
"ts"
setup
name=
"MockChannelForm"
>
import
{
createChannel
,
getChannel
,
updateChannel
}
from
'@/api/pay/channel'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
{
DICT_TYPE
,
getDictOptions
}
from
'@/utils/dict'
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
const
formLoading
=
ref
(
false
)
const
title
=
ref
(
''
)
const
formData
=
ref
<
any
>
({
appId
:
''
,
code
:
''
,
status
:
undefined
,
feeRate
:
0
,
remark
:
''
,
config
:
{
name
:
'mock-conf'
}
})
const
rules
=
{
status
:
[{
required
:
true
,
message
:
'渠道状态不能为空'
,
trigger
:
'blur'
}]
}
const
formRef
=
ref
()
const
emit
=
defineEmits
([
'success'
])
const
open
=
async
(
appId
,
code
)
=>
{
dialogVisible
.
value
=
true
formLoading
.
value
=
true
reset
(
appId
,
code
)
try
{
const
data
=
await
getChannel
(
appId
,
code
)
if
(
data
&&
data
.
id
)
{
formData
.
value
=
data
formData
.
value
.
config
=
JSON
.
parse
(
data
.
config
)
}
title
.
value
=
!
formData
.
value
.
id
?
'创建支付渠道'
:
'编辑支付渠道'
}
finally
{
formLoading
.
value
=
false
}
}
const
close
=
()
=>
{
dialogVisible
.
value
=
false
reset
(
undefined
,
undefined
)
}
const
submitForm
=
async
()
=>
{
const
valid
=
await
formRef
.
value
?.
validate
()
if
(
!
valid
)
{
return
}
const
data
=
{
...
formData
.
value
}
data
.
config
=
JSON
.
stringify
(
formData
.
value
.
config
)
if
(
!
data
.
id
)
{
createChannel
(
data
).
then
(()
=>
{
message
.
success
(
'新增成功'
)
emit
(
'success'
)
close
()
})
}
else
{
updateChannel
(
data
).
then
(()
=>
{
message
.
success
(
'修改成功'
)
emit
(
'success'
)
close
()
})
}
}
/** 重置表单 */
const
reset
=
(
appId
,
code
)
=>
{
formData
.
value
=
{
appId
:
appId
,
code
:
code
,
status
:
CommonStatusEnum
.
ENABLE
,
remark
:
''
,
feeRate
:
0
,
config
:
{
name
:
'mock-conf'
}
}
formRef
.
value
?.
resetFields
()
}
defineExpose
({
open
})
</
script
>
src/views/pay/app/components/weixinChannelForm.vue
0 → 100644
View file @
dae9bc13
<
template
>
<div>
<el-dialog
v-model=
"dialogVisible"
:title=
"title"
@
close=
"close"
append-to-body
destroy-on-close
width=
"800px"
>
<el-form
ref=
"formRef"
:model=
"formData"
:rules=
"rules"
label-width=
"120px"
v-loading=
"formLoading"
>
<el-form-item
label-width=
"180px"
label=
"渠道费率"
prop=
"feeRate"
>
<el-input
v-model=
"formData.feeRate"
placeholder=
"请输入渠道费率"
clearable
:style=
"
{ width: '100%' }"
>
<template
#
append
>
%
</
template
>
</el-input>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"公众号 APPID"
prop=
"config.appId"
>
<el-input
v-model=
"formData.config.appId"
placeholder=
"请输入公众号 APPID"
clearable
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"商户号"
prop=
"config.mchId"
>
<el-input
v-model=
"formData.config.mchId"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"渠道状态"
prop=
"status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio
v-for=
"dict in getDictOptions(DICT_TYPE.COMMON_STATUS)"
:key=
"parseInt(dict.value)"
:label=
"parseInt(dict.value)"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"API 版本"
prop=
"config.apiVersion"
>
<el-radio-group
v-model=
"formData.config.apiVersion"
>
<el-radio
label=
"v2"
>
v2
</el-radio>
<el-radio
label=
"v3"
>
v3
</el-radio>
</el-radio-group>
</el-form-item>
<div
v-if=
"formData.config.apiVersion === 'v2'"
>
<el-form-item
label-width=
"180px"
label=
"商户密钥"
prop=
"config.mchKey"
>
<el-input
v-model=
"formData.config.mchKey"
placeholder=
"请输入商户密钥"
clearable
:style=
"{ width: '100%' }"
type=
"textarea"
:autosize=
"{ minRows: 8, maxRows: 8 }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"apiclient_cert.p12 证书"
prop=
"config.keyContent"
>
<el-input
v-model=
"formData.config.keyContent"
type=
"textarea"
placeholder=
"请上传 apiclient_cert.p12 证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
>
<el-upload
:limit=
"1"
accept=
".p12"
action=
""
:before-upload=
"p12FileBeforeUpload"
:http-request=
"keyContentUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
</div>
<div
v-if=
"formData.config.apiVersion === 'v3'"
>
<el-form-item
label-width=
"180px"
label=
"API V3 密钥"
prop=
"config.apiV3Key"
>
<el-input
v-model=
"formData.config.apiV3Key"
placeholder=
"请输入 API V3 密钥"
clearable
:style=
"{ width: '100%' }"
type=
"textarea"
:autosize=
"{ minRows: 8, maxRows: 8 }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"apiclient_key.pem 证书"
prop=
"config.privateKeyContent"
>
<el-input
v-model=
"formData.config.privateKeyContent"
type=
"textarea"
placeholder=
"请上传 apiclient_key.pem 证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
prop=
"privateKeyContentFile"
>
<el-upload
ref=
"privateKeyContentFile"
:limit=
"1"
accept=
".pem"
action=
""
:before-upload=
"pemFileBeforeUpload"
:http-request=
"privateKeyContentUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
"apiclient_cert.pem证书"
prop=
"config.privateCertContent"
>
<el-input
v-model=
"formData.config.privateCertContent"
type=
"textarea"
placeholder=
"请上传apiclient_cert.pem证书"
readonly
:autosize=
"{ minRows: 8, maxRows: 8 }"
:style=
"{ width: '100%' }"
/>
</el-form-item>
<el-form-item
label-width=
"180px"
label=
""
prop=
"privateCertContentFile"
>
<el-upload
ref=
"privateCertContentFile"
:limit=
"1"
accept=
".pem"
action=
""
:before-upload=
"pemFileBeforeUpload"
:http-request=
"privateCertContentUpload"
>
<el-button
size=
"small"
type=
"primary"
icon=
"el-icon-upload"
>
点击上传
</el-button>
</el-upload>
</el-form-item>
</div>
<el-form-item
label-width=
"180px"
label=
"备注"
prop=
"remark"
>
<el-input
v-model=
"formData.remark"
:style=
"{ width: '100%' }"
/>
</el-form-item>
</el-form>
<
template
#
footer
>
<el-button
@
click=
"close"
>
取消
</el-button>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确定
</el-button>
</
template
>
</el-dialog>
</div>
</template>
<
script
lang=
"ts"
setup
name=
"WeixinChannelForm"
>
import
{
createChannel
,
getChannel
,
updateChannel
}
from
'@/api/pay/channel'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
import
{
DICT_TYPE
,
getDictOptions
}
from
'@/utils/dict'
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
const
formLoading
=
ref
(
false
)
const
title
=
ref
(
''
)
const
formData
=
ref
<
any
>
({
appId
:
''
,
code
:
''
,
status
:
undefined
,
feeRate
:
undefined
,
remark
:
''
,
config
:
{
appId
:
''
,
mchId
:
''
,
apiVersion
:
''
,
mchKey
:
''
,
keyContent
:
''
,
privateKeyContent
:
''
,
privateCertContent
:
''
,
apiV3Key
:
''
}
})
const
formRef
=
ref
()
const
emit
=
defineEmits
([
'success'
])
const
rules
=
{
feeRate
:
[{
required
:
true
,
message
:
'请输入渠道费率'
,
trigger
:
'blur'
}],
status
:
[{
required
:
true
,
message
:
'渠道状态不能为空'
,
trigger
:
'blur'
}],
'config.mchId'
:
[{
required
:
true
,
message
:
'请传入商户号'
,
trigger
:
'blur'
}],
'config.appId'
:
[{
required
:
true
,
message
:
'请输入公众号APPID'
,
trigger
:
'blur'
}],
'config.apiVersion'
:
[{
required
:
true
,
message
:
'API版本不能为空'
,
trigger
:
'blur'
}],
'config.mchKey'
:
[{
required
:
true
,
message
:
'请输入商户密钥'
,
trigger
:
'blur'
}],
'config.keyContent'
:
[
{
required
:
true
,
message
:
'请上传 apiclient_cert.p12 证书'
,
trigger
:
'blur'
}
],
'config.privateKeyContent'
:
[
{
required
:
true
,
message
:
'请上传 apiclient_key.pem 证书'
,
trigger
:
'blur'
}
],
'config.privateCertContent'
:
[
{
required
:
true
,
message
:
'请上传 apiclient_cert.pem证 书'
,
trigger
:
'blur'
}
],
'config.apiV3Key'
:
[{
required
:
true
,
message
:
'请上传 api V3 密钥值'
,
trigger
:
'blur'
}]
}
const
open
=
async
(
appId
,
code
)
=>
{
dialogVisible
.
value
=
true
formLoading
.
value
=
true
reset
(
appId
,
code
)
try
{
const
data
=
await
getChannel
(
appId
,
code
)
if
(
data
&&
data
.
id
)
{
formData
.
value
=
data
formData
.
value
.
config
=
JSON
.
parse
(
data
.
config
)
}
title
.
value
=
!
formData
.
value
.
id
?
'创建支付渠道'
:
'编辑支付渠道'
}
finally
{
formLoading
.
value
=
false
}
}
const
close
=
()
=>
{
dialogVisible
.
value
=
false
reset
(
undefined
,
undefined
)
}
const
submitForm
=
async
()
=>
{
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
{
return
}
const
data
:
any
=
{
...
formData
.
value
}
data
.
config
=
JSON
.
stringify
(
formData
.
value
.
config
)
if
(
!
data
.
id
)
{
createChannel
(
data
).
then
(()
=>
{
message
.
alertSuccess
(
'新增成功'
)
emit
(
'success'
)
close
()
})
}
else
{
updateChannel
(
data
).
then
(()
=>
{
message
.
alertSuccess
(
'修改成功'
)
emit
(
'success'
)
close
()
})
}
}
/** 重置表单 */
const
reset
=
(
appId
,
code
)
=>
{
formData
.
value
=
{
appId
:
appId
,
code
:
code
,
status
:
CommonStatusEnum
.
ENABLE
,
feeRate
:
undefined
,
remark
:
''
,
config
:
{
appId
:
''
,
mchId
:
''
,
apiVersion
:
''
,
mchKey
:
''
,
keyContent
:
''
,
privateKeyContent
:
''
,
privateCertContent
:
''
,
apiV3Key
:
''
}
}
formRef
.
value
?.
resetFields
()
}
/**
* apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem 上传前的校验
*/
const
fileBeforeUpload
=
(
file
,
fileAccept
)
=>
{
let
format
=
'.'
+
file
.
name
.
split
(
'.'
)[
1
]
if
(
format
!==
fileAccept
)
{
debugger
message
.
error
(
'请上传指定格式"'
+
fileAccept
+
'"文件'
)
return
false
}
let
isRightSize
=
file
.
size
/
1024
/
1024
<
2
if
(
!
isRightSize
)
{
message
.
error
(
'文件大小超过 2MB'
)
}
return
isRightSize
}
const
p12FileBeforeUpload
=
(
file
)
=>
{
fileBeforeUpload
(
file
,
'.p12'
)
}
const
pemFileBeforeUpload
=
(
file
)
=>
{
fileBeforeUpload
(
file
,
'.pem'
)
}
/**
* 读取 apiclient_key.pem 到 privateKeyContent 字段
*/
const
privateKeyContentUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
privateKeyContent
=
e
.
target
.
result
}
readFile
.
readAsText
(
event
.
file
)
}
/**
* 读取 apiclient_cert.pem 到 privateCertContent 字段
*/
const
privateCertContentUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
privateCertContent
=
e
.
target
.
result
}
readFile
.
readAsText
(
event
.
file
)
}
/**
* 读取 apiclient_cert.p12 到 keyContent 字段
*/
const
keyContentUpload
=
(
event
)
=>
{
const
readFile
=
new
FileReader
()
readFile
.
onload
=
(
e
:
any
)
=>
{
formData
.
value
.
config
.
keyContent
=
e
.
target
.
result
.
split
(
','
)[
1
]
}
readFile
.
readAsDataURL
(
event
.
file
)
// 读成 base64
}
defineExpose
({
open
})
</
script
>
src/views/pay/app/index.vue
View file @
dae9bc13
...
@@ -17,15 +17,6 @@
...
@@ -17,15 +17,6 @@
class=
"!w-240px"
class=
"!w-240px"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
label=
"商户名称"
prop=
"contactName"
>
<el-input
v-model=
"queryParams.contactName"
placeholder=
"请输入商户名称"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"开启状态"
prop=
"status"
>
<el-form-item
label=
"开启状态"
prop=
"status"
>
<el-select
<el-select
v-model=
"queryParams.status"
v-model=
"queryParams.status"
...
@@ -53,8 +44,8 @@
...
@@ -53,8 +44,8 @@
/>
/>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"handleQuery"
>
<Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
@
click=
"resetQuery"
>
<Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
<el-button
type=
"primary"
type=
"primary"
plain
plain
...
@@ -83,19 +74,21 @@
...
@@ -83,19 +74,21 @@
<el-table-column
label=
"应用名"
align=
"center"
prop=
"name"
/>
<el-table-column
label=
"应用名"
align=
"center"
prop=
"name"
/>
<el-table-column
label=
"开启状态"
align=
"center"
prop=
"status"
>
<el-table-column
label=
"开启状态"
align=
"center"
prop=
"status"
>
<template
#
default=
"scope"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.COMMON_STATUS"
:value=
"scope.row.status"
/>
<el-switch
v-model=
"scope.row.status"
:active-value=
"0"
:inactive-value=
"1"
@
change=
"handleStatusChange(scope.row)"
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"商户名称"
align=
"center"
prop=
"payMerchant.name"
/>
<el-table-column
label=
"支付宝配置"
align=
"center"
>
<el-table-column
label=
"支付宝配置"
align=
"center"
>
<el-table-column
:label=
"PayChannelEnum.ALIPAY_APP.name"
align=
"center"
>
<el-table-column
:label=
"PayChannelEnum.ALIPAY_APP.name"
align=
"center"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<el-button
<el-button
type=
"success"
type=
"success"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_APP.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_APP.code)"
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)"
handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)
"
circle
circle
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
...
@@ -104,9 +97,7 @@
...
@@ -104,9 +97,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)"
handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_APP.code, PayType.ALIPAY)
"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -118,7 +109,7 @@
...
@@ -118,7 +109,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_PC.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_PC.code)"
@
click=
"
handleUpdateChannel
(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -126,7 +117,7 @@
...
@@ -126,7 +117,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
handleCreateChannel
(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.ALIPAY_PC.code, PayType.ALIPAY)"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -138,9 +129,7 @@
...
@@ -138,9 +129,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_WAP.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_WAP.code)"
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)"
handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)
"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -148,9 +137,7 @@
...
@@ -148,9 +137,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)"
handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_WAP.code, PayType.ALIPAY)
"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -162,7 +149,7 @@
...
@@ -162,7 +149,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_QR.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_QR.code)"
@
click=
"
handleUpdateChannel
(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -170,7 +157,7 @@
...
@@ -170,7 +157,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
handleCreateChannel
(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.ALIPAY_QR.code, PayType.ALIPAY)"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -182,9 +169,7 @@
...
@@ -182,9 +169,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_BAR.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.ALIPAY_BAR.code)"
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)"
handleUpdateChannel(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)
"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -192,9 +177,7 @@
...
@@ -192,9 +177,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
@
click=
"openChannelForm(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)"
handleCreateChannel(scope.row, PayChannelEnum.ALIPAY_BAR.code, PayType.ALIPAY)
"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -208,7 +191,7 @@
...
@@ -208,7 +191,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_LITE.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_LITE.code)"
@
click=
"
handleUpdateChannel
(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -216,7 +199,7 @@
...
@@ -216,7 +199,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
handleCreateChannel
(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_LITE.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -228,7 +211,7 @@
...
@@ -228,7 +211,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_PUB.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_PUB.code)"
@
click=
"
handleUpdateChannel
(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -236,7 +219,7 @@
...
@@ -236,7 +219,7 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
handleCreateChannel
(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_PUB.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
...
@@ -248,7 +231,7 @@
...
@@ -248,7 +231,7 @@
type=
"success"
type=
"success"
circle
circle
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_APP.code)"
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.WX_APP.code)"
@
click=
"
handleUpdateChannel
(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:check"
/>
<Icon
icon=
"ep:check"
/>
</el-button>
</el-button>
...
@@ -256,20 +239,33 @@
...
@@ -256,20 +239,33 @@
v-else
v-else
type=
"danger"
type=
"danger"
circle
circle
@
click=
"
handleCreateChannel
(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
@
click=
"
openChannelForm
(scope.row, PayChannelEnum.WX_APP.code, PayType.WECHAT)"
>
>
<Icon
icon=
"ep:close"
/>
<Icon
icon=
"ep:close"
/>
</el-button>
</el-button>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
</el-table-column>
</el-table-column>
<el-table-column
<el-table-column
label=
"模拟支付配置"
align=
"center"
>
label=
"创建时间"
<el-table-column
:label=
"PayChannelEnum.MOCK.name"
align=
"center"
>
align=
"center"
<
template
#
default=
"scope"
>
prop=
"createTime"
<el-button
width=
"180"
type=
"success"
:formatter=
"dateFormatter"
circle
/>
v-if=
"isChannelExists(scope.row.channelCodes, PayChannelEnum.MOCK.code)"
@
click=
"openChannelForm(scope.row, PayChannelEnum.MOCK.code)"
><Icon
icon=
"ep:check"
/></el-button>
<el-button
v-else
type=
"danger"
circle
@
click=
"openChannelForm(scope.row, PayChannelEnum.MOCK.code)"
><Icon
icon=
"ep:close"
/></el-button>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
min-width=
"110"
fixed=
"right"
>
<el-table-column
label=
"操作"
align=
"center"
min-width=
"110"
fixed=
"right"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<el-button
<el-button
...
@@ -302,20 +298,30 @@
...
@@ -302,20 +298,30 @@
<!-- 表单弹窗:添加/修改 -->
<!-- 表单弹窗:添加/修改 -->
<AppForm
ref=
"formRef"
@
success=
"getList"
/>
<AppForm
ref=
"formRef"
@
success=
"getList"
/>
<AlipayChannelForm
ref=
"alipayFormRef"
@
success=
"getList"
/>
<WeixinChannelForm
ref=
"weixinFormRef"
@
success=
"getList"
/>
<MockChannelForm
ref=
"mockFormRef"
@
success=
"getList"
/>
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
*
as
A
ppApi
from
'@/api/pay/app'
import
*
as
Paya
ppApi
from
'@/api/pay/app'
import
AppForm
from
'
@/views/pay/app
/AppForm.vue'
import
AppForm
from
'
./components
/AppForm.vue'
import
{
PayChannelEnum
,
PayType
}
from
'@/utils/constants'
import
{
PayChannelEnum
,
PayType
}
from
'@/utils/constants'
import
AlipayChannelForm
from
'./components/alipayChannelForm.vue'
import
WeixinChannelForm
from
'./components/weixinChannelForm.vue'
import
MockChannelForm
from
'./components/mockChannelForm.vue'
import
{
CommonStatusEnum
}
from
'@/utils/constants'
defineOptions
({
name
:
'PayApp'
})
defineOptions
({
name
:
'PayApp'
})
const
message
=
useMessage
()
// 消息弹窗
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
{
t
}
=
useI18n
()
// 国际化
const
alipayFormRef
=
ref
()
const
weixinFormRef
=
ref
()
const
mockFormRef
=
ref
()
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
list
=
ref
([])
// 列表的数据
...
@@ -334,9 +340,6 @@ const queryFormRef = ref() // 搜索的表单
...
@@ -334,9 +340,6 @@ const queryFormRef = ref() // 搜索的表单
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
exportLoading
=
ref
(
false
)
// 导出的加载中
const
channelParam
=
reactive
({
const
channelParam
=
reactive
({
loading
:
false
,
loading
:
false
,
edit
:
false
,
// 是否修改
wechatOpen
:
false
,
// 微信是否显示
aliPayOpen
:
false
,
// 支付宝是否显示
appId
:
null
,
// 应用 ID
appId
:
null
,
// 应用 ID
payCode
:
null
,
// 渠道编码
payCode
:
null
,
// 渠道编码
// 商户对象
// 商户对象
...
@@ -350,7 +353,7 @@ const channelParam = reactive({
...
@@ -350,7 +353,7 @@ const channelParam = reactive({
const
getList
=
async
()
=>
{
const
getList
=
async
()
=>
{
loading
.
value
=
true
loading
.
value
=
true
try
{
try
{
const
data
=
await
A
ppApi
.
getAppPage
(
queryParams
)
const
data
=
await
Paya
ppApi
.
getAppPage
(
queryParams
)
list
.
value
=
data
.
list
list
.
value
=
data
.
list
total
.
value
=
data
.
total
total
.
value
=
data
.
total
}
finally
{
}
finally
{
...
@@ -370,6 +373,20 @@ const resetQuery = () => {
...
@@ -370,6 +373,20 @@ const resetQuery = () => {
handleQuery
()
handleQuery
()
}
}
// 用户状态修改
const
handleStatusChange
=
async
(
row
:
any
)
=>
{
let
text
=
row
.
status
===
CommonStatusEnum
.
ENABLE
?
'启用'
:
'停用'
try
{
await
message
.
confirm
(
'确认要"'
+
text
+
'""'
+
row
.
name
+
'"应用吗?'
)
await
PayappApi
.
changeAppStatus
({
id
:
row
.
id
,
status
:
row
.
status
})
message
.
success
(
text
+
'成功'
)
}
catch
{
row
.
status
=
row
.
status
===
CommonStatusEnum
.
ENABLE
?
CommonStatusEnum
.
DISABLE
:
CommonStatusEnum
.
ENABLE
}
}
/** 添加/修改操作 */
/** 添加/修改操作 */
const
formRef
=
ref
()
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
...
@@ -382,7 +399,7 @@ const handleDelete = async (id: number) => {
...
@@ -382,7 +399,7 @@ const handleDelete = async (id: number) => {
// 删除的二次确认
// 删除的二次确认
await
message
.
delConfirm
()
await
message
.
delConfirm
()
// 发起删除
// 发起删除
await
A
ppApi
.
deleteApp
(
id
)
await
Paya
ppApi
.
deleteApp
(
id
)
message
.
success
(
t
(
'common.delSuccess'
))
message
.
success
(
t
(
'common.delSuccess'
))
// 刷新列表
// 刷新列表
await
getList
()
await
getList
()
...
@@ -396,9 +413,8 @@ const handleExport = async () => {
...
@@ -396,9 +413,8 @@ const handleExport = async () => {
await
message
.
exportConfirm
()
await
message
.
exportConfirm
()
// 发起导出
// 发起导出
exportLoading
.
value
=
true
exportLoading
.
value
=
true
const
data
=
await
A
ppApi
.
exportApp
(
queryParams
)
const
data
=
await
Paya
ppApi
.
exportApp
(
queryParams
)
download
.
excel
(
data
,
'支付应用信息.xls'
)
download
.
excel
(
data
,
'支付应用信息.xls'
)
}
catch
{
}
finally
{
}
finally
{
exportLoading
.
value
=
false
exportLoading
.
value
=
false
}
}
...
@@ -417,46 +433,28 @@ const isChannelExists = (channels, channelCode) => {
...
@@ -417,46 +433,28 @@ const isChannelExists = (channels, channelCode) => {
return
channels
.
indexOf
(
channelCode
)
!==
-
1
return
channels
.
indexOf
(
channelCode
)
!==
-
1
}
}
// TODO @芋艿:handleUpdateChannel 和 handleCreateChannel 合并,成为 openChannelForm
/**
* 修改支付渠道信息
*
* @param row 行记录
* @param payCode 支付编码
* @param type 支付类型
*/
const
handleUpdateChannel
=
async
(
row
,
payCode
,
type
)
=>
{
// TODO @芋艿:表单未实现
message
.
alert
(
'待实现'
)
await
settingChannelParam
(
row
,
payCode
,
type
)
channelParam
.
edit
=
true
channelParam
.
loading
=
true
}
/**
/**
* 新增支付渠道信息
* 新增支付渠道信息
*/
*/
const
handleCreateChannel
=
async
(
row
,
payCode
,
type
)
=>
{
const
openChannelForm
=
async
(
row
,
payCode
,
type
)
=>
{
message
.
alert
(
'待实现'
)
await
settingChannelParam
(
row
,
payCode
,
type
)
channelParam
.
edit
=
false
channelParam
.
loading
=
false
}
const
settingChannelParam
=
async
(
row
,
payCode
,
type
)
=>
{
if
(
type
===
PayType
.
WECHAT
)
{
channelParam
.
wechatOpen
=
true
channelParam
.
aliPayOpen
=
false
}
if
(
type
===
PayType
.
ALIPAY
)
{
channelParam
.
aliPayOpen
=
true
channelParam
.
wechatOpen
=
false
}
channelParam
.
edit
=
false
channelParam
.
loading
=
false
channelParam
.
loading
=
false
channelParam
.
appId
=
row
.
id
channelParam
.
appId
=
row
.
id
channelParam
.
payCode
=
payCode
channelParam
.
payCode
=
payCode
channelParam
.
payMerchant
=
row
.
payMerchant
channelParam
.
payMerchant
=
row
.
payMerchant
switch
(
type
)
{
case
PayType
.
ALIPAY
:
alipayFormRef
.
value
.
open
(
row
.
id
,
payCode
)
break
case
PayType
.
WECHAT
:
weixinFormRef
.
value
.
open
(
row
.
id
,
payCode
)
break
case
PayType
.
MOCK
:
mockFormRef
.
value
.
open
(
row
.
id
,
payCode
)
break
}
}
}
/** 初始化 **/
/** 初始化 **/
...
...
src/views/pay/order/index.vue
View file @
dae9bc13
...
@@ -325,7 +325,7 @@ const openDetail = (id: number) => {
...
@@ -325,7 +325,7 @@ const openDetail = (id: number) => {
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
getList
()
await
getList
()
// 加载商户列表
// 加载商户列表
merchantList
.
value
=
await
MerchantApi
.
getMerchantListByName
()
//
merchantList.value = await MerchantApi.getMerchantListByName()
// 加载 App 列表
// 加载 App 列表
// TODO 芋艿:候选少一个查询应用列表的接口
// TODO 芋艿:候选少一个查询应用列表的接口
// appList.value = await AppApi.getAppListByMerchantId()
// appList.value = await AppApi.getAppListByMerchantId()
...
...
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