refactor(merchant): 商户端页面去冗余标题强调与死代码清理

- 列表页查询区Card移除重复模块名标题(对齐订单列表范式)
- 配置/工作台页移除标题(商户名)/(应用名)后缀
- 商户资料页表单移除商户名称字段及校验
- 清理仅为标题服务的merchantInfo/appName等死代码
This commit is contained in:
DaxPay Dev
2026-07-24 20:51:12 +08:00
parent 5748e5c2b6
commit 4119a3879e
15 changed files with 40 additions and 180 deletions

View File

@@ -1,38 +1,18 @@
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { $t } from '@vben/locales';
import { IconifyIcon } from '@vben-core/icons';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
defineOptions({ name: 'ChannelMerchantCreate' });
const router = useRouter();
const merchantInfo = ref<MerchantInfo>({});
const merchantLoading = ref(false);
/** 加载当前商户信息 */
async function loadMerchantInfo() {
merchantLoading.value = true;
try {
const { data } = await MerchantApi.get();
merchantInfo.value = data || {};
} finally {
merchantLoading.value = false;
}
}
/** 返回列表 */
function handleBack() {
router.push({ path: '/mch/channel-merchant' });
}
onMounted(() => {
loadMerchantInfo();
});
</script>
<template>
@@ -50,13 +30,9 @@
</template>
</a-button>
<!-- 国际化创建通道商户与菜单一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('payment.merchant.channelMerchant.createTitle') }}</span>
<span v-if="merchantLoading" class="text-sm text-muted-foreground">
<a-skeleton-input :active="true" size="small" />
</span>
<span v-else-if="merchantInfo.mchName" class="text-sm text-muted-foreground"
>({{ merchantInfo.mchName }})</span
>
<span class="text-lg font-bold text-foreground">{{
$t('payment.merchant.channelMerchant.createTitle')
}}</span>
</div>
</template>

View File

@@ -12,7 +12,6 @@
ChannelMerchantApi,
type ChannelMerchantResult,
} from '#/api/payment/global/channel-merchant/channel-merchant.api';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import ChannelLogo from '#/components/channel/ChannelLogo.vue';
import { PermCodes } from '#/constants/perm-codes';
import { productChannelMap, productI18nMap, productNameMap } from '#/enums/payment';
@@ -28,15 +27,10 @@
const { hasPermission } = usePermission();
const loading = ref(false);
// 商户信息加载状态
const merchantLoading = ref(false);
// 切换启用状态按行 loading
const enableLoadingMap = ref<Record<string, boolean>>({});
const xTable = ref<VxeTableInstance>();
const xToolbar = ref<VxeToolbarInstance>();
// 当前商户号MerchantApi.get不走 URL
const mchNo = ref('');
const merchantInfo = ref<MerchantInfo>({});
const list = ref<ChannelMerchantResult[]>([]);
const pageConfig = ref({
currentPage: 1,
@@ -79,18 +73,6 @@
});
}
/** 加载当前商户信息 */
async function loadMerchantInfo() {
merchantLoading.value = true;
try {
const { data } = await MerchantApi.get();
merchantInfo.value = data || {};
mchNo.value = data?.mchNo || '';
} finally {
merchantLoading.value = false;
}
}
/** 加载通道商户列表(后端强制当前商户) */
function loadList() {
loading.value = true;
@@ -166,9 +148,8 @@
});
}
onMounted(async () => {
onMounted(() => {
xTable.value?.connectToolbar(xToolbar.value as VxeToolbarInstance);
await loadMerchantInfo();
loadList();
});
</script>
@@ -176,19 +157,6 @@
<template>
<div class="m-4">
<a-card variant="borderless" class="rounded-xl shadow-sm">
<template #title>
<div class="flex items-center gap-2">
<!-- 国际化通道商户与菜单 title 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('payment.merchant.channelMerchant.title') }}</span>
<span v-if="merchantLoading" class="text-sm text-muted-foreground">
<a-skeleton-input :active="true" size="small" />
</span>
<span v-else-if="merchantInfo.mchName" class="text-sm text-muted-foreground"
>({{ merchantInfo.mchName }})</span
>
</div>
</template>
<vxe-toolbar ref="xToolbar" custom refresh :refresh-options="{ queryMethod: loadList }">
<template #buttons>
<a-button v-if="hasPermission(PermCodes.Channel.Merchant.MANAGE)" type="primary" @click="handleCreate">

View File

@@ -6,7 +6,7 @@
import { $t } from '@vben/locales';
import { TerminalDeviceApi, type TerminalDeviceResult } from '#/api/payment/device/terminal.api';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import { MerchantApi } from '#/api/payment/merchant/merchant.api';
import { BQuery, type QueryField } from '#/components/query';
import { PermCodes } from '#/constants/perm-codes';
import { useMessage } from '#/hooks/useMessage';
@@ -20,9 +20,8 @@
const { confirm, message } = useMessage();
const { hasPermission } = usePermission();
// 当前商户号MerchantApi.get不走 URL
// 当前商户号MerchantApi.get不走 URL;新增终端时传入
const mchNo = ref('');
const merchantInfo = ref<MerchantInfo>({});
const loading = ref(false);
const xTable = ref<VxeTableInstance>();
@@ -131,10 +130,9 @@
});
}
/** 加载商户信息用于标题展示 */
/** 加载当前商户号(新增终端时传入) */
async function loadMerchantInfo() {
const { data } = await MerchantApi.get();
merchantInfo.value = data || {};
mchNo.value = data?.mchNo || '';
}
@@ -148,13 +146,6 @@
<template>
<div class="m-3 p-3 bg-background rounded-lg list-page-compact">
<a-card>
<template #title>
<div class="flex items-center gap-2">
<!-- 国际化系统终端与菜单一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('payment.device.terminal.systemTitle') }}</span>
<span v-if="merchantInfo.mchName" class="text-sm text-muted-foreground">({{ merchantInfo.mchName }})</span>
</div>
</template>
<BQuery :fields="queryFields" :query-params="queryForm" @query="queryPage" @reset="resetQuery" />
</a-card>

View File

@@ -44,7 +44,6 @@
const loading = ref(false);
const editing = ref(false);
const appInfo = ref<MchAppInfoResult>({});
const appName = computed(() => appInfo.value.appName || '');
const mchNo = computed(() => appInfo.value.mchNo || '');
const config = ref<AggregateConfigResult>({});
@@ -377,7 +376,6 @@
</template>
</a-button>
<span class="text-lg font-bold">{{ $t('menu.payment.merchant.aggregateScan') }}</span>
<span v-if="appName" class="text-sm text-muted-foreground"> ({{ appName }}) </span>
</div>
</template>

View File

@@ -7,7 +7,7 @@
import { IconifyIcon } from '@vben-core/icons';
import { MchAppInfoApi, type MchAppInfoResult } from '#/api/payment/merchant/mch-app-info.api';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import { MerchantApi } from '#/api/payment/merchant/merchant.api';
import { PermCodes } from '#/constants/perm-codes';
import { usePermission } from '#/hooks/usePermission';
import useTablePage from '#/hooks/useTablePage';
@@ -20,9 +20,8 @@
const router = useRouter();
const { hasPermission } = usePermission();
// 当前商户号MerchantApi.get不走 URL
// 当前商户号MerchantApi.get不走 URL;新增应用时传入
const mchNo = ref('');
const merchantInfo = ref<MerchantInfo>({});
const appEditRef = ref<InstanceType<typeof MchAppInfoEdit>>();
/**
@@ -78,12 +77,11 @@
const showNoDefaultTip = computed(() => hasAppWithoutDefault.value && !loading.value);
/**
* 加载当前商户信息
* 加载当前商户号(新增应用时传入)
*/
async function loadMerchantInfo() {
const { data } = await MerchantApi.get();
if (data) {
merchantInfo.value = data;
mchNo.value = data.mchNo || '';
}
}
@@ -111,14 +109,6 @@
<template>
<div class="m-4">
<a-card variant="borderless" class="rounded-xl shadow-sm">
<template #title>
<div class="flex items-center gap-2">
<!-- 国际化应用管理与菜单 i18n_key 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.app') }}</span>
<span v-if="merchantInfo.mchName" class="text-sm text-muted-foreground">({{ merchantInfo.mchName }})</span>
</div>
</template>
<!-- 国际化有应用但未设置默认应用时提示 -->
<div v-if="showNoDefaultTip" class="mb-4">
<a-alert :message="$t('payment.merchant.app.app.noDefaultAppTip')" type="warning" show-icon />
@@ -157,7 +147,7 @@
<style scoped>
.app-card-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 16px;
}
</style>

View File

@@ -361,7 +361,6 @@
<span class="text-lg font-bold text-foreground">
{{ $t('payment.merchant.app.app.workbenchTitle') }}
</span>
<span v-if="appInfo.appName" class="text-sm text-muted-foreground"> ({{ appInfo.appName }}) </span>
<a-tag v-if="appInfo.defaultApp" color="processing" class="!m-0 !text-xs">
{{ $t('payment.merchant.app.app.defaultTag') }}
</a-tag>

View File

@@ -42,7 +42,6 @@
const loading = ref(false);
const appInfo = ref<MchAppInfoResult>({});
const appName = computed(() => appInfo.value.appName || '');
const mchNo = computed(() => appInfo.value.mchNo || '');
const tableData = ref<CashierItemResult[]>([]);
const methodLabelMap = ref<Record<string, string>>({});
@@ -228,7 +227,6 @@
</template>
</a-button>
<span class="text-lg font-bold">{{ $t('menu.payment.merchant.cashierConfig') }}</span>
<span v-if="appName" class="text-sm text-muted-foreground"> ({{ appName }}) </span>
</div>
</template>

View File

@@ -52,7 +52,6 @@
const loading = ref(false);
const editing = ref(false);
const appInfo = ref<MchAppInfoResult>({});
const appName = computed(() => appInfo.value.appName || '');
const mchNo = computed(() => appInfo.value.mchNo || '');
const config = ref<CodeConfigResult>({});
@@ -472,7 +471,6 @@
</template>
</a-button>
<span class="text-lg font-bold">{{ $t('menu.payment.merchant.codePayConfig') }}</span>
<span v-if="appName" class="text-sm text-muted-foreground"> ({{ appName }}) </span>
</div>
</template>

View File

@@ -13,7 +13,7 @@
type MerchantCredentialResult,
} from '#/api/payment/merchant/credential.api';
import { KeyGenApi } from '#/api/payment/merchant/key-gen.api';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import { MerchantApi } from '#/api/payment/merchant/merchant.api';
import { PermCodes } from '#/constants/perm-codes';
import { useFormEdit } from '#/hooks/useFormEdit';
import { useMessage } from '#/hooks/useMessage';
@@ -32,7 +32,6 @@
const isEditing = ref(false);
// 当前商户号MerchantApi.get
const mchNo = ref('');
const merchantInfo = ref<MerchantInfo>({});
// 表单数据
const formState = ref<MerchantCredentialResult>({});
// 原始脱敏数据,用于 diffForm 比对
@@ -46,7 +45,6 @@
*/
async function loadMerchantInfo() {
const { data } = await MerchantApi.get();
merchantInfo.value = data || {};
mchNo.value = data?.mchNo || '';
}
@@ -199,11 +197,8 @@
<div class="m-4">
<a-card variant="borderless" class="rounded-xl shadow-sm">
<template #title>
<div class="flex items-center gap-2">
<!-- 对接配置与菜单 menu.payment.merchant.credential 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.credential') }}</span>
<span v-if="merchantInfo.mchName" class="text-sm text-muted-foreground">({{ merchantInfo.mchName }})</span>
</div>
<!-- 对接配置与菜单 menu.payment.merchant.credential 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.credential') }}</span>
</template>
<template #extra>
@@ -328,7 +323,9 @@
<div>
<div class="mb-2 flex items-center justify-between">
<!-- 私钥 -->
<span class="font-medium text-foreground">{{ $t('payment.merchant.credential.credential.privateKey') }}</span>
<span class="font-medium text-foreground">{{
$t('payment.merchant.credential.credential.privateKey')
}}</span>
<a-button size="small" type="primary" ghost @click="handleCopy(privateKeyContent)">
<template #icon>
<IconifyIcon icon="ant-design:copy-outlined" />

View File

@@ -46,7 +46,6 @@
// 编辑模式
const isEditing = ref(false);
const appInfo = ref<MchAppInfoResult>({});
const appName = computed(() => appInfo.value.appName || '');
const form = reactive<EasyPayCredentialResult>({
enable: false,
enableV1: false,
@@ -288,7 +287,6 @@
<span class="text-lg font-bold text-foreground">
{{ $t('menu.payment.merchant.easypay') }}
</span>
<span v-if="appName" class="text-sm text-muted-foreground"> ({{ appName }}) </span>
</div>
</template>

View File

@@ -3,7 +3,7 @@
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 { PermCodes } from '#/constants/perm-codes';
import { useMessage } from '#/hooks/useMessage';
import { usePermission } from '#/hooks/usePermission';
@@ -48,7 +48,6 @@
// 表单校验规则
const rules = {
mchName: [{ required: true, message: $t('payment.merchant.base.validation.pleaseInputMchName') }],
mchShortName: [{ required: true, message: $t('payment.merchant.base.validation.pleaseInputMchShortName') }],
status: [{ required: true, message: $t('payment.merchant.base.validation.pleaseSelectStatus') }],
};
@@ -129,11 +128,8 @@
<div class="m-4">
<a-card variant="borderless" class="rounded-xl shadow-sm">
<template #title>
<div class="flex items-center gap-2">
<!-- 商户资料与菜单 menu.payment.merchant.profile 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.profile') }}</span>
<span v-if="form.mchName" class="text-sm text-muted-foreground">({{ form.mchName }})</span>
</div>
<!-- 商户资料与菜单 menu.payment.merchant.profile 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.profile') }}</span>
</template>
<template #extra>
<a-space>
@@ -169,14 +165,6 @@
<a-form-item :label="$t('payment.merchant.base.field.subjectType')">
<a-input :value="subjectTypeMap[form.subjectType || ''] || form.subjectType" disabled />
</a-form-item>
<!-- 商户名称 -->
<a-form-item :label="$t('payment.merchant.base.field.mchName')" name="mchName">
<a-input
v-model:value="form.mchName"
:disabled="!isEditing"
:placeholder="$t('payment.merchant.form.add.mchNamePlaceholder')"
/>
</a-form-item>
<!-- 商户简称 -->
<a-form-item :label="$t('payment.merchant.base.field.mchShortName')" name="mchShortName">
<a-input

View File

@@ -247,26 +247,28 @@
function getActionMenu(row: MchStoreInfoResult): MenuProps {
const items: MenuProps['items'] = [];
if (hasPermission(PermCodes.Merchant.Store.MANAGE)) {
if (!row.defaultStore) {
items.push({
key: 'setDefault',
// 设为默认
label: $t('payment.merchant.store.store.setDefault'),
});
} else {
if (row.defaultStore) {
items.push({
key: 'clearDefault',
// 取消默认
label: $t('payment.merchant.store.store.clearDefault'),
});
} else {
items.push({
key: 'setDefault',
// 设为默认
label: $t('payment.merchant.store.store.setDefault'),
});
}
items.push({ type: 'divider' });
items.push({
key: 'delete',
// 删除
label: $t('common.delete'),
danger: true,
});
items.push(
{ type: 'divider' },
{
key: 'delete',
// 删除
label: $t('common.delete'),
danger: true,
},
);
}
return {
items,
@@ -293,10 +295,6 @@
<template>
<div class="m-3 p-3 bg-background rounded-lg list-page-compact">
<a-card>
<template #title>
<!-- 门店管理与菜单 menu.payment.merchant.store 一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('menu.payment.merchant.store') }}</span>
</template>
<BQuery :fields="queryFields" :query-params="queryForm" @query="queryPage" @reset="resetQuery" />
</a-card>

View File

@@ -8,8 +8,8 @@
import { IconifyIcon } from '@vben-core/icons';
import { MerchantApi } from '#/api/payment/merchant/merchant.api';
import { MerchantUserApi, type MerchantUserResult } from '#/api/payment/merchant/merchant-user.api';
import { MerchantApi } from '#/api/payment/merchant/merchant.api';
import { BQuery, type QueryField } from '#/components/query';
import { PermCodes } from '#/constants/perm-codes';
import { useMessage } from '#/hooks/useMessage';
@@ -341,11 +341,6 @@
<template>
<div class="m-3 p-3 bg-background rounded-lg list-page-compact">
<a-card>
<template #title>
<!-- 商户用户与菜单 menu.payment.merchant.user 一致 -->
<span>{{ $t('menu.payment.merchant.user') }}</span>
</template>
<!-- 查询表单 -->
<BQuery :fields="queryFields" :query-params="queryForm" @query="queryPage" @reset="resetQuery" />
</a-card>
@@ -355,11 +350,7 @@
<vxe-toolbar ref="xToolbar" custom refresh :refresh-options="{ queryMethod: queryPage }">
<template #buttons>
<a-space>
<a-button
v-if="hasPermission(PermCodes.Merchant.User.MANAGE)"
type="primary"
@click="handleAdd"
>
<a-button v-if="hasPermission(PermCodes.Merchant.User.MANAGE)" type="primary" @click="handleAdd">
{{ $t('common.add') }}
</a-button>
<a-dropdown v-if="hasPermission(PermCodes.Merchant.User.MANAGE)" :menu="getBatchActionMenu()">
@@ -427,10 +418,7 @@
>
{{ $t('common.edit') }}
</a-button>
<a-dropdown
v-if="hasPermission(PermCodes.Merchant.User.MANAGE)"
:menu="getActionMenu(row)"
>
<a-dropdown v-if="hasPermission(PermCodes.Merchant.User.MANAGE)" :menu="getActionMenu(row)">
<a-button type="link" size="small">
{{ $t('common.more') }}
<IconifyIcon icon="ant-design:down-outlined" class="inline" />

View File

@@ -7,7 +7,6 @@
import { IconifyIcon } from '@vben-core/icons';
import { MerchantApi, type MerchantInfo } from '#/api/payment/merchant/merchant.api';
import {
MchWxDomainVerifyApi,
type MchWxDomainVerifyQuery,
@@ -31,8 +30,6 @@
const xTable = ref<VxeTableInstance>();
const xToolbar = ref<VxeToolbarInstance>();
const merchantInfo = ref<MerchantInfo>({});
// 查询条件mchNo 由后端上下文决定)
const queryForm = ref<MchWxDomainVerifyQuery>({});
@@ -60,12 +57,6 @@
},
]);
/** 加载商户信息(展示商户名) */
async function loadMerchantInfo() {
const { data } = await MerchantApi.get();
merchantInfo.value = data || {};
}
/** 分页查询当前商户的验证文件列表 */
function queryPage() {
loading.value = true;
@@ -141,7 +132,6 @@
}
onMounted(() => {
loadMerchantInfo();
xTable.value?.connectToolbar(xToolbar.value as VxeToolbarInstance);
queryPage();
});
@@ -150,16 +140,6 @@
<template>
<div class="m-4">
<a-card variant="borderless" class="rounded-xl shadow-sm">
<template #title>
<div class="flex items-center gap-2">
<!-- 国际化微信域名验证与菜单一致 -->
<span class="text-lg font-bold text-foreground">{{ $t('payment.wxVerify.title') }}</span>
<span v-if="merchantInfo.mchName" class="text-sm text-muted-foreground"
>({{ merchantInfo.mchName }})</span
>
</div>
</template>
<BQuery :fields="queryFields" :query-params="queryForm" @query="queryPage" @reset="resetQuery" />
<div class="mt-4">
@@ -201,12 +181,7 @@
:min-width="200"
show-overflow
/>
<vxe-column
field="remark"
:title="$t('payment.wxVerify.field.remark')"
:min-width="160"
show-overflow
/>
<vxe-column field="remark" :title="$t('payment.wxVerify.field.remark')" :min-width="160" show-overflow />
<vxe-column
field="createTime"
:title="$t('payment.wxVerify.field.createTime')"

View File

@@ -35,7 +35,6 @@
const appId = computed(() => routeContext.query.value.appId);
const appInfo = ref<MchAppInfoResult>({});
const appName = computed(() => appInfo.value.appName || '');
/** 加载当前应用信息 */
async function loadAppInfo() {
@@ -154,7 +153,6 @@
</a-button>
<!-- 国际化通道路由与菜单一致 -->
<span class="text-lg font-bold">{{ $t('menu.payment.merchant.payRoute') }}</span>
<span v-if="appName" class="text-sm text-muted-foreground">({{ appName }})</span>
</div>
</template>