新增商品详情md转html
This commit is contained in:
@@ -3,6 +3,12 @@ import type { ApiResult, PageResult } from '@/api';
|
|||||||
import type { ShopGoods, ShopGoodsParam } from './model';
|
import type { ShopGoods, ShopGoodsParam } from './model';
|
||||||
import { MODULES_API_URL } from '@/config/setting';
|
import { MODULES_API_URL } from '@/config/setting';
|
||||||
|
|
||||||
|
export interface ConvertGoodsContentResult {
|
||||||
|
total: number;
|
||||||
|
success: number;
|
||||||
|
updatedGoodsIds: number[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 分页查询商品
|
* 分页查询商品
|
||||||
*/
|
*/
|
||||||
@@ -115,6 +121,30 @@ export async function getCount(params: ShopGoodsParam) {
|
|||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 商品详情Markdown图片转HTML
|
||||||
|
*/
|
||||||
|
export async function convertMarkdownImagesToHtml(params?: {
|
||||||
|
tenantId?: number;
|
||||||
|
goodsId?: number;
|
||||||
|
code?: string;
|
||||||
|
}) {
|
||||||
|
const res = await request.post<ApiResult<ConvertGoodsContentResult>>(
|
||||||
|
MODULES_API_URL + '/shop/shop-goods/content/markdown-images/to-html',
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
params
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return {
|
||||||
|
message: res.data.message,
|
||||||
|
data: res.data.data
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入商品
|
* 导入商品
|
||||||
*/
|
*/
|
||||||
@@ -146,3 +176,19 @@ export async function importShopGoodsImages(file: File) {
|
|||||||
}
|
}
|
||||||
return Promise.reject(new Error(res.data.message));
|
return Promise.reject(new Error(res.data.message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入商品详情
|
||||||
|
*/
|
||||||
|
export async function importShopGoodsDetails(file: File) {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', file);
|
||||||
|
const res = await request.post<ApiResult<unknown>>(
|
||||||
|
MODULES_API_URL + '/shop/shop-goods/import/details',
|
||||||
|
formData
|
||||||
|
);
|
||||||
|
if (res.data.code === 0) {
|
||||||
|
return res.data.message;
|
||||||
|
}
|
||||||
|
return Promise.reject(new Error(res.data.message));
|
||||||
|
}
|
||||||
|
|||||||
@@ -31,6 +31,23 @@
|
|||||||
</template>
|
</template>
|
||||||
<span>导入图片</span>
|
<span>导入图片</span>
|
||||||
</a-button>
|
</a-button>
|
||||||
|
<a-button type="dashed" class="ele-btn-icon" @click="openDetailImport">
|
||||||
|
<template #icon>
|
||||||
|
<UploadOutlined />
|
||||||
|
</template>
|
||||||
|
<span>导入详情</span>
|
||||||
|
</a-button>
|
||||||
|
<a-button
|
||||||
|
type="dashed"
|
||||||
|
class="ele-btn-icon"
|
||||||
|
:disabled="selection?.length === 0"
|
||||||
|
@click="convertContent"
|
||||||
|
>
|
||||||
|
<template #icon>
|
||||||
|
<SyncOutlined />
|
||||||
|
</template>
|
||||||
|
<span>转换详情</span>
|
||||||
|
</a-button>
|
||||||
<a-button type="dashed" class="ele-btn-icon" @click="handleExport">
|
<a-button type="dashed" class="ele-btn-icon" @click="handleExport">
|
||||||
导出xls
|
导出xls
|
||||||
</a-button>
|
</a-button>
|
||||||
@@ -70,7 +87,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { PlusOutlined, DeleteOutlined, UploadOutlined } from '@ant-design/icons-vue';
|
import {
|
||||||
|
PlusOutlined,
|
||||||
|
DeleteOutlined,
|
||||||
|
UploadOutlined,
|
||||||
|
SyncOutlined
|
||||||
|
} from '@ant-design/icons-vue';
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { getCount } from '@/api/shop/shopGoods';
|
import { getCount } from '@/api/shop/shopGoods';
|
||||||
import type { GoodsCount, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
import type { GoodsCount, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
||||||
@@ -112,6 +134,8 @@
|
|||||||
(e: 'batchMove'): void;
|
(e: 'batchMove'): void;
|
||||||
(e: 'import'): void;
|
(e: 'import'): void;
|
||||||
(e: 'imageImport'): void;
|
(e: 'imageImport'): void;
|
||||||
|
(e: 'detailImport'): void;
|
||||||
|
(e: 'convertContent'): void;
|
||||||
(e: 'export'): void;
|
(e: 'export'): void;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
@@ -134,6 +158,14 @@
|
|||||||
emit('imageImport');
|
emit('imageImport');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openDetailImport = () => {
|
||||||
|
emit('detailImport');
|
||||||
|
};
|
||||||
|
|
||||||
|
const convertContent = () => {
|
||||||
|
emit('convertContent');
|
||||||
|
};
|
||||||
|
|
||||||
// 导出
|
// 导出
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
emit('export');
|
emit('export');
|
||||||
|
|||||||
@@ -24,9 +24,14 @@
|
|||||||
>
|
>
|
||||||
<a-tabs type="card" v-model:active-key="active" @change="onChange">
|
<a-tabs type="card" v-model:active-key="active" @change="onChange">
|
||||||
<a-tab-pane tab="基本信息" key="base">
|
<a-tab-pane tab="基本信息" key="base">
|
||||||
<!-- <a-form-item label="商品ID" name="goodsId">-->
|
<a-form-item label="商品名称" name="name">
|
||||||
<!-- {{ form.goodsId }}-->
|
<a-input
|
||||||
<!-- </a-form-item>-->
|
allow-clear
|
||||||
|
style="width: 558px"
|
||||||
|
placeholder="请输入商品名称"
|
||||||
|
v-model:value="form.name"
|
||||||
|
/>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item label="商品分类" name="categoryId">
|
<a-form-item label="商品分类" name="categoryId">
|
||||||
<a-tree-select
|
<a-tree-select
|
||||||
allow-clear
|
allow-clear
|
||||||
@@ -41,12 +46,12 @@
|
|||||||
@change="onCategoryId"
|
@change="onCategoryId"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="商品名称" name="name">
|
<a-form-item label="商品编码" name="code">
|
||||||
<a-input
|
<a-input
|
||||||
allow-clear
|
allow-clear
|
||||||
style="width: 558px"
|
style="width: 558px"
|
||||||
placeholder="请输入商品名称"
|
placeholder="请输入商品编码"
|
||||||
v-model:value="form.name"
|
v-model:value="form.code"
|
||||||
/>
|
/>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="商品卖点" name="comments">
|
<a-form-item label="商品卖点" name="comments">
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
@batchMove="openMove"
|
@batchMove="openMove"
|
||||||
@import="openImport"
|
@import="openImport"
|
||||||
@imageImport="openImageImport"
|
@imageImport="openImageImport"
|
||||||
|
@detailImport="openDetailImport"
|
||||||
|
@convertContent="convertSelectedContent"
|
||||||
@export="handleExport"
|
@export="handleExport"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
@@ -91,6 +93,11 @@
|
|||||||
v-model:visible="showImageImport"
|
v-model:visible="showImageImport"
|
||||||
@done="reload"
|
@done="reload"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ShopGoodsDetailImport
|
||||||
|
v-model:visible="showDetailImport"
|
||||||
|
@done="reload"
|
||||||
|
/>
|
||||||
</a-page-header>
|
</a-page-header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -114,7 +121,15 @@
|
|||||||
import Extra from '@/views/shop/shopGoods/components/extra.vue';
|
import Extra from '@/views/shop/shopGoods/components/extra.vue';
|
||||||
import ShopGoodsImport from './components/shop-goods-import.vue';
|
import ShopGoodsImport from './components/shop-goods-import.vue';
|
||||||
import ShopGoodsImageImport from './components/shop-goods-image-import.vue';
|
import ShopGoodsImageImport from './components/shop-goods-image-import.vue';
|
||||||
import { listShopGoods, pageShopGoods, removeShopGoods, removeBatchShopGoods, updateShopGoods } from '@/api/shop/shopGoods';
|
import ShopGoodsDetailImport from './components/shop-goods-detail-import.vue';
|
||||||
|
import {
|
||||||
|
convertMarkdownImagesToHtml,
|
||||||
|
listShopGoods,
|
||||||
|
pageShopGoods,
|
||||||
|
removeShopGoods,
|
||||||
|
removeBatchShopGoods,
|
||||||
|
updateShopGoods
|
||||||
|
} from '@/api/shop/shopGoods';
|
||||||
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
import type { ShopGoods, ShopGoodsParam } from '@/api/shop/shopGoods/model';
|
||||||
import { getPageTitle } from '@/utils/common';
|
import { getPageTitle } from '@/utils/common';
|
||||||
import { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model';
|
import { ShopGoodsCategory } from '@/api/shop/shopGoodsCategory/model';
|
||||||
@@ -137,6 +152,8 @@
|
|||||||
const showImport = ref(false);
|
const showImport = ref(false);
|
||||||
// 是否显示图片导入弹窗
|
// 是否显示图片导入弹窗
|
||||||
const showImageImport = ref(false);
|
const showImageImport = ref(false);
|
||||||
|
// 是否显示详情导入弹窗
|
||||||
|
const showDetailImport = ref(false);
|
||||||
// 是否显示批量移动弹窗
|
// 是否显示批量移动弹窗
|
||||||
const showMove = ref(false);
|
const showMove = ref(false);
|
||||||
// 加载状态
|
// 加载状态
|
||||||
@@ -176,12 +193,12 @@
|
|||||||
key: 'name',
|
key: 'name',
|
||||||
width: 300
|
width: 300
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: '编号',
|
title: '编号',
|
||||||
// dataIndex: 'code',
|
dataIndex: 'code',
|
||||||
// key: 'code',
|
key: 'code',
|
||||||
// align: 'center',
|
align: 'center',
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
title: '价格',
|
title: '价格',
|
||||||
dataIndex: 'price',
|
dataIndex: 'price',
|
||||||
@@ -273,6 +290,50 @@
|
|||||||
showImageImport.value = true;
|
showImageImport.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* 打开详情导入弹窗 */
|
||||||
|
const openDetailImport = () => {
|
||||||
|
showDetailImport.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 转换选中商品详情Markdown图片为HTML */
|
||||||
|
const convertSelectedContent = () => {
|
||||||
|
const goodsIds = selection.value
|
||||||
|
.map((goods) => goods.goodsId)
|
||||||
|
.filter((goodsId): goodsId is number => goodsId != null);
|
||||||
|
if (!goodsIds.length) {
|
||||||
|
message.error('请至少选择一条商品');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Modal.confirm({
|
||||||
|
title: '转换商品详情内容',
|
||||||
|
content: `确定要转换选中的 ${goodsIds.length} 个商品详情内容吗?`,
|
||||||
|
icon: createVNode(ExclamationCircleOutlined),
|
||||||
|
maskClosable: true,
|
||||||
|
onOk: async () => {
|
||||||
|
const hide = message.loading('正在转换商品详情..', 0);
|
||||||
|
try {
|
||||||
|
const results = await Promise.all(
|
||||||
|
goodsIds.map((goodsId) => convertMarkdownImagesToHtml({ goodsId }))
|
||||||
|
);
|
||||||
|
const total = results.reduce(
|
||||||
|
(sum, item) => sum + (item.data?.total || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
const success = results.reduce(
|
||||||
|
(sum, item) => sum + (item.data?.success || 0),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
hide();
|
||||||
|
message.success(`转换完成,匹配${total}个商品,成功转换${success}个`);
|
||||||
|
reload();
|
||||||
|
} catch (e: any) {
|
||||||
|
hide();
|
||||||
|
message.error(e.message || '转换失败,请重试');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/* 导出商品列表 */
|
/* 导出商品列表 */
|
||||||
const handleExport = async () => {
|
const handleExport = async () => {
|
||||||
if (loading.value) {
|
if (loading.value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user