From c2285e42e4596d83d1f692af65c7ff355f334c30 Mon Sep 17 00:00:00 2001 From: yf <770153798@qq.com> Date: Sat, 4 Jan 2025 22:41:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=20=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E5=AF=BC=E5=85=A5=EF=BC=8C=E7=A8=BF=E4=BB=B6?= =?UTF-8?q?=E4=B8=8B=E8=BD=BD=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../productinfo/ProductInfoController.java | 25 +++- .../productinfo/vo/ProductInfoExcelVO.java | 32 ++++ .../oms/service/brand/BrandService.java | 2 + .../oms/service/brand/BrandServiceImpl.java | 23 +++ .../productinfo/ProductInfoService.java | 3 + .../productinfo/ProductInfoServiceImpl.java | 34 +++++ .../src/api/oms/productinfo/index.ts | 5 +- hangtag-ui/hangtag-ui-admin/src/locales/en.ts | 1 + .../hangtag-ui-admin/src/locales/zh-CN.ts | 1 + .../productinfo/ProductInfoExcelImport.vue | 138 ++++++++++++++++++ .../src/views/oms/productinfo/index.vue | 32 +++- .../src/components/DraftDesign/index.vue | 4 +- hangtag-ui/hangtag-ui-front/src/locales/en.ts | 1 + .../hangtag-ui-front/src/locales/zh-CN.ts | 1 + .../OrderAddProductStep/ProductItem1.vue | 40 +++++ sql/mysql/20250102/产品信息新增字段.sql | 5 + 16 files changed, 340 insertions(+), 7 deletions(-) create mode 100644 hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java create mode 100644 hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/ProductInfoExcelImport.vue create mode 100644 sql/mysql/20250102/产品信息新增字段.sql diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/ProductInfoController.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/ProductInfoController.java index 5f9fb18..90f07da 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/ProductInfoController.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/ProductInfoController.java @@ -1,8 +1,9 @@ package cn.hangtag.module.oms.controller.admin.productinfo; import cn.hangtag.framework.mybatis.build.QueryFilterInfo; +import io.swagger.v3.oas.annotations.Parameters; +import lombok.AllArgsConstructor; import org.springframework.web.bind.annotation.*; -import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; import org.springframework.security.access.prepost.PreAuthorize; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,15 +29,17 @@ import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.*; import cn.hangtag.module.oms.controller.admin.productinfo.vo.*; import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO; import cn.hangtag.module.oms.service.productinfo.ProductInfoService; +import org.springframework.web.multipart.MultipartFile; @Tag(name = "管理后台 - 产品资料 ") @RestController @RequestMapping("/oms/product-info") @Validated +@AllArgsConstructor public class ProductInfoController { - @Resource - private ProductInfoService productInfoService; + private final ProductInfoService productInfoService; + @PostMapping("/create") @Operation(summary = "创建产品资料 ") @@ -88,6 +91,22 @@ public class ProductInfoController { return success(BeanUtils.toBean(pageResult, ProductInfoRespVO.class)); } + @GetMapping("/excel-template") + @Operation(summary = "产品信息导入模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 输出 + ExcelUtils.write(response, "产品信息导入模板.xls", "产品信息", ProductInfoExcelVO.class, null); + } + @PostMapping("/import") + @Operation(summary = "导入生产制单") + @Parameters({ @Parameter(name = "file", description = "Excel 文件", required = true), + }) + public CommonResult importExcel(@RequestParam("file") MultipartFile file) throws Exception { + List list = ExcelUtils.read(file, ProductInfoExcelVO.class); + String res = productInfoService.importExcel(list); + return success(res); + } + @GetMapping("/export-excel") @Operation(summary = "导出产品资料 Excel") @PreAuthorize("@ss.hasPermission('oms:product-info:export')") diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java new file mode 100644 index 0000000..f2341a7 --- /dev/null +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/controller/admin/productinfo/vo/ProductInfoExcelVO.java @@ -0,0 +1,32 @@ +package cn.hangtag.module.oms.controller.admin.productinfo.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +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; + +/** + * 产品信息导入 Excel VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = false) // 设置 chain = false,避免数据导入有问题 +public class ProductInfoExcelVO { + + @ExcelProperty("产品编码") + private String code; + + @ExcelProperty("产品名称") + private String name; + + @ExcelProperty("品牌名称") + private String brandName; + +} diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandService.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandService.java index facba3f..5da021c 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandService.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandService.java @@ -78,4 +78,6 @@ public interface BrandService { * @return {@link Integer } */ Integer updateProductCount(Long id); + + BrandDO getBrandByName(String brandName); } \ No newline at end of file diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandServiceImpl.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandServiceImpl.java index d89bac3..85e6e66 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandServiceImpl.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/brand/BrandServiceImpl.java @@ -3,6 +3,7 @@ package cn.hangtag.module.oms.service.brand; import cn.hangtag.framework.common.exception.ServiceException; import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants; import cn.hangtag.framework.common.util.FuncUtil; +import cn.hangtag.framework.common.util.cache.CacheUtils; import cn.hangtag.framework.mybatis.core.dataobject.BaseDO; import cn.hangtag.module.oms.base.dal.dataobject.producttype.ProductTypeDO; import cn.hangtag.module.oms.dal.dataobject.customerbrand.CustomerBrandDO; @@ -14,6 +15,8 @@ import cn.hangtag.module.oms.serialnumber.CodingRulesUtils; import cn.hangtag.module.system.dal.dataobject.permission.MenuDO; import cn.hangtag.module.system.dal.dataobject.permission.RoleMenuDO; import cn.hangtag.module.system.dal.mysql.permission.RoleMenuMapper; +import cn.hutool.cache.CacheUtil; +import cn.hutool.cache.impl.FIFOCache; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.AllArgsConstructor; @@ -159,6 +162,26 @@ public class BrandServiceImpl implements BrandService { } return convertSet(customerBrandMapper.selectListByCustomerId(customerIds), CustomerBrandDO::getBrandId); } + private final FIFOCache brandDOS = CacheUtil.newFIFOCache(100,1000*60*60*10); + @Override + public BrandDO getBrandByName(String brandName) { + + if (FuncUtil.isNotEmpty(brandName)) { + BrandDO brandDO = brandDOS.get(brandName); + if (FuncUtil.isNotEmpty(brandDO)) { + return brandDO; + } + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.eq(BrandDO::getName, brandName); + lambdaQueryWrapper.eq(BrandDO::getDeleted, false); + List dos = brandMapper.selectList(lambdaQueryWrapper); + if (FuncUtil.isNotEmpty(dos)) { + brandDOS.put(brandName, dos.get(0)); + return brandDO; + } + } + return null; + } private void checkCode(Long id, String code) { diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoService.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoService.java index 0f3eab3..6448d03 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoService.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoService.java @@ -9,6 +9,7 @@ import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO; import cn.hangtag.framework.common.pojo.PageResult; import java.math.BigDecimal; +import java.util.List; /** * 产品资料 Service 接口 @@ -72,4 +73,6 @@ public interface ProductInfoService { * @return {@link BigDecimal } */ BigDecimal queryPriceByProductId(Long productId, String currency); + + String importExcel(List list); } \ No newline at end of file diff --git a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoServiceImpl.java b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoServiceImpl.java index 21296c1..77fb3ac 100644 --- a/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoServiceImpl.java +++ b/hangtag-module-oms/hangtag-module-oms-biz/src/main/java/cn/hangtag/module/oms/service/productinfo/ProductInfoServiceImpl.java @@ -272,4 +272,38 @@ public class ProductInfoServiceImpl implements ProductInfoService { return new BigDecimal(0); } + + @Override + public String importExcel(List list) { + List newList = new ArrayList<>(); + for (int i = 0; i < list.size(); i++) { + ProductInfoExcelVO excelVO = list.get(i); + ProductInfoDO productInfo = new ProductInfoDO(); + + String code = excelVO.getCode(); + if(FuncUtil.isNotEmpty(code)){ + try { + checkCode(productInfo.getId(),code); + }catch (Exception e){ + return "第"+(i+1)+"行编码重复:"+code; + } + }else { + code = productInfo.getCode(); + } + productInfo.setName(excelVO.getName()); + String brandName = excelVO.getBrandName(); + productInfo.setCode(code); + productInfo.setTemplateType("2"); + if(FuncUtil.isNotEmpty(brandName)){ + BrandDO brandDO = brandService.getBrandByName(brandName); + if(FuncUtil.isNotEmpty(brandDO)){ + productInfo.setBrandId(brandDO.getId()); + } + } + newList.add(productInfo); + } + + productInfoMapper.insertBatch(newList); + return ""; + } } \ No newline at end of file diff --git a/hangtag-ui/hangtag-ui-admin/src/api/oms/productinfo/index.ts b/hangtag-ui/hangtag-ui-admin/src/api/oms/productinfo/index.ts index ed2fa71..a453c8b 100644 --- a/hangtag-ui/hangtag-ui-admin/src/api/oms/productinfo/index.ts +++ b/hangtag-ui/hangtag-ui-admin/src/api/oms/productinfo/index.ts @@ -54,6 +54,9 @@ export const ProductInfoApi = { // 导出产品资料 Excel exportProductInfo: async (params) => { - return await request.download({ url: `/oms/product-info/export-excel`, params }) + return await request.download({ url: `/oms/product-info/export-excel`, params ,timeout: 1000*60 * 20}) }, + downloadTemplate: async()=> { + return await request.download({ url: `/oms/product-info/excel-template` }) + } } diff --git a/hangtag-ui/hangtag-ui-admin/src/locales/en.ts b/hangtag-ui/hangtag-ui-admin/src/locales/en.ts index 12131ab..9611d4f 100644 --- a/hangtag-ui/hangtag-ui-admin/src/locales/en.ts +++ b/hangtag-ui/hangtag-ui-admin/src/locales/en.ts @@ -670,6 +670,7 @@ export default { "viewOrder": "viewOrder", "backHome": "BackHome", "tipsDataChange": "DataChange Click Update Button", + "downloadSuccess": "downloadSuccess", }, "productDialogList": { "title": "Product List", diff --git a/hangtag-ui/hangtag-ui-admin/src/locales/zh-CN.ts b/hangtag-ui/hangtag-ui-admin/src/locales/zh-CN.ts index 8a43b62..a0462ce 100644 --- a/hangtag-ui/hangtag-ui-admin/src/locales/zh-CN.ts +++ b/hangtag-ui/hangtag-ui-admin/src/locales/zh-CN.ts @@ -666,6 +666,7 @@ export default { viewOrder: "查看订单", backHome: "返回首页", tipsDataChange: "数据已更新,请点击更新按钮", + downloadSuccess: "下载成功", }, productDialogList:{ title: '产品列表', diff --git a/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/ProductInfoExcelImport.vue b/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/ProductInfoExcelImport.vue new file mode 100644 index 0000000..0c9ca95 --- /dev/null +++ b/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/ProductInfoExcelImport.vue @@ -0,0 +1,138 @@ + + diff --git a/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/index.vue b/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/index.vue index 41f6992..b4cf4a7 100644 --- a/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/index.vue +++ b/hangtag-ui/hangtag-ui-admin/src/views/oms/productinfo/index.vue @@ -102,7 +102,19 @@ 导出 +
+ + + excel导入 + + +
+ @@ -200,6 +212,7 @@ const designPreviewDialogRef = ref() const loading = ref(true) // 列表的加载中 const list = ref([]) // 列表的数据 const total = ref(0) // 列表的总页数 +const excelImportRef = ref(); const queryParams = reactive({ pageNo: 1, pageSize: 20, @@ -313,8 +326,25 @@ onMounted(() => { openForm('create') } } - getList(); init(); }) +const importSuccess = (res)=>{ + if(!res){ + message.success('导入成功') + excelImportRef.value.close() + getList(); + }else { + message.error(res) + excelImportRef.value.resetForm() + } +} +const downloadTemplate = ()=>{ + ProductInfoApi.downloadTemplate().then(res => { + download.excel(res, '产品导入模板.xlsx') + }) +} +const handleImport = () => { + excelImportRef.value.open() +} diff --git a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue index 8a1ee6c..4563ce7 100644 --- a/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue +++ b/hangtag-ui/hangtag-ui-front/src/components/DraftDesign/index.vue @@ -747,8 +747,8 @@ const toSVGData = (callback: (url: string) => void, options?: { } }) => { - let widthScale = 20 // options && options.widthScale ? options.widthScale : 5 - let heightScale = 20 // options && options.heightScale ? options.heightScale : 5 + let widthScale = 60 // options && options.widthScale ? options.widthScale : 5 + let heightScale = 60 // options && options.heightScale ? options.heightScale : 5 graph.toSVG((dataUri) => { that.previewUrl = dataUri; callback(that.previewUrl) diff --git a/hangtag-ui/hangtag-ui-front/src/locales/en.ts b/hangtag-ui/hangtag-ui-front/src/locales/en.ts index 41e2843..d40b348 100644 --- a/hangtag-ui/hangtag-ui-front/src/locales/en.ts +++ b/hangtag-ui/hangtag-ui-front/src/locales/en.ts @@ -670,6 +670,7 @@ export default { "viewOrder": "viewOrder", "backHome": "BackHome", "tipsDataChange": "DataChange Click Update Button", + "downloadSuccess": "downloadSuccess", }, "productDialogList": { diff --git a/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts b/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts index 8a43b62..a0462ce 100644 --- a/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts +++ b/hangtag-ui/hangtag-ui-front/src/locales/zh-CN.ts @@ -666,6 +666,7 @@ export default { viewOrder: "查看订单", backHome: "返回首页", tipsDataChange: "数据已更新,请点击更新按钮", + downloadSuccess: "下载成功", }, productDialogList:{ title: '产品列表', diff --git a/hangtag-ui/hangtag-ui-front/src/views/oms/order/createorder/components/OrderAddProductStep/ProductItem1.vue b/hangtag-ui/hangtag-ui-front/src/views/oms/order/createorder/components/OrderAddProductStep/ProductItem1.vue index 861b838..8980f5f 100644 --- a/hangtag-ui/hangtag-ui-front/src/views/oms/order/createorder/components/OrderAddProductStep/ProductItem1.vue +++ b/hangtag-ui/hangtag-ui-front/src/views/oms/order/createorder/components/OrderAddProductStep/ProductItem1.vue @@ -117,6 +117,7 @@ const getValue = (item:any) => { } return arr.join(";") } + const formData = ref({}) watch(() => props.productInfo, (newVal) => { console.log("newVal",newVal) @@ -182,11 +183,50 @@ const change = () => { emit("change", formData.value) } const imagePreview = (imgUrl: string) => { + addDownloadImg(imgUrl,new Date().getTime()) createImageViewer({ zIndex: 9999999, urlList: [imgUrl] }) } +const addDownloadImg = (url: string,name = 'img') => { + setTimeout(() => { + let wrapper = document.getElementsByClassName("el-image-viewer__btn el-image-viewer__actions"); + if (wrapper.length > 0) { + let downImg = document.createElement("i"); + downImg.style.fontSize = "20px"; + downImg.style.padding = "4px"; + downImg.style.color = "#fff"; + downImg.setAttribute("class", "icon-lk_down"); + + // 将下载按钮添加到容器中 + wrapper[0].appendChild(downImg); + + // 为下载按钮添加点击事件 + downImg.addEventListener("click", () => { + // 创建下载链接 + const link = document.createElement("a"); + useMessage().success(t("createOrder.downloadSuccess")) + // 使用 fetch 请求获取图片的二进制数据 + fetch(url) + .then((res) => res.blob()) + .then((blob) => { + const blobUrl = URL.createObjectURL(blob); // 创建 blob URL + link.href = blobUrl; // 设置下载链接 + link.download = name+".jpg"; // 设置下载文件名 + link.click(); // 触发下载 + URL.revokeObjectURL(blobUrl); // 释放 blob URL 资源 + }) + .catch((err) => { + console.error("下载失败:", err); + }); + }); + } + }, 100); +}; + + + defineExpose({ init }) diff --git a/sql/mysql/20250102/产品信息新增字段.sql b/sql/mysql/20250102/产品信息新增字段.sql new file mode 100644 index 0000000..e33107c --- /dev/null +++ b/sql/mysql/20250102/产品信息新增字段.sql @@ -0,0 +1,5 @@ + + +-- 销售订单sku备注 +ALTER TABLE oms_sale_order_sku + ADD COLUMN `remark` varchar(1024) DEFAULT NULL COMMENT '备注信息' AFTER `main_color`; \ No newline at end of file