11
This commit is contained in:
1 parent
fc8a9e4a84
commit
44f47fe5bc
4 files changed
+906
-19
No files matched your search
+21
@@ -35,3 +35,24 @@ export function retry(id: string | number, mchId: string | number) {
|
||||
params: { mchId },
|
||||
})
|
||||
}
|
||||
|
||||
/** 提交支付宝直付通二级商户全量资料修改申请;支付宝处理完成后才会在账单和支付结果页生效。 */
|
||||
export function modifyAlipayAlias(id: string | number, data: Record<string, any>) {
|
||||
return request({
|
||||
url: `/third/third-mch-fz-relation/${id}/alipay-alias`,
|
||||
method: "post",
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
/** 将资料图片上传到支付宝,返回可填入资料表单的 image_id。 */
|
||||
export function uploadAlipayImage(id: string | number, file: File) {
|
||||
const formData = new FormData()
|
||||
formData.append("file", file)
|
||||
return request({
|
||||
url: `/third/third-mch-fz-relation/${id}/alipay-image`,
|
||||
method: "post",
|
||||
headers: { "Content-Type": "multipart/form-data" },
|
||||
data: formData,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="flex w-full min-w-0 items-start gap-2">
|
||||
<el-select v-if="multiple" :model-value="normalizedValues" class="min-w-0 flex-1" multiple filterable
|
||||
allow-create default-first-option placeholder="上传图片或粘贴支付宝 image_id"
|
||||
@update:model-value="updateMultiple">
|
||||
<el-option v-for="value in normalizedValues" :key="value" :label="value" :value="value" />
|
||||
</el-select>
|
||||
<el-input v-else :model-value="singleValue" class="min-w-0 flex-1" clearable
|
||||
placeholder="上传图片或粘贴支付宝 image_id" @update:model-value="updateSingle" />
|
||||
<el-upload :show-file-list="false" :accept="acceptedTypes" :http-request="uploadImage"
|
||||
:before-upload="beforeUpload" :disabled="uploading">
|
||||
<el-button :icon="Upload" :loading="uploading">上传到支付宝</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Upload } from '@element-plus/icons-vue'
|
||||
import type { UploadProps, UploadRequestOptions } from 'element-plus'
|
||||
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { uploadAlipayImage } from '/@/api/thirdparty/third-mch-fz-relation'
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
modelValue?: string | string[]
|
||||
relationId: string | number
|
||||
multiple?: boolean
|
||||
}>(), {
|
||||
modelValue: '',
|
||||
multiple: false,
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'update:modelValue', value: string | string[]): void
|
||||
}>()
|
||||
|
||||
const acceptedTypes = '.bmp,.jpg,.jpeg,.png,.gif,image/bmp,image/jpeg,image/png,image/gif'
|
||||
const uploading = ref(false)
|
||||
const normalizedValues = computed(() => Array.isArray(props.modelValue)
|
||||
? props.modelValue.filter(Boolean)
|
||||
: String(props.modelValue || '').split(',').map(item => item.trim()).filter(Boolean))
|
||||
const singleValue = computed(() => Array.isArray(props.modelValue)
|
||||
? (props.modelValue[0] || '')
|
||||
: String(props.modelValue || ''))
|
||||
|
||||
const updateMultiple = (value: string[]) => emit('update:modelValue', value.map(item => item.trim()).filter(Boolean))
|
||||
const updateSingle = (value: string) => emit('update:modelValue', value.trim())
|
||||
|
||||
const beforeUpload: UploadProps['beforeUpload'] = (file) => {
|
||||
const extension = file.name.split('.').pop()?.toLowerCase()
|
||||
if (!extension || !['bmp', 'jpg', 'jpeg', 'png', 'gif'].includes(extension)) {
|
||||
useMessage().warning('只支持 bmp、jpg、jpeg、png、gif 图片')
|
||||
return false
|
||||
}
|
||||
if (file.size > 10 * 1024 * 1024) {
|
||||
useMessage().warning('图片不能超过10MB')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const uploadImage = async (options: UploadRequestOptions) => {
|
||||
try {
|
||||
uploading.value = true
|
||||
const { data, code } = await uploadAlipayImage(props.relationId, options.file)
|
||||
if (code !== 0 || !data) throw new Error('支付宝未返回图片标识')
|
||||
if (props.multiple) {
|
||||
emit('update:modelValue', Array.from(new Set([...normalizedValues.value, String(data)])))
|
||||
} else {
|
||||
emit('update:modelValue', String(data))
|
||||
}
|
||||
options.onSuccess({ data })
|
||||
useMessage().success('图片已上传到支付宝')
|
||||
} catch (error: any) {
|
||||
options.onError(error)
|
||||
useMessage().error(error?.msg || error?.message || '支付宝图片上传失败')
|
||||
} finally {
|
||||
uploading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,745 @@
|
||||
<template>
|
||||
<el-dialog :model-value="modelValue" title="修改支付宝商户资料" width="92%" top="4vh" style="max-width: 1180px"
|
||||
:close-on-click-modal="false" :close-on-press-escape="!loading" :show-close="!loading" append-to-body
|
||||
@update:model-value="closeDialog">
|
||||
<el-alert class="mb-4" type="warning" :closable="false" show-icon
|
||||
title="支付宝会按全量资料重新审核。请按当前已生效的进件资料填写,图片必须使用本表单上传后返回的支付宝 image_id。" />
|
||||
|
||||
<div class="mb-4 flex items-center gap-3">
|
||||
<el-alert class="min-w-0 flex-1"
|
||||
:type="profileStatus === 'success' ? 'success' : profileStatus === 'warning' ? 'warning' : 'info'"
|
||||
:closable="false" show-icon :title="profileMessage" />
|
||||
<el-button :icon="Refresh" :loading="profileLoading" :disabled="loading || !relationId"
|
||||
@click="loadAlipayProfile">重新读取支付宝资料</el-button>
|
||||
</div>
|
||||
|
||||
<el-form ref="formRef" :model="form" :rules="rules" label-width="150px" v-loading="loading || profileLoading"
|
||||
class="max-h-[72vh] overflow-y-auto pr-2">
|
||||
<el-tabs v-model="activeTab">
|
||||
<el-tab-pane label="商户主体" name="basic">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="直付通商户标识">
|
||||
<el-input :model-value="relation?.channelSubMchId" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item prop="name">
|
||||
<template #label>
|
||||
<span>商户名称</span>
|
||||
<tip content="填写支付宝直付通进件登记的主体名称,不是分账接收方名称或联系人姓名。" />
|
||||
</template>
|
||||
<el-input v-model="form.name" maxlength="128" show-word-limit
|
||||
placeholder="与营业执照或身份证名称一致" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="商户简称" prop="aliasName">
|
||||
<el-input v-model="form.aliasName" maxlength="128" show-word-limit
|
||||
placeholder="账单和支付结果页展示名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="商户类型" prop="merchantType">
|
||||
<el-select v-model="form.merchantType" class="w-full">
|
||||
<el-option v-for="item in merchantTypeOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="商户证件类型" prop="certType">
|
||||
<el-select v-model="form.certType" class="w-full" disabled>
|
||||
<el-option v-for="item in certTypeOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item prop="mcc">
|
||||
<template #label>
|
||||
<span>MCC</span>
|
||||
<tip content="支付宝进件商户类别码。特殊行业还需在“资质材料”中上传行业资质。" />
|
||||
</template>
|
||||
<el-input v-model="form.mcc" maxlength="16" placeholder="例如 5812" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="当前已开通服务" prop="services">
|
||||
<el-select v-model="form.services" class="w-full" multiple filterable
|
||||
placeholder="请选择该二级商户当前已开通的全部服务">
|
||||
<el-option v-for="item in serviceOptions" :key="item" :label="item" :value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="客服电话" prop="servicePhone">
|
||||
<el-input v-model="form.servicePhone" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="服务商签约日期" prop="signTimeWithIsv">
|
||||
<el-date-picker v-model="form.signTimeWithIsv" class="w-full" type="date"
|
||||
value-format="YYYY-MM-DD" format="YYYY-MM-DD" placeholder="选择原签约日期" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<template v-if="form.merchantType !== '06'">
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="法人名称" prop="legalName">
|
||||
<el-input v-model="form.legalName" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="法人证件类型" prop="legalCertType">
|
||||
<el-select v-model="form.legalCertType" class="w-full">
|
||||
<el-option v-for="item in legalCertTypeOptions" :key="item.value"
|
||||
:label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="法人证件号码" prop="legalCertNo">
|
||||
<el-input v-model="form.legalCertNo" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="联系人与结算" name="settlement">
|
||||
<div class="mb-4 border-b border-[var(--el-border-color)] pb-2 text-sm font-medium">商户联系人</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人姓名" prop="contact.name">
|
||||
<el-input v-model="form.contact.name" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人手机号" prop="contact.mobile">
|
||||
<el-input v-model="form.contact.mobile" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人类型">
|
||||
<el-select v-model="form.contact.type" class="w-full" clearable>
|
||||
<el-option v-for="item in contactTypeOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人身份证号">
|
||||
<el-input v-model="form.contact.idCardNo" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人电话">
|
||||
<el-input v-model="form.contact.phone" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联系人邮箱">
|
||||
<el-input v-model="form.contact.email" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="联系人职责标识">
|
||||
<el-select v-model="form.contact.tag" class="w-full" multiple filterable allow-create
|
||||
default-first-option placeholder="选填;按原进件资料填写职责标识" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="mb-4 mt-2 border-b border-[var(--el-border-color)] pb-2 text-sm font-medium">签约与结算</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="签约支付宝账号">
|
||||
<el-input v-model="form.bindingAlipayLogonId" maxlength="128"
|
||||
placeholder="需要协议确认或增值服务签约时填写" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="结算方式" prop="settlementMode">
|
||||
<el-radio-group v-model="form.settlementMode">
|
||||
<el-radio-button label="alipayAccount">支付宝账号</el-radio-button>
|
||||
<el-radio-button label="bankCard">银行卡</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="form.settlementMode === 'alipayAccount'" :span="24">
|
||||
<el-form-item label="结算支付宝账号" prop="alipayLogonId">
|
||||
<el-input v-model="form.alipayLogonId" maxlength="128" placeholder="需与商户名称同名且已实名认证" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<template v-else>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="银行卡号" prop="settleCard.accountNo">
|
||||
<el-input v-model="form.settleCard.accountNo" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="银行卡户名" prop="settleCard.accountHolderName">
|
||||
<el-input v-model="form.settleCard.accountHolderName" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="银行卡类型">
|
||||
<el-select v-model="form.settleCard.accountType" class="w-full">
|
||||
<el-option label="借记卡" value="DC" />
|
||||
<el-option label="信用卡" value="CC" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="账号使用类型">
|
||||
<el-select v-model="form.settleCard.usageType" class="w-full">
|
||||
<el-option label="对公" value="01" />
|
||||
<el-option label="对私" value="02" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="银行名称">
|
||||
<el-input v-model="form.settleCard.accountInstName" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="开户行简称">
|
||||
<el-input v-model="form.settleCard.accountInstId" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="开户行所在省">
|
||||
<el-input v-model="form.settleCard.accountInstProvince" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="开户行所在市">
|
||||
<el-input v-model="form.settleCard.accountInstCity" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="开户支行名称">
|
||||
<el-input v-model="form.settleCard.accountBranchName" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="联行号(选填)">
|
||||
<el-input v-model="form.settleCard.bankCode" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="设置默认结算规则">
|
||||
<el-switch v-model="form.useDefaultSettleRule" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="经营地址与图片" name="images">
|
||||
<template v-if="usesFaceToFace">
|
||||
<div class="mb-4 border-b border-[var(--el-border-color)] pb-2 text-sm font-medium">经营地址</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="省份编码">
|
||||
<el-input v-model="form.businessAddress.provinceCode" maxlength="12" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="城市编码">
|
||||
<el-input v-model="form.businessAddress.cityCode" maxlength="12" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="区县编码">
|
||||
<el-input v-model="form.businessAddress.districtCode" maxlength="12" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="经营详细地址">
|
||||
<el-input v-model="form.businessAddress.address" maxlength="256" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="高德 POI ID">
|
||||
<el-input v-model="form.businessAddress.poiid" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="经度">
|
||||
<el-input v-model="form.businessAddress.longitude" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="纬度">
|
||||
<el-input v-model="form.businessAddress.latitude" maxlength="32" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<div class="mb-4 mt-2 border-b border-[var(--el-border-color)] pb-2 text-sm font-medium">商户材料</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col v-if="usesFaceToFace" :span="24">
|
||||
<el-form-item label="门头照">
|
||||
<alipay-image-upload v-model="form.outDoorImages" :relation-id="relationId" multiple />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="usesFaceToFace" :span="24">
|
||||
<el-form-item label="内景照">
|
||||
<alipay-image-upload v-model="form.inDoorImages" :relation-id="relationId" multiple />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="商户证件正面/主页">
|
||||
<alipay-image-upload v-model="form.certImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="form.merchantType === '06'" :span="24">
|
||||
<el-form-item label="个人证件反面">
|
||||
<alipay-image-upload v-model="form.certImageBack" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="法人证件正面">
|
||||
<alipay-image-upload v-model="form.legalCertFrontImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="法人证件反面">
|
||||
<alipay-image-upload v-model="form.legalCertBackImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="授权函/说明函">
|
||||
<alipay-image-upload v-model="form.licenseAuthLetterImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<template v-if="form.merchantType === '06'">
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="补充证件类型">
|
||||
<el-select v-model="form.additionalCertType" class="w-full" clearable>
|
||||
<el-option
|
||||
v-for="item in certTypeOptions.filter(option => option.value !== '100')"
|
||||
:key="item.value" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="12">
|
||||
<el-form-item label="补充证件号码">
|
||||
<el-input v-model="form.additionalCertNo" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="补充证件图片">
|
||||
<alipay-image-upload v-model="form.additionalCertImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="站点与应用" name="sites">
|
||||
<div class="mb-4 flex items-center justify-between gap-3">
|
||||
<el-select v-model="form.tradeScene" class="max-w-[520px] flex-1" multiple clearable
|
||||
placeholder="交易场景(选填;WAP、APP、PC 需站点截图)">
|
||||
<el-option label="小程序支付(TINY_APP)" value="TINY_APP" />
|
||||
<el-option label="H5(WAP)" value="WAP" />
|
||||
<el-option label="线下当面付(OFFLINE)" value="OFFLINE" />
|
||||
<el-option label="APP" value="APP" />
|
||||
<el-option label="网站支付(PC)" value="PC" />
|
||||
</el-select>
|
||||
<el-button :icon="Plus" @click="addSite()">添加站点</el-button>
|
||||
</div>
|
||||
<el-empty v-if="!form.sites.length" description="当前服务不需要站点资料" :image-size="72" />
|
||||
<div v-for="(site, index) in form.sites" :key="site.key"
|
||||
class="border-t border-[var(--el-border-color)] py-4 first:border-t-0 first:pt-0">
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<span class="text-sm font-medium">站点 {{ index + 1 }}</span>
|
||||
<el-tooltip content="删除站点">
|
||||
<el-button circle text type="danger" :icon="Delete" @click="removeSite(index)" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="站点类型">
|
||||
<el-select v-model="site.siteType" class="w-full">
|
||||
<el-option v-for="item in siteTypeOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="站点名称">
|
||||
<el-input v-model="site.siteName" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="site.siteType === '06'" :xs="24" :md="8">
|
||||
<el-form-item label="支付宝小程序AppID">
|
||||
<el-input v-model="site.tinyAppId" maxlength="64" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="8">
|
||||
<el-form-item label="站点地址">
|
||||
<el-input v-model="site.siteUrl" maxlength="512" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="站点截图">
|
||||
<alipay-image-upload v-model="site.screenshotImage" :relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-collapse>
|
||||
<el-collapse-item title="更多站点资料">
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="12"><el-form-item label="下载地址"><el-input
|
||||
v-model="site.download" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="应用市场"><el-input
|
||||
v-model="site.market" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="上架状态"><el-input
|
||||
v-model="site.status" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="网站域名"><el-input
|
||||
v-model="site.siteDomain" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="测试账号"><el-input
|
||||
v-model="site.account" autocomplete="off" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="测试密码"><el-input
|
||||
v-model="site.password" type="password" autocomplete="new-password"
|
||||
show-password /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="ICP信息服务名称"><el-input
|
||||
v-model="site.icpServiceName" /></el-form-item></el-col>
|
||||
<el-col :xs="24" :md="12"><el-form-item label="ICP号"><el-input
|
||||
v-model="site.icpNo" /></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="ICP主办单位"><el-input
|
||||
v-model="site.icpOrgName" /></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="站点授权函"><alipay-image-upload
|
||||
v-model="site.authLetterImage"
|
||||
:relation-id="relationId" /></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="备注"><el-input v-model="site.remark"
|
||||
type="textarea" /></el-form-item></el-col>
|
||||
<el-col :span="24"><el-form-item label="备注图片"><alipay-image-upload
|
||||
v-model="site.remarkImage"
|
||||
:relation-id="relationId" /></el-form-item></el-col>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="资质材料" name="qualifications">
|
||||
<div class="mb-4 flex justify-end">
|
||||
<el-button :icon="Plus" @click="addQualification">添加行业资质</el-button>
|
||||
</div>
|
||||
<el-alert class="mb-4" type="info" :closable="false" show-icon
|
||||
title="仅特殊行业 MCC 需要行业资质;每项的资质类型与图片必须同时填写。法人证件照片在“经营地址与图片”中上传。" />
|
||||
<el-empty v-if="!form.qualifications.length" description="没有行业资质" :image-size="72" />
|
||||
<div v-for="(item, index) in form.qualifications" :key="item.key"
|
||||
class="border-t border-[var(--el-border-color)] py-4 first:border-t-0 first:pt-0">
|
||||
<div class="mb-3 flex items-center justify-between">
|
||||
<span class="text-sm font-medium">行业资质 {{ index + 1 }}</span>
|
||||
<el-tooltip content="删除资质">
|
||||
<el-button circle text type="danger" :icon="Delete"
|
||||
@click="form.qualifications.splice(index, 1)" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-row :gutter="20">
|
||||
<el-col :xs="24" :md="10">
|
||||
<el-form-item label="行业资质类型">
|
||||
<el-input v-model="item.industryQualificationType" maxlength="128" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :xs="24" :md="14">
|
||||
<el-form-item label="行业资质图片">
|
||||
<alipay-image-upload v-model="item.industryQualificationImage"
|
||||
:relation-id="relationId" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
|
||||
<template #footer>
|
||||
<el-button :disabled="loading" @click="closeDialog(false)">取消</el-button>
|
||||
<el-button type="primary" :loading="loading" :disabled="profileLoading" @click="submit">提交修改申请</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Delete, Plus, Refresh } from '@element-plus/icons-vue'
|
||||
|
||||
import { useMessage } from '/@/hooks/message'
|
||||
import { getAlipayMerchantProfile, modifyAlipayAlias } from '/@/api/thirdparty/third-mch-fz-relation'
|
||||
import AlipayImageUpload from './alipay-image-upload.vue'
|
||||
|
||||
interface RelationInfo {
|
||||
id?: string | number
|
||||
channelSubMchId?: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: boolean
|
||||
relation: RelationInfo | null
|
||||
}>()
|
||||
const emit = defineEmits(['update:modelValue', 'loading-change', 'submitted'])
|
||||
|
||||
const serviceOptions = ['当面付', 'jsapi支付', 'app支付', 'wap支付', '电脑支付', '预授权支付', '商户代扣', '小程序支付', '订单码支付']
|
||||
const merchantTypeOptions = [
|
||||
{ value: '01', label: '企业' }, { value: '02', label: '事业单位' },
|
||||
{ value: '03', label: '民办非企业组织' }, { value: '04', label: '社会团体' },
|
||||
{ value: '05', label: '党政及国家机关' }, { value: '06', label: '个人商户' },
|
||||
{ value: '07', label: '个体工商户' },
|
||||
]
|
||||
const certTypeOptions = [
|
||||
{ value: '201', label: '营业执照' }, { value: '218', label: '事业单位法人证书' },
|
||||
{ value: '204', label: '民办非企业登记证书' }, { value: '206', label: '社会团体法人登记证书' },
|
||||
{ value: '219', label: '党政机关批准设立文件' }, { value: '100', label: '大陆身份证' },
|
||||
]
|
||||
const legalCertTypeOptions = [
|
||||
{ value: '100', label: '大陆身份证' }, { value: '105', label: '港澳居民往来内地通行证' },
|
||||
{ value: '106', label: '台湾同胞往来大陆通行证' }, { value: '108', label: '外国人居留证' },
|
||||
]
|
||||
const contactTypeOptions = [
|
||||
{ value: 'LEGAL_PERSON', label: '法人' }, { value: 'CONTROLLER', label: '实际控制人' },
|
||||
{ value: 'AGENT', label: '代理人' }, { value: 'OTHER', label: '其他' },
|
||||
]
|
||||
const siteTypeOptions = [
|
||||
{ value: '01', label: '网站' }, { value: '02', label: 'APP' }, { value: '06', label: '支付宝小程序' },
|
||||
]
|
||||
const merchantCertTypes: Record<string, string> = {
|
||||
'01': '201', '02': '218', '03': '204', '04': '206', '05': '219', '06': '100', '07': '201',
|
||||
}
|
||||
|
||||
const createSite = (siteType = '01') => ({
|
||||
key: `${Date.now()}-${Math.random()}`, siteType, siteName: '', siteUrl: '', screenshotImage: '', tinyAppId: '',
|
||||
account: '', password: '', status: '', market: '', download: '', authLetterImage: '', remark: '',
|
||||
remarkImage: '', siteDomain: '', icpServiceName: '', icpNo: '', icpOrgName: '',
|
||||
})
|
||||
const createForm = () => ({
|
||||
name: '', aliasName: '', merchantType: '01', mcc: '', services: [] as string[], servicePhone: '',
|
||||
signTimeWithIsv: '', certType: '201', legalName: '', legalCertNo: '', legalCertType: '100',
|
||||
bindingAlipayLogonId: '', alipayLogonId: '', settlementMode: 'alipayAccount', useDefaultSettleRule: true,
|
||||
contact: { name: '', mobile: '', phone: '', email: '', idCardNo: '', tag: [] as string[], type: 'LEGAL_PERSON' },
|
||||
businessAddress: { provinceCode: '', cityCode: '', districtCode: '', address: '', poiid: '', longitude: '', latitude: '', type: 'BUSINESS_ADDRESS' },
|
||||
settleCard: { accountBranchName: '', accountHolderName: '', accountInstCity: '', accountInstId: '', accountInstName: '', accountInstProvince: '', accountNo: '', accountType: 'DC', usageType: '01', bankCode: '' },
|
||||
outDoorImages: [] as string[], inDoorImages: [] as string[], certImage: '', certImageBack: '',
|
||||
legalCertFrontImage: '', legalCertBackImage: '', licenseAuthLetterImage: '',
|
||||
additionalCertType: '', additionalCertNo: '', additionalCertImage: '',
|
||||
sites: [] as ReturnType<typeof createSite>[], tradeScene: [] as string[],
|
||||
qualifications: [] as Array<{ key: string, industryQualificationType: string, industryQualificationImage: string }>,
|
||||
})
|
||||
|
||||
const formRef = ref()
|
||||
const loading = ref(false)
|
||||
const profileLoading = ref(false)
|
||||
const profileStatus = ref<'idle' | 'success' | 'warning'>('idle')
|
||||
const profileMessage = ref('打开弹窗后会自动从支付宝读取二级商户基础资料。')
|
||||
const activeTab = ref('basic')
|
||||
const form = reactive(createForm())
|
||||
const relationId = computed(() => props.relation?.id || '')
|
||||
const usesFaceToFace = computed(() => form.services.includes('当面付'))
|
||||
let profileRequestSerial = 0
|
||||
const requiredRule = (message: string, trigger = 'blur') => ({ required: true, message, trigger })
|
||||
const rules = {
|
||||
name: [requiredRule('商户名称不能为空')], aliasName: [requiredRule('商户简称不能为空')],
|
||||
merchantType: [requiredRule('请选择商户类型', 'change')], certType: [requiredRule('请选择商户证件类型', 'change')],
|
||||
mcc: [requiredRule('MCC不能为空')], services: [{ type: 'array', required: true, min: 1, message: '请选择全部已开通服务', trigger: 'change' }],
|
||||
servicePhone: [requiredRule('客服电话不能为空')], signTimeWithIsv: [requiredRule('请选择服务商签约日期', 'change')],
|
||||
legalName: [requiredRule('法人名称不能为空')], legalCertNo: [requiredRule('法人证件号码不能为空')],
|
||||
legalCertType: [requiredRule('请选择法人证件类型', 'change')],
|
||||
'contact.name': [requiredRule('联系人姓名不能为空')], 'contact.mobile': [requiredRule('联系人手机号不能为空')],
|
||||
settlementMode: [requiredRule('请选择结算方式', 'change')], alipayLogonId: [requiredRule('结算支付宝账号不能为空')],
|
||||
'settleCard.accountNo': [requiredRule('银行卡号不能为空')],
|
||||
'settleCard.accountHolderName': [requiredRule('银行卡户名不能为空')],
|
||||
}
|
||||
|
||||
watch(() => props.modelValue, (visible) => {
|
||||
profileRequestSerial += 1
|
||||
profileLoading.value = false
|
||||
if (!visible) return
|
||||
Object.assign(form, createForm())
|
||||
profileStatus.value = 'idle'
|
||||
profileMessage.value = '正在从支付宝读取二级商户基础资料...'
|
||||
activeTab.value = 'basic'
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
void loadAlipayProfile()
|
||||
})
|
||||
watch(() => form.merchantType, (value) => {
|
||||
form.certType = merchantCertTypes[value] || ''
|
||||
if (value === '06') {
|
||||
form.legalName = ''
|
||||
form.legalCertNo = ''
|
||||
}
|
||||
})
|
||||
watch(() => [...form.services], (services) => {
|
||||
if ((services.includes('电脑支付') || services.includes('wap支付')) && !form.sites.some(item => item.siteType === '01')) addSite('01')
|
||||
if (services.includes('app支付') && !form.sites.some(item => ['02', '06'].includes(item.siteType))) addSite('02')
|
||||
if ((services.includes('jsapi支付') || services.includes('小程序支付')) && !form.sites.some(item => item.siteType === '06')) addSite('06')
|
||||
})
|
||||
|
||||
const addSite = (siteType = '01') => form.sites.push(createSite(siteType))
|
||||
const removeSite = (index: number) => form.sites.splice(index, 1)
|
||||
const addQualification = () => form.qualifications.push({
|
||||
key: `${Date.now()}-${Math.random()}`, industryQualificationType: '', industryQualificationImage: '',
|
||||
})
|
||||
const closeDialog = (visible: boolean) => {
|
||||
if (!loading.value) emit('update:modelValue', visible)
|
||||
}
|
||||
|
||||
const applyAlipayProfile = (data: Record<string, any>) => {
|
||||
const textFields = ['name', 'aliasName', 'mcc', 'servicePhone', 'merchantType', 'certType', 'alipayLogonId']
|
||||
textFields.forEach((field) => {
|
||||
if (String(data?.[field] || '').trim()) (form as any)[field] = data[field]
|
||||
})
|
||||
if (Array.isArray(data?.services) && data.services.length) form.services = [...data.services]
|
||||
if (data?.contact) Object.assign(form.contact, data.contact)
|
||||
if (data?.businessAddress) Object.assign(form.businessAddress, data.businessAddress)
|
||||
if (data?.settleCard) Object.assign(form.settleCard, data.settleCard)
|
||||
if (Array.isArray(data?.sites) && data.sites.length) {
|
||||
form.sites = data.sites.map((site: Record<string, any>) => ({
|
||||
...createSite(site.siteType || '01'),
|
||||
...site,
|
||||
}))
|
||||
}
|
||||
if (String(data?.alipayLogonId || '').trim()) {
|
||||
form.settlementMode = 'alipayAccount'
|
||||
} else if (String(data?.settleCard?.accountNo || '').trim()) {
|
||||
form.settlementMode = 'bankCard'
|
||||
}
|
||||
}
|
||||
|
||||
const loadAlipayProfile = async () => {
|
||||
if (profileLoading.value || !relationId.value) return
|
||||
const requestSerial = ++profileRequestSerial
|
||||
const requestedRelationId = relationId.value
|
||||
try {
|
||||
profileLoading.value = true
|
||||
profileStatus.value = 'idle'
|
||||
profileMessage.value = '正在从支付宝读取二级商户基础资料...'
|
||||
const { data, code } = await getAlipayMerchantProfile(requestedRelationId)
|
||||
if (requestSerial !== profileRequestSerial || requestedRelationId !== relationId.value || !props.modelValue) return
|
||||
if (code !== 0 || !data) throw new Error('支付宝未返回商户资料')
|
||||
applyAlipayProfile(data)
|
||||
profileStatus.value = 'success'
|
||||
profileMessage.value = '已回填支付宝可查询的基础资料;法人证件、原签约日期、审核图片、行业资质及未返回字段仍需核对补充。'
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
} catch (error: any) {
|
||||
if (requestSerial !== profileRequestSerial || !props.modelValue) return
|
||||
profileStatus.value = 'warning'
|
||||
profileMessage.value = error?.msg || error?.message || '支付宝资料读取失败,请手工填写或稍后重试。'
|
||||
} finally {
|
||||
if (requestSerial === profileRequestSerial) profileLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const conditionalError = (): { message: string, tab: string } | null => {
|
||||
const missing = (value: unknown) => !String(value || '').trim()
|
||||
if (form.merchantType !== '06' && (missing(form.legalName) || missing(form.legalCertNo))) {
|
||||
return { message: '非个人商户必须填写法人名称和法人证件号码', tab: 'basic' }
|
||||
}
|
||||
if (form.settlementMode === 'bankCard') {
|
||||
const card = form.settleCard
|
||||
if ([card.accountNo, card.accountHolderName, card.accountType, card.usageType, card.accountInstName,
|
||||
card.accountInstId, card.accountInstProvince, card.accountInstCity, card.accountBranchName].some(missing)) {
|
||||
return { message: '请完整填写结算银行卡资料', tab: 'settlement' }
|
||||
}
|
||||
if (form.name.trim() !== card.accountHolderName.trim() && missing(form.licenseAuthLetterImage)) {
|
||||
return { message: '结算卡户名与商户名称不一致时必须上传授权函或说明函', tab: 'images' }
|
||||
}
|
||||
}
|
||||
if (form.merchantType !== '06' && form.legalCertType !== '100' && missing(form.licenseAuthLetterImage)) {
|
||||
return { message: '外籍或非大陆身份证法人必须上传身份说明材料', tab: 'images' }
|
||||
}
|
||||
if (usesFaceToFace.value) {
|
||||
const address = form.businessAddress
|
||||
if ([address.provinceCode, address.cityCode, address.districtCode, address.address].some(missing)) {
|
||||
return { message: '当面付必须完整填写经营地址', tab: 'images' }
|
||||
}
|
||||
if (!form.outDoorImages.length || !form.inDoorImages.length) {
|
||||
return { message: '当面付必须上传门头照和内景照', tab: 'images' }
|
||||
}
|
||||
if ((form.merchantType !== '06' || form.settlementMode === 'bankCard') && missing(form.certImage)) {
|
||||
return { message: '当前商户必须上传商户证件图片', tab: 'images' }
|
||||
}
|
||||
if (form.merchantType === '06' && missing(form.certImageBack)) {
|
||||
return { message: '个人商户使用当面付必须上传证件反面图片', tab: 'images' }
|
||||
}
|
||||
}
|
||||
for (const site of form.sites) {
|
||||
if (missing(site.siteType) || missing(site.siteName)) return { message: '每个站点都必须填写类型和名称', tab: 'sites' }
|
||||
}
|
||||
if ((form.services.includes('电脑支付') || form.services.includes('wap支付'))
|
||||
&& !form.sites.some(item => item.siteType === '01' && !missing(item.siteUrl))) {
|
||||
return { message: '电脑支付或wap支付必须填写网站名称和地址', tab: 'sites' }
|
||||
}
|
||||
if (form.services.includes('app支付') && !form.sites.some(item => ['02', '06'].includes(item.siteType))) {
|
||||
return { message: 'app支付必须填写APP或支付宝小程序资料', tab: 'sites' }
|
||||
}
|
||||
if ((form.services.includes('jsapi支付') || form.services.includes('小程序支付'))
|
||||
&& !form.sites.some(item => item.siteType === '06' && !missing(item.tinyAppId) && !missing(item.siteUrl))) {
|
||||
return { message: 'jsapi支付或小程序支付必须填写支付宝小程序AppID和站点地址', tab: 'sites' }
|
||||
}
|
||||
for (const scene of form.tradeScene) {
|
||||
if (!['WAP', 'APP', 'PC'].includes(scene)) continue
|
||||
const targetTypes = scene === 'APP' ? ['02', '06'] : ['01']
|
||||
if (!form.sites.some(item => targetTypes.includes(item.siteType) && !missing(item.screenshotImage))) {
|
||||
return { message: `${scene}交易场景必须上传对应站点截图`, tab: 'sites' }
|
||||
}
|
||||
}
|
||||
if (form.qualifications.some(item => missing(item.industryQualificationType) !== missing(item.industryQualificationImage))) {
|
||||
return { message: '行业资质类型和资质图片必须同时填写', tab: 'qualifications' }
|
||||
}
|
||||
if (form.qualifications.some(item => !missing(item.industryQualificationType) && !missing(item.industryQualificationImage))
|
||||
&& (missing(form.legalCertFrontImage) || missing(form.legalCertBackImage))) {
|
||||
return { message: '特殊行业必须上传法人证件正面和反面图片', tab: 'images' }
|
||||
}
|
||||
const additionalCertValues = [form.additionalCertType, form.additionalCertNo, form.additionalCertImage]
|
||||
if (additionalCertValues.some(value => !missing(value)) && additionalCertValues.some(missing)) {
|
||||
return { message: '补充证件类型、证件号和图片必须同时填写', tab: 'images' }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
if (loading.value || !relationId.value) return
|
||||
const valid = await formRef.value?.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
const error = conditionalError()
|
||||
if (error) {
|
||||
activeTab.value = error.tab
|
||||
useMessage().warning(error.message)
|
||||
return
|
||||
}
|
||||
const payload: Record<string, any> = JSON.parse(JSON.stringify(form))
|
||||
delete payload.settlementMode
|
||||
delete payload.useDefaultSettleRule
|
||||
payload.sites.forEach((site: any) => delete site.key)
|
||||
payload.qualifications.forEach((item: any) => delete item.key)
|
||||
if (form.settlementMode === 'alipayAccount') {
|
||||
payload.settleCard = null
|
||||
} else {
|
||||
payload.alipayLogonId = null
|
||||
}
|
||||
payload.defaultSettleRule = form.useDefaultSettleRule ? {
|
||||
defaultSettleType: form.settlementMode,
|
||||
defaultSettleTarget: form.settlementMode === 'alipayAccount' ? form.alipayLogonId : form.settleCard.accountNo,
|
||||
} : null
|
||||
try {
|
||||
loading.value = true
|
||||
emit('loading-change', true)
|
||||
const { data, code } = await modifyAlipayAlias(relationId.value, payload)
|
||||
if (code !== 0 || !data?.orderId) throw new Error('支付宝未返回申请单号')
|
||||
useMessage().success(`申请已提交,等待支付宝处理。申请单号:${data.orderId}`)
|
||||
emit('submitted', data.orderId)
|
||||
emit('update:modelValue', false)
|
||||
} catch (error: any) {
|
||||
useMessage().error(error?.msg || error?.message || '支付宝商户资料修改申请提交失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
emit('loading-change', false)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -19,8 +19,8 @@
|
||||
<dict-select v-model="form.platformType" dict-code="platform_pay" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-alert v-if="form.platformType === '10'" class="mt-[4px]" type="info" show-icon
|
||||
:closable="false" title="微信子商户号和分账开关统一由下方关系配置;关闭分账后该关系只提供服务商支付路由。" />
|
||||
<el-alert v-if="form.platformType === '10'" class="mt-[4px]" type="info" show-icon :closable="false"
|
||||
title="微信子商户号和分账开关统一由下方关系配置;关闭分账后该关系只提供服务商支付路由。" />
|
||||
<el-alert v-else-if="form.platformType === '20'" class="mt-[4px]" type="info" show-icon
|
||||
:closable="false" title="支付宝未配置关系或默认关系关闭分账时按普通支付处理;直付通商户、授权和抽佣统一由下方关系配置。" />
|
||||
</el-row>
|
||||
@@ -29,15 +29,16 @@
|
||||
<div class="mb-3 flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<div class="text-base font-medium text-[var(--el-text-color-primary)]">分账关系</div>
|
||||
<div class="mt-1 text-xs text-[var(--el-text-color-secondary)]">默认关系负责支付渠道商户路由;只有“开启分账”且渠道已绑定时才执行平台抽佣。
|
||||
<div class="mt-1 text-xs text-[var(--el-text-color-secondary)]">
|
||||
默认关系负责支付渠道商户路由;只有“开启分账”且渠道已绑定时才执行平台抽佣。
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<el-button icon="Refresh" :disabled="!form.id || relationActionId !== null || relationLoading"
|
||||
v-auth="'wallet_mchManage_setting'" @click="loadRelations">刷新</el-button>
|
||||
<el-button type="primary" icon="Plus" :disabled="!form.id || relationActionId !== null || relationLoading"
|
||||
v-auth="'wallet_mchManage_setting'"
|
||||
@click="openRelationDialog()">新增关系</el-button>
|
||||
<el-button type="primary" icon="Plus"
|
||||
:disabled="!form.id || relationActionId !== null || relationLoading"
|
||||
v-auth="'wallet_mchManage_setting'" @click="openRelationDialog()">新增关系</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<el-alert v-if="!form.id" type="warning" :closable="false" show-icon title="请先保存支付配置,再维护一对多分账关系。" />
|
||||
@@ -73,32 +74,41 @@
|
||||
<el-tag v-if="!isRelationFzEnabled(row)" type="info">分账已关闭</el-tag>
|
||||
<el-tag v-else :type="relationStatusMeta(row.status).type">{{
|
||||
relationStatusMeta(row.status).label
|
||||
}}</el-tag>
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="boundTime" label="绑定时间" min-width="170">
|
||||
<template #default="{ row }">{{ isRelationFzEnabled(row) ? (row.boundTime || '-') : '-' }}</template>
|
||||
<template #default="{ row }">{{ isRelationFzEnabled(row) ? (row.boundTime || '-') : '-'
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="bindError" label="最近错误" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ isRelationFzEnabled(row) ? (row.bindError || '-') : '-' }}</template>
|
||||
<template #default="{ row }">{{ isRelationFzEnabled(row) ? (row.bindError || '-') : '-'
|
||||
}}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="350" fixed="right" align="center">
|
||||
<el-table-column label="操作" width="460" fixed="right" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-button v-if="form.platformType === '20' && row.status !== 'SUPERSEDED' && false" text
|
||||
type="warning" v-auth="'wallet_mchManage_setting'"
|
||||
:disabled="relationActionId !== null || relationLoading || aliasLoading"
|
||||
@click="openAlipayAliasDialog(row)">修改商户简称</el-button>
|
||||
<el-button v-if="row.status !== 'SUPERSEDED'" text type="primary"
|
||||
v-auth="'wallet_mchManage_setting'" :disabled="relationActionId !== null || relationLoading"
|
||||
@click="openRelationDialog(row)">编辑</el-button>
|
||||
<el-button v-if="row.isDefault !== '1'" text type="primary"
|
||||
v-auth="'wallet_mchManage_setting'" :loading="relationActionId === row.id"
|
||||
<el-button v-if="row.isDefault !== '1'" text type="primary" v-auth="'wallet_mchManage_setting'"
|
||||
:loading="relationActionId === row.id"
|
||||
:disabled="relationActionId !== null || relationLoading" @click="setRelationDefault(row)">
|
||||
{{ row.status === 'SUPERSEDED' ? '恢复' : '设为默认' }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="isRelationFzEnabled(row) && row.fzRatio > 0 && ['PENDING_BIND', 'BINDING', 'BIND_FAILED'].includes(row.status)"
|
||||
text type="warning" v-auth="'wallet_mchManage_setting'" :loading="relationActionId === row.id"
|
||||
:disabled="relationActionId !== null || relationLoading" @click="retryRelation(row)">重试</el-button>
|
||||
text type="warning" v-auth="'wallet_mchManage_setting'"
|
||||
:loading="relationActionId === row.id"
|
||||
:disabled="relationActionId !== null || relationLoading"
|
||||
@click="retryRelation(row)">重试</el-button>
|
||||
<el-button v-if="row.status !== 'SUPERSEDED'" text type="danger"
|
||||
v-auth="'wallet_mchManage_setting'" :loading="relationActionId === row.id"
|
||||
:disabled="relationActionId !== null || relationLoading" @click="removeRelation(row)">删除</el-button>
|
||||
:disabled="relationActionId !== null || relationLoading"
|
||||
@click="removeRelation(row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -121,8 +131,8 @@
|
||||
<span>是否开启分账</span>
|
||||
<tip content="关闭后仅使用当前关系的渠道商户路由,不绑定接收方、不抽佣、不退分账。" />
|
||||
</template>
|
||||
<el-switch v-model="relationForm.enableFz" active-value="1" inactive-value="0"
|
||||
active-text="开启" inactive-text="关闭" />
|
||||
<el-switch v-model="relationForm.enableFz" active-value="1" inactive-value="0" active-text="开启"
|
||||
inactive-text="关闭" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.platformType === '20'" label="平台账号键" prop="accountKey">
|
||||
<el-input v-model="relationForm.accountKey" maxlength="64" placeholder="为空使用平台默认支付宝账号" />
|
||||
@@ -153,7 +163,8 @@
|
||||
<span class="ml-2 text-[var(--el-text-color-secondary)]">%</span>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.platformType === '10' && relationForm.enableFz === '1'" label="微信关系类型" prop="channelRelationType">
|
||||
<el-form-item v-if="form.platformType === '10' && relationForm.enableFz === '1'" label="微信关系类型"
|
||||
prop="channelRelationType">
|
||||
<el-select v-model="relationForm.channelRelationType" class="w-full">
|
||||
<el-option v-for="item in wechatRelationOptions" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
@@ -166,7 +177,8 @@
|
||||
<el-alert type="info" :closable="false" show-icon>
|
||||
<template #title>{{ form.platformType === '20'
|
||||
? '支付宝关系只允许填写 userId、loginName、openId 或 cardAliasNo 中的一种。'
|
||||
: '微信接收方类型和关系类型在开启分账后提交微信分账关系接口。' }} 修改二级商户、平台账号或接收方身份时会生成新关系版本;仅开启分账的关系会进入渠道绑定任务。历史订单仍保留原关系。</template>
|
||||
: '微信接收方类型和关系类型在开启分账后提交微信分账关系接口。' }}
|
||||
修改二级商户、平台账号或接收方身份时会生成新关系版本;仅开启分账的关系会进入渠道绑定任务。历史订单仍保留原关系。</template>
|
||||
</el-alert>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@@ -176,6 +188,9 @@
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<alipay-merchant-profile-dialog v-model="aliasVisible" :relation="aliasRelation"
|
||||
@loading-change="aliasLoading = $event" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="PaySettingForm">
|
||||
@@ -183,6 +198,7 @@ import { useMessage, useMessageBox } from "/@/hooks/message"
|
||||
|
||||
import * as mchPaySettingApi from "/@/api/wallet/mch-pay-setting";
|
||||
import * as mchFzRelationApi from "/@/api/thirdparty/third-mch-fz-relation";
|
||||
import AlipayMerchantProfileDialog from './alipay-merchant-profile-dialog.vue'
|
||||
|
||||
const emit = defineEmits(["refresh"])
|
||||
|
||||
@@ -196,6 +212,12 @@ const relationActionId = ref<string | number | null>(null)
|
||||
const relationVisible = ref(false)
|
||||
const relationFormRef = ref()
|
||||
const relations = ref<any[]>([])
|
||||
/** 支付宝商户简称修改弹窗是否显示。 */
|
||||
const aliasVisible = ref(false)
|
||||
/** 支付宝商户简称修改申请是否正在提交。 */
|
||||
const aliasLoading = ref(false)
|
||||
/** 当前正在修改支付宝全量资料的关系。 */
|
||||
const aliasRelation = ref<any>(null)
|
||||
const relationForm = reactive<any>({
|
||||
id: undefined,
|
||||
mchId: '',
|
||||
@@ -383,6 +405,24 @@ const openRelationDialog = (row?: any) => {
|
||||
relationVisible.value = true
|
||||
}
|
||||
|
||||
/** 打开支付宝商户简称修改弹窗;简称属于支付宝二级商户资料,不并入分账关系编辑表单。 */
|
||||
const openAlipayAliasDialog = (row: any) => {
|
||||
if (form.platformType !== '20') {
|
||||
useMessage().warning('只有支付宝支付配置支持修改商户简称')
|
||||
return
|
||||
}
|
||||
if (!row?.id || row.status === 'SUPERSEDED') {
|
||||
useMessage().warning('当前关系不能修改支付宝商户简称')
|
||||
return
|
||||
}
|
||||
if (!String(row.channelSubMchId || '').trim()) {
|
||||
useMessage().warning('请先配置支付宝直付通二级商户标识')
|
||||
return
|
||||
}
|
||||
aliasRelation.value = row
|
||||
aliasVisible.value = true
|
||||
}
|
||||
|
||||
/** 保存关系配置;渠道身份变更由后端创建新版本,其余渠道字段变更会唤醒稳定的 Quartz 绑定任务。 */
|
||||
const saveRelation = async () => {
|
||||
const valid = await relationFormRef.value?.validate().catch(() => false)
|
||||
|
||||
Reference in new issue
Block a user