feat(payment): 商户与通道商户列表新增删除按钮(强确认)

- MerchantList: 操作列改 a-space, 新增 danger 删除按钮, useDeleteConfirm 输入商户名强确认
- ChannelMerchantList: 新增 danger 删除按钮, useDeleteConfirm 输入通道商户名强确认
- channel-merchant.api.ts: 新增 delete(id) 方法, 调 POST /admin/merchant/channel-merchant/delete
- i18n 六语种同步: merchant/base.json 新增 action.delete; channelMerchant.json 补齐 confirmDelete/confirmDeleteDesc/confirmDeleteOk/deleteSuccess
This commit is contained in:
DaxPay Dev
2026-07-20 10:11:48 +08:00
parent eb4e06d439
commit d4b6632c09
15 changed files with 120 additions and 36 deletions

View File

@@ -36,6 +36,12 @@ export const ChannelMerchantApi = {
update(data: ChannelMerchantEditParam): Promise<Result<void>> {
return defHttp.post({ url: '/admin/merchant/channel-merchant/update', data });
},
/**
* 删除通道商户
*/
delete(id: string): Promise<Result<void>> {
return defHttp.post({ url: '/admin/merchant/channel-merchant/delete', params: { id } });
},
};
/**

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "Are you sure you want to enable this merchant?",
"confirmDisableContent": "Are you sure you want to disable this merchant? After disabling, the merchant account will not be able to log in."
"confirmDisableContent": "Are you sure you want to disable this merchant? After disabling, the merchant account will not be able to log in.",
"delete": "Delete Merchant"
},
"validation": {
"pleaseInputMchName": "Please enter merchant name",

View File

@@ -45,11 +45,11 @@
"confirmEnableDesc": "Payment via this channel merchant will be available after enabling",
"confirmDisable": "Confirm to disable this channel merchant?",
"confirmDisableDesc": "Payment via this channel merchant will be unavailable after disabling",
"confirmDelete": "Confirm to delete this channel merchant?",
"confirmDeleteDesc": "This action cannot be undone",
"confirmDelete": "Delete this channel merchant?",
"confirmDeleteDesc": "This channel merchant and all its configurations will become unavailable and this action cannot be undone. Please type the channel merchant name to confirm deletion.",
"confirmEnableOk": "Enable",
"confirmDisableOk": "Disable",
"confirmDeleteOk": "Delete",
"confirmDeleteOk": "Confirm Delete",
"editTitle": "Edit Channel Merchant",
"pleaseInputName": "Please enter merchant name",
"enableSuccess": "Enabled successfully",

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "この販売者を有効にしてもよろしいですか?",
"confirmDisableContent": "この販売者を無効にしてもよろしいですか?無効にすると、販売アカウントはログインできなくなります。"
"confirmDisableContent": "この販売者を無効にしてもよろしいですか?無効にすると、販売アカウントはログインできなくなります。",
"delete": "マーチャントを削除"
},
"validation": {
"pleaseInputMchName": "販売者名を入力してください",

View File

@@ -45,16 +45,16 @@
"confirmEnableDesc": "有効にした後、このチャネル販売者を介した支払いが可能になります",
"confirmDisable": "このチャネル販売者を無効にすることを確認しますか?",
"confirmDisableDesc": "無効化すると、このチャネル販売者による支払いは利用できなくなります",
"confirmDelete": "このチャネル販売者を削除しますか?",
"confirmDeleteDesc": "この操作は元に戻せません",
"confirmDelete": "このチャネルマーチャントを削除しますか",
"confirmDeleteDesc": "削除後、このチャネルマーチャントおよび関連するすべての設定は利用できなくなり、元に戻すことはできません。確認のためチャネルマーチャント名を入力してください。",
"confirmEnableOk": "有効にする",
"confirmDisableOk": "無効にする",
"confirmDeleteOk": "消去",
"confirmDeleteOk": "削除を確認",
"editTitle": "チャネル販売者の編集",
"pleaseInputName": "販売者名を入力してください",
"enableSuccess": "正常に有効になりました",
"disableSuccess": "正常に無効になりました",
"deleteSuccess": "正常に削除されました",
"deleteSuccess": "削除が成功しました",
"noData": "チャネル販売者のデータがない",
"create": "チャネル販売者の作成",
"createTitle": "チャネル販売者の作成",

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "이 판매자를 활성화하시겠습니까?",
"confirmDisableContent": "이 판매자를 비활성화하시겠습니까? 비활성화한 후에는 판매자 계정에 로그인할 수 없습니다."
"confirmDisableContent": "이 판매자를 비활성화하시겠습니까? 비활성화한 후에는 판매자 계정에 로그인할 수 없습니다.",
"delete": "가맹점 삭제"
},
"validation": {
"pleaseInputMchName": "판매자 이름을 입력하세요.",

View File

@@ -45,16 +45,16 @@
"confirmEnableDesc": "이 채널 판매자를 통한 결제는 활성화 후 가능합니다.",
"confirmDisable": "이 채널 판매자를 비활성화하시겠습니까?",
"confirmDisableDesc": "비활성화 후에는 이 채널 판매자를 통한 결제를 사용할 수 없습니다.",
"confirmDelete": "이 채널 판매자를 삭제하시겠습니까?",
"confirmDeleteDesc": "이 작업은 취소할 수 없습니다.",
"confirmDelete": "이 채널 가맹점을 삭제하시겠습니까?",
"confirmDeleteDesc": "삭제 후 이 채널 가맹점과 모든 설정을 사용할 수 없게 되며, 이 작업은 취소할 수 없습니다. 확인을 위해 채널 가맹점 이름을 입력하세요.",
"confirmEnableOk": "할 수 있게 하다",
"confirmDisableOk": "장애를 입히다",
"confirmDeleteOk": "삭제",
"confirmDeleteOk": "삭제 확인",
"editTitle": "채널 판매자 편집",
"pleaseInputName": "판매자 이름을 입력하세요.",
"enableSuccess": "성공적으로 활성화되었습니다",
"disableSuccess": "성공적으로 비활성화되었습니다",
"deleteSuccess": "삭제되었습니다.",
"deleteSuccess": "삭제 성공",
"noData": "채널 판매자 데이터 없음",
"create": "채널 판매자 만들기",
"createTitle": "채널 판매자 만들기",

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "确定要启用该商户吗?",
"confirmDisableContent": "确定要禁用该商户吗?禁用后商户账号将无法登录。"
"confirmDisableContent": "确定要禁用该商户吗?禁用后商户账号将无法登录。",
"delete": "删除商户"
},
"validation": {
"pleaseInputMchName": "请输入商户名称",

View File

@@ -46,7 +46,7 @@
"confirmDisable": "确认禁用该通道商户?",
"confirmDisableDesc": "禁用后该通道商户支付将不可用",
"confirmDelete": "确认删除该通道商户?",
"confirmDeleteDesc": "删除后不可恢复",
"confirmDeleteDesc": "删除后该通道商户及其所有配置将不可使用,且操作不可撤销。请输入通道商户名称以确认删除。",
"confirmEnableOk": "确认启用",
"confirmDisableOk": "确认禁用",
"confirmDeleteOk": "确认删除",

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "確定要啓用該商户嗎?",
"confirmDisableContent": "確定要禁用該商户嗎?禁用後商户賬號將無法登錄。"
"confirmDisableContent": "確定要禁用該商户嗎?禁用後商户賬號將無法登錄。",
"delete": "刪除商戶"
},
"validation": {
"pleaseInputMchName": "請輸入商户名稱",

View File

@@ -45,8 +45,8 @@
"confirmEnableDesc": "啓用後該通道商户支付將恢復正常",
"confirmDisable": "確認禁用該通道商户?",
"confirmDisableDesc": "禁用後該通道商户支付將不可用",
"confirmDelete": "確認刪除該通道商",
"confirmDeleteDesc": "刪除後不可恢復",
"confirmDelete": "確認刪除該通道商",
"confirmDeleteDesc": "刪除後該通道商戶及其所有配置將不可使用,且操作不可撤銷。請輸入通道商戶名稱以確認刪除。",
"confirmEnableOk": "確認啓用",
"confirmDisableOk": "確認禁用",
"confirmDeleteOk": "確認刪除",

View File

@@ -19,7 +19,8 @@
},
"action": {
"confirmEnableContent": "確定要啟用該商戶嗎?",
"confirmDisableContent": "確定要停用該商戶嗎?停用後商戶賬號將無法登入。"
"confirmDisableContent": "確定要停用該商戶嗎?停用後商戶賬號將無法登入。",
"delete": "刪除商戶"
},
"validation": {
"pleaseInputMchName": "請輸入商戶名稱",

View File

@@ -46,7 +46,7 @@
"confirmDisable": "確認停用該通道商戶?",
"confirmDisableDesc": "停用後該通道商戶支付將不可用",
"confirmDelete": "確認刪除該通道商戶?",
"confirmDeleteDesc": "刪除後不可恢復",
"confirmDeleteDesc": "刪除後該通道商戶及其所有配置將不可使用,且操作不可撤銷。請輸入通道商戶名稱以確認刪除。",
"confirmEnableOk": "確認啟用",
"confirmDisableOk": "確認停用",
"confirmDeleteOk": "確認刪除",

View File

@@ -14,6 +14,7 @@
import RouteQueryMissingState from '#/components/route/RouteQueryMissingState.vue';
import { PermCodes } from '#/constants/perm-codes';
import { productChannelMap, productI18nMap, productNameMap } from '#/enums/payment';
import { useDeleteConfirm } from '#/hooks/useDeleteConfirm';
import { useMessage } from '#/hooks/useMessage';
import { usePermission } from '#/hooks/usePermission';
import { useRequiredRouteQuery } from '#/hooks/useRequiredRouteQuery';
@@ -28,6 +29,7 @@
fallbackPath: '/payment/merchant',
});
const { confirm, message } = useMessage();
const { openDeleteConfirm } = useDeleteConfirm();
const { hasPermission } = usePermission();
// 通道商户新增权限
@@ -207,6 +209,23 @@
});
}
/**
* 删除通道商户(强确认:用户必须输入通道商户名称匹配才能确认)
*/
function handleDelete(record: ChannelMerchantResult) {
openDeleteConfirm({
name: record.channelMerchantName || '',
verificationText: record.channelMerchantName || '',
title: $t('payment.merchant.channelMerchant.confirmDeleteOk'),
descriptionKey: 'payment.merchant.channelMerchant.confirmDeleteDesc',
onConfirm: () =>
ChannelMerchantApi.delete(record.id!).then(() => {
message.success($t('payment.merchant.channelMerchant.deleteSuccess'));
loadList();
}),
});
}
onMounted(() => {
xTable.value?.connectToolbar(xToolbar.value as VxeToolbarInstance);
if (!routeContext.isValid.value) {
@@ -327,12 +346,27 @@
:show-overflow="true"
/>
<vxe-column fixed="right" width="100" :show-overflow="false" :title="$t('common.operation')">
<vxe-column fixed="right" width="200" :show-overflow="false" :title="$t('common.operation')">
<template #default="{ row }">
<!-- 管理 -->
<a-button type="link" size="small" @click="handleManage(row)">
{{ $t('payment.merchant.channelMerchant.manage') }}
</a-button>
<a-space :size="2">
<template #separator>
<a-divider type="vertical" />
</template>
<!-- 管理 -->
<a-button type="link" size="small" @click="handleManage(row)">
{{ $t('payment.merchant.channelMerchant.manage') }}
</a-button>
<!-- 删除危险操作强确认 -->
<a-button
v-if="hasPermission(PermCodes.Channel.Merchant.MANAGE)"
type="link"
size="small"
danger
@click="handleDelete(row)"
>
{{ $t('common.delete') }}
</a-button>
</a-space>
</template>
</vxe-column>
</vxe-table>

View File

@@ -6,15 +6,19 @@
import { $t } from '@vben/locales';
import { type MerchantInfo, MerchantApi } from '#/api/payment/merchant/merchant.api';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import { BQuery, type QueryField } from '#/components/query';
import { PermCodes } from '#/constants/perm-codes';
import { useDeleteConfirm } from '#/hooks/useDeleteConfirm';
import { useMessage } from '#/hooks/useMessage';
import { usePermission } from '#/hooks/usePermission';
import MerchantAdd from './MerchantAdd.vue';
const router = useRouter();
const { hasPermission } = usePermission();
const { openDeleteConfirm } = useDeleteConfirm();
const { message } = useMessage();
// 商户新增权限
const loading = ref(false);
@@ -104,6 +108,22 @@
function handleManage(row: MerchantInfo) {
router.push({ path: '/payment/merchant/manage', query: { mchNo: row.mchNo! } });
}
/**
* 删除商户(强确认:用户必须输入商户名称匹配才能确认)
*/
function handleDelete(row: MerchantInfo) {
openDeleteConfirm({
name: row.mchName || '',
verificationText: row.mchName || '',
title: $t('payment.merchant.base.action.delete'),
onConfirm: () =>
MerchantApi.delete(row.id!).then(() => {
message.success($t('common.deleteSuccess'));
queryPage();
}),
});
}
</script>
<template>
@@ -161,16 +181,34 @@
<a-tag v-else color="red">{{ $t('payment.merchant.base.status.disabled') }}</a-tag>
</template>
</vxe-column>
<vxe-column field="createTime" :title="$t('payment.merchant.base.field.createTime')" :min-width="180" formatter="formatDateTime" />
<vxe-column fixed="right" width="100" :show-overflow="false" :title="$t('common.operation')">
<vxe-column
field="createTime"
:title="$t('payment.merchant.base.field.createTime')"
:min-width="180"
formatter="formatDateTime"
/>
<vxe-column fixed="right" width="200" :show-overflow="false" :title="$t('common.operation')">
<template #default="{ row }">
<a
v-if="hasPermission(PermCodes.Merchant.Info.VIEW)"
href="javascript:"
class="vben-link"
@click="handleManage(row)"
>{{ $t('payment.merchant.manage.manage.title') }}</a
>
<a-space :size="2">
<template #separator>
<a-divider type="vertical" />
</template>
<a-button
v-if="hasPermission(PermCodes.Merchant.Info.VIEW)"
type="link"
size="small"
@click="handleManage(row)"
>{{ $t('payment.merchant.manage.manage.title') }}</a-button
>
<a-button
v-if="hasPermission(PermCodes.Merchant.Info.MANAGE)"
type="link"
size="small"
danger
@click="handleDelete(row)"
>{{ $t('common.delete') }}</a-button
>
</a-space>
</template>
</vxe-column>
</vxe-table>