feat(shopGoods): 优化商品列表加载及封面图性能
- image.ts 中 getCompressedImageUrl 增加缓存,避免列表重渲染时重复计算压缩 URL - shopGoods 页面用原生 img 标签替换 antdv a-image,支持浏览器懒加载减少首屏网络压力 - shopGoods 页面数据加载流程优化,取消表格自动首屏加载,改为手动触发,合并请求避免重复调用 - 首屏分类数据延迟加载,不阻塞首屏渲染,提升页面响应速度 - search.vue 中用 onMounted 替代 watch immediate,防止首次入场重复触发请求 - 新增商品封面图样式,保证图片大小固定且样式统一
This commit is contained in:
@@ -119,7 +119,7 @@
|
||||
ArrowDownOutlined,
|
||||
DownOutlined
|
||||
} from '@ant-design/icons-vue';
|
||||
import { ref, watch } from 'vue';
|
||||
import { ref, watch, onMounted } from 'vue';
|
||||
import { getCount } from '@/api/shop/shopGoods';
|
||||
import type { GoodsCount, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
||||
import useSearch from '@/utils/use-search';
|
||||
@@ -244,18 +244,20 @@
|
||||
emit('search', where);
|
||||
};
|
||||
|
||||
// 首次进入:设置商户条件并触发统计 + 列表加载。
|
||||
// 用 onMounted 替代 watch 的 immediate,避免与 ele-pro-table 的自动加载(initLoad)重复发请求。
|
||||
onMounted(() => {
|
||||
const id = props.merchantId;
|
||||
where.merchantId = Number(id) > 0 ? id : undefined;
|
||||
reload();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.merchantId,
|
||||
(id) => {
|
||||
if (Number(id) > 0) {
|
||||
where.merchantId = id;
|
||||
reload();
|
||||
} else {
|
||||
where.merchantId = undefined;
|
||||
reload();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
where.merchantId = Number(id) > 0 ? id : undefined;
|
||||
reload();
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
:columns="columns"
|
||||
:datasource="datasource"
|
||||
:customRow="customRow"
|
||||
:init-load="false"
|
||||
:scroll="{ x: 1800 }"
|
||||
size="small"
|
||||
v-model:selection="selection"
|
||||
@@ -36,12 +37,14 @@
|
||||
<template #bodyCell="{ column, record }">
|
||||
<template v-if="column.key === 'name'">
|
||||
<a-space class="flex items-center cursor-pointer">
|
||||
<a-image
|
||||
:src="getCompressedImageUrl(record.image)"
|
||||
<img
|
||||
v-if="record.image"
|
||||
:preview="false"
|
||||
:width="50"
|
||||
:height="50"
|
||||
:src="getCompressedImageUrl(record.image)"
|
||||
class="goods-thumb"
|
||||
loading="lazy"
|
||||
alt=""
|
||||
width="50"
|
||||
height="50"
|
||||
/>
|
||||
<div class="flex flex-col justify-center leading-tight">
|
||||
<span class="text-gray-700 font-bold">{{ record.name }}</span>
|
||||
@@ -154,7 +157,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { createVNode, ref } from 'vue';
|
||||
import { createVNode, ref, onMounted } from 'vue';
|
||||
import { message, Modal } from 'ant-design-vue';
|
||||
import {
|
||||
ExclamationCircleOutlined,
|
||||
@@ -511,9 +514,8 @@
|
||||
});
|
||||
};
|
||||
|
||||
/* 查询 */
|
||||
/* 查询:分类数据延迟到列表首屏渲染完成后再加载,不阻塞首屏 */
|
||||
const query = () => {
|
||||
loading.value = true;
|
||||
// 加载分类数据
|
||||
if (!navigationList.value) {
|
||||
listShopGoodsCategory({}).then((res) => {
|
||||
@@ -623,7 +625,7 @@
|
||||
}
|
||||
};
|
||||
};
|
||||
query();
|
||||
onMounted(query);
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
@@ -632,4 +634,14 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
<style lang="less" scoped>
|
||||
.goods-thumb {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
background-color: rgba(255, 255, 255, 0.06);
|
||||
flex-shrink: 0;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user