feat(shopGoods): 新增商品置顶功能及批量上下架操作

- 在商品模型中新增 isTop 字段支持置顶状态(1置顶,0不置顶)
- 商品列表新增置顶列,支持列表内联切换置顶状态
- 启用排序号列排序功能,置顶列参与前端排序
- 新增单个商品上架/下架切换接口及批量上下架操作
- 优化商品列表工具栏和选中操作栏,加入批量上架、下架按钮
- 商品分类及图片列表调用 OSS 图片压缩接口处理展示图片
- 新增删除商品导入模板及图片导入模板下载链接与使用说明
- 优化图片压缩工具,新增去除 URL 中 x-oss-process 参数功能,确保调用参数生效
This commit is contained in:
2026-07-24 10:57:23 +08:00
parent 44e416525d
commit e2f6dce7a1
11 changed files with 453 additions and 107 deletions
+29 -5
View File
@@ -41,6 +41,26 @@ export function ensureFullUrl(url: string): string {
return `${OSS_BASE_URL}${url.startsWith('/') ? '' : '/'}${url}`;
}
/**
* 移除 URL 中已有的 x-oss-process 参数(无论其在 query 中的位置)
*
* 阿里云 OSS 的图片处理参数通常以 `x-oss-process=image/...` 形式附加在 query 中,
* 可能位于首个或后续参数位。本函数精确剔除该参数,保留其余 query 参数。
*
* @param url 完整图片 URL
* @returns 已剥离 x-oss-process 的 URL
*/
function removeOssProcess(url: string): string {
const qIndex = url.indexOf('?');
if (qIndex === -1) return url;
const base = url.slice(0, qIndex);
const params = url
.slice(qIndex + 1)
.split('&')
.filter((p) => !p.startsWith('x-oss-process='));
return params.length ? `${base}?${params.join('&')}` : base;
}
/**
* 获取 OSS 压缩后的图片 URL
*
@@ -49,8 +69,11 @@ export function ensureFullUrl(url: string): string {
*
* 注意:预览原图时不需要调用此函数,直接用原始 URL 即可。
*
* 优先级:以调用方指定的 width/quality 为准。若 URL 已自带 x-oss-process
* (接口已返回压缩参数),会先剥离再按本函数参数重新拼接,确保调用方参数生效。
*
* @param url 原始图片 URL
* @param options 压缩选项
* @param options 压缩选项width/quality 不传则使用默认值)
* @returns 处理后的图片 URL
*/
export function getCompressedImageUrl(
@@ -66,11 +89,12 @@ export function getCompressedImageUrl(
// 未启用压缩,原样返回
if (!enabled) return fullUrl;
// 已包含 OSS 处理参数,避免重复拼接
if (fullUrl.includes('x-oss-process')) return fullUrl;
// 优先使用调用方指定的 width/quality
// 先剥离 URL 自带的 x-oss-process,再按本函数参数重新拼接,确保以调用方为准。
const baseUrl = removeOssProcess(fullUrl);
// 已有其他 query 参数用 & 拼接,否则用 ?
const separator = fullUrl.includes('?') ? '&' : '?';
const separator = baseUrl.includes('?') ? '&' : '?';
return `${fullUrl}${separator}x-oss-process=image/resize,w_${width}/quality,Q_${quality}`;
return `${baseUrl}${separator}x-oss-process=image/resize,w_${width}/quality,Q_${quality}`;
}