优化 产品导入导出
This commit is contained in:
parent
88d5a41f5c
commit
9df51bddda
|
|
@ -95,7 +95,7 @@ public class ProductInfoController {
|
|||
@Operation(summary = "产品信息导入模板")
|
||||
public void importTemplate(HttpServletResponse response) throws IOException {
|
||||
// 输出
|
||||
ExcelUtils.write(response, "产品信息导入模板.xls", "产品信息", ProductInfoExcelVO.class, null);
|
||||
ExcelUtils.write(response, "产品信息导入模板.xlsx", "产品信息", ProductInfoExcelVO.class, null);
|
||||
}
|
||||
@PostMapping("/import")
|
||||
@Operation(summary = "导入生产制单")
|
||||
|
|
@ -116,7 +116,7 @@ public class ProductInfoController {
|
|||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<ProductInfoRespVO> list = productInfoService.getProductInfoPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "产品资料 .xls", "数据", ProductInfoRespVO.class,list);
|
||||
ExcelUtils.write(response, "产品资料.xlsx", "数据", ProductInfoRespVO.class,list);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,14 +1,17 @@
|
|||
package cn.hangtag.module.oms.controller.admin.productinfo.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.alibaba.excel.annotation.write.style.ContentStyle;
|
||||
import com.alibaba.excel.annotation.write.style.HeadFontStyle;
|
||||
import com.alibaba.excel.annotation.write.style.HeadStyle;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import org.apache.poi.ss.usermodel.Font;
|
||||
import org.apache.poi.ss.usermodel.IndexedColors;
|
||||
|
||||
/**
|
||||
* 产品信息导入 Excel VO
|
||||
|
|
@ -17,16 +20,48 @@ import java.time.LocalDateTime;
|
|||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Accessors(chain = false) // 设置 chain = false,避免数据导入有问题
|
||||
@Accessors(chain = false) // 保持 chain = false 避免导入数据异常
|
||||
public class ProductInfoExcelVO {
|
||||
|
||||
@ExcelProperty("产品编码")
|
||||
@Schema(description = "产品编码")
|
||||
@ExcelProperty("*产品编码")
|
||||
@HeadFontStyle(color = Font.COLOR_RED)
|
||||
private String code;
|
||||
|
||||
@ExcelProperty("产品名称")
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ExcelProperty("*产品名称")
|
||||
@HeadFontStyle(color = Font.COLOR_RED)
|
||||
private String name;
|
||||
|
||||
|
||||
@Schema(description = "产品简介")
|
||||
@ExcelProperty("产品简介")
|
||||
@HeadFontStyle(color = Font.COLOR_NORMAL)
|
||||
private String introduction;
|
||||
|
||||
@Schema(description = "产品规格-宽")
|
||||
@ExcelProperty("产品规格-宽")
|
||||
@HeadFontStyle(color = Font.COLOR_NORMAL)
|
||||
private String specWidth;
|
||||
|
||||
@Schema(description = "产品规格-高")
|
||||
@ExcelProperty("产品规格-高")
|
||||
private String specHeight;
|
||||
|
||||
@Schema(description = "产品规格-厚度")
|
||||
@ExcelProperty("产品规格-厚度")
|
||||
private String specThickness;
|
||||
|
||||
@Schema(description = "材质(颜色)")
|
||||
@ExcelProperty("材质(颜色)")
|
||||
private String material;
|
||||
|
||||
@Schema(description = "品牌名称")
|
||||
@ExcelProperty("品牌名称")
|
||||
private String brandName;
|
||||
|
||||
}
|
||||
|
||||
@Schema(description = "备注")
|
||||
@ExcelProperty("备注")
|
||||
private String remarks;
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package cn.hangtag.module.oms.controller.admin.productinfo.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.write.style.ColumnWidth;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
|
@ -15,7 +16,7 @@ import com.alibaba.excel.annotation.*;
|
|||
@ExcelIgnoreUnannotated
|
||||
public class ProductInfoRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "3187")
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "102")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
|
|
@ -23,35 +24,32 @@ public class ProductInfoRespVO {
|
|||
@ExcelProperty("产品编码")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "示例名称")
|
||||
@ExcelProperty("产品名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "封面")
|
||||
@ExcelProperty("封面")
|
||||
@ColumnWidth(10)
|
||||
private String cover;
|
||||
|
||||
@Schema(description = "品牌", example = "12523")
|
||||
@ExcelProperty("品牌")
|
||||
|
||||
private Long brandId;
|
||||
|
||||
@Schema(description = "客户组别id oms_customer_group", example = "12523,1233")
|
||||
private String customerGroupId;
|
||||
|
||||
@Schema(description = "客户组别 oms_customer_group name", example = "vip")
|
||||
@ExcelProperty("客户组别")
|
||||
private String customerGroupName;
|
||||
|
||||
|
||||
@Schema(description = "产品类型id", example = "26002")
|
||||
@ExcelProperty("产品类型id")
|
||||
|
||||
private Long productTypeId;
|
||||
|
||||
@Schema(description = "设计稿id", example = "29789")
|
||||
@ExcelProperty("设计稿id")
|
||||
|
||||
private String draftDesignDataId;
|
||||
|
||||
@Schema(description = "设计稿列表")
|
||||
@ExcelProperty("设计稿列表")
|
||||
|
||||
private String draftDesignList;
|
||||
|
||||
@Schema(description = "启用状态")
|
||||
|
|
@ -73,10 +71,12 @@ public class ProductInfoRespVO {
|
|||
|
||||
@Schema(description = "详情介绍")
|
||||
@ExcelProperty("详情介绍")
|
||||
@ColumnWidth(100)
|
||||
private String details;
|
||||
|
||||
@Schema(description = "简述")
|
||||
@ExcelProperty("简述")
|
||||
@ColumnWidth(60)
|
||||
private String summary;
|
||||
|
||||
/**
|
||||
|
|
@ -86,6 +86,9 @@ public class ProductInfoRespVO {
|
|||
/**
|
||||
* 默认售价
|
||||
*/
|
||||
@Schema(description = "默认售价")
|
||||
@ExcelProperty("默认售价")
|
||||
@ColumnWidth(60)
|
||||
private BigDecimal sellingPrice;
|
||||
/**
|
||||
* 币种 字典 currency_type value
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import cn.hangtag.module.oms.dal.mysql.productprocess.ProductProcessMapper;
|
|||
import cn.hangtag.module.oms.serialnumber.CodingRulesUtils;
|
||||
import cn.hangtag.module.oms.service.brand.BrandService;
|
||||
import cn.hangtag.module.oms.service.draftdesigndata.DraftDesignDataService;
|
||||
import cn.hutool.cache.CacheUtil;
|
||||
import cn.hutool.cache.impl.LFUCache;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
|
|
@ -185,7 +187,34 @@ public class ProductInfoServiceImpl implements ProductInfoService {
|
|||
public PageResult<ProductInfoRespVO> getProductInfoPage(ProductInfoPageReqVO pageReqVO) {
|
||||
PageResult<ProductInfoDO> productInfoDOPageResult = productInfoMapper.selectPage(pageReqVO);
|
||||
List<ProductInfoDO> list = productInfoDOPageResult.getList();
|
||||
List<ProductInfoRespVO> resList = wrapperRespVO(list);
|
||||
List<ProductInfoRespVO> resList = new ArrayList<>();
|
||||
Set<String> groupIds = new HashSet<>();
|
||||
Set<Long> productTypeIds = new HashSet<>();
|
||||
Set<Long> brandIds = new HashSet<>();
|
||||
for (ProductInfoDO infoDO : list) {
|
||||
String customerGroupId = infoDO.getCustomerGroupId();
|
||||
if(FuncUtil.isNotEmpty(customerGroupId)){
|
||||
groupIds.add(customerGroupId);
|
||||
}
|
||||
Long productTypeId = infoDO.getProductTypeId();
|
||||
if(FuncUtil.isNotEmpty(productTypeId)){
|
||||
productTypeIds.add(productTypeId);
|
||||
}
|
||||
Long brandId = infoDO.getBrandId();
|
||||
if(FuncUtil.isNotEmpty(brandId)){
|
||||
brandIds.add(brandId);
|
||||
}
|
||||
}
|
||||
initBrandNameCache(brandIds);
|
||||
initCustomerGroupNameCache(groupIds);
|
||||
initProductTypeNameCache(productTypeIds);
|
||||
list.forEach(productInfoDO -> {
|
||||
ProductInfoRespVO vo = BeanUtils.toBean(productInfoDO, ProductInfoRespVO.class);
|
||||
wrapperBrandName(vo);
|
||||
wrapperProductTypeName(vo);
|
||||
wrapperCustomerGroupName(vo);
|
||||
resList.add(vo);
|
||||
});
|
||||
return new PageResult<>(resList, productInfoDOPageResult.getTotal());
|
||||
}
|
||||
|
||||
|
|
@ -256,10 +285,20 @@ public class ProductInfoServiceImpl implements ProductInfoService {
|
|||
|
||||
}
|
||||
|
||||
private static LFUCache<String,Long> brandIdCache = CacheUtil.newLFUCache(10000, 1000 * 60 *30);
|
||||
|
||||
@Override
|
||||
public String importExcel(List<ProductInfoExcelVO> list) {
|
||||
List<ProductInfoDO> newList = new ArrayList<>();
|
||||
|
||||
LambdaQueryWrapper<BrandDO> brandDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
brandDOLambdaQueryWrapper.select(BrandDO::getName,BrandDO::getId,BrandDO::getCode);
|
||||
brandDOLambdaQueryWrapper.eq(BaseDO::getDeleted,false);
|
||||
List<BrandDO> brandDOS = brandMapper.selectList(brandDOLambdaQueryWrapper);
|
||||
for (BrandDO brandDO : brandDOS) {
|
||||
brandIdCache.put(brandDO.getName(),brandDO.getId());
|
||||
}
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
ProductInfoExcelVO excelVO = list.get(i);
|
||||
ProductInfoDO productInfo = new ProductInfoDO();
|
||||
|
|
@ -279,10 +318,17 @@ public class ProductInfoServiceImpl implements ProductInfoService {
|
|||
productInfo.setCode(code);
|
||||
productInfo.setTemplateType("2");
|
||||
if(FuncUtil.isNotEmpty(brandName)){
|
||||
BrandDO brandDO = brandService.getBrandByName(brandName);
|
||||
if(FuncUtil.isNotEmpty(brandDO)){
|
||||
productInfo.setBrandId(brandDO.getId());
|
||||
Long brandId = brandIdCache.get(brandName);
|
||||
if(FuncUtil.isNotEmpty(brandId)){
|
||||
productInfo.setBrandId(brandId);
|
||||
}else {
|
||||
BrandDO brandDO = brandService.getBrandByName(brandName);
|
||||
if(FuncUtil.isNotEmpty(brandDO)){
|
||||
productInfo.setBrandId(brandDO.getId());
|
||||
brandIdCache.put(brandName,brandDO.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
newList.add(productInfo);
|
||||
}
|
||||
|
|
@ -328,11 +374,44 @@ public class ProductInfoServiceImpl implements ProductInfoService {
|
|||
}
|
||||
return vo;
|
||||
}
|
||||
private static LFUCache<String, String> CustomerGroupNameCache = CacheUtil.newLFUCache(10000, 1000 * 60 * 60);
|
||||
|
||||
private ProductInfoRespVO wrapperCustomerGroupName(ProductInfoRespVO vo){
|
||||
if(FuncUtil.isNotEmpty(vo)){
|
||||
if(FuncUtil.isNotEmpty(vo.getCustomerGroupId())){
|
||||
String s = CustomerGroupNameCache.get(vo.getCustomerGroupId());
|
||||
if(FuncUtil.isNotEmpty(s)){
|
||||
vo.setCustomerGroupName(s);
|
||||
|
||||
}else {
|
||||
LambdaQueryWrapper<CustomerGroupDO> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(CustomerGroupDO::getId, FuncUtil.toStrList(vo.getCustomerGroupId()));
|
||||
wrapper.eq(BaseDO::getDeleted,false);
|
||||
List<CustomerGroupDO> groupDOS = customerGroupMapper.selectList(wrapper);
|
||||
String name = null;
|
||||
if(FuncUtil.isNotEmpty(groupDOS)){
|
||||
List<String> names = new ArrayList<>();
|
||||
for (CustomerGroupDO groupDO : groupDOS) {
|
||||
if(names.contains(groupDO.getName())){
|
||||
continue;
|
||||
}
|
||||
names.add(groupDO.getName());
|
||||
}
|
||||
name = String.join(",", names);
|
||||
}
|
||||
vo.setCustomerGroupName(name);
|
||||
CustomerGroupNameCache.put(vo.getCustomerGroupId(), name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
private void initCustomerGroupNameCache(Set<String> ids){
|
||||
if (FuncUtil.isNotEmpty(ids)) {
|
||||
for (String db : ids) {
|
||||
LambdaQueryWrapper<CustomerGroupDO> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(CustomerGroupDO::getId, FuncUtil.toStrList(vo.getCustomerGroupId()));
|
||||
wrapper.in(CustomerGroupDO::getId, FuncUtil.toStrList(db));
|
||||
wrapper.eq(BaseDO::getDeleted,false);
|
||||
List<CustomerGroupDO> groupDOS = customerGroupMapper.selectList(wrapper);
|
||||
String name = null;
|
||||
|
|
@ -346,31 +425,66 @@ public class ProductInfoServiceImpl implements ProductInfoService {
|
|||
}
|
||||
name = String.join(",", names);
|
||||
}
|
||||
vo.setCustomerGroupName(name);
|
||||
CustomerGroupNameCache.put(db, name);
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
|
||||
}
|
||||
|
||||
private static LFUCache<Long, String> ProductTypeNameCache = CacheUtil.newLFUCache(10000, 1000 * 60 * 60);
|
||||
private ProductInfoRespVO wrapperProductTypeName(ProductInfoRespVO vo){
|
||||
if(FuncUtil.isNotEmpty(vo)){
|
||||
if(FuncUtil.isNotEmpty(vo.getProductTypeId())){
|
||||
ProductTypeDO productTypeDO = productTypeMapper.selectById(vo.getProductTypeId());
|
||||
if(FuncUtil.isNotEmpty(productTypeDO)){
|
||||
vo.setProductTypeName(productTypeDO.getLabel());
|
||||
String s = ProductTypeNameCache.get(vo.getProductTypeId());
|
||||
if (FuncUtil.isNotEmpty(s)){
|
||||
vo.setProductTypeName(s);
|
||||
}else {
|
||||
ProductTypeDO productTypeDO = productTypeMapper.selectById(vo.getProductTypeId());
|
||||
if(FuncUtil.isNotEmpty(productTypeDO)){
|
||||
vo.setProductTypeName(productTypeDO.getLabel());
|
||||
ProductTypeNameCache.put(vo.getProductTypeId(), vo.getProductTypeName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
private void initProductTypeNameCache(Set<Long> ids){
|
||||
if(FuncUtil.isNotEmpty(ids)){
|
||||
List<ProductTypeDO> dos = productTypeMapper.selectBatchIds(ids);
|
||||
for (ProductTypeDO db : dos) {
|
||||
brandNameCache.put(db.getId(), db.getLabel());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static LFUCache<Long, String> brandNameCache = CacheUtil.newLFUCache(10000, 1000 * 60 * 60);
|
||||
private ProductInfoRespVO wrapperBrandName(ProductInfoRespVO vo){
|
||||
if(FuncUtil.isNotEmpty(vo)){
|
||||
if(FuncUtil.isNotEmpty(vo.getBrandId())){
|
||||
BrandDO brandDO = brandMapper.selectById(vo.getBrandId());
|
||||
if(FuncUtil.isNotEmpty(brandDO)){
|
||||
vo.setBrandName(brandDO.getName());
|
||||
String s = brandNameCache.get(vo.getBrandId());
|
||||
if(FuncUtil.isNotEmpty(s)){
|
||||
vo.setBrandName(s);
|
||||
}else {
|
||||
BrandDO brandDO = brandMapper.selectById(vo.getBrandId());
|
||||
if(FuncUtil.isNotEmpty(brandDO)){
|
||||
vo.setBrandName(brandDO.getName());
|
||||
brandNameCache.put(vo.getBrandId(), brandDO.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
private void initBrandNameCache(Set<Long> ids){
|
||||
if(FuncUtil.isNotEmpty(ids)){
|
||||
List<BrandDO> brandDOS = brandMapper.selectBatchIds(ids);
|
||||
for (BrandDO brandDO : brandDOS) {
|
||||
brandNameCache.put(brandDO.getId(), brandDO.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -199,6 +199,7 @@
|
|||
import download from '@/utils/download'
|
||||
import {ProductInfoApi, ProductInfoVO} from '@/api/oms/productinfo'
|
||||
import ProductInfoForm from './ProductInfoForm.vue'
|
||||
import ProductInfoExcelImport from './ProductInfoExcelImport.vue'
|
||||
import {ProductTypeApi} from "@/api/base/producttype";
|
||||
import {buildQuery} from "@/utils/queryUtil";
|
||||
|
||||
|
|
@ -288,10 +289,12 @@ const handleExport = async () => {
|
|||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await ProductInfoApi.exportProductInfo(queryParams)
|
||||
download.excel(data, '产品资料 .xls')
|
||||
download.excel(data, '产品资料.xlsx')
|
||||
message.success('导出完成');
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
|
||||
}
|
||||
}
|
||||
const previewDraftDesign = (id) => {
|
||||
|
|
@ -342,6 +345,7 @@ const importSuccess = (res)=>{
|
|||
const downloadTemplate = ()=>{
|
||||
ProductInfoApi.downloadTemplate().then(res => {
|
||||
download.excel(res, '产品导入模板.xlsx')
|
||||
message.success("下载完成")
|
||||
})
|
||||
}
|
||||
const handleImport = () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue