fix: 修复商户中心下拉跳转无匹配路由

启用 external 路由并注册 MerchantCenter 页面,补齐商户中心文案与页面实现,确保头像下拉点击可正常进入商户中心。
This commit is contained in:
2026-02-06 13:28:49 +08:00
parent b9018c1ad8
commit dc0259339e
6 changed files with 191 additions and 4 deletions

View File

@@ -0,0 +1,41 @@
import { requestClient } from '#/api/request';
/**
* 商户信息 DTO
*/
export interface MerchantDto {
/** 商户ID */
id: string;
/** 商户名称 */
merchantName: string;
/** 联系人 */
contactName: string;
/** 联系电话 */
contactPhone: string;
/** 商户地址 */
address: string;
/** 商户状态 (1: 正常, 2: 禁用) */
status: number;
/** 营业执照代码 */
businessLicenseCode: string;
/** 商户简介 */
description: string;
/** 创建时间 */
createTime: string;
/** 商户Logo */
logo?: string;
}
/**
* 获取当前商户信息
*/
export async function getMerchantInfoApi() {
return requestClient.get<MerchantDto>('/merchant/info');
}
/**
* 更新商户信息
*/
export async function updateMerchantInfoApi(data: Partial<MerchantDto>) {
return requestClient.post('/merchant/update', data);
}

View File

@@ -87,7 +87,7 @@ const showDot = computed(() =>
const menus = computed(() => [
{
handler: () => {
router.push({ name: 'Profile' });
router.push({ name: 'MerchantCenter' });
},
icon: 'lucide:store',
text: '商户中心',

View File

@@ -11,5 +11,9 @@
"title": "概览",
"analytics": "分析页",
"workspace": "工作台"
},
"merchant": {
"title": "商户管理",
"center": "商户中心"
}
}

View File

@@ -0,0 +1,29 @@
import type { RouteRecordRaw } from 'vue-router';
import { BasicLayout } from '#/layouts';
import { $t } from '#/locales';
const routes: RouteRecordRaw[] = [
{
component: BasicLayout,
meta: {
hideInMenu: true,
title: $t('page.merchant.title'),
},
name: 'MerchantLayout',
path: '/merchant',
children: [
{
name: 'MerchantCenter',
path: 'center',
component: () => import('#/views/merchant/center/index.vue'),
meta: {
hideInMenu: true,
title: $t('page.merchant.center'),
},
},
],
},
];
export default routes;

View File

@@ -9,17 +9,18 @@ const dynamicRouteFiles = import.meta.glob('./modules/**/*.ts', {
});
// 有需要可以自行打开注释,并创建文件夹
// const externalRouteFiles = import.meta.glob('./external/**/*.ts', { eager: true });
const externalRouteFiles = import.meta.glob('./external/**/*.ts', {
eager: true,
});
// const staticRouteFiles = import.meta.glob('./static/**/*.ts', { eager: true });
/** 动态路由 */
const dynamicRoutes: RouteRecordRaw[] = mergeRouteModules(dynamicRouteFiles);
/** 外部路由列表访问这些页面可以不需要Layout可能用于内嵌在别的系统(不会显示在菜单中) */
// const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
// const staticRoutes: RouteRecordRaw[] = mergeRouteModules(staticRouteFiles);
const staticRoutes: RouteRecordRaw[] = [];
const externalRoutes: RouteRecordRaw[] = [];
const externalRoutes: RouteRecordRaw[] = mergeRouteModules(externalRouteFiles);
/** 路由列表由基本路由、外部路由和404兜底路由组成
* 无需走权限验证(会一直显示在菜单中) */

View File

@@ -0,0 +1,112 @@
<script setup lang="ts">
import type { MerchantDto } from '#/api/merchant';
import { computed, onMounted, ref } from 'vue';
import { Profile } from '@vben/common-ui';
import { useUserStore } from '@vben/stores';
import { getMerchantInfoApi } from '#/api/merchant';
// 1. 状态定义
const userStore = useUserStore();
const merchantInfo = ref<MerchantDto | null>(null);
const loading = ref(false);
const tabsValue = ref('basic');
const tabs = [
{
label: '基本信息',
value: 'basic',
},
{
label: '资质信息',
value: 'license',
},
];
// 2. 获取数据
async function fetchMerchantInfo() {
loading.value = true;
try {
const data = await getMerchantInfoApi();
merchantInfo.value = data;
} catch (error) {
console.error('获取商户信息失败:', error);
} finally {
loading.value = false;
}
}
onMounted(() => {
fetchMerchantInfo();
});
// 3. 格式化显示
const displayInfo = computed(() => [
{ label: '商户名称', value: merchantInfo.value?.merchantName },
{ label: '联系人', value: merchantInfo.value?.contactName },
{ label: '联系电话', value: merchantInfo.value?.contactPhone },
{ label: '商户地址', value: merchantInfo.value?.address },
{ label: '创建时间', value: merchantInfo.value?.createTime },
]);
const licenseInfo = computed(() => [
{ label: '营业执照代码', value: merchantInfo.value?.businessLicenseCode },
{ label: '商户简介', value: merchantInfo.value?.description },
]);
</script>
<template>
<div class="p-5">
<Profile
v-model:model-value="tabsValue"
:title="$t('page.merchant.center')"
:user-info="{
realName: merchantInfo?.merchantName || '加载中...',
avatar: merchantInfo?.logo || userStore.userInfo?.avatar || '',
userId: userStore.userInfo?.userId || '',
username: merchantInfo?.contactName || '',
}"
:tabs="tabs"
>
<template #content>
<div v-loading="loading" class="rounded-lg bg-card p-6">
<!-- 基本信息 -->
<div v-if="tabsValue === 'basic'">
<h3 class="mb-4 text-lg font-medium">基本信息</h3>
<a-descriptions :column="1" bordered>
<a-descriptions-item
v-for="item in displayInfo"
:key="item.label"
:label="item.label"
>
{{ item.value || '-' }}
</a-descriptions-item>
</a-descriptions>
</div>
<!-- 资质信息 -->
<div v-if="tabsValue === 'license'">
<h3 class="mb-4 text-lg font-medium">资质信息</h3>
<a-descriptions :column="1" bordered>
<a-descriptions-item
v-for="item in licenseInfo"
:key="item.label"
:label="item.label"
>
{{ item.value || '-' }}
</a-descriptions-item>
</a-descriptions>
</div>
</div>
</template>
</Profile>
</div>
</template>
<style scoped lang="scss">
.bg-card {
background-color: var(--el-bg-color-overlay);
}
</style>