mirror of
https://gitee.com/beijing_hongye_huicheng/lilishop-ui.git
synced 2026-11-11 03:18:56 +08:00
fix(buyer): 修复路由兼容与页面加载体验
- 为文章 API 添加 skipMessage 选项,由页面接管错误提示 - 添加旧路由重定向(UserInfo -> Profile, Msg -> MsgList) - 重构文章页面,增加分页、骨架屏、分类独立加载与重试机制 - 用户权益组件接入真实登录状态与购物车、优惠券、订单数量 - 修正装修组件中收藏、足迹、领券等服务的旧地址映射 - 删除已过时的 MIGRATION-VUE3.md 迁移文档
This commit is contained in:
@@ -45,32 +45,36 @@ export function getRegion (id) {
|
||||
|
||||
/**
|
||||
* 分页获取文章列表
|
||||
* @param cateId 文章分类id
|
||||
* @param params 分页及分类查询条件
|
||||
* @param options 请求选项,skipMessage 为 true 时由页面展示错误
|
||||
*/
|
||||
export function articleList (params) {
|
||||
export function articleList (params, options = {}) {
|
||||
return request({
|
||||
url: `/buyer/other/article`,
|
||||
method: Method.GET,
|
||||
params
|
||||
params,
|
||||
skipMessage: options.skipMessage
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取帮助中心文章分类列表
|
||||
* @param cateId 文章分类id
|
||||
* @param options 请求选项,skipMessage 为 true 时由页面展示错误
|
||||
*/
|
||||
export function articleCateList () {
|
||||
export function articleCateList (options = {}) {
|
||||
return request({
|
||||
url: `/buyer/other/article/articleCategory/list`,
|
||||
method: Method.GET
|
||||
method: Method.GET,
|
||||
skipMessage: options.skipMessage
|
||||
});
|
||||
}
|
||||
|
||||
// 通过id获取文章
|
||||
export function articleDetail (id) {
|
||||
/** 通过文章 ID 获取正文;可由页面接管错误提示。 */
|
||||
export function articleDetail (id, options = {}) {
|
||||
return request({
|
||||
url: `/buyer/other/article/get/${id}`,
|
||||
method: Method.GET
|
||||
method: Method.GET,
|
||||
skipMessage: options.skipMessage
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -50,10 +50,10 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const defaultMenus = [
|
||||
{ title: '基本信息', url: '/home/UserInfo' },
|
||||
{ title: '基本信息', url: '/home/Profile' },
|
||||
{ title: '我的订单', url: '/home/MyOrder' },
|
||||
{ title: '账户安全', url: '/home/AccountSafe' },
|
||||
{ title: '消息', url: '/home/Msg' }
|
||||
{ title: '消息', url: '/home/MsgList' }
|
||||
];
|
||||
|
||||
const username = computed(() => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- 1. 用户头像与信息区 -->
|
||||
<div class="user-main-info">
|
||||
<div class="avatar-box">
|
||||
<img v-if="options.avatar" :src="options.avatar" alt="avatar" />
|
||||
<img v-if="displayAvatar" :src="displayAvatar" alt="用户头像" />
|
||||
<div v-else class="avatar-placeholder">
|
||||
<svg viewBox="0 0 24 24" width="22" height="22" fill="#ffffff">
|
||||
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
|
||||
@@ -12,18 +12,22 @@
|
||||
</div>
|
||||
|
||||
<div class="user-greeting">
|
||||
<div class="badge-tag">{{ options.badgeText || '请登录' }}</div>
|
||||
<div class="welcome-text" :title="options.welcomeText || '欢迎来到商城'">
|
||||
{{ options.welcomeText || '欢迎来到商城' }}
|
||||
<div class="badge-tag">{{ isLoggedIn ? '已登录' : (options.badgeText || '请登录') }}</div>
|
||||
<div class="welcome-text" :title="welcomeText">
|
||||
{{ welcomeText }}
|
||||
</div>
|
||||
<div class="sub-text" :title="options.subtitle || '登录后查看专属权益'">
|
||||
{{ options.subtitle || '登录后查看专属权益' }}
|
||||
<div class="sub-text" :title="subtitle">
|
||||
{{ subtitle }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 登录 / 注册按钮组 -->
|
||||
<div class="action-btn-row">
|
||||
<!-- 已登录时提供会员入口,装修中的登录与注册文案仅用于游客。 -->
|
||||
<div v-if="isLoggedIn" class="action-btn-row">
|
||||
<router-link to="/home" class="action-btn login-btn">会员中心</router-link>
|
||||
<router-link to="/home/MyOrder" class="action-btn register-btn">我的订单</router-link>
|
||||
</div>
|
||||
<div v-else class="action-btn-row">
|
||||
<a href="javascript:;" class="action-btn login-btn" @click="handleNavigate(options.loginUrl || '/login')">
|
||||
{{ options.loginText || '登录' }}
|
||||
</a>
|
||||
@@ -35,19 +39,23 @@
|
||||
<!-- 3. 指标数据卡 (购物车 / 优惠券 / 订单) -->
|
||||
<div class="metrics-cards-row">
|
||||
<a href="javascript:;" class="metric-card" v-if="options.showCart !== false" @click="handleNavigate(options.cartUrl || '/cart')">
|
||||
<div class="metric-val">0</div>
|
||||
<div class="metric-val">{{ metricText('cart') }}</div>
|
||||
<div class="metric-label">{{ options.cartText || '购物车' }}</div>
|
||||
</a>
|
||||
<a href="javascript:;" class="metric-card" v-if="options.showCoupons !== false" @click="handleNavigate(options.couponUrl || '/member/coupon')">
|
||||
<div class="metric-val">0</div>
|
||||
<a href="javascript:;" class="metric-card" v-if="options.showCoupons !== false" @click="handleNavigate(metricUrl('coupons'))">
|
||||
<div class="metric-val">{{ metricText('coupons') }}</div>
|
||||
<div class="metric-label">{{ options.couponText || '优惠券' }}</div>
|
||||
</a>
|
||||
<a href="javascript:;" class="metric-card" v-if="options.showOrders !== false" @click="handleNavigate(options.orderUrl || '/member/order')">
|
||||
<div class="metric-val">0</div>
|
||||
<a href="javascript:;" class="metric-card" v-if="options.showOrders !== false" @click="handleNavigate(metricUrl('orders'))">
|
||||
<div class="metric-val">{{ metricText('orders') }}</div>
|
||||
<div class="metric-label">{{ options.orderText || '订单' }}</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button v-if="hasMetricError" type="button" class="metrics-retry" @click="loadMetrics">
|
||||
数量加载失败,点击重试
|
||||
</button>
|
||||
|
||||
<!-- 4. 快捷便民服务入口(底部图标排) -->
|
||||
<div class="quick-service-row">
|
||||
<a
|
||||
@@ -65,11 +73,17 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, onActivated, onBeforeUnmount, onDeactivated, onMounted, reactive, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { Star, Clock, Present, Service } from '@element-plus/icons-vue';
|
||||
import storage from '@/plugins/storage';
|
||||
import { cartCount } from '@/api/cart';
|
||||
import { memberCouponList } from '@/api/member';
|
||||
import { getOrderList } from '@/api/order';
|
||||
import { useAppStore } from '@/stores/app';
|
||||
|
||||
const router = useRouter();
|
||||
const appStore = useAppStore();
|
||||
|
||||
const props = defineProps({
|
||||
options: {
|
||||
@@ -86,6 +100,113 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const userInfo = ref({});
|
||||
const isLoggedIn = ref(false);
|
||||
|
||||
/** 读取现有登录缓存;缺少令牌时按游客展示,损坏的资料缓存不阻断首页。 */
|
||||
function syncLoginState() {
|
||||
isLoggedIn.value = Boolean(storage.getItem('accessToken'));
|
||||
userInfo.value = {};
|
||||
if (!isLoggedIn.value) return;
|
||||
try {
|
||||
const cached = JSON.parse(storage.getItem('userInfo') || '{}');
|
||||
userInfo.value = cached && typeof cached === 'object' ? cached : {};
|
||||
} catch {
|
||||
userInfo.value = {};
|
||||
}
|
||||
}
|
||||
|
||||
syncLoginState();
|
||||
|
||||
// 购物车沿用顶部购物车的有效 SKU 种数;优惠券统计未使用张数,订单统计全部订单。
|
||||
const metrics = reactive({
|
||||
cart: { status: 'idle', value: 0 },
|
||||
coupons: { status: 'idle', value: 0 },
|
||||
orders: { status: 'idle', value: 0 }
|
||||
});
|
||||
let metricRequestId = 0;
|
||||
let metricsLoading = false;
|
||||
const hasMetricError = computed(() => Object.values(metrics).some(item => item.status === 'error'));
|
||||
|
||||
/** 游客显示 0;已登录时区分加载、失败和真实的零值,购物车随公共状态更新。 */
|
||||
function metricText(key) {
|
||||
if (!isLoggedIn.value) return 0;
|
||||
const metric = metrics[key];
|
||||
if (metric.status === 'loading' || metric.status === 'idle') return '…';
|
||||
if (metric.status === 'error') return '—';
|
||||
return key === 'cart' ? appStore.cartNum : metric.value;
|
||||
}
|
||||
|
||||
/** 将装修默认的历史地址映射到现有列表,保留商家配置的其他自定义链接。 */
|
||||
function metricUrl(key) {
|
||||
const isCoupon = key === 'coupons';
|
||||
const configured = isCoupon ? props.options.couponUrl : props.options.orderUrl;
|
||||
const legacy = isCoupon ? '/member/coupon' : '/member/order';
|
||||
return !configured || configured === legacy
|
||||
? (isCoupon ? '/home/Coupons' : '/home/MyOrder')
|
||||
: configured;
|
||||
}
|
||||
|
||||
/** 并行读取汇总;失败独立展示,离开页面后忽略旧请求,重入首页时刷新数量。 */
|
||||
async function loadMetrics() {
|
||||
if (metricsLoading) return;
|
||||
syncLoginState();
|
||||
const requestId = ++metricRequestId;
|
||||
if (!isLoggedIn.value) {
|
||||
Object.values(metrics).forEach(item => { item.status = 'idle'; item.value = 0; });
|
||||
return;
|
||||
}
|
||||
metricsLoading = true;
|
||||
const page = { pageNumber: 1, pageSize: 1 };
|
||||
const queries = [
|
||||
['cart', props.options.showCart !== false, () => cartCount()],
|
||||
['coupons', props.options.showCoupons !== false, () => memberCouponList({ ...page, memberCouponStatus: 'NEW' })],
|
||||
['orders', props.options.showOrders !== false, () => getOrderList({ ...page, tag: 'ALL' })]
|
||||
];
|
||||
await Promise.all(queries.filter(([, visible]) => visible).map(async ([key, , fetchCount]) => {
|
||||
metrics[key].status = 'loading';
|
||||
try {
|
||||
const response = await fetchCount();
|
||||
const raw = key === 'cart' ? response?.result : response?.result?.total;
|
||||
const count = Number(raw);
|
||||
if (!response?.success || raw == null || !Number.isSafeInteger(count) || count < 0) {
|
||||
throw new Error('无效的数量响应');
|
||||
}
|
||||
if (requestId !== metricRequestId) return;
|
||||
metrics[key].value = count;
|
||||
metrics[key].status = 'ready';
|
||||
if (key === 'cart') {
|
||||
appStore.setCartNum(count);
|
||||
storage.setItem('cartNum', count);
|
||||
}
|
||||
} catch {
|
||||
if (requestId === metricRequestId) metrics[key].status = 'error';
|
||||
}
|
||||
}));
|
||||
if (requestId === metricRequestId) metricsLoading = false;
|
||||
}
|
||||
|
||||
/** 使离开首页前的异步响应失效,避免覆盖下一次进入后的数据。 */
|
||||
function invalidateMetrics() {
|
||||
metricRequestId += 1;
|
||||
metricsLoading = false;
|
||||
}
|
||||
|
||||
onMounted(loadMetrics);
|
||||
onActivated(loadMetrics);
|
||||
onDeactivated(invalidateMetrics);
|
||||
onBeforeUnmount(invalidateMetrics);
|
||||
|
||||
const displayAvatar = computed(() => isLoggedIn.value
|
||||
? userInfo.value.face
|
||||
: props.options.avatar);
|
||||
const welcomeText = computed(() => isLoggedIn.value
|
||||
? `你好,${userInfo.value.nickName || userInfo.value.username || '会员'}`
|
||||
: (props.options.welcomeText || '欢迎来到商城'));
|
||||
const subtitle = computed(() => isLoggedIn.value
|
||||
? '查看我的订单与专属权益'
|
||||
: (props.options.subtitle || '登录后查看专属权益'));
|
||||
|
||||
function handleNavigate(url) {
|
||||
if (!url) return;
|
||||
if (/^https?:\/\//i.test(url)) {
|
||||
@@ -96,10 +217,10 @@ function handleNavigate(url) {
|
||||
}
|
||||
|
||||
const defaultServices = [
|
||||
{ name: '收藏', url: '/member/favorites', icon: 'Star' },
|
||||
{ name: '足迹', url: '/member/footprint', icon: 'Clock' },
|
||||
{ name: '红包', url: '/couponCenter', icon: 'Present' },
|
||||
{ name: '客服', url: '/article', icon: 'Service' }
|
||||
{ name: '收藏', url: '/home/Favorites', icon: 'Star' },
|
||||
{ name: '足迹', url: '/home/MyTracks', icon: 'Clock' },
|
||||
{ name: '领券', url: '/coupon', icon: 'Present' },
|
||||
{ name: '帮助', url: '/article', icon: 'Service' }
|
||||
];
|
||||
|
||||
const iconMap = {
|
||||
@@ -114,12 +235,26 @@ function getServiceIcon(iconName) {
|
||||
}
|
||||
|
||||
const displayServices = computed(() => {
|
||||
if (Array.isArray(props.options?.services) && props.options.services.length > 0) {
|
||||
return props.options.services;
|
||||
}
|
||||
return defaultServices;
|
||||
const services = Array.isArray(props.options?.services) && props.options.services.length > 0
|
||||
? props.options.services
|
||||
: defaultServices;
|
||||
return services.map(normalizeService);
|
||||
});
|
||||
|
||||
/** 兼容装修中保存的旧默认入口,仅修正已知地址,不覆盖其他自定义链接。 */
|
||||
function normalizeService(service) {
|
||||
const legacyRoutes = {
|
||||
'/member/favorites': '/home/Favorites',
|
||||
'/member/footprint': '/home/MyTracks',
|
||||
'/couponCenter': '/coupon'
|
||||
};
|
||||
const url = legacyRoutes[service.url] || service.url;
|
||||
let name = service.name;
|
||||
if (name === '红包' && url === '/coupon') name = '领券';
|
||||
if (name === '客服' && url === '/article') name = '帮助';
|
||||
return { ...service, url, name };
|
||||
}
|
||||
|
||||
const customStyle = computed(() => {
|
||||
const s = props.componentStyle || {};
|
||||
const hasRowHeight = Boolean(props.rowStyle?.height && Number(props.rowStyle.height) > 0);
|
||||
@@ -135,6 +270,14 @@ const customStyle = computed(() => {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.metrics-retry {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: #409eff;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.decor-user-benefits {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -8,6 +8,11 @@
|
||||
<div class="layoutAll">
|
||||
<el-aside class="side-bar" width="220px">
|
||||
<div class="article-cate">文章分类</div>
|
||||
<p v-if="categoryError" role="alert" class="load-message">
|
||||
分类加载失败,可先浏览全部文章。
|
||||
<el-button link type="primary" :loading="categoryLoading" @click="getCateList">重试分类</el-button>
|
||||
</p>
|
||||
<el-button link type="primary" @click="onSelect('')">全部文章</el-button>
|
||||
<el-menu
|
||||
class="side-menu"
|
||||
:key="menuKey"
|
||||
@@ -31,14 +36,22 @@
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
<el-main class="content">
|
||||
<ul class="article-list" v-show="showList">
|
||||
<div v-if="contentError" role="alert" class="load-message">
|
||||
{{ contentError }}
|
||||
<el-button link type="primary" @click="retryContent">重新加载</el-button>
|
||||
</div>
|
||||
<el-skeleton v-if="contentLoading" :rows="5" animated />
|
||||
<ul class="article-list" v-show="showList && !contentLoading && !contentError">
|
||||
<li v-if="!articleList.length" class="article-empty">暂无文章</li>
|
||||
<li v-for="(article, index) in articleList" :key="article.id || index" @click="getDetail(article.id)">
|
||||
{{ article.title }}
|
||||
</li>
|
||||
</ul>
|
||||
<div v-show="!showList" class="article-detail">
|
||||
<button type="button" class="back-btn" @click="showList = true">返回列表</button>
|
||||
<el-pagination v-if="showList && !contentLoading && !contentError && total > params.pageSize"
|
||||
:current-page="params.pageNumber" :page-size="params.pageSize" :total="total"
|
||||
layout="prev, pager, next" @current-change="changePage" />
|
||||
<div v-show="!showList && !contentLoading && !contentError" class="article-detail">
|
||||
<button type="button" class="back-btn" @click="getList()">返回列表</button>
|
||||
<h2>{{ detail.title }}</h2>
|
||||
<div class="article-html" v-html="detail.content"></div>
|
||||
</div>
|
||||
@@ -60,82 +73,111 @@ defineOptions({ name: 'ArticleIndex' })
|
||||
const route = useRoute()
|
||||
|
||||
const list = ref([])
|
||||
const detail = ref('')
|
||||
const detail = ref({})
|
||||
const articleList = ref([])
|
||||
const activeName = ref('1347456734864367616')
|
||||
const activeName = ref('')
|
||||
const openName = ref([])
|
||||
const menuKey = ref(0)
|
||||
const params = reactive({
|
||||
pageNumber: 1,
|
||||
pageSize: 100,
|
||||
categoryId: '',
|
||||
sort: 'sort'
|
||||
})
|
||||
const params = reactive({ pageNumber: 1, pageSize: 20, categoryId: '', sort: 'sort' })
|
||||
const showList = ref(true)
|
||||
const total = ref(0)
|
||||
const categoryError = ref(false)
|
||||
const categoryLoading = ref(false)
|
||||
const contentError = ref('')
|
||||
const contentLoading = ref(false)
|
||||
const detailId = ref('')
|
||||
let contentRequestId = 0
|
||||
|
||||
function onSelect (id) {
|
||||
getList(id)
|
||||
detail.value = ''
|
||||
showList.value = true
|
||||
/** 切换分类时重置分页,并使之前的列表或正文请求失效。 */
|
||||
function onSelect(id) {
|
||||
activeName.value = id
|
||||
params.pageNumber = 1
|
||||
return getList(id)
|
||||
}
|
||||
|
||||
function getCateList () {
|
||||
articleCateList().then(res => {
|
||||
if (res.success) {
|
||||
list.value = res.result || []
|
||||
openName.value = []
|
||||
if (route.query.id && detail.value && detail.value.categoryId) {
|
||||
activeName.value = detail.value.categoryId
|
||||
list.value.forEach(e => {
|
||||
const children = e.children || []
|
||||
const hitParent = String(e.id) === String(activeName.value)
|
||||
const hitChild = children.some(i => i && String(i.id) === String(activeName.value))
|
||||
if ((hitParent || hitChild) && children.length) {
|
||||
openName.value.push(String(e.id))
|
||||
}
|
||||
})
|
||||
} else if (list.value[0] && list.value[0].id) {
|
||||
activeName.value = list.value[0].id
|
||||
if (list.value[0].children && list.value[0].children.length) {
|
||||
openName.value.push(String(list.value[0].id))
|
||||
}
|
||||
}
|
||||
menuKey.value++
|
||||
if (activeName.value) {
|
||||
getList(activeName.value)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getList (id) {
|
||||
params.categoryId = id
|
||||
fetchArticleList(params).then(res => {
|
||||
if (res.success) {
|
||||
articleList.value = res.result.records
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async function getDetail (id) {
|
||||
await articleDetail(id).then(res => {
|
||||
if (res.success) {
|
||||
detail.value = res.result
|
||||
showList.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const articleId = route.query.id
|
||||
if (articleId) {
|
||||
await getDetail(articleId)
|
||||
/** 独立加载分类;分类服务不可用时保留全部文章入口,不阻断正文和列表。 */
|
||||
async function getCateList() {
|
||||
if (categoryLoading.value) return
|
||||
categoryLoading.value = true
|
||||
categoryError.value = false
|
||||
try {
|
||||
const res = await articleCateList({ skipMessage: true })
|
||||
if (!res.success || !Array.isArray(res.result)) throw new Error('分类响应无效')
|
||||
list.value = res.result
|
||||
openName.value = list.value.filter(item => Array.isArray(item.children) && item.children.length)
|
||||
.map(item => String(item.id))
|
||||
menuKey.value++
|
||||
} catch {
|
||||
categoryError.value = true
|
||||
} finally {
|
||||
categoryLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 按分类分页查询公开文章;只接收最新一次请求结果,失败不冒充空列表。 */
|
||||
async function getList(id = activeName.value) {
|
||||
const requestId = ++contentRequestId
|
||||
showList.value = true
|
||||
contentLoading.value = true
|
||||
contentError.value = ''
|
||||
params.categoryId = id || ''
|
||||
try {
|
||||
const res = await fetchArticleList({ ...params }, { skipMessage: true })
|
||||
if (!res.success || !Array.isArray(res.result?.records)) throw new Error('列表响应无效')
|
||||
if (requestId !== contentRequestId) return
|
||||
articleList.value = res.result.records
|
||||
total.value = Number(res.result.total) || 0
|
||||
} catch {
|
||||
if (requestId === contentRequestId) contentError.value = '文章加载失败,请稍后重试。'
|
||||
} finally {
|
||||
if (requestId === contentRequestId) contentLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 加载指定文章;失败可原地重试,过时的正文响应不得覆盖用户新选择。 */
|
||||
async function getDetail(id) {
|
||||
const requestId = ++contentRequestId
|
||||
detailId.value = id
|
||||
showList.value = false
|
||||
contentLoading.value = true
|
||||
contentError.value = ''
|
||||
try {
|
||||
const res = await articleDetail(id, { skipMessage: true })
|
||||
if (!res.success || !res.result) throw new Error('文章不存在')
|
||||
if (requestId !== contentRequestId) return
|
||||
detail.value = res.result
|
||||
} catch {
|
||||
if (requestId === contentRequestId) contentError.value = '文章详情加载失败或已不存在,请稍后重试。'
|
||||
} finally {
|
||||
if (requestId === contentRequestId) contentLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重试当前列表或正文,保留分类和分页条件。 */
|
||||
function retryContent() {
|
||||
return showList.value ? getList() : getDetail(detailId.value)
|
||||
}
|
||||
|
||||
/** 切换文章列表页码,沿用当前分类。 */
|
||||
function changePage(page) {
|
||||
params.pageNumber = page
|
||||
return getList()
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCateList()
|
||||
if (route.query.id) getDetail(route.query.id)
|
||||
else getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.load-message {
|
||||
padding: 12px;
|
||||
color: #64748b;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
padding: 20px 0 40px;
|
||||
|
||||
@@ -279,6 +279,10 @@ export const router = createRouter({
|
||||
component: MemberGrade,
|
||||
meta: { title: "我的等级" },
|
||||
},
|
||||
{
|
||||
path: "UserInfo",
|
||||
redirect: { name: "Profile" },
|
||||
},
|
||||
{
|
||||
path: "Profile",
|
||||
name: "Profile",
|
||||
@@ -307,6 +311,11 @@ export const router = createRouter({
|
||||
name: "AddAddress",
|
||||
component: AddAddress,
|
||||
},
|
||||
{
|
||||
// 兼容已保存的装修顶部菜单中的旧消息地址,统一进入现有消息列表。
|
||||
path: "Msg",
|
||||
redirect: { name: "MsgList" },
|
||||
},
|
||||
{
|
||||
path: "MsgList",
|
||||
name: "MsgList",
|
||||
|
||||
Reference in New Issue
Block a user