Преглед изворни кода

feature:
经销商管理、品相管理、产品管理根据客户需求重构

yingjian.wu пре 5 месеци
родитељ
комит
505e6e0a9b

+ 250 - 0
src/main/java/com/qlm/controller/jinzai/ItemNewController.java

@@ -0,0 +1,250 @@
+package com.qlm.controller.jinzai;
+
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import cn.hutool.core.collection.CollUtil;
+import com.jfinal.aop.Clear;
+import com.jfinal.kit.HttpKit;
+import com.jfinal.kit.JsonKit;
+import com.jfinal.plugin.activerecord.Db;
+import com.jfinal.plugin.activerecord.Record;
+import com.jfinal.upload.UploadFile;
+import com.qlm.annotation.RequestUrl;
+import com.qlm.common.ApiResponse;
+import com.qlm.controller.common.CommonController;
+import com.qlm.dto.ItemDto;
+import com.qlm.dto.ItemExportDto;
+import com.qlm.dto.ItemImportDto;
+import com.qlm.dto.LineProductImportDto;
+import com.qlm.oss.OssUtil;
+import com.qlm.service.IItemService;
+import com.qlm.service.impl.ItemServiceImpl;
+import com.qlm.tools.EasyExcelUtil;
+import com.qlm.tools.WxUtil;
+import com.alibaba.fastjson.JSON;
+import com.qlm.view.core.AdminView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author wuyingjianwu
+ * @date 2025/xx/xx
+ * 品相信息管理
+ */
+@RequestUrl("/itemNew")
+public class ItemNewController extends CommonController {
+    private static final Logger logger = LoggerFactory.getLogger(ItemController.class);
+    private final IItemService itemService = new ItemServiceImpl();
+
+    public void getItemList() {
+        renderJsp("/page/jinzai/itemNew.jsp");
+    }
+
+    /**
+     * 保存品相信息
+     */
+    @Override
+    public void save() {
+        ApiResponse apiResponse;
+        try {
+            // 使用HttpKit.readData获取请求Body
+            String bodyData = HttpKit.readData(getRequest());
+            // 将JSON字符串转换为ItemDto对象
+            ItemDto itemDto = JSON.parseObject(bodyData, ItemDto.class);
+
+            // 数据验证
+            if (WxUtil.isNull(itemDto.getItemName())) {
+                apiResponse = ApiResponse.error("品相名称不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            if (WxUtil.isNull(itemDto.getItemNo())) {
+                apiResponse = ApiResponse.error("品相编号不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            if (itemDto.getProductId() == null) {
+                apiResponse = ApiResponse.error("产品ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            // 调用Service层保存数据
+            apiResponse = itemService.saveItem(itemDto);
+        } catch (Exception e) {
+            logger.error("保存品相信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 更新品相信息
+     */
+    public void update() {
+        ApiResponse apiResponse;
+        try {
+            String bodyData = HttpKit.readData(getRequest());
+            ItemDto itemDto = JSON.parseObject(bodyData, ItemDto.class);
+
+            if (itemDto.getId() == null) {
+                apiResponse = ApiResponse.error("品相ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = itemService.updateItem(itemDto);
+        } catch (Exception e) {
+            logger.error("更新品相信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 删除品相信息
+     */
+    public void delete() {
+        ApiResponse apiResponse;
+        try {
+            Long id = getParaToLong("id");
+            if (id == null) {
+                apiResponse = ApiResponse.error("品相ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = itemService.deleteItem(id);
+        } catch (Exception e) {
+            logger.error("删除品相信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 根据ID获取品相信息
+     */
+    @Override
+    public void getById() {
+        ApiResponse apiResponse;
+        try {
+            Long id = getParaToLong("id");
+            if (id == null) {
+                apiResponse = ApiResponse.error("品相ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = itemService.getItemById(id);
+        } catch (Exception e) {
+            logger.error("获取品相信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 品相列表查询
+     */
+    @Override
+    public void list() {
+        try {
+            // 获取分页参数
+            int pageNumber = getParaToInt("pageNumber", 1);
+            int pageSize = getParaToInt("pageSize", 10);
+            // 获取查询条件
+            String itemName = getPara("itemName");
+            String itemNo = getPara("itemCode");
+            Long productId = getParaToLong("productId");
+            Integer status = getParaToInt("status");
+            String sku = getPara("sku");
+
+            // 调用Service层查询列表
+            renderJson(itemService.listItem(pageNumber, pageSize, itemName, itemNo, productId, status,sku));
+        } catch (Exception e) {
+            logger.error("查询品相列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 获取产品列表(用于下拉选择)
+     */
+    public void getProductList() {
+        String keyword = getPara("keyword");
+        try {
+            ApiResponse apiResponse = itemService.getAllProducts(keyword);
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("获取产品列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 导入品相
+     */
+    public void importItem() {
+        try {
+            // 获取当前登录用户
+            AdminView loginUser = getLoginUser();
+            // 获取上传的文件
+            UploadFile uploadFile = getFile("file");
+            if (uploadFile == null) {
+                renderJson(ApiResponse.error("请选择要导入的文件"));
+                return;
+            }
+            // 使用EasyExcelUtil解析文件
+            InputStream inputStream = Files.newInputStream(uploadFile.getFile().toPath());
+            List<ItemImportDto> importList = EasyExcelUtil.getImportData(inputStream, ItemImportDto.class);
+            inputStream.close();
+            // 调用Service层导入数据
+            ApiResponse apiResponse = itemService.importItem(importList, loginUser.getUsername());
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("导入产线产品关联信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 导出品相列表
+     */
+    @Clear
+    public void exportItemList() {
+        ApiResponse apiResponse = ApiResponse.success();
+        try {
+            // 获取查询参数
+            String itemName = getPara("itemName");
+            String itemNo = getPara("itemCode");
+            Long productId = getParaToLong("productId");
+            Integer status = getParaToInt("status");
+            String sku = getPara("sku");
+
+            // 调用Service层获取导出数据
+            List<ItemExportDto> dtos = itemService.exportItemList(itemName, itemNo, productId, status, sku);
+
+            if (CollUtil.isEmpty(dtos)) {
+                renderJson(ApiResponse.error("没有要导出的数据"));
+                return;
+            }
+            // 使用EasyExcelUtil生成Excel文件流
+            InputStream inputStream = EasyExcelUtil.export(dtos, "品相列表", ItemExportDto.class);
+            String fileName = URLEncoder.encode("品相列表.xlsx", "UTF-8");
+            String ossUrl = OssUtil.upload(inputStream, fileName);
+            apiResponse = ApiResponse.success(ossUrl);
+        } catch (Exception e) {
+            logger.error("导出品相列表异常:", e);
+            renderJson(ApiResponse.error("导出品相列表失败:" + e.getMessage()));
+        }
+        renderJson(apiResponse);
+    }
+}

+ 186 - 0
src/main/java/com/qlm/controller/jinzai/JxsNewController.java

@@ -0,0 +1,186 @@
+package com.qlm.controller.jinzai;
+
+import cn.hutool.core.collection.CollUtil;
+import com.alibaba.fastjson.JSON;
+import com.jfinal.aop.Clear;
+import com.jfinal.kit.HttpKit;
+import com.jfinal.upload.UploadFile;
+import com.qlm.annotation.RequestUrl;
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.controller.common.CommonController;
+import com.qlm.dto.*;
+import com.qlm.oss.OssUtil;
+import com.qlm.service.IJxsService;
+import com.qlm.service.impl.JxsServiceImpl;
+import com.qlm.tools.EasyExcelUtil;
+import com.qlm.view.core.AdminView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.nio.file.Files;
+import java.util.List;
+
+/**
+ * @author wuyingjianwu
+ * @date 2025/xx/xx
+ * 经销商信息管理
+ */
+@RequestUrl("/jxsNew")
+public class JxsNewController extends CommonController {
+    private static final Logger logger = LoggerFactory.getLogger(JxsNewController.class);
+    private final IJxsService jxsService = new JxsServiceImpl();
+
+    public void getJxsList() {
+        renderJsp("/page/jinzai/jxsNew.jsp");
+    }
+
+    /**
+     * 保存经销商信息
+     */
+    @Override
+    public void save() {
+        AdminView loginUser = getLoginUser();
+        try {
+            // 使用HttpKit.readData获取请求Body
+            String bodyData = HttpKit.readData(getRequest());
+            // 将JSON字符串转换为JxsDto对象
+            JxsDto jxsDto = JSON.parseObject(bodyData, JxsDto.class);
+
+            ApiResponse apiResponse = jxsService.saveJxs(jxsDto,loginUser);
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("保存经销商信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 更新经销商信息
+     */
+    public void update() {
+        try {
+            // 使用HttpKit.readData获取请求Body
+            String bodyData = HttpKit.readData(getRequest());
+            // 将JSON字符串转换为JxsDto对象
+            JxsDto jxsDto = JSON.parseObject(bodyData, JxsDto.class);
+
+            ApiResponse apiResponse = jxsService.updateJxs(jxsDto);
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("更新经销商信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 删除经销商信息
+     */
+    public void delete() {
+        try {
+            Integer id = getParaToInt("id");
+            ApiResponse apiResponse = jxsService.deleteJxs(id);
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("删除经销商信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 根据ID获取经销商信息
+     */
+    public void getById() {
+        try {
+            Integer id = getParaToInt("id");
+            ApiResponse apiResponse = jxsService.getJxsById(id);
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("获取经销商信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 经销商列表查询
+     */
+    @Override
+    public void list() {
+        try {
+            // 获取分页参数
+            int pageNumber = getParaToInt("pageNumber", 1);
+            int pageSize = getParaToInt("pageSize", 10);
+
+            // 获取查询条件
+            String jxsName = getPara("jxsName");
+            String code = getPara("jxsCode");
+            Integer status = getParaToInt("status");
+
+            // 调用Service层查询列表
+            PageResult<JxsDto> pageResult = jxsService.listJxs(pageNumber, pageSize, jxsName, code, status);
+            renderJson(pageResult);
+        } catch (Exception e) {
+            logger.error("查询经销商列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 导入经销商
+     */
+    @Clear
+    public void importJxs() {
+        try {
+            // 获取当前登录用户
+            AdminView loginUser = getLoginUser();
+            // 获取上传的文件
+            UploadFile uploadFile = getFile("file");
+            if (uploadFile == null) {
+                renderJson(ApiResponse.error("请选择要导入的文件"));
+                return;
+            }
+            // 使用EasyExcelUtil解析文件
+            InputStream inputStream = Files.newInputStream(uploadFile.getFile().toPath());
+            List<JxsImportDto> importList = EasyExcelUtil.getImportData(inputStream, JxsImportDto.class);
+            inputStream.close();
+            // 调用Service层导入数据
+            ApiResponse apiResponse = jxsService.importJxs(importList, loginUser.getUsername());
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("导入产线产品关联信息异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 导出经销商列表
+     */
+    public void exportJxsList() {
+        ApiResponse apiResponse = ApiResponse.success();
+        try {
+            // 获取查询条件
+            String jxsName = getPara("jxsName");
+            String code = getPara("code");
+            Integer status = getParaToInt("status");
+
+            // 调用Service层获取导出数据
+            List<JxsExportDto> dtos = jxsService.exportJxsList(jxsName, code,status);
+
+            if (CollUtil.isEmpty(dtos)) {
+                renderJson(ApiResponse.error("没有要导出的数据"));
+                return;
+            }
+            // 使用EasyExcelUtil生成Excel文件流
+            InputStream inputStream = EasyExcelUtil.export(dtos, "经销商列表", JxsExportDto.class);
+            String fileName = URLEncoder.encode("经销商列表.xlsx", "UTF-8");
+            String ossUrl = OssUtil.upload(inputStream, fileName);
+            apiResponse = ApiResponse.success(ossUrl);
+        } catch (Exception e) {
+            logger.error("导出品相列表异常:", e);
+            renderJson(ApiResponse.error("导出品相列表失败:" + e.getMessage()));
+        }
+        renderJson(apiResponse);
+    }
+}

+ 1 - 1
src/main/java/com/qlm/controller/jinzai/ProduceOrderController.java

@@ -300,7 +300,7 @@ public class ProduceOrderController extends CommonController{
 		//组装返回信息
 		//产品信息对象、入库信息对象、出库信息对象
 		Record productInfo = new Record();
-		productInfo.set("productCode", product.getStr("product_code")).set("productName", product.getStr("product_name"))
+		productInfo.set("productCode", product.getStr("product_no")).set("productName", product.getStr("product_name"))
 		.set("itemCode", quality.getStr("item_code")).set("itemName", quality.getStr("item_name"))
 		.set("category", product.getStr("type_name"));
 

+ 228 - 0
src/main/java/com/qlm/controller/jinzai/ProductNewController.java

@@ -0,0 +1,228 @@
+package com.qlm.controller.jinzai;
+
+
+import cn.hutool.core.collection.CollUtil;
+import com.jfinal.aop.Clear;
+import com.jfinal.kit.HttpKit;
+import com.qlm.annotation.RequestUrl;
+import com.qlm.common.ApiResponse;
+import com.qlm.controller.common.CommonController;
+import com.qlm.dto.ItemExportDto;
+import com.qlm.dto.ProductDto;
+import com.qlm.dto.ProductExportDto;
+import com.qlm.oss.OssUtil;
+import com.qlm.service.IProductService;
+import com.qlm.service.impl.ProductServiceImpl;
+import com.qlm.tools.EasyExcelUtil;
+import com.qlm.tools.WxUtil;
+import com.alibaba.fastjson.JSON;
+import com.qlm.view.core.AdminView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.List;
+
+/**
+ * @author wuyingjianwu
+ * @date 2025/xx/xx
+ * 产品信息管理
+ */
+@RequestUrl("/productNew")
+public class ProductNewController extends CommonController {
+    private static final Logger logger = LoggerFactory.getLogger(ProductNewController.class);
+    private final IProductService productService = new ProductServiceImpl();
+
+    public void getProductList() {
+        renderJsp("/page/jinzai/productList.jsp");
+    }
+
+    /**
+     * 保存产品信息
+     */
+    @Override
+    public void save() {
+        AdminView loginUser = getLoginUser();
+        ApiResponse apiResponse;
+        try {
+            // 使用HttpKit.readData获取请求Body
+            String bodyData = HttpKit.readData(getRequest());
+            // 将JSON字符串转换为ProductDto对象
+            ProductDto productDto = JSON.parseObject(bodyData, ProductDto.class);
+
+            // 数据验证
+            if (WxUtil.isNull(productDto.getProductName())) {
+                apiResponse = ApiResponse.error("产品名称不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            if (WxUtil.isNull(productDto.getProductNo())) {
+                apiResponse = ApiResponse.error("产品编号不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            if (productDto.getProductType() == null) {
+                apiResponse = ApiResponse.error("产品分类不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            // 调用Service层保存数据
+            apiResponse = productService.saveProduct(productDto,loginUser);
+        } catch (Exception e) {
+            logger.error("保存产品信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 更新产品信息
+     */
+    public void update() {
+        AdminView loginUser = getLoginUser();
+        ApiResponse apiResponse;
+        try {
+            String bodyData = HttpKit.readData(getRequest());
+            ProductDto productDto = JSON.parseObject(bodyData, ProductDto.class);
+
+            if (productDto.getId() == null) {
+                apiResponse = ApiResponse.error("产品ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = productService.updateProduct(productDto,loginUser);
+        } catch (Exception e) {
+            logger.error("更新产品信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 删除产品信息
+     */
+    public void delete() {
+        ApiResponse apiResponse;
+        try {
+            Long id = getParaToLong("id");
+            if (id == null) {
+                apiResponse = ApiResponse.error("产品ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = productService.deleteProduct(id);
+        } catch (Exception e) {
+            logger.error("删除产品信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 根据ID获取产品信息
+     */
+    @Override
+    public void getById() {
+        ApiResponse apiResponse;
+        try {
+            Long id = getParaToLong("id");
+            if (id == null) {
+                apiResponse = ApiResponse.error("产品ID不能为空");
+                renderJson(apiResponse);
+                return;
+            }
+
+            apiResponse = productService.getProductById(id);
+        } catch (Exception e) {
+            logger.error("获取产品信息异常:", e);
+            apiResponse = ApiResponse.error("系统异常:" + e.getMessage());
+        }
+        renderJson(apiResponse);
+    }
+
+    /**
+     * 产品列表查询
+     */
+    @Override
+    public void list() {
+        try {
+            // 获取分页参数
+            int pageNumber = getParaToInt("pageNumber", 1);
+            int pageSize = getParaToInt("pageSize", 10);
+            // 获取查询条件
+            String productName = getPara("productName");
+            Integer productType = getParaToInt("categoryId");
+            Integer status = getParaToInt("status");
+            Integer brandId = getParaToInt("brandId");
+
+            // 调用Service层查询列表
+            renderJson(productService.listProducts(pageNumber, pageSize, productName, productType, status, brandId));
+        } catch (Exception e) {
+            logger.error("查询产品列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 获取产品分类列表(用于下拉选择)
+     */
+    public void getProductTypeList() {
+        try {
+            ApiResponse apiResponse = productService.getAllProductTypes();
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("获取产品分类列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 获取品牌列表(用于下拉选择)
+     */
+    public void getBrandList() {
+        try {
+            ApiResponse apiResponse = productService.getAllBrands();
+            renderJson(apiResponse);
+        } catch (Exception e) {
+            logger.error("获取品牌列表异常:", e);
+            renderJson(ApiResponse.error("系统异常:" + e.getMessage()));
+        }
+    }
+
+    /**
+     * 导出品相列表
+     */
+    @Clear
+    public void exportProductList() {
+        ApiResponse apiResponse = ApiResponse.success();
+        try {
+            // 获取查询参数
+            String productName = getPara("productName");
+            Integer productType = getParaToInt("categoryId");
+            Integer status = getParaToInt("status");
+            Integer brandId = getParaToInt("brandId");
+
+            // 调用Service层获取导出数据
+            List<ProductExportDto> dtos =productService.exportProductList(productName, productType, status, brandId);
+            if (CollUtil.isEmpty(dtos)) {
+                renderJson(ApiResponse.error("没有要导出的数据"));
+                return;
+            }
+            // 使用EasyExcelUtil生成Excel文件流
+            InputStream inputStream = EasyExcelUtil.export(dtos, "产品列表", ProductExportDto.class);
+            String fileName = URLEncoder.encode("产品列表.xlsx", "UTF-8");
+            String ossUrl = OssUtil.upload(inputStream, fileName);
+            apiResponse = ApiResponse.success(ossUrl);
+        } catch (Exception e) {
+            logger.error("导出产品列表异常:", e);
+            renderJson(ApiResponse.error("导出产品列表失败:" + e.getMessage()));
+        }
+        renderJson(apiResponse);
+    }
+}

+ 50 - 0
src/main/java/com/qlm/dto/DealerAreaDto.java

@@ -0,0 +1,50 @@
+package com.qlm.dto;
+
+import java.io.Serializable;
+
+/**
+ * 经销商区域DTO
+ */
+public class DealerAreaDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 经销商ID
+     */
+    private Long dealerId;
+
+    /**
+     * 省名称
+     */
+    private String province;
+
+    /**
+     * 市名称
+     */
+    private String city;
+
+    // getter和setter方法
+    public Long getDealerId() {
+        return dealerId;
+    }
+
+    public void setDealerId(Long dealerId) {
+        this.dealerId = dealerId;
+    }
+
+    public String getProvince() {
+        return province;
+    }
+
+    public void setProvince(String province) {
+        this.province = province;
+    }
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+}

+ 67 - 0
src/main/java/com/qlm/dto/ItemDto.java

@@ -0,0 +1,67 @@
+package com.qlm.dto;
+
+import java.util.Date;
+
+/**
+ * 品相信息数据传输对象
+ */
+public class ItemDto {
+    private Long id;
+    private String itemName;      // 品相名称
+    private String productNo;
+    private Long productId;       // 产品ID
+    private String productName;   // 产品名称
+    private Date createTime;      // 创建时间
+    private String sku;           // SKU
+    private String bip;           // BIP编码
+    private String kouwei;        // 口味
+    private Integer status;       // 状态(0禁用 1启用)
+    private Integer codeLength;
+    private String itemNo;        // 品相编号
+    private String operator;      // 操作人
+
+    public Long getId() { return id; }
+    public void setId(Long id) { this.id = id; }
+
+    public String getItemName() { return itemName; }
+    public void setItemName(String itemName) { this.itemName = itemName; }
+
+    public Long getProductId() { return productId; }
+    public void setProductId(Long productId) { this.productId = productId; }
+
+    public String getProductName() { return productName; }
+    public void setProductName(String productName) { this.productName = productName; }
+
+    public Date getCreateTime() { return createTime; }
+    public void setCreateTime(Date createTime) { this.createTime = createTime; }
+
+    public String getSku() { return sku; }
+    public void setSku(String sku) { this.sku = sku; }
+
+    public String getBip() { return bip; }
+    public void setBip(String bip) { this.bip = bip; }
+
+    public String getKouwei() { return kouwei; }
+    public void setKouwei(String kouwei) { this.kouwei = kouwei; }
+
+    public Integer getStatus() { return status; }
+    public void setStatus(Integer status) { this.status = status; }
+
+    public Integer getCodeLength() { return codeLength; }
+    public void setCodeLength(Integer codeLength) { this.codeLength = codeLength; }
+
+    public String getItemNo() { return itemNo; }
+    public void setItemNo(String itemNo) { this.itemNo = itemNo; }
+
+    public String getOperator() { return operator; }
+    public void setOperator(String operator) { this.operator = operator; }
+
+
+    public String getProductNo() {
+        return productNo;
+    }
+
+    public void setProductNo(String productNo) {
+        this.productNo = productNo;
+    }
+}

+ 89 - 0
src/main/java/com/qlm/dto/ItemExportDto.java

@@ -0,0 +1,89 @@
+package com.qlm.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+import java.io.Serializable;
+
+/**
+ * 品相导出DTO
+ * 用于导出品相列表数据
+ */
+public class ItemExportDto implements Serializable {
+
+    @ExcelProperty("产品编码")
+    private String productCode;
+
+    @ExcelProperty("产品名称")
+    private String productName;
+
+    @ExcelProperty("品相编码")
+    private String itemNo;
+
+    @ExcelProperty("品相名称")
+    private String itemName;
+
+    @ExcelProperty("SKU")
+    private String sku;
+
+    @ExcelProperty("BIP编号")
+    private String bipCode;
+
+    @ExcelProperty("状态")
+    private String statusName;
+
+    public String getProductCode() {
+        return productCode;
+    }
+
+    public void setProductCode(String productCode) {
+        this.productCode = productCode;
+    }
+
+    public String getItemNo() {
+        return itemNo;
+    }
+
+    public void setItemNo(String itemNo) {
+        this.itemNo = itemNo;
+    }
+
+    public String getItemName() {
+        return itemName;
+    }
+
+    public void setItemName(String itemName) {
+        this.itemName = itemName;
+    }
+
+    public String getSku() {
+        return sku;
+    }
+
+    public void setSku(String sku) {
+        this.sku = sku;
+    }
+
+    public String getBipCode() {
+        return bipCode;
+    }
+
+    public void setBipCode(String bipCode) {
+        this.bipCode = bipCode;
+    }
+
+    public String getStatusName() {
+        return statusName;
+    }
+
+    public void setStatusName(String statusName) {
+        this.statusName = statusName;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public void setProductName(String productName) {
+        this.productName = productName;
+    }
+}

+ 91 - 0
src/main/java/com/qlm/dto/ItemImportDto.java

@@ -0,0 +1,91 @@
+package com.qlm.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+import java.io.Serializable;
+
+/**
+ * 品相导入DTO
+ */
+public class ItemImportDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ExcelProperty("产品编号")
+    private String productNo;
+
+    @ExcelProperty("品相编号")
+    private String itemNo;
+
+    @ExcelProperty("品相名称")
+    private String itemName;
+
+    @ExcelProperty("SKU")
+    private String sku;
+
+    @ExcelProperty("BIP编号")
+    private String bipCode;
+
+    @ExcelProperty("状态")
+    private String status;
+
+    /**
+     * 用于存储导入错误信息
+     */
+    private String errorMsg;
+
+    public String getProductNo() {
+        return productNo;
+    }
+
+    public void setProductNo(String productNo) {
+        this.productNo = productNo;
+    }
+
+    public String getItemNo() {
+        return itemNo;
+    }
+
+    public void setItemNo(String itemNo) {
+        this.itemNo = itemNo;
+    }
+
+    public String getItemName() {
+        return itemName;
+    }
+
+    public void setItemName(String itemName) {
+        this.itemName = itemName;
+    }
+
+    public String getSku() {
+        return sku;
+    }
+
+    public void setSku(String sku) {
+        this.sku = sku;
+    }
+
+    public String getBipCode() {
+        return bipCode;
+    }
+
+    public void setBipCode(String bipCode) {
+        this.bipCode = bipCode;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+    }
+}

+ 129 - 0
src/main/java/com/qlm/dto/JxsDto.java

@@ -0,0 +1,129 @@
+package com.qlm.dto;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 经销商信息DTO
+ */
+public class JxsDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    private Integer id;
+
+    /**
+     * 经销商名称
+     */
+    private String jxs;
+
+    /**
+     * 经销商编码
+     */
+    private String code;
+
+    /**
+     * 联系方式
+     */
+    private String contactPhone;
+
+    /**
+     * 联系人
+     */
+    private String contactName;
+
+    /**
+     * 状态 0停用 1启用
+     */
+    private Integer status;
+
+    /**
+     * 创建时间
+     */
+    private String createTime;
+
+    /**
+     * 创建人
+     */
+    private String createUser;
+
+    /**
+     * 经销商销售区域拼接
+     */
+    private String dealerAreas;
+
+    // getter和setter方法
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getJxs() {
+        return jxs;
+    }
+
+    public void setJxs(String jxs) {
+        this.jxs = jxs;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getContactPhone() {
+        return contactPhone;
+    }
+
+    public void setContactPhone(String contactPhone) {
+        this.contactPhone = contactPhone;
+    }
+
+    public String getContactName() {
+        return contactName;
+    }
+
+    public void setContactName(String contactName) {
+        this.contactName = contactName;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public String getDealerAreas() {
+        return dealerAreas;
+    }
+
+    public void setDealerAreas(String dealerAreas) {
+        this.dealerAreas = dealerAreas;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getCreateUser() {
+        return createUser;
+    }
+
+    public void setCreateUser(String createUser) {
+        this.createUser = createUser;
+    }
+}

+ 79 - 0
src/main/java/com/qlm/dto/JxsExportDto.java

@@ -0,0 +1,79 @@
+package com.qlm.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+import java.io.Serializable;
+
+/**
+ * 经销商导出DTO
+ * 用于导出经销商列表数据
+ */
+public class JxsExportDto implements Serializable {
+
+    @ExcelProperty("经销商编码")
+    private String jxsCode;
+
+    @ExcelProperty("经销商名称")
+    private String jxsName;
+
+    @ExcelProperty("销售区域")
+    private String areas;
+
+    @ExcelProperty("联系人")
+    private String  contact;
+
+    @ExcelProperty("联系方式")
+    private String  phone;
+
+
+    @ExcelProperty("状态")
+    private String statusName;
+
+    public String getJxsCode() {
+        return jxsCode;
+    }
+
+    public void setJxsCode(String jxsCode) {
+        this.jxsCode = jxsCode;
+    }
+
+    public String getJxsName() {
+        return jxsName;
+    }
+
+    public void setJxsName(String jxsName) {
+        this.jxsName = jxsName;
+    }
+
+    public String getAreas() {
+        return areas;
+    }
+
+    public void setAreas(String areas) {
+        this.areas = areas;
+    }
+
+    public String getContact() {
+        return contact;
+    }
+
+    public void setContact(String contact) {
+        this.contact = contact;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getStatusName() {
+        return statusName;
+    }
+
+    public void setStatusName(String statusName) {
+        this.statusName = statusName;
+    }
+}

+ 91 - 0
src/main/java/com/qlm/dto/JxsImportDto.java

@@ -0,0 +1,91 @@
+package com.qlm.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+import java.io.Serializable;
+
+/**
+ * 经销商导入DTO
+ */
+public class JxsImportDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ExcelProperty("经销商编号")
+    private String jxsNo;
+
+    @ExcelProperty("经销商名称")
+    private String jxsName;
+
+    @ExcelProperty("销售区域")
+    private String areas;
+
+    @ExcelProperty("联系人")
+    private String  contact;
+
+    @ExcelProperty("联系方式")
+    private String  phone;
+
+    @ExcelProperty("状态")
+    private String status;
+
+    /**
+     * 用于存储导入错误信息
+     */
+    private String errorMsg;
+
+    public String getJxsNo() {
+        return jxsNo;
+    }
+
+    public void setJxsNo(String jxsNo) {
+        this.jxsNo = jxsNo;
+    }
+
+    public String getJxsName() {
+        return jxsName;
+    }
+
+    public void setJxsName(String jxsName) {
+        this.jxsName = jxsName;
+    }
+
+    public String getAreas() {
+        return areas;
+    }
+
+    public void setAreas(String areas) {
+        this.areas = areas;
+    }
+
+    public String getContact() {
+        return contact;
+    }
+
+    public void setContact(String contact) {
+        this.contact = contact;
+    }
+
+    public String getPhone() {
+        return phone;
+    }
+
+    public void setPhone(String phone) {
+        this.phone = phone;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public String getErrorMsg() {
+        return errorMsg;
+    }
+
+    public void setErrorMsg(String errorMsg) {
+        this.errorMsg = errorMsg;
+    }
+}

+ 167 - 0
src/main/java/com/qlm/dto/ProductDto.java

@@ -0,0 +1,167 @@
+package com.qlm.dto;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 产品信息数据传输对象
+ */
+public class ProductDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+    
+    private Long id;
+    private String productNo;        // 产品编号
+    private String productName;      // 产品名称
+    private Integer productType;     // 产品类型ID
+    private String typeName;         // 产品类型名称
+    private Integer xiangNum;        // 箱数
+    private Integer tuoNum;          // 托数
+    private String barCode;
+    private Integer brandId;
+    private String brandName;
+    private String unit;
+    private String spec;
+    private Integer status;          // 状态(0禁用 1启用)
+    private Integer level;
+    private String detail;
+    private String  createTime;
+    private String operator;
+
+
+    // getter和setter方法
+    public Long getId() {
+        return id;
+    }
+    
+    public void setId(Long id) {
+        this.id = id;
+    }
+    
+    public String getProductNo() {
+        return productNo;
+    }
+    
+    public void setProductNo(String productNo) {
+        this.productNo = productNo;
+    }
+    
+    public String getProductName() {
+        return productName;
+    }
+    
+    public void setProductName(String productName) {
+        this.productName = productName;
+    }
+    
+    public Integer getProductType() {
+        return productType;
+    }
+    
+    public void setProductType(Integer productType) {
+        this.productType = productType;
+    }
+    
+    public String getTypeName() {
+        return typeName;
+    }
+    
+    public void setTypeName(String typeName) {
+        this.typeName = typeName;
+    }
+    
+    public Integer getXiangNum() {
+        return xiangNum;
+    }
+    
+    public void setXiangNum(Integer xiangNum) {
+        this.xiangNum = xiangNum;
+    }
+    
+    public Integer getTuoNum() {
+        return tuoNum;
+    }
+    
+    public void setTuoNum(Integer tuoNum) {
+        this.tuoNum = tuoNum;
+    }
+
+    public String getBarCode() {
+        return barCode;
+    }
+
+    public void setBarCode(String barCode) {
+        this.barCode = barCode;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
+    public String getSpec() {
+        return spec;
+    }
+
+    public void setSpec(String spec) {
+        this.spec = spec;
+    }
+
+    public Integer getBrandId() {
+        return brandId;
+    }
+
+    public void setBrandId(Integer brandId) {
+        this.brandId = brandId;
+    }
+
+    public Integer getLevel() {
+        return level;
+    }
+
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    public String getDetail() {
+        return detail;
+    }
+
+    public void setDetail(String detail) {
+        this.detail = detail;
+    }
+
+    public Integer getStatus() {
+        return status;
+    }
+
+    public void setStatus(Integer status) {
+        this.status = status;
+    }
+
+    public String getBrandName() {
+        return brandName;
+    }
+
+    public void setBrandName(String brandName) {
+        this.brandName = brandName;
+    }
+
+    public String getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(String createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getOperator() {
+        return operator;
+    }
+
+    public void setOperator(String operator) {
+        this.operator = operator;
+    }
+}

+ 78 - 0
src/main/java/com/qlm/dto/ProductExportDto.java

@@ -0,0 +1,78 @@
+package com.qlm.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+
+import java.io.Serializable;
+
+/**
+ * 产品导出DTO
+ * 用于导出产品列表数据
+ */
+public class ProductExportDto implements Serializable {
+
+    @ExcelProperty("产品编号")
+    private String productCode;
+
+    @ExcelProperty("产品名称")
+    private String productName;
+
+    @ExcelProperty("产品类别")
+    private String productTypeName;
+
+    @ExcelProperty("品牌名称")
+    private String brandName;
+
+    @ExcelProperty("单位")
+    private String unit;
+
+    @ExcelProperty("状态")
+    private String status;
+
+    public String getProductCode() {
+        return productCode;
+    }
+
+    public void setProductCode(String productCode) {
+        this.productCode = productCode;
+    }
+
+    public String getProductName() {
+        return productName;
+    }
+
+    public void setProductName(String productName) {
+        this.productName = productName;
+    }
+
+    public String getProductTypeName() {
+        return productTypeName;
+    }
+
+    public void setProductTypeName(String productTypeName) {
+        this.productTypeName = productTypeName;
+    }
+
+    public String getBrandName() {
+        return brandName;
+    }
+
+    public void setBrandName(String brandName) {
+        this.brandName = brandName;
+    }
+
+    public String getUnit() {
+        return unit;
+    }
+
+    public void setUnit(String unit) {
+        this.unit = unit;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+}

+ 45 - 0
src/main/java/com/qlm/service/IItemService.java

@@ -0,0 +1,45 @@
+package com.qlm.service;
+
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.dto.ItemDto;
+import com.qlm.dto.ItemExportDto;
+import com.qlm.dto.ItemImportDto;
+
+import java.util.List;
+
+/**
+ * 品相信息服务接口
+ */
+public interface IItemService {
+    /**
+     * 保存品相信息
+     */
+    ApiResponse saveItem(ItemDto itemDto);
+
+    /**
+     * 更新品相信息
+     */
+    ApiResponse updateItem(ItemDto itemDto);
+
+    /**
+     * 删除品相信息
+     */
+    ApiResponse deleteItem(Long id);
+
+    /**
+     * 根据ID获取品相信息
+     */
+    ApiResponse getItemById(Long id);
+
+    /**
+     * 分页查询品相列表
+     */
+    PageResult<ItemDto> listItem(int pageNumber, int pageSize, String itemName, String itemNo, Long productId, Integer status,String sku);
+
+    ApiResponse getAllProducts(String keyword);
+
+    ApiResponse importItem(List<ItemImportDto> importList, String username);
+
+    List<ItemExportDto> exportItemList(String itemName, String itemNo, Long productId, Integer status, String sku);
+}

+ 47 - 0
src/main/java/com/qlm/service/IJxsService.java

@@ -0,0 +1,47 @@
+package com.qlm.service;
+
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.dto.*;
+import com.qlm.view.core.AdminView;
+
+import java.util.List;
+
+/**
+ * 经销商服务接口
+ */
+public interface IJxsService {
+    /**
+     * 保存经销商信息
+     */
+    ApiResponse saveJxs(JxsDto jxsDto, AdminView loginUser);
+
+    /**
+     * 更新经销商信息
+     */
+    ApiResponse updateJxs(JxsDto jxsDto);
+
+    /**
+     * 删除经销商信息
+     */
+    ApiResponse deleteJxs(Integer id);
+
+    /**
+     * 根据ID获取经销商信息
+     */
+    ApiResponse getJxsById(Integer id);
+
+    /**
+     * 分页查询经销商列表
+     */
+    PageResult<JxsDto> listJxs(int pageNumber, int pageSize, String jxsName, String code, Integer status);
+
+    /**
+     * 将Record转换为JxsDto
+     */
+    JxsDto convertRecordToDto(com.jfinal.plugin.activerecord.Record record);
+
+    ApiResponse importJxs(List<JxsImportDto> importList, String username);
+
+    List<JxsExportDto> exportJxsList(String jxsName, String code, Integer status);
+}

+ 50 - 4
src/main/java/com/qlm/service/IProductService.java

@@ -1,12 +1,58 @@
 package com.qlm.service;
 
 import java.util.List;
-
 import com.jfinal.plugin.activerecord.Record;
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.dto.ProductDto;
+import com.qlm.dto.ProductExportDto;
 import com.qlm.view.core.AdminView;
 
 public interface IProductService {
-	public abstract List<Record> getProductInfoList(AdminView loginUser);
-	
-	public abstract Record getProductInfoByType(Integer type);
+    
+    /**
+     * 根据登录用户获取产品信息列表
+     */
+    List<Record> getProductInfoList(AdminView loginUser);
+    
+    /**
+     * 根据类型获取产品信息
+     */
+    Record getProductInfoByType(Integer type);
+    
+    /**
+     * 分页查询产品列表
+     */
+    PageResult<ProductDto> listProducts(int pageNumber, int pageSize, String productName, Integer productType, Integer status,Integer brandId);
+    
+    /**
+     * 根据ID获取产品信息
+     */
+    ApiResponse getProductById(Long id);
+    
+    /**
+     * 保存产品信息
+     */
+    ApiResponse saveProduct(ProductDto productDto, AdminView loginUser);
+    
+    /**
+     * 更新产品信息
+     */
+    ApiResponse updateProduct(ProductDto productDto, AdminView loginUser);
+    
+    /**
+     * 删除产品信息
+     */
+    ApiResponse deleteProduct(Long id);
+    
+    /**
+     * 根据产品编号获取产品ID
+     */
+    Long getProductIdByCode(String productCode);
+
+    ApiResponse getAllProductTypes();
+
+    ApiResponse getAllBrands();
+
+    List<ProductExportDto> exportProductList(String productName, Integer productType, Integer status, Integer brandId);
 }

+ 412 - 0
src/main/java/com/qlm/service/impl/ItemServiceImpl.java

@@ -0,0 +1,412 @@
+package com.qlm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.jfinal.kit.StrKit;
+import com.jfinal.plugin.activerecord.Db;
+import com.jfinal.plugin.activerecord.Page;
+import com.jfinal.plugin.activerecord.Record;
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.dto.ItemDto;
+import com.qlm.dto.ItemExportDto;
+import com.qlm.dto.ItemImportDto;
+import com.qlm.dto.LineProductImportDto;
+import com.qlm.oss.OssUtil;
+import com.qlm.service.IItemService;
+import com.qlm.tools.EasyExcelUtil;
+import com.qlm.tools.WxUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 品相信息服务实现类
+ */
+public class ItemServiceImpl implements IItemService {
+    private static final Logger logger = LoggerFactory.getLogger(ItemServiceImpl.class);
+
+    /**
+     * 保存品相信息
+     */
+    @Override
+    public ApiResponse saveItem(ItemDto itemDto) {
+        try {
+            // 检查品相编号是否已存在
+            Record existingItem = Db.findFirst("SELECT id FROM t_jz_item WHERE item_no = ?", itemDto.getItemNo());
+            if (existingItem != null) {
+                return ApiResponse.error("品相编号已存在");
+            }
+
+            // 检查产品是否存在
+            Record product = Db.findFirst("SELECT id, product_name FROM t_jz_product WHERE id = ?", itemDto.getProductId());
+            if (product == null) {
+                return ApiResponse.error("产品不存在");
+            }
+
+            // 创建新记录
+            Record item = new Record();
+            item.set("item_name", itemDto.getItemName());
+            item.set("product_id", itemDto.getProductId());
+            item.set("create_time", new Date());
+            item.set("sku", itemDto.getSku());
+            item.set("bip", itemDto.getBip());
+            item.set("status", itemDto.getStatus() != null ? itemDto.getStatus() : 1);
+            item.set("code_length", itemDto.getCodeLength());
+            item.set("item_no", itemDto.getItemNo());
+
+            Db.save("t_jz_item", item);
+            return ApiResponse.success("保存成功");
+        } catch (Exception e) {
+            logger.error("保存品相信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 更新品相信息
+     */
+    @Override
+    public ApiResponse updateItem(ItemDto itemDto) {
+        try {
+            // 检查记录是否存在
+            Record item = Db.findById("t_jz_item", itemDto.getId());
+            if (item == null) {
+                return ApiResponse.error("品相信息不存在");
+            }
+            Record existingItem = Db.findFirst("SELECT id FROM t_jz_item WHERE item_no = ? AND id != ?",
+                    itemDto.getItemNo(), itemDto.getId());
+            if (existingItem != null) {
+                return ApiResponse.error("品相编号已存在");
+            }
+            item.set("item_name", itemDto.getItemName());
+            item.set("product_id", itemDto.getProductId());
+            item.set("sku", itemDto.getSku());
+            item.set("bip", itemDto.getBip());
+            item.set("status", itemDto.getStatus());
+            item.set("item_no", itemDto.getItemNo());
+            item.set("updated_time", new Date());
+            Db.update("t_jz_item", item);
+            return ApiResponse.success("更新成功");
+        } catch (Exception e) {
+            logger.error("更新品相信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 删除品相信息
+     */
+    @Override
+    public ApiResponse deleteItem(Long id) {
+        try {
+            // 检查记录是否存在
+            Record item = Db.findById("t_jz_item", id);
+            if (item == null) {
+                return ApiResponse.error("品相信息不存在");
+            }
+
+            Db.deleteById("t_jz_item", id);
+            return ApiResponse.success("删除成功");
+        } catch (Exception e) {
+            logger.error("删除品相信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 根据ID获取品相信息
+     */
+    @Override
+    public ApiResponse getItemById(Long id) {
+        try {
+            // 联合查询获取产品名称
+            String sql = "SELECT i.*, p.product_name FROM t_jz_item i " +
+                         "LEFT JOIN t_jz_product p ON i.product_id = p.id " +
+                         "WHERE i.id = ?";
+            Record item = Db.findFirst(sql, id);
+            if (item == null) {
+                return ApiResponse.error("品相信息不存在");
+            }
+
+            // 转换为ItemDto
+            ItemDto itemDto = convertRecordToDto(item);
+            return ApiResponse.success(itemDto);
+        } catch (Exception e) {
+            logger.error("获取品相信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 分页查询品相列表
+     */
+    @Override
+    public PageResult<ItemDto> listItem(int pageNumber, int pageSize, String itemName, String itemNo,
+                                       Long productId, Integer status,String sku) {
+        try {
+            // 构建查询条件
+            StringBuilder whereSql = new StringBuilder("FROM t_jz_item i LEFT JOIN t_jz_product p ON i.product_id = p.id WHERE 1=1");
+            List<Object> params = new ArrayList<>();
+
+            if (!WxUtil.isNull(itemName)) {
+                whereSql.append(" AND i.item_name LIKE ?");
+                params.add("%" + itemName + "%");
+            }
+
+            if (!WxUtil.isNull(itemNo)) {
+                whereSql.append(" AND i.item_no LIKE ?");
+                params.add("%" + itemNo + "%");
+            }
+
+            if (productId != null) {
+                whereSql.append(" AND i.product_id = ?");
+                params.add(productId);
+            }
+
+            if (status != null) {
+                whereSql.append(" AND i.status = ?");
+                params.add(status);
+            }
+
+            if (!WxUtil.isNull(sku)) {
+                whereSql.append(" AND i.sku LIKE ?");
+                params.add("%" + sku + "%");
+            }
+
+            whereSql.append(" ORDER BY i.updated_time desc");
+
+            // 分页查询
+            Page<Record> page = Db.paginate(pageNumber, pageSize,
+                    "SELECT i.*, p.product_name,p.product_no",
+                    whereSql.toString(),
+                    params.toArray());
+
+            // 转换为ItemDto列表
+            List<ItemDto> itemList = new ArrayList<>();
+            for (Record record : page.getList()) {
+                itemList.add(convertRecordToDto(record));
+            }
+
+            // 构建返回结果
+            return new PageResult<>(
+                    page.getTotalRow(),
+                    page.getPageNumber(),
+                    page.getPageSize(),
+                    itemList
+            );
+        } catch (Exception e) {
+            logger.error("查询品相列表异常:", e);
+            throw new RuntimeException("系统异常:" + e.getMessage());
+        }
+    }
+
+
+    @Override
+    public ApiResponse getAllProducts(String keyword) {
+        try {
+            StringBuilder sql = new StringBuilder("select id, product_name from t_jz_product where status = 1 ");
+            List<Object> params = new ArrayList<>();
+
+            if (StrKit.notBlank(keyword)) {
+                sql.append(" and product_name like ? ");
+                params.add("%" + keyword + "%");
+            }
+
+            sql.append(" order by product_name asc ");
+            List<Record> records = Db.find(sql.toString(), params.toArray());
+            return ApiResponse.success(records);
+        } catch (Exception e) {
+            logger.error("获取产品列表异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse importItem(List<ItemImportDto> importList, String username) {
+        List<ItemImportDto> errorList = new ArrayList<>();
+        int successCount = 0;
+        ApiResponse response = ApiResponse.success();
+        Record record = new Record();
+        record.set("successCount", successCount);
+        record.set("errorCount", 0);
+        for (ItemImportDto importDto : importList) {
+            try {
+                // 验证必填字段
+                if (StrKit.isBlank(importDto.getProductNo())) {
+                    importDto.setErrorMsg("商品编号不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                if (StrKit.isBlank(importDto.getItemNo())) {
+                    importDto.setErrorMsg("品相编号不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                if (StrKit.isBlank(importDto.getItemName())) {
+                    importDto.setErrorMsg("品相名称不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                if (StrKit.isBlank(importDto.getSku())) {
+                    importDto.setErrorMsg("品相SKU不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                int status = 0;
+                // 状态转换: 启用->1, 禁用->0
+                if ("启用".equals(importDto.getStatus())) {
+                    status = 1;
+                } else if ("禁用".equals(importDto.getStatus())) {
+                } else {
+                    importDto.setErrorMsg("状态值无效,请使用'启用'或'禁用'");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                Long productId = getProductIdByCode(importDto.getProductNo());
+                if (productId == null) {
+                    importDto.setErrorMsg("未找到产品编号对应的产品");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                //校验品相编号是否重复
+                Record existRecord = Db.findFirst("select 1 from t_jz_item where item_no = ?", importDto.getItemNo());
+                if (existRecord != null) {
+                    importDto.setErrorMsg("品相编号已存在");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                // 创建新记录
+                Record item = new Record();
+                item.set("item_name", importDto.getItemName());
+                item.set("product_id", productId);
+                item.set("create_time", new Date());
+                item.set("sku", importDto.getSku());
+                item.set("bip", importDto.getBipCode());
+                item.set("status", status);
+                item.set("item_no", importDto.getItemNo());
+                boolean result = Db.save("t_jz_item", item);
+                if (result) {
+                    successCount++;
+                } else {
+                    importDto.setErrorMsg("保存失败");
+                    errorList.add(importDto);
+                }
+            } catch (Exception e) {
+                logger.error("导入品相信息异常:", e);
+                importDto.setErrorMsg("系统异常:" + e.getMessage());
+                errorList.add(importDto);
+            }
+        }
+        record.set("successCount", successCount);
+        if (!errorList.isEmpty()) {
+            record.set("errorCount", errorList.size());
+            try {
+                String errorFileName = "item_import_error_" + System.currentTimeMillis() + ".xlsx";
+                InputStream errorInputStream = EasyExcelUtil.export(errorList, "导入错误数据", ItemImportDto.class);
+                // 上传到OSS
+                String ossUrl = OssUtil.upload(errorInputStream, errorFileName);
+                // 添加到响应
+                record.set("errorFileUrl", ossUrl);
+            } catch (Exception e) {
+                logger.error("导出错误数据并上传到OSS异常:", e);
+                record.set("errorMsg", "导出错误数据并上传到OSS异常:" + e.getMessage());
+            }
+        }
+        response.setData(record);
+        return response;
+    }
+
+    @Override
+    public List<ItemExportDto> exportItemList(String itemName, String itemNo, Long productId, Integer status, String sku) {
+        // 构建查询条件
+        StringBuilder whereSql = new StringBuilder("SELECT i.*, p.product_name,p.product_no FROM t_jz_item i LEFT JOIN t_jz_product p ON i.product_id = p.id WHERE 1=1");
+        List<Object> params = new ArrayList<>();
+
+        if (!WxUtil.isNull(itemName)) {
+            whereSql.append(" AND i.item_name LIKE ?");
+            params.add("%" + itemName + "%");
+        }
+
+        if (!WxUtil.isNull(itemNo)) {
+            whereSql.append(" AND i.item_no LIKE ?");
+            params.add("%" + itemNo + "%");
+        }
+
+        if (productId != null) {
+            whereSql.append(" AND i.product_id = ?");
+            params.add(productId);
+        }
+
+        if (status != null) {
+            whereSql.append(" AND i.status = ?");
+            params.add(status);
+        }
+
+        if (!WxUtil.isNull(sku)) {
+            whereSql.append(" AND i.sku LIKE ?");
+            params.add("%" + sku + "%");
+        }
+
+        whereSql.append(" ORDER BY i.updated_time desc");
+
+        List<Record> records = Db.find(whereSql.toString(), params.toArray());
+
+        if(CollUtil.isEmpty(records)){
+            return null;
+        }
+
+        // 转换为ItemDto列表
+        List<ItemExportDto> itemList = new ArrayList<>();
+        ItemExportDto itemDto;
+        for (Record record:records) {
+            itemDto = new ItemExportDto();
+            itemDto.setItemName(record.getStr("item_name"));
+            itemDto.setProductName(record.getStr("product_name"));
+            itemDto.setProductCode(record.getStr("product_no"));
+            itemDto.setItemNo(record.getStr("item_no"));
+            itemDto.setSku(record.getStr("sku"));
+            itemDto.setBipCode(record.getStr("bip"));
+            itemDto.setStatusName(record.getInt("status") == 1 ? "启用" : "禁用");
+            itemList.add(itemDto);
+        }
+
+        // 构建返回结果
+        return itemList;
+    }
+
+    /**
+     * 将Record转换为ItemDto
+     */
+    private ItemDto convertRecordToDto(Record record) {
+        ItemDto itemDto = new ItemDto();
+        itemDto.setId(WxUtil.getInt("id",record).longValue());
+        itemDto.setItemName(record.getStr("item_name"));
+        itemDto.setProductId(WxUtil.getInt("product_id",record).longValue());
+        itemDto.setProductName(record.getStr("product_name"));
+        itemDto.setProductNo(record.getStr("product_no"));
+        itemDto.setCreateTime(record.getDate("create_time"));
+        itemDto.setSku(record.getStr("sku"));
+        itemDto.setBip(record.getStr("bip"));
+        itemDto.setKouwei(record.getStr("kouwei"));
+        itemDto.setStatus(record.getInt("status"));
+        itemDto.setCodeLength(record.getInt("code_length"));
+        itemDto.setItemNo(record.getStr("item_no"));
+        return itemDto;
+    }
+
+    public Long getProductIdByCode(String productCode) {
+        Record record = Db.findFirst("select id from t_jz_product where product_no = ?", productCode);
+        return record != null ? WxUtil.getInt("id", record).longValue() : null;
+    }
+}

+ 500 - 0
src/main/java/com/qlm/service/impl/JxsServiceImpl.java

@@ -0,0 +1,500 @@
+package com.qlm.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import com.jfinal.kit.StrKit;
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
+import com.qlm.dto.*;
+import com.qlm.oss.OssUtil;
+import com.qlm.service.IJxsService;
+import com.jfinal.plugin.activerecord.Db;
+import com.jfinal.plugin.activerecord.Record;
+import com.qlm.tools.EasyExcelUtil;
+import com.qlm.tools.WxUtil;
+import com.qlm.view.core.AdminView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 经销商服务实现类
+ */
+public class JxsServiceImpl implements IJxsService {
+    private static final Logger logger = LoggerFactory.getLogger(JxsServiceImpl.class);
+
+    @Override
+    public ApiResponse saveJxs(JxsDto jxsDto, AdminView loginUser) {
+        try {
+            // 数据验证
+            if (jxsDto.getJxs() == null || jxsDto.getJxs().isEmpty()) {
+                return ApiResponse.error("经销商名称不能为空");
+            }
+
+            if (jxsDto.getCode() == null || jxsDto.getCode().isEmpty()) {
+                return ApiResponse.error("经销商编码不能为空");
+            }
+
+            // 检查编码是否已存在
+            Record existRecord = Db.findFirst("select 1 from jinzai_jxs_area where code = ?", jxsDto.getCode());
+            if (existRecord != null) {
+                return ApiResponse.error("该经销商编码已存在");
+            }
+
+            boolean flag = Db.tx(() -> {
+                // 保存经销商基本信息
+                Record record = new Record();
+                record.set("jxs", jxsDto.getJxs());
+                record.set("code", jxsDto.getCode());
+                record.set("contact_phone", jxsDto.getContactPhone());
+                record.set("contact_name", jxsDto.getContactName());
+                record.set("create_user", loginUser.getUsername());
+                record.set("status", jxsDto.getStatus() != null ? jxsDto.getStatus() : 1);
+                Db.save("jinzai_jxs_area", record);
+
+                // 获取保存后的经销商ID
+                Integer dealerId = WxUtil.getInt("id", record);
+
+                // 保存经销商区域信息
+                saveDealerAreas(dealerId, jxsDto.getDealerAreas());
+                return true;
+            });
+            if (!flag) {
+                return ApiResponse.error("保存失败");
+            }
+            return ApiResponse.success("保存成功");
+        } catch (Exception e) {
+            logger.error("保存经销商信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse updateJxs(JxsDto jxsDto) {
+        try {
+            // 数据验证
+            if (jxsDto.getId() == null) {
+                return ApiResponse.error("经销商ID不能为空");
+            }
+
+            if (jxsDto.getJxs() == null || jxsDto.getJxs().isEmpty()) {
+                return ApiResponse.error("经销商名称不能为空");
+            }
+
+            if (jxsDto.getCode() == null || jxsDto.getCode().isEmpty()) {
+                return ApiResponse.error("经销商编码不能为空");
+            }
+
+            // 检查编码是否已存在(排除当前记录)
+            Record existRecord = Db.findFirst("select 1 from jinzai_jxs_area where code = ? and id != ?", 
+                    jxsDto.getCode(), jxsDto.getId());
+            if (existRecord != null) {
+                return ApiResponse.error("该经销商编码已存在");
+            }
+
+            boolean flag = Db.tx(() -> {
+                // 更新经销商基本信息
+                Record record = new Record();
+                record.set("id", jxsDto.getId());
+                record.set("jxs", jxsDto.getJxs());
+                record.set("code", jxsDto.getCode());
+                record.set("contact_phone", jxsDto.getContactPhone());
+                record.set("contact_name", jxsDto.getContactName());
+                record.set("status", jxsDto.getStatus());
+                Db.update("jinzai_jxs_area", record);
+
+                // 删除旧的经销商区域信息
+                Db.update("delete from t_dealer_area where dealer_id = ?", jxsDto.getId());
+
+                // 保存新的经销商区域信息
+                saveDealerAreas(jxsDto.getId(), jxsDto.getDealerAreas());
+
+                return true;
+            });
+            if (!flag) {
+                return ApiResponse.error("更新失败");
+            }
+            return ApiResponse.success("更新成功");
+        } catch (Exception e) {
+            logger.error("更新经销商信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse deleteJxs(Integer id) {
+        try {
+            if (id == null) {
+                return ApiResponse.error("经销商ID不能为空");
+            }
+
+            // 删除经销商区域信息
+            Db.update("delete from t_dealer_area where dealer_id = ?", id);
+
+            // 删除经销商基本信息
+            Db.update("delete from jinzai_jxs_area where id = ?", id);
+
+            return ApiResponse.success("删除成功");
+        } catch (Exception e) {
+            logger.error("删除经销商信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse getJxsById(Integer id) {
+        try {
+            if (id == null) {
+                return ApiResponse.error("经销商ID不能为空");
+            }
+
+            // 获取经销商基本信息
+            Record record = Db.findById("jinzai_jxs_area", id);
+            if (record == null) {
+                return ApiResponse.error("未找到指定的经销商信息");
+            }
+
+            // 转换为JxsDto对象
+            JxsDto jxsDto = convertRecordToDto(record);
+
+            // 获取经销商区域信息
+            List<Record> areaRecords = Db.find("select * from t_dealer_area where dealer_id = ?", id);
+            List<DealerAreaDto> dealerAreas = new ArrayList<>();
+            for (Record areaRecord : areaRecords) {
+                DealerAreaDto areaDto = new DealerAreaDto();
+                areaDto.setDealerId(areaRecord.getLong("dealer_id"));
+                areaDto.setProvince(areaRecord.getStr("province"));
+                areaDto.setCity(areaRecord.getStr("city"));
+                dealerAreas.add(areaDto);
+            }
+            jxsDto.setDealerAreas(dealerAreas.stream()
+                    .map(area -> area.getProvince() + "-" + area.getCity())
+                    .collect(Collectors.joining(",")));
+            return ApiResponse.success(jxsDto);
+        } catch (Exception e) {
+            logger.error("获取经销商信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public PageResult<JxsDto> listJxs(int pageNumber, int pageSize, String jxsName, String code, Integer status) {
+        try {
+            // 构建查询条件
+            StringBuilder sqlWhere = new StringBuilder(" from jinzai_jxs_area where 1=1 ");
+            List<Object> params = new ArrayList<>();
+
+            if (jxsName != null && !jxsName.isEmpty()) {
+                sqlWhere.append(" and jxs like ? ");
+                params.add("%" + jxsName + "%");
+            }
+
+            if (code != null && !code.isEmpty()) {
+                sqlWhere.append(" and code like ? ");
+                params.add("%" + code + "%");
+            }
+
+            if (status != null) {
+                sqlWhere.append(" and status = ? ");
+                params.add(status);
+            }
+
+            sqlWhere.append(" order by create_time desc ");
+
+            // 执行分页查询
+            com.jfinal.plugin.activerecord.Page<Record> recordPage = Db.paginate(pageNumber, pageSize,
+                    "select * ",
+                    sqlWhere.toString(),
+                    params.toArray());
+
+            // 转换为Dto对象列表
+            List<JxsDto> jxsDtoList = new ArrayList<>();
+            if (recordPage != null && recordPage.getList() != null) {
+                // 先获取所有经销商ID
+                List<Integer> dealerIds = recordPage.getList().stream()
+                        .map(record -> record.getInt("id"))
+                        .collect(Collectors.toList());
+
+                // 批量获取所有经销商的区域信息
+                Map<Integer, List<DealerAreaDto>> areaMap = getDealerAreasMap(dealerIds);
+
+                // 转换经销商信息并设置区域
+                for (Record record : recordPage.getList()) {
+                    JxsDto jxsDto = convertRecordToDto(record);
+                    jxsDtoList.add(jxsDto);
+                }
+            }
+
+            // 创建返回结果
+            return new PageResult<>(
+                    recordPage != null ? recordPage.getTotalRow() : 0,
+                    pageNumber,
+                    pageSize,
+                    jxsDtoList
+            );
+        } catch (Exception e) {
+            logger.error("查询经销商列表异常:", e);
+            return new PageResult<>(0, pageNumber, pageSize, new ArrayList<>());
+        }
+    }
+
+    public void saveDealerAreas(Integer dealerId, String dealerAreas) {
+        if(StrKit.isBlank(dealerAreas)){
+            return;
+        }
+        //根据逗号分割成数组
+        String[] split = dealerAreas.split(",");
+        for (String area : split) {
+            String[] split1 = area.split("-");
+            Record areaRecord = new Record();
+            areaRecord.set("dealer_id", dealerId);
+            areaRecord.set("province",split1[0]);
+            areaRecord.set("city", split1[1]);
+            Db.save("t_dealer_area", areaRecord);
+        }
+    }
+
+    @Override
+    public JxsDto convertRecordToDto(Record record) {
+        JxsDto jxsDto = new JxsDto();
+        jxsDto.setId(record.getInt("id"));
+        jxsDto.setJxs(record.getStr("jxs"));
+        jxsDto.setCode(record.getStr("code"));
+        jxsDto.setContactPhone(record.getStr("contact_phone"));
+        jxsDto.setContactName(record.getStr("contact_name"));
+        jxsDto.setStatus(record.getInt("status"));
+        jxsDto.setCreateTime(DateUtil.format(record.getDate("create_time"), "yyyy-MM-dd HH:mm:ss"));
+        jxsDto.setCreateUser(record.getStr("create_user"));
+        return jxsDto;
+    }
+
+    @Override
+    public ApiResponse importJxs(List<JxsImportDto> importList, String username) {
+        List<JxsImportDto> errorList = new ArrayList<>();
+        int successCount = 0;
+        ApiResponse response = ApiResponse.success();
+        Record record = new Record();
+        record.set("successCount", successCount);
+        record.set("errorCount", 0);
+        for (JxsImportDto importDto : importList) {
+            try {
+                // 验证必填字段
+                if (StrKit.isBlank(importDto.getJxsNo())) {
+                    importDto.setErrorMsg("经销商编号不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                if (StrKit.isBlank(importDto.getJxsName())) {
+                    importDto.setErrorMsg("经销商名称不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                if (StrKit.isBlank(importDto.getAreas())) {
+                    importDto.setErrorMsg("销售区域不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                int status;
+                if(StrKit.notBlank(importDto.getStatus())){
+                    // 状态转换: 启用->1, 禁用->0
+                    if ("启用".equals(importDto.getStatus())) {
+                        status = 1;
+                    } else {
+                        status = 0;
+                        if ("禁用".equals(importDto.getStatus())) {
+                        } else {
+                            importDto.setErrorMsg("状态值无效,请使用'启用'或'禁用'");
+                            errorList.add(importDto);
+                            continue;
+                        }
+                    }
+                }else {
+                    importDto.setErrorMsg("状态不能为空");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+
+                //校验品相编号是否重复
+                Record existRecord = Db.findFirst("select 1 from jinzai_jxs_area where code = ?", importDto.getJxsNo());
+                if (existRecord != null) {
+                    importDto.setErrorMsg("经销商编号已存在");
+                    errorList.add(importDto);
+                    continue;
+                }
+
+                boolean validationPassed = true;
+                //根据逗号分割销售区域 例子:湖南省-长沙市,湖南省-株洲市
+                String[] areas = importDto.getAreas().split(",");
+                for (String area : areas) {
+                    String[] provinceAndCity = area.split("-");
+                    if (provinceAndCity.length != 2) {
+                        importDto.setErrorMsg("销售区域格式错误");
+                        errorList.add(importDto);
+                        validationPassed = false;
+                        break;
+                    }
+                    //判断区域是否绑定了经销商
+                    Record existAreaRecord = Db.findFirst("select 1 from t_dealer_area where province = ? and city = ?", provinceAndCity[0], provinceAndCity[1]);
+                    if (existAreaRecord != null) {
+                        importDto.setErrorMsg("销售区域已绑定其他经销商");
+                        errorList.add(importDto);
+                        validationPassed = false;
+                        break;
+                    }
+                }
+
+                if (!validationPassed) {
+                    continue;
+                }
+
+                boolean result= Db.tx(() -> {
+                    // 保存经销商基本信息
+                    Record jxsRecord = new Record();
+                    jxsRecord.set("jxs", importDto.getJxsName());
+                    jxsRecord.set("code", importDto.getJxsNo());
+                    jxsRecord.set("contact_phone", importDto.getContact());
+                    jxsRecord.set("contact_name", importDto.getPhone());
+                    jxsRecord.set("create_user", "系统导入");
+                    jxsRecord.set("status", status);
+                    Db.save("jinzai_jxs_area", jxsRecord);
+
+                    // 获取保存后的经销商ID
+                    Integer dealerId = WxUtil.getInt("id", jxsRecord);
+                    // 保存经销商区域信息
+                    saveDealerAreas(dealerId, importDto.getAreas());
+                    return true;
+                });
+
+                if (result) {
+                    successCount++;
+                } else {
+                    importDto.setErrorMsg("保存失败");
+                    errorList.add(importDto);
+                }
+            } catch (Exception e) {
+                logger.error("导入经销商信息异常:", e);
+                importDto.setErrorMsg("系统异常:" + e.getMessage());
+                errorList.add(importDto);
+            }
+        }
+        record.set("successCount", successCount);
+        if (!errorList.isEmpty()) {
+            record.set("errorCount", errorList.size());
+            try {
+                String errorFileName = "item_import_error_" + System.currentTimeMillis() + ".xlsx";
+                InputStream errorInputStream = EasyExcelUtil.export(errorList, "导入错误数据", JxsImportDto.class);
+                // 上传到OSS
+                String ossUrl = OssUtil.upload(errorInputStream, errorFileName);
+                // 添加到响应
+                record.set("errorFileUrl", ossUrl);
+            } catch (Exception e) {
+                logger.error("导出错误数据并上传到OSS异常:", e);
+                record.set("errorMsg", "导出错误数据并上传到OSS异常:" + e.getMessage());
+            }
+        }
+        response.setData(record);
+        return response;
+    }
+
+    @Override
+    public List<JxsExportDto> exportJxsList(String jxsName, String code, Integer status) {
+        // 构建查询条件
+        StringBuilder sqlWhere = new StringBuilder("select *  from jinzai_jxs_area where 1=1 ");
+        List<Object> params = new ArrayList<>();
+
+        if (jxsName != null && !jxsName.isEmpty()) {
+            sqlWhere.append(" and jxs like ? ");
+            params.add("%" + jxsName + "%");
+        }
+
+        if (code != null && !code.isEmpty()) {
+            sqlWhere.append(" and code like ? ");
+            params.add("%" + code + "%");
+        }
+
+        if (status != null) {
+            sqlWhere.append(" and status = ? ");
+            params.add(status);
+        }
+
+        sqlWhere.append(" order by create_time desc ");
+
+        List<Record> records = Db.find(sqlWhere.toString(), params.toArray());
+
+        // 转换为Dto对象列表
+        List<JxsExportDto> jxsDtoList = new ArrayList<>();
+        if(CollUtil.isEmpty(records)){
+            return null;
+        }
+
+        // 先获取所有经销商ID
+        List<Integer> dealerIds = records.stream()
+                .map(record -> record.getInt("id"))
+                .collect(Collectors.toList());
+
+        // 批量获取所有经销商的区域信息
+        Map<Integer, List<DealerAreaDto>> areaMap = getDealerAreasMap(dealerIds);
+
+        // 转换经销商信息并设置区域
+        for (Record record : records) {
+            JxsExportDto jxsExportDto = new     JxsExportDto();
+            jxsExportDto.setJxsCode(record.getStr("code"));
+            jxsExportDto.setJxsName(record.getStr("jxs"));
+            jxsExportDto.setContact(record.getStr("contact_phone"));
+            jxsExportDto.setPhone(record.getStr("contact_name"));
+            jxsExportDto.setStatusName(record.getInt("status") == 1 ? "正常" : "禁用");
+            List<DealerAreaDto> jxsAreas = areaMap.getOrDefault(WxUtil.getInt("id", record), new ArrayList<>());
+            if(CollUtil.isNotEmpty(jxsAreas)){
+                //例子:湖南省-长沙市,湖南省-株洲市
+                jxsExportDto.setAreas(jxsAreas.stream()
+                        .map(area -> area.getProvince() + "-" + area.getCity())
+                        .collect(Collectors.joining(",")));
+            }
+            jxsDtoList.add(jxsExportDto);
+        }
+
+        // 创建返回结果
+        return jxsDtoList;
+    }
+
+    /**
+     * 批量获取经销商区域信息映射
+     */
+    private Map<Integer, List<DealerAreaDto>> getDealerAreasMap(List<Integer> dealerIds) {
+        if (dealerIds == null || dealerIds.isEmpty()) {
+            return java.util.Collections.emptyMap();
+        }
+
+        StringBuilder sql = new StringBuilder("select * from t_dealer_area where dealer_id in (");
+        for (int i = 0; i < dealerIds.size(); i++) {
+            sql.append("?");
+            if (i < dealerIds.size() - 1) {
+                sql.append(",");
+            }
+        }
+        sql.append(")");
+
+        List<Record> records = Db.find(sql.toString(), dealerIds.toArray());
+
+        // 构建映射
+        Map<Integer, List<DealerAreaDto>> map = new java.util.HashMap<>();
+        for (Record record : records) {
+            Integer dealerId = WxUtil.getInt("dealer_id", record);
+            DealerAreaDto areaDto = new DealerAreaDto();
+            areaDto.setDealerId(dealerId.longValue());
+            areaDto.setProvince(record.getStr("province"));
+            areaDto.setCity(record.getStr("city"));
+
+            map.computeIfAbsent(dealerId, k -> new ArrayList<>()).add(areaDto);
+        }
+
+        return map;
+    }
+}

+ 275 - 12
src/main/java/com/qlm/service/impl/ProductServiceImpl.java

@@ -1,24 +1,287 @@
 package com.qlm.service.impl;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
 import java.util.List;
 
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateUtil;
+import com.qlm.common.ApiResponse;
+import com.qlm.common.PageResult;
 import com.jfinal.plugin.activerecord.Db;
 import com.jfinal.plugin.activerecord.Record;
+import com.qlm.dto.ItemExportDto;
+import com.qlm.dto.ProductDto;
+import com.qlm.dto.ProductExportDto;
 import com.qlm.service.IProductService;
+import com.qlm.tools.WxUtil;
 import com.qlm.view.core.AdminView;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ProductServiceImpl implements IProductService {
 
-	@Override
-	public List<Record> getProductInfoList(AdminView loginUser){
-		// TODO Auto-generated method stub
-		int uid = loginUser.getId();
-		return Db.find("select id,name_,type_,desc_ from t_product where uid = ?",uid);
-	}
-
-	@Override
-	public Record getProductInfoByType(Integer type) {
-		// TODO Auto-generated method stub
-		return Db.findFirst("select id,name_,type_,desc_,isUpload_ from t_product where type_ = ?",type);
-	}
+    private static final Logger logger = LoggerFactory.getLogger(ProductServiceImpl.class);
+
+
+    @Override
+    public List<Record> getProductInfoList(AdminView loginUser) {
+        // TODO Auto-generated method stub
+        int uid = loginUser.getId();
+        return Db.find("select id,name_,type_,desc_ from t_product where uid = ?", uid);
+    }
+
+    @Override
+    public Record getProductInfoByType(Integer type) {
+        // TODO Auto-generated method stub
+        return Db.findFirst("select id,name_,type_,desc_,isUpload_ from t_product where type_ = ?", type);
+    }
+
+    @Override
+    public PageResult<ProductDto> listProducts(int pageNumber, int pageSize, String productName, Integer productType, Integer status,Integer brandId) {
+        try {
+            // 构建查询条件
+            StringBuilder sqlWhere = new StringBuilder();
+            List<Object> params = new ArrayList<>();
+
+            if (productName != null && !productName.isEmpty()) {
+                sqlWhere.append(" and product_name like ? ");
+                params.add("%" + productName + "%");
+            }
+
+            if (productType != null) {
+                sqlWhere.append(" and product_type = ? ");
+                params.add(productType);
+            }
+
+            if (brandId != null) {
+                sqlWhere.append(" and brand_id = ? ");
+                params.add(brandId);
+            }
+
+            if (status != null) {
+                sqlWhere.append(" and t.status = ? ");
+                params.add(status);
+            }
+
+            sqlWhere.append(" order by create_time desc ");
+
+            // 执行分页查询
+            com.jfinal.plugin.activerecord.Page<Record> recordPage = Db.paginate(pageNumber, pageSize,
+                    "select t.*, tp.type_name,tb.brand_name ",
+                    "from t_jz_product t " +
+                            "left join t_jz_product_type tp on t.product_type = tp.id left join t_brand tb on t.brand_id = tb.id where 1=1 " + sqlWhere.toString(),
+                    params.toArray());
+
+            if (recordPage == null) {
+                return new PageResult<>(0, pageNumber, pageSize, new ArrayList<>());
+            }
+
+            // 转换为Dto对象
+            List<ProductDto> productDtoList = new ArrayList<>();
+            for (Record record : recordPage.getList()) {
+                productDtoList.add(convertRecordToDto(record));
+            }
+
+            // 创建新的Page对象,包含Dto列表
+            return new PageResult<>(recordPage.getTotalRow(),
+                    recordPage.getPageNumber(),
+                    recordPage.getPageSize(),
+                    productDtoList);
+
+        } catch (Exception e) {
+            logger.error("查询产品列表异常:", e);
+            return new PageResult<>(0, pageNumber, pageSize, new ArrayList<>());
+        }
+    }
+
+    @Override
+    public ApiResponse getProductById(Long id) {
+        try {
+            Record record = Db.findFirst("select t.*, tp.type_name,tb.brand_name from t_jz_product t left join t_jz_product_type tp on t.product_type = tp.id left join t_brand tb on t.brand_id = tb.id where t.id = ?", id);
+            if (record == null) {
+                return ApiResponse.error("产品不存在");
+            }
+            return ApiResponse.success(convertRecordToDto(record));
+        } catch (Exception e) {
+            logger.error("根据ID获取产品信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse saveProduct(ProductDto productDto, AdminView loginUser) {
+        try {
+            Record record = new Record();
+            record.set("product_no", productDto.getProductNo());
+            record.set("product_name", productDto.getProductName());
+            record.set("product_type", productDto.getProductType());
+            record.set("xiang_num", productDto.getXiangNum());
+            record.set("tuo_num", productDto.getTuoNum());
+            record.set("status", productDto.getStatus() != null ? productDto.getStatus() : 1);
+            record.set("create_time", new Date());
+            record.set("detail", productDto.getDetail());
+            record.set("brand_id", productDto.getBrandId());
+            record.set("baozhuang_level", productDto.getLevel());
+            record.set("product_code", productDto.getBarCode());
+            record.set("unit", productDto.getUnit());
+            record.set("standard", productDto.getSpec());
+            record.set("operator", loginUser.getUsername());
+
+            boolean save = Db.save("t_jz_product", record);
+            return save ? ApiResponse.success() : ApiResponse.error("保存产品信息失败");
+        } catch (Exception e) {
+            logger.error("保存产品信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse updateProduct(ProductDto productDto, AdminView loginUser) {
+        try {
+            Record record = Db.findById("t_jz_product", productDto.getId());
+            if (record == null) {
+                return ApiResponse.error("产品不存在");
+            }
+            
+            record.set("product_no", productDto.getProductNo());
+            record.set("product_name", productDto.getProductName());
+            record.set("product_type", productDto.getProductType());
+            record.set("xiang_num", productDto.getXiangNum());
+            record.set("tuo_num", productDto.getTuoNum());
+            record.set("status", productDto.getStatus() != null ? productDto.getStatus() : 1);
+            record.set("detail", productDto.getDetail());
+            record.set("brand_id", productDto.getBrandId());
+            record.set("baozhuang_level", productDto.getLevel());
+            record.set("product_code", productDto.getBarCode());
+            record.set("unit", productDto.getUnit());
+            record.set("standard", productDto.getSpec());
+            record.set("operator", loginUser.getUsername());
+
+            boolean update = Db.update("t_jz_product", record);
+            return update ? ApiResponse.success() : ApiResponse.error("更新产品信息失败");
+        } catch (Exception e) {
+            logger.error("更新产品信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse deleteProduct(Long id) {
+        try {
+            boolean b = Db.deleteById("t_jz_product", id);
+            return b ? ApiResponse.success() : ApiResponse.error("删除产品信息失败");
+        } catch (Exception e) {
+            logger.error("删除产品信息异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public Long getProductIdByCode(String productCode) {
+        try {
+            Record record = Db.findFirst("select id from t_jz_product where product_no = ?", productCode);
+            return record != null ? WxUtil.getInt("id", record).longValue() : null;
+        } catch (Exception e) {
+            logger.error("根据产品编号获取产品ID异常:", e);
+            return null;
+        }
+    }
+
+    @Override
+    public ApiResponse getAllProductTypes() {
+        try {
+            List<Record> recordList = Db.find("select id, type_name from t_jz_product_type");
+            return ApiResponse.success(recordList);
+        } catch (Exception e) {
+            logger.error("获取产品分类列表异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public ApiResponse getAllBrands() {
+        try {
+            List<Record> recordList = Db.find("select id, brand_name from t_brand");
+            return ApiResponse.success(recordList);
+        } catch (Exception e) {
+            logger.error("获取品牌列表异常:", e);
+            return ApiResponse.error("系统异常:" + e.getMessage());
+        }
+    }
+
+    @Override
+    public List<ProductExportDto> exportProductList(String productName, Integer productType, Integer status, Integer brandId) {
+        // 构建查询条件
+        StringBuilder sqlWhere = new StringBuilder("select t.*, tp.type_name,tb.brand_name from t_jz_product t left join t_jz_product_type tp on t.product_type = tp.id left join t_brand tb on t.brand_id = tb.id where 1=1");
+        List<Object> params = new ArrayList<>();
+
+        if (productName != null && !productName.isEmpty()) {
+            sqlWhere.append(" and product_name like ? ");
+            params.add("%" + productName + "%");
+        }
+
+        if (productType != null) {
+            sqlWhere.append(" and product_type = ? ");
+            params.add(productType);
+        }
+
+        if (brandId != null) {
+            sqlWhere.append(" and brand_id = ? ");
+            params.add(brandId);
+        }
+
+        if (status != null) {
+            sqlWhere.append(" and t.status = ? ");
+            params.add(status);
+        }
+
+        List<Record> records = Db.find(sqlWhere.toString(), params.toArray());
+
+        if(CollUtil.isEmpty(records)){
+            return null;
+        }
+
+        // 转换为ItemDto列表
+        List<ProductExportDto> prodList = new ArrayList<>();
+        ProductExportDto exportDto;
+        for (Record record:records) {
+            exportDto = new ProductExportDto();
+            exportDto.setProductCode(record.getStr("product_code"));
+            exportDto.setProductName(record.getStr("product_name"));
+            exportDto.setProductTypeName(record.getStr("type_name"));
+            exportDto.setBrandName(record.getStr("brand_name"));
+            exportDto.setUnit(record.getStr("unit"));
+            exportDto.setStatus(record.getInt("status") == 1 ? "启用" : "禁用");
+            prodList.add(exportDto);
+        }
+        // 构建返回结果
+        return prodList;
+    }
+
+    /**
+     * 将Record转换为ProductDto的工具方法
+     */
+    private ProductDto convertRecordToDto(Record record) {
+        ProductDto dto = new ProductDto();
+        dto.setId(WxUtil.getInt("id", record).longValue());
+        dto.setProductNo(record.getStr("product_no"));
+        dto.setProductName(record.getStr("product_name"));
+        dto.setProductType(record.getInt("product_type"));
+        dto.setTypeName(record.getStr("type_name"));
+        dto.setXiangNum(record.getInt("xiang_num"));
+        dto.setTuoNum(record.getInt("tuo_num"));
+        dto.setStatus(record.getInt("status"));
+        dto.setLevel(record.getInt("baozhuang_level"));
+        dto.setBarCode(record.getStr("product_code"));
+        dto.setUnit(record.getStr("unit"));
+        dto.setSpec(record.getStr("standard"));
+        dto.setBrandId(record.getInt("brand_id"));
+        dto.setBrandName(record.getStr("brand_name"));
+        dto.setDetail(record.getStr("detail"));
+        dto.setCreateTime(DateUtil.format(record.getDate("create_time"), "yyyy-MM-dd HH:mm:ss"));
+        dto.setOperator(record.getStr("operator"));
+        return dto;
+    }
 }

+ 874 - 0
src/main/webapp/page/jinzai/itemNew.jsp

@@ -0,0 +1,874 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+         pageEncoding="UTF-8" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<c:set value="<%=request.getContextPath()%>" var="ctx"></c:set>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>品相管理列表</title>
+    <meta name="keywords" content="品相管理">
+    <meta name="description" content="品相信息管理页面">
+    <link href="${ctx}/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
+    <link href="${ctx}/css/font-awesome.css?v=4.4.0" rel="stylesheet">
+    <link href="${ctx}/css/bootstrap-select.min.css" rel="stylesheet">
+    <link href="${ctx}/css/plugins/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
+    <link href="${ctx}/css/animate.css" rel="stylesheet">
+    <link href="${ctx}/css/style.css?v=4.1.0" rel="stylesheet">
+    <style>
+        .required::before {
+            content: '*';
+            color: red;
+            margin-right: 5px;
+        }
+
+        .form-group {
+            margin-bottom: 1.5rem;
+        }
+
+        .toggle-switch {
+            position: relative;
+            display: inline-block;
+            width: 60px;
+            height: 34px;
+        }
+
+        .toggle-switch input {
+            opacity: 0;
+            width: 0;
+            height: 0;
+        }
+
+        .row.mb-4 {
+            margin-bottom: 1.5rem; /* 或者使用 20px 等其他值 */
+        }
+
+        .slider {
+            position: absolute;
+            cursor: pointer;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background-color: #ccc;
+            transition: .4s;
+            border-radius: 34px;
+        }
+
+        .slider:before {
+            position: absolute;
+            content: "";
+            height: 26px;
+            width: 26px;
+            left: 4px;
+            bottom: 4px;
+            background-color: white;
+            transition: .4s;
+            border-radius: 50%;
+        }
+
+        input:checked + .slider {
+            background-color: #2196F3;
+        }
+
+        input:checked + .slider:before {
+            transform: translateX(26px);
+        }
+
+        .form-container {
+            padding: 20px;
+            border-radius: 8px;
+            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+            background-color: #fff;
+        }
+
+        .form-inline-flex {
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            gap: 5px;
+        }
+
+        @media (max-width: 768px) {
+            .form-inline-flex {
+                flex-direction: column;
+                align-items: stretch;
+            }
+
+            .form-inline-flex .form-control,
+            .form-inline-flex .btn,
+            .form-inline-flex .selectpicker {
+                width: 100% !important;
+                margin-right: 0 !important;
+            }
+        }
+    </style>
+</head>
+
+<body class="gray-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="ibox">
+                <div class="ibox-title">
+                    <div class="row">
+                        <div class="col-sm-10">
+                            <h3>品相管理列表</h3>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="ibox-content">
+                    <div class="row row-lg mb-4">
+                        <div class="col-lg-12">
+                            <div class="form-inline-flex">
+                                <div style="width: 200px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;">
+                                    <select id="productId" class="form-control selectpicker" data-live-search="true" title="请选择产品">
+                                    </select>
+                                </div>
+                                <input id="itemCode" class="form-control" style="width: 150px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;" placeholder="请输入品相编码"/>
+                                <input id="itemName" class="form-control" style="width: 150px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;" placeholder="请输入品相名称"/>
+                                <select id="status" class="form-control" style="width: 120px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;">
+                                    <option value="">请选择状态</option>
+                                    <option value="1">启用</option>
+                                    <option value="0">禁用</option>
+                                </select>
+                                <input id="sku" class="form-control" style="width: 150px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;" placeholder="请输入SKU"/>
+                                <button type="button" id="searchBtn" class="btn btn-success" onclick="search();return false;" style="margin-right: 5px; margin-bottom: 5px;">查询
+                                </button>
+                                <button type="button" id="resetBtn" class="btn btn-default" style="margin-right: 5px; margin-bottom: 5px;">重置
+                                </button>
+                                <button type="button" class="btn btn-primary" onclick="showAddModal();" style="margin-right: 5px; margin-bottom: 5px;">新增
+                                </button>
+                                <button type="button" class="btn btn-info" onclick="exportData();" style="margin-right: 5px; margin-bottom: 5px;">导出
+                                </button>
+                                <button type="button" class="btn btn-info" onclick="importData();" style="margin-right: 5px; margin-bottom: 5px;">导入
+                                </button>
+                                <button type="button" class="btn btn-warning" onclick="syncData();" style="margin-right: 5px; margin-bottom: 5px;">同步
+                                </button>
+                                <button type="button" class="btn btn-success" onclick="autoSyncSettings();" style="margin-bottom: 5px;">自动同步设置
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row row-lg mt-3">
+                        <div class="col-sm-12">
+                            <table id="table" data-toggle="table" data-mobile-responsive="true"></table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 新增/编辑品相模态框 -->
+<div class="modal fade" id="itemModal" tabindex="-1" role="dialog" aria-labelledby="itemModalLabel">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                <h4 class="modal-title" id="itemModalLabel">新增品相</h4>
+            </div>
+            <div class="modal-body">
+                <div class="form-container">
+                    <form id="itemForm">
+                        <input type="hidden" id="itemId" name="itemId">
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label for="modalProductId" class="required control-label">产品ID</label>
+                                <select id="modalProductId" class="form-control" required>
+                                    <option value="">请选择产品ID</option>
+                                    <!-- 产品ID下拉框选项将通过JavaScript动态加载 -->
+                                </select>
+                            </div>
+                            <div class="col-md-6">
+                                <label for="modalItemCode" class="required control-label">品相编号</label>
+                                <input type="text" class="form-control" id="modalItemCode" name="modalItemCode" placeholder="请输入" required>
+                            </div>
+                        </div>
+
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label for="modalItemName" class="required control-label">品相名称</label>
+                                <input type="text" class="form-control" id="modalItemName" name="modalItemName" placeholder="请输入" required>
+                            </div>
+                            <div class="col-md-6">
+                                <label for="modalSku" class="required control-label">SKU</label>
+                                <input type="text" class="form-control" id="modalSku" name="modalSku" placeholder="请输入" required>
+                            </div>
+                        </div>
+
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label for="modalbip" class="required control-label">BIP编号</label>
+                                <input type="text" class="form-control" id="modalbip" name="modalbip" placeholder="请输入" required>
+                            </div>
+                            <div class="col-md-6">
+                                <label class="required control-label">状态</label>
+                                <div class="d-flex align-items-center gap-2">
+                                    <label class="toggle-switch">
+                                        <input type="checkbox" id="modalStatus" name="modalStatus" checked>
+                                        <span class="slider"></span>
+                                    </label>
+                                    <span id="statusText">启用</span>
+                                    <div class="text-muted">状态:启用、禁用,默认启用</div>
+                                </div>
+                            </div>
+                        </div>
+                    </form>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary" onclick="saveItem();">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 全局js -->
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+<!-- 全局js -->
+<script src="${ctx}/js/jquery.min.js?v=2.1.4"></script>
+<script src="${ctx}/js/bootstrap.min.js?v=3.3.6"></script>
+<script src="${ctx}/js/bootstrap-select.min.js"></script>
+<!-- 自定义js -->
+<script src="${ctx}/js/content.js?v=1.0.0"></script>
+<!-- jQuery Validation plugin javascript-->
+<script src="${ctx}/js/plugins/validate/jquery.validate.min.js"></script>
+<script src="${ctx}/js/plugins/validate/messages_zh.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
+<script src="${ctx}/js/common.js"></script>
+<script src="${ctx}/js/plugins/layer/layer.min.js"></script>
+<script src="${ctx}/js/Math.uuid.js"></script>
+</body>
+<script>
+    var table = null;
+    var products = []; // 存储产品数据
+
+    $(document).ready(function () {
+        $('.selectpicker').selectpicker({
+            liveSearch: true,
+            size: 5,
+            actionsBox: true,
+            selectedTextFormat: 'count > 2'
+        });
+        // 加载产品数据
+        loadProducts();
+
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+        initValidation();
+
+        // 绑定重置按钮点击事件
+        $('#resetBtn').on('click', function() {
+            reset();
+        });
+
+        // 状态切换按钮
+        const statusToggle = document.getElementById('modalStatus');
+        const statusText = document.getElementById('statusText');
+
+        statusToggle.addEventListener('change', function () {
+            if (this.checked) {
+                statusText.textContent = '启用';
+            } else {
+                statusText.textContent = '禁用';
+            }
+        });
+    });
+
+    // 加载产品数据
+    function loadModalProducts() {
+        $.ajax({
+            url: '${ctx}/itemNew/getProductList',
+            type: 'GET',
+            dataType: 'json',
+            success: function (data) {
+                if (data.code === 0) {
+                    products = data.data;
+                    // 填充产品下拉框
+                    const modalProductSelect = $('#modalProductId');
+
+                    modalProductSelect.empty().append('<option value="">请选择产品ID</option>');
+
+                    products.forEach(product => {
+                        modalProductSelect.append('<option value="' + product.id + '">' + product.product_name + '</option>');
+                    });
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                layer.msg('加载产品数据失败', {icon: 5});
+            }
+        });
+    }
+
+    // 加载产品数据
+    function loadProducts() {
+        $.ajax({
+            url: '${ctx}/itemNew/getProductList',
+            type: 'POST',
+            dataType: 'json',
+            beforeSend: function () {
+                $('#productId').prop('disabled', true).selectpicker('refresh');
+            },
+            success: function (res) {
+                $('#productId').empty();
+                if (res.data && res.data.length) {
+                    res.data.forEach(item => {
+                        $('#productId').append('<option value="' + item.id + '">' + item.product_name + '</option>');
+                    });
+                }
+                $('#productId').selectpicker('refresh');
+            },
+            error: function (xhr) {
+                $('#productId').empty().append('<option value="">加载失败</option>');
+                $('#productId').selectpicker('refresh');
+                layer.msg('获取产品数据失败: ' + xhr.statusText);
+            },
+            complete: function () {
+                $('#productId').prop('disabled', false).selectpicker('refresh');
+            }
+        });
+    }
+
+    function queryParams(param) {
+        let productId = $.trim($("#productId").val());
+        let itemCode = $.trim($("#itemCode").val());
+        let itemName = $.trim($("#itemName").val());
+        let status = $.trim($("#status").val());
+        let sku = $.trim($("#sku").val());
+
+        if (productId) {
+            param['productId'] = productId;
+        }
+        if (itemCode) {
+            param['itemCode'] = itemCode;
+        }
+        if (itemName) {
+            param['itemName'] = itemName;
+        }
+        if (status) {
+            param['status'] = status;
+        }
+        if (sku) {
+            param['sku'] = sku;
+        }
+
+        return param;
+    }
+
+    function search() {
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+    }
+
+    function reset() {
+        $("#productId").val('');
+        $("#productId").selectpicker('val', '');
+        $("#productId").selectpicker('deselectAll');
+        $("#productId").selectpicker('refresh');
+        $("#itemCode").val('');
+        $("#itemName").val('');
+        $("#status").val('');
+        $("#sku").val('');
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+    }
+
+    function showAddModal() {
+        loadModalProducts();
+        // 清空表单
+        $('#itemForm')[0].reset();
+        $('#itemId').val('');
+        $('#modalStatus').prop('checked', true);
+        $('#statusText').text('启用');
+        $('#itemModalLabel').text('新增品相');
+
+        // 重置表单验证状态
+        if ($('#itemForm').data('validator')) {
+            $('#itemForm').data('validator').resetForm();
+        }
+
+        // 清除所有错误类
+        $('#itemForm .error').removeClass('error');
+        $('#itemForm label.error').remove();
+
+        // 显示模态框
+        $('#itemModal').modal('show');
+    }
+
+    function showEditModal(id) {
+        // 清空表单
+        $('#itemForm')[0].reset();
+        // 加载品相数据
+        loadItemData(id);
+        $('#itemModalLabel').text('编辑品相');
+
+        // 重置表单验证状态
+        if ($('#itemForm').data('validator')) {
+            $('#itemForm').data('validator').resetForm();
+        }
+
+        // 清除所有错误类
+        $('#itemForm .error').removeClass('error');
+        $('#itemForm label.error').remove();
+
+        // 显示模态框
+        $('#itemModal').modal('show');
+    }
+
+    function loadItemData(id) {
+        loadModalProducts();
+        $.ajax({
+            url: '${ctx}/itemNew/getById?id=' + id,
+            type: 'GET',
+            dataType: 'json',
+            success: function (data) {
+                if (data.code === 0) {
+                    const item = data.data;
+                    // 填充表单数据
+                    $('#itemId').val(item.id);
+                    $('#modalProductId').val(item.productId);
+                    $('#modalItemCode').val(item.itemNo);
+                    $('#modalItemName').val(item.itemName);
+                    $('#modalSku').val(item.sku);
+                    $('#modalbip').val(item.bip);
+
+                    // 设置状态开关
+                    if (item.status === 1) {
+                        $('#modalStatus').prop('checked', true);
+                        $('#statusText').text('启用');
+                    } else {
+                        $('#modalStatus').prop('checked', false);
+                        $('#statusText').text('禁用');
+                    }
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                layer.msg('加载品相数据失败', {icon: 5});
+            }
+        });
+    }
+
+    function saveItem() {
+        if (!$('#itemForm').valid()) {
+            return;
+        }
+
+        // 获取表单数据
+        const id = $('#itemId').val();
+        const formData = {
+            id: id,
+            productId: $('#modalProductId').val(),
+            itemNo: $('#modalItemCode').val(),
+            itemName: $('#modalItemName').val(),
+            sku: $('#modalSku').val(),
+            bip: $('#modalbip').val(),
+            status: $('#modalStatus').is(':checked') ? 1 : 0
+        };
+
+        $.ajax({
+            url: id ? '${ctx}/itemNew/update' : '${ctx}/itemNew/save',
+            type: 'POST',
+            data: JSON.stringify(formData),
+            contentType: 'application/json',
+            success: function (data) {
+                if (data.code === 0) {
+                    layer.msg('保存成功', {icon: 6});
+                    // 关闭模态框
+                    $('#itemModal').modal('hide');
+                    // 刷新表格
+                    search();
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                layer.msg('保存失败', {icon: 5});
+            }
+        });
+    }
+
+    function deleteItem(id) {
+        layer.confirm('确定要删除该品相吗?此操作不可撤销!', {
+            btn: ['确定', '取消']
+        }, function () {
+            $.ajax({
+                url: '${ctx}/itemNew/delete',
+                type: 'post',
+                data: {
+                    id: id
+                },
+                success: function (result) {
+                    if (result.code === 0) {
+                        layer.msg(result.msg, {icon: 1});
+                        search(); // 刷新表格
+                    } else {
+                        layer.msg(result.msg, {icon: 2});
+                    }
+                },
+                error: function () {
+                    layer.msg('删除失败', {icon: 2});
+                }
+            });
+        });
+    }
+
+    function initValidation() {
+        $('#itemForm').validate({
+            rules: {
+                modalProductId: {
+                    required: true
+                },
+                modalItemCode: {
+                    required: true,
+                    maxlength: 50
+                },
+                modalItemName: {
+                    required: true,
+                    maxlength: 100
+                },
+                modalSku: {
+                    required: true,
+                    maxlength: 50
+                },
+                modalbip: {
+                    required: true,
+                    maxlength: 50
+                }
+            },
+            messages: {
+                modalProductId: {
+                    required: '请选择产品ID'
+                },
+                modalItemCode: {
+                    required: '请输入品相编号',
+                    maxlength: '品相编号最多50个字符'
+                },
+                modalItemName: {
+                    required: '请输入品相名称',
+                    maxlength: '品相名称最多100个字符'
+                },
+                modalSku: {
+                    required: '请输入SKU',
+                    maxlength: 'SKU最多50个字符'
+                },
+                modalbip: {
+                    required: '请输入BIP编号',
+                    maxlength: 'BIP编号最多50个字符'
+                }
+            }
+        });
+    }
+
+    function initTable() {
+        table = $('#table').bootstrapTable({
+            method: 'get',
+            sortable: true,
+            toolbar: '#toolbar',    //工具按钮用哪个容器
+            striped: true,      //是否显示行间隔色
+            cache: false,      //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
+            pagination: true,     //是否显示分页(*)
+            pageNumber: 1,      //初始化加载第一页,默认第一页
+            pageSize: 10,      //每页的记录行数(*)
+            pageList: [10, 25, 50, 100],  //可供选择的每页的行数(*)
+            url: '${ctx}/itemNew/list',//这个接口需要处理bootstrap table传递的固定参数
+            queryParamsType: '', //默认值为 'limit' ,在默认情况下 传给服务端的参数为:offset,limit,sort
+            // 设置为 ''  在这种情况下传给服务器的参数为:pageSize,pageNumber
+
+            queryParams: queryParams,//前端调用服务时,会默认传递上边所述的参数,如果需要添加自定义参数,可以自定义一个函数返回请求参数
+            sidePagination: "server",   //分页方式:client客户端分页,server服务端分页(*)
+            strictSearch: false,
+            minimumCountColumns: 2,    //最少允许的列数
+            clickToSelect: true,    //是否启用点击选中行
+            searchOnEnterKey: true,
+            idField: "id",
+            // 设置数据格式转换
+            responseHandler: function (res) {
+                // 这里假设接口返回的data就是我们需要的表格数据
+                return {
+                    total: res.total,  // 总记录数
+                    rows: res.records  // 数据列表
+                };
+            },
+            columns: [{
+                title: '序号',
+                align: 'center',
+                formatter: function (value, row, index) {
+                    // 使用this关键字访问表格实例
+                    var pageNumber = this.pageNumber || 1;
+                    var pageSize = this.pageSize || 10;
+                    return (pageNumber - 1) * pageSize + index + 1;
+                },
+                width: "5%"
+            }, {
+                field: 'productNo',
+                title: '产品编号',
+                align: 'center',
+                width: "10%"
+            }, {
+                field: 'productName',
+                title: '产品名称',
+                align: 'center',
+                width: "15%"
+            }, {
+                field: 'bip',
+                title: 'BIP编号',
+                align: 'center',
+                width: "10%"
+            }, {
+                field: 'itemNo',
+                title: '品相编号',
+                align: 'center',
+                width: "10%"
+            }, {
+                field: 'itemName',
+                title: '品相名称',
+                align: 'center',
+                width: "15%"
+            }, {
+                field: 'sku',
+                title: 'SKU',
+                align: 'center',
+                width: "10%"
+            }, {
+                field: 'status',
+                title: '状态',
+                align: 'center',
+                formatter: function (value) {
+                    if (value === 1) {
+                        return '<span class="label label-success">启用</span>';
+                    } else {
+                        return '<span class="label label-danger">禁用</span>';
+                    }
+                },
+                width: "10%"
+            }, {
+                title: '操作',
+                align: 'center',
+                width: "15%",
+                formatter: function (value, row) {
+                    return '<button class="btn btn-primary btn-sm me-1" onclick="showEditModal(' + row.id + ')">编辑</button> ' +
+                        '<button class="btn btn-danger btn-sm" onclick="deleteItem(' + row.id + ')">删除</button>';
+                }
+            }],
+            onLoadSuccess: function (data) {
+                console.log("数据加载成功", data);
+            },
+            onLoadError: function () {
+                layer.msg('数据加载失败', {icon: 2});
+            }
+        });
+    }
+
+    // 在script标签内的合适位置添加以下代码
+
+    // 导出功能实现
+    // 导出数据函数 - 修改版
+    function exportData() {
+        // 收集查询参数
+        let productId = $.trim($("#productId").val());
+        let itemCode = $.trim($("#itemCode").val());
+        let itemName = $.trim($("#itemName").val());
+        let status = $.trim($("#status").val());
+        let sku = $.trim($("#sku").val());
+    
+        // 显示加载中提示
+        let loadingIndex = layer.load(1, {shade: [0.5, '#fff']});
+    
+        // 发送请求到后端获取导出URL
+        $.ajax({
+            url: '${ctx}/itemNew/exportItemList',
+            type: 'GET',
+            data: {
+                productId: productId,
+                itemCode: itemCode,
+                itemName: itemName,
+                status: status,
+                sku: sku
+            },
+            dataType: 'json',
+            success: function (res) {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+    
+                if (res.code === 0) {
+                    // 获取导出URL并打开
+                    let exportUrl = res.data;
+                    if (exportUrl) {
+                        // 使用新窗口打开URL进行下载
+                        window.open(exportUrl, '_blank');
+                        layer.msg('导出成功,请在新窗口中查看下载文件', {icon: 1});
+                    } else {
+                        layer.msg('未获取到有效的导出URL', {icon: 5});
+                    }
+                } else {
+                    layer.msg(res.msg || '导出失败', {icon: 5});
+                }
+            },
+            error: function () {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+                layer.msg('导出请求失败', {icon: 5});
+            }
+        });
+    }
+
+    // 导入功能实现
+    function importData() {
+        const importHtml = `
+        <div style="padding: 20px;">
+            <div class="upload-area" style="border: 2px dashed #e0e0e0; padding: 30px; text-align: center; margin-bottom: 20px;">
+                <div style="margin-bottom: 15px;">
+                    <i class="fa fa-cloud-upload" style="font-size: 50px; color: #ccc;"></i>
+                </div>
+                <p style="margin-bottom: 10px;">将文件拖到此处,或 <span style="color: #0066cc; cursor: pointer;" id="clickUpload">点击上传</span></p>
+                <p style="font-size: 12px; color: #999;">仅允许导入xls、xlsx格式文件。<a href="https://hyscancode.oss-cn-hangzhou.aliyuncs.com/jinzaiimport/%E5%93%81%E7%9B%B8%E5%AF%BC%E5%85%A5%E6%A8%A1%E7%89%88.xlsx" style="color: #0066cc;">下载模板</a></p>
+                <div id="selectedFileName" style="margin-top: 15px; font-size: 12px; color: #333; display: none; justify-content: center; align-items: center;"></div>
+                <input type="file" id="fileUpload" accept=".xlsx, .xls" style="display: none;">
+            </div>
+            <div style="text-align: center;">
+                <button type="button" class="btn btn-warning" style="margin-right: 10px;" onclick="uploadItemFile()">确定</button>
+                <button type="button" class="btn btn-default" onclick="layer.closeAll()">取消</button>
+            </div>
+        </div>
+    `;
+
+        layer.open({
+            type: 1,
+            title: '导入品相数据',
+            area: ['500px', '350px'],
+            content: importHtml
+        });
+
+        // 绑定点击上传事件
+        setTimeout(function() {
+            document.getElementById('clickUpload').addEventListener('click', function() {
+                document.getElementById('fileUpload').click();
+            });
+
+            // 监听文件选择事件
+            document.getElementById('fileUpload').addEventListener('change', function() {
+                const fileName = this.files[0]?.name;
+                const fileNameElement = document.getElementById('selectedFileName');
+                if (fileName) {
+                    // 创建包含文件名和关闭按钮的HTML
+                    fileNameElement.innerHTML =
+                        '<span>已选择文件: ' + fileName + '</span>' +
+                        '<span style="margin-left: 8px; cursor: pointer; color: #ff4444;" id="clearFileSelection">×</span>';
+                    fileNameElement.style.display = 'flex';
+
+                    // 绑定清除按钮事件
+                    document.getElementById('clearFileSelection').addEventListener('click', function() {
+                        // 清除文件选择
+                        const fileInput = document.getElementById('fileUpload');
+                        fileInput.value = '';
+
+                        // 隐藏文件名显示
+                        fileNameElement.textContent = '';
+                        fileNameElement.style.display = 'none';
+                    });
+                } else {
+                    fileNameElement.textContent = '';
+                    fileNameElement.style.display = 'none';
+                }
+            });
+
+            // 实现拖拽上传效果
+            const uploadArea = document.querySelector('.upload-area');
+            uploadArea.addEventListener('dragover', function(e) {
+                e.preventDefault();
+                this.style.borderColor = '#0066cc';
+                this.style.backgroundColor = '#f5f9ff';
+            });
+
+            uploadArea.addEventListener('dragleave', function() {
+                this.style.borderColor = '#e0e0e0';
+                this.style.backgroundColor = 'transparent';
+            });
+
+            uploadArea.addEventListener('drop', function(e) {
+                e.preventDefault();
+                this.style.borderColor = '#e0e0e0';
+                this.style.backgroundColor = 'transparent';
+
+                if (e.dataTransfer.files.length) {
+                    document.getElementById('fileUpload').files = e.dataTransfer.files;
+                    // 触发change事件以更新文件名显示
+                    const event = new Event('change');
+                    document.getElementById('fileUpload').dispatchEvent(event);
+                }
+            });
+        }, 100);
+    }
+
+    function uploadItemFile() {
+        const fileInput = document.getElementById('fileUpload');
+        if (!fileInput.files || fileInput.files.length === 0) {
+            layer.msg('请选择要上传的文件', {icon: 2});
+            return;
+        }
+
+        const formData = new FormData();
+        formData.append('file', fileInput.files[0]);
+
+        $.ajax({
+            url: '${ctx}/itemNew/importItem',
+            type: 'POST',
+            data: formData,
+            processData: false,
+            contentType: false,
+            beforeSend: function() {
+                layer.load(1); // 显示加载动画
+            },
+            success: function(result) {
+                layer.closeAll('loading'); // 关闭加载动画
+                if (result.code === 0) {
+                    let successCount = result.data.successCount;
+                    let errorCount = result.data.errorCount;
+                    let errorFileUrl = result.data.errorFileUrl;
+
+                    // 检查是否有错误数据
+                    if (errorCount > 0) {
+                        // 创建错误信息HTML
+                        const errorHtml =
+                            '<div style="padding: 20px;">' +
+                            '<p style="text-align: center; margin-bottom: 15px;">导入结果:成功 ' + successCount + ' 条,失败 ' + errorCount + ' 条</p>' +
+                            '<div style="text-align: center; margin-bottom: 15px;">' +
+                            '<a href="' + errorFileUrl + '" class="btn btn-warning" target="_blank">下载错误数据</a>' +
+                            '</div>' +
+                            '</div>';
+
+                        layer.open({
+                            type: 1,
+                            title: '导入结果',
+                            area: ['400px', '250px'],
+                            content: errorHtml
+                        });
+                    } else {
+                        layer.msg('导入成功,共 ' + successCount + ' 条数据', {icon: 1});
+                    }
+
+                    // 刷新表格数据
+                    search();
+                } else {
+                    layer.msg(result.msg, {icon: 2});
+                }
+            },
+            error: function() {
+                layer.closeAll('loading'); // 关闭加载动画
+                layer.msg('导入失败,请重试', {icon: 2});
+            }
+        });
+    }
+</script>
+</html>

+ 979 - 0
src/main/webapp/page/jinzai/jxsNew.jsp

@@ -0,0 +1,979 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<c:set value="<%=request.getContextPath()%>" var="ctx"></c:set>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>经销商管理</title>
+    <meta name="keywords" content="经销商管理">
+    <meta name="description" content="经销商信息管理页面">
+    <link href="${ctx}/css/bootstrap.min.css?v=3.3.6" rel="stylesheet">
+    <link href="${ctx}/css/font-awesome.css?v=4.4.0" rel="stylesheet">
+    <link href="${ctx}/css/bootstrap-select.min.css" rel="stylesheet">
+    <link href="${ctx}/css/plugins/bootstrap-table/bootstrap-table.min.css" rel="stylesheet">
+    <link href="${ctx}/css/animate.css" rel="stylesheet">
+    <link href="${ctx}/css/style.css?v=4.1.0" rel="stylesheet">
+    <style>
+        .required::before {
+            content: '*';
+            color: red;
+            margin-right: 5px;
+        }
+
+        .row.mb-4 {
+            margin-bottom: 1.5rem; /* 或者使用 20px 等其他值 */
+        }
+
+        .form-group {
+            margin-bottom: 1.5rem;
+        }
+
+        .toggle-switch {
+            position: relative;
+            display: inline-block;
+            width: 60px;
+            height: 34px;
+        }
+
+        .toggle-switch input {
+            opacity: 0;
+            width: 0;
+            height: 0;
+        }
+
+        .slider {
+            position: absolute;
+            cursor: pointer;
+            top: 0;
+            left: 0;
+            right: 0;
+            bottom: 0;
+            background-color: #ccc;
+            transition: .4s;
+            border-radius: 34px;
+        }
+
+        .slider:before {
+            position: absolute;
+            content: "";
+            height: 26px;
+            width: 26px;
+            left: 4px;
+            bottom: 4px;
+            background-color: white;
+            transition: .4s;
+            border-radius: 50%;
+        }
+
+        input:checked + .slider {
+            background-color: #2196F3;
+        }
+
+        input:checked + .slider:before {
+            transform: translateX(26px);
+        }
+
+        .form-container {
+            padding: 20px;
+            border-radius: 8px;
+            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+            background-color: #fff;
+        }
+
+        .form-inline-flex {
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            gap: 5px;
+        }
+
+        @media (max-width: 768px) {
+            .form-inline-flex {
+                flex-direction: column;
+                align-items: stretch;
+            }
+
+            .form-inline-flex .form-control,
+            .form-inline-flex .btn,
+            .form-inline-flex .selectpicker {
+                width: 100% !important;
+                margin-right: 0 !important;
+            }
+        }
+    </style>
+</head>
+
+<body class="gray-bg">
+<div class="wrapper wrapper-content animated fadeInRight">
+    <div class="row">
+        <div class="col-sm-12">
+            <div class="ibox">
+                <div class="ibox-title">
+                    <div class="row">
+                        <div class="col-sm-10">
+                            <h3>经销商管理</h3>
+                        </div>
+                    </div>
+                </div>
+
+                <div class="ibox-content">
+                    <div class="row row-lg mb-4">
+                        <div class="col-lg-12">
+                            <div class="form-inline-flex">
+                                <input id="jxsCode" class="form-control"
+                                       style="width: 180px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;"
+                                       placeholder="请输入经销商编号"/>
+                                <input id="jxsName" class="form-control"
+                                       style="width: 180px; flex-shrink: 0; margin-right: 10px; margin-bottom: 5px;"
+                                       placeholder="请输入经销商名称"/>
+                                <button type="button" id="searchBtn" class="btn btn-success"
+                                        onclick="search();return false;" style="margin-right: 5px; margin-bottom: 5px;">
+                                    查询
+                                </button>
+                                <button type="button" id="resetBtn" class="btn btn-default"
+                                        style="margin-right: 5px; margin-bottom: 5px;">重置
+                                </button>
+                                <button type="button" class="btn btn-primary" onclick="showAddModal();"
+                                        style="margin-right: 5px; margin-bottom: 5px;">新增
+                                </button>
+                                <button type="button" class="btn btn-info" onclick="exportData();"
+                                        style="margin-right: 5px; margin-bottom: 5px;">导出
+                                </button>
+                                <button type="button" class="btn btn-info" onclick="importData();"
+                                        style="margin-bottom: 5px;">导入
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                    <div class="row row-lg mt-3">
+                        <div class="col-sm-12">
+                            <table id="table" data-toggle="table" data-mobile-responsive="true"></table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 新增/编辑经销商模态框 -->
+<div class="modal fade" id="jxsModal" tabindex="-1" role="dialog" aria-labelledby="jxsModalLabel">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
+                </button>
+                <h4 class="modal-title" id="jxsModalLabel">新增经销商</h4>
+            </div>
+            <div class="modal-body">
+                <div class="form-container">
+                    <form id="jxsForm">
+                        <input type="hidden" id="jxsId" name="jxsId">
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label for="modalJxsCode" class="required control-label">经销商编号</label>
+                                <input type="text" class="form-control" id="modalJxsCode" name="modalJxsCode"
+                                       placeholder="请输入" required>
+                            </div>
+                            <div class="col-md-6">
+                                <label for="modalJxsName" class="required control-label">经销商名称</label>
+                                <input type="text" class="form-control" id="modalJxsName" name="modalJxsName"
+                                       placeholder="请输入" required>
+                            </div>
+                        </div>
+
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label for="modalContactPerson" class="required control-label">联系人</label>
+                                <input type="text" class="form-control" id="modalContactPerson"
+                                       name="modalContactPerson" placeholder="请输入" required>
+                            </div>
+                            <div class="col-md-6">
+                                <label for="modalContactPhone" class="required control-label">联系方式</label>
+                                <input type="text" class="form-control" id="modalContactPhone" name="modalContactPhone"
+                                       placeholder="请输入" required>
+                            </div>
+                        </div>
+
+                        <div class="row mb-4">
+                            <div class="col-md-12">
+                                <label for="modalSalesArea" class="required control-label">销售地区</label>
+                                <select id="modalSalesArea" class="form-control selectpicker" multiple="multiple"
+                                        data-live-search="true" title="请选择销售地区" required>
+                                    <!-- 销售地区选项将通过JavaScript动态加载 -->
+                                </select>
+                            </div>
+                        </div>
+
+                        <div class="row mb-4">
+                            <div class="col-md-6">
+                                <label class="required control-label">状态</label>
+                                <div class="d-flex align-items-center gap-2">
+                                    <label class="toggle-switch">
+                                        <input type="checkbox" id="modalStatus" name="modalStatus" checked>
+                                        <span class="slider"></span>
+                                    </label>
+                                    <span id="statusText">启用</span>
+                                    <div class="text-muted">状态:启用、禁用,默认启用</div>
+                                </div>
+                            </div>
+                            <div class="col-md-6">
+                                <!-- 预留一列 -->
+                            </div>
+                        </div>
+                    </form>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
+                <button type="button" class="btn btn-primary" onclick="saveJxs();">确定</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<div class="modal fade" id="jxsDetailModal" tabindex="-1" role="dialog" aria-labelledby="jxsDetailModalLabel">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
+                </button>
+                <h4 class="modal-title" id="productDetailModalLabel">经销商详情</h4>
+            </div>
+            <div class="modal-body">
+                <div class="row">
+                    <div class="col-md-12">
+                        <div class="table-responsive">
+                            <table class="table table-bordered table-hover">
+                                <tbody>
+                                <tr>
+                                    <td class="text-right" width="30%"><strong>经销商编码:</strong></td>
+                                    <td id="detailJxsCode"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>联系人:</strong></td>
+                                    <td id="detailContactName"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>联系方式:</strong></td>
+                                    <td id="detailContactPhone"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>销售地区:</strong></td>
+                                    <td id="detailAreas"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>状态:</strong></td>
+                                    <td id="detailStatus"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>创建人:</strong></td>
+                                    <td id="detailCreateUser"></td>
+                                </tr>
+                                <tr>
+                                    <td class="text-right"><strong>创建时间:</strong></td>
+                                    <td id="detailCreateTime"></td>
+                                </tr>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+
+<!-- 全局js -->
+<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+<!-- 全局js -->
+<script src="${ctx}/js/jquery.min.js?v=2.1.4"></script>
+<script src="${ctx}/js/bootstrap.min.js?v=3.3.6"></script>
+<script src="${ctx}/js/bootstrap-select.min.js"></script>
+<!-- 自定义js -->
+<script src="${ctx}/js/content.js?v=1.0.0"></script>
+<!-- jQuery Validation plugin javascript-->
+<script src="${ctx}/js/plugins/validate/jquery.validate.min.js"></script>
+<script src="${ctx}/js/plugins/validate/messages_zh.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/bootstrap-table.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/bootstrap-table-mobile.min.js"></script>
+<script src="${ctx}/js/plugins/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script>
+<script src="${ctx}/js/common.js"></script>
+<script src="${ctx}/js/plugins/layer/layer.min.js"></script>
+<script src="${ctx}/js/Math.uuid.js"></script>
+</body>
+<script>
+    var table = null;
+    var salesAreas = []; // 存储销售地区数据
+
+    $(document).ready(function () {
+        $('.selectpicker').selectpicker({
+            liveSearch: true,
+            size: 5,
+            actionsBox: true,
+            selectedTextFormat: 'count > 2'
+        });
+
+        // 初始化表格
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+        initValidation();
+
+        // 绑定重置按钮点击事件
+        $('#resetBtn').on('click', function () {
+            reset();
+        });
+
+        // 状态切换按钮
+        const statusToggle = document.getElementById('modalStatus');
+        const statusText = document.getElementById('statusText');
+
+        statusToggle.addEventListener('change', function () {
+            if (this.checked) {
+                statusText.textContent = '启用';
+            } else {
+                statusText.textContent = '禁用';
+            }
+        });
+    });
+
+    // 加载销售地区数据
+    function loadSalesAreas() {
+        // 显示加载中提示
+        var loadingIndex = layer.load(1, {
+            shade: [0.2, '#000']
+        });
+
+        // 从JSON文件加载地区数据
+        $.ajax({
+            url: '${ctx}/common/area.json',
+            type: 'GET',
+            dataType: 'json',
+            success: function (data) {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+
+                // 清空选择框
+                $('#modalSalesArea').empty();
+
+                // 遍历数据,只取省市两级,格式为"湖南省-长沙市"
+                for (var province in data) {
+                    if (data.hasOwnProperty(province)) {
+                        var cities = data[province];
+                        for (var city in cities) {
+                            if (cities.hasOwnProperty(city)) {
+                                // 构建省市组合,如"湖南省-长沙市"
+                                var areaText = province + '-' + city;
+                                $('#modalSalesArea').append('<option value="' + areaText + '">' + areaText + '</option>');
+                            }
+                        }
+                    }
+                }
+
+                // 刷新selectpicker
+                $('#modalSalesArea').selectpicker('refresh');
+            },
+            error: function () {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+                layer.msg('加载销售地区数据失败', {icon: 5});
+            }
+        });
+    }
+
+    function queryParams(param) {
+        let jxsCode = $.trim($("#jxsCode").val());
+        let jxsName = $.trim($("#jxsName").val());
+
+        if (jxsCode) {
+            param['jxsCode'] = jxsCode;
+        }
+        if (jxsName) {
+            param['jxsName'] = jxsName;
+        }
+
+        return param;
+    }
+
+    function search() {
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+    }
+
+    function reset() {
+        $("#jxsCode").val('');
+        $("#jxsName").val('');
+        table = $('#table').bootstrapTable("destroy");
+        initTable();
+    }
+
+    function showAddModal() {
+        loadSalesAreas();
+        // 清空表单
+        $('#jxsForm')[0].reset();
+        $('#jxsId').val('');
+        $('#modalStatus').prop('checked', true);
+        $('#statusText').text('启用');
+        $('#jxsModalLabel').text('新增经销商');
+
+        // 重置表单验证状态
+        if ($('#jxsForm').data('validator')) {
+            $('#jxsForm').data('validator').resetForm();
+        }
+
+        // 清除所有错误类
+        $('#jxsForm .error').removeClass('error');
+        $('#jxsForm label.error').remove();
+
+        // 显示模态框
+        $('#jxsModal').modal('show');
+    }
+
+    function showEditModal(id) {
+        // 清空表单
+        $('#jxsForm')[0].reset();
+        // 加载经销商数据
+        loadJxsData(id);
+        $('#jxsModalLabel').text('编辑经销商');
+
+        // 重置表单验证状态
+        if ($('#jxsForm').data('validator')) {
+            $('#jxsForm').data('validator').resetForm();
+        }
+
+        // 清除所有错误类
+        $('#jxsForm .error').removeClass('error');
+        $('#jxsForm label.error').remove();
+
+        // 显示模态框
+        $('#jxsModal').modal('show');
+    }
+
+    function loadJxsData(id) {
+        loadSalesAreas();
+        $.ajax({
+            url: '${ctx}/jxsNew/getById?id=' + id,
+            type: 'GET',
+            dataType: 'json',
+            success: function (data) {
+                if (data.code === 0) {
+                    const jxs = data.data;
+                    // 填充表单数据
+                    $('#jxsId').val(jxs.id);
+                    $('#modalJxsCode').val(jxs.code);
+                    $('#modalJxsName').val(jxs.jxs);
+                    $('#modalContactPerson').val(jxs.contactName);
+                    $('#modalContactPhone').val(jxs.contactPhone);
+
+                    // 设置销售地区,需要等待selectpicker初始化完成后再设置
+                    setTimeout(function () {
+                        if (jxs.dealerAreas) {
+                            // 假设salesArea是逗号分隔的字符串
+                            var areas = jxs.dealerAreas.split(',');
+                            $('#modalSalesArea').val(areas);
+                            $('#modalSalesArea').selectpicker('refresh');
+                        }
+                    }, 500);
+
+                    // 设置状态开关
+                    if (jxs.status === 1) {
+                        $('#modalStatus').prop('checked', true);
+                        $('#statusText').text('启用');
+                    } else {
+                        $('#modalStatus').prop('checked', false);
+                        $('#statusText').text('禁用');
+                    }
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                layer.msg('加载经销商数据失败', {icon: 5});
+            }
+        });
+    }
+
+    function saveJxs() {
+        if (!$('#jxsForm').valid()) {
+            return;
+        }
+
+        // 获取表单数据
+        const id = $('#jxsId').val();
+        // 获取选中的销售地区(数组)
+        const selectedAreas = $('#modalSalesArea').val() || [];
+
+        const formData = {
+            id: id,
+            code: $('#modalJxsCode').val(),
+            jxs: $('#modalJxsName').val(),
+            contactName: $('#modalContactPerson').val(),
+            contactPhone: $('#modalContactPhone').val(),
+            dealerAreas: selectedAreas.join(','), // 将数组转换为逗号分隔的字符串
+            status: $('#modalStatus').is(':checked') ? 1 : 0
+        };
+
+        $.ajax({
+            url: id ? '${ctx}/jxsNew/update' : '${ctx}/jxsNew/save',
+            type: 'POST',
+            data: JSON.stringify(formData),
+            contentType: 'application/json',
+            success: function (data) {
+                if (data.code === 0) {
+                    layer.msg('保存成功', {icon: 6});
+                    // 关闭模态框
+                    $('#jxsModal').modal('hide');
+                    // 刷新表格
+                    search();
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                layer.msg('保存失败', {icon: 5});
+            }
+        });
+    }
+
+    function deleteJxs(id) {
+        layer.confirm('确定要删除该经销商吗?此操作不可撤销!', {
+            btn: ['确定', '取消']
+        }, function () {
+            $.ajax({
+                url: '${ctx}/jxsNew/delete',
+                type: 'post',
+                data: {
+                    id: id
+                },
+                success: function (result) {
+                    if (result.code === 0) {
+                        layer.msg(result.msg, {icon: 1});
+                        search(); // 刷新表格
+                    } else {
+                        layer.msg(result.msg, {icon: 2});
+                    }
+                },
+                error: function () {
+                    layer.msg('删除失败', {icon: 2});
+                }
+            });
+        });
+    }
+
+    function initValidation() {
+        $('#jxsForm').validate({
+            rules: {
+                modalJxsCode: {
+                    required: true,
+                    maxlength: 50
+                },
+                modalJxsName: {
+                    required: true,
+                    maxlength: 100
+                },
+                modalContactPerson: {
+                    required: true,
+                    maxlength: 50
+                },
+                modalContactPhone: {
+                    required: true,
+                    maxlength: 20
+                },
+                modalSalesArea: {
+                    required: true
+                }
+            },
+            messages: {
+                modalJxsCode: {
+                    required: '请输入经销商编号',
+                    maxlength: '经销商编号最多50个字符'
+                },
+                modalJxsName: {
+                    required: '请输入经销商名称',
+                    maxlength: '经销商名称最多100个字符'
+                },
+                modalContactPerson: {
+                    required: '请输入联系人',
+                    maxlength: '联系人最多50个字符'
+                },
+                modalContactPhone: {
+                    required: '请输入联系方式',
+                    maxlength: '联系方式最多20个字符'
+                },
+                modalSalesArea: {
+                    required: '请选择销售地区'
+                }
+            },
+            errorElement: 'label',
+            errorClass: 'error',
+            errorPlacement: function (error, element) {
+                if (element.is(':checkbox') || element.is(':radio')) {
+                    error.appendTo(element.parent().parent());
+                } else if (element.hasClass('selectpicker')) {
+                    // 为selectpicker特殊处理错误信息位置
+                    error.insertAfter(element.next('.bootstrap-select'));
+                } else {
+                    error.insertAfter(element);
+                }
+            },
+            highlight: function (element, errorClass, validClass) {
+                if ($(element).hasClass('selectpicker')) {
+                    $(element).next('.bootstrap-select').find('.btn').addClass('error').removeClass('valid');
+                } else {
+                    $(element).addClass('error').removeClass('valid');
+                }
+            },
+            unhighlight: function (element, errorClass, validClass) {
+                if ($(element).hasClass('selectpicker')) {
+                    $(element).next('.bootstrap-select').find('.btn').removeClass('error').addClass('valid');
+                } else {
+                    $(element).removeClass('error').addClass('valid');
+                }
+            }
+        });
+    }
+
+    function initTable() {
+        table = $('#table').bootstrapTable({
+            method: 'get',
+            sortable: true,
+            toolbar: '#toolbar',    //工具按钮用哪个容器
+            striped: true,      //是否显示行间隔色
+            cache: false,      //是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
+            pagination: true,     //是否显示分页(*)
+            pageNumber: 1,      //初始化加载第一页,默认第一页
+            pageSize: 10,      //每页的记录行数(*)
+            pageList: [10, 25, 50, 100],  //可供选择的每页的行数(*)
+            url: '${ctx}/jxsNew/list',//这个接口需要处理bootstrap table传递的固定参数
+            queryParamsType: '', //默认值为 'limit' ,在默认情况下 传给服务端的参数为:offset,limit,sort
+            // 设置为 ''  在这种情况下传给服务器的参数为:pageSize,pageNumber
+
+            queryParams: queryParams,//前端调用服务时,会默认传递上边所述的参数,如果需要添加自定义参数,可以自定义一个函数返回请求参数
+            sidePagination: "server",   //分页方式:client客户端分页,server服务端分页(*)
+            strictSearch: false,
+            minimumCountColumns: 2,    //最少允许的列数
+            clickToSelect: true,    //是否启用点击选中行
+            searchOnEnterKey: true,
+            idField: "id",
+            responseHandler: function (res) {
+                // 这里假设接口返回的data就是我们需要的表格数据
+                return {
+                    total: res.total,  // 总记录数
+                    rows: res.records  // 数据列表
+                };
+            },
+            columns: [
+                {
+                    field: 'id',
+                    title: '序号',
+                    formatter: function (value, row, index) {
+                        // 使用this关键字访问表格实例
+                        var pageNumber = this.pageNumber || 1;
+                        var pageSize = this.pageSize || 10;
+                        return (pageNumber - 1) * pageSize + index + 1;
+                    },
+                    align: 'center',
+                },
+                {
+                    field: 'code',
+                    title: '经销商编号',
+                    align: 'center'
+                },
+                {
+                    field: 'jxs',
+                    title: '经销商名称',
+                    align: 'center',
+                    formatter: function (value, row, index) {
+                        return '<a href="javascript:void(0);" onclick="showJxsDetail(' + row.id + ')">' + value + '</a>';
+                    }
+                },
+                {
+                    field: 'contactName',
+                    title: '联系人',
+                    align: 'center'
+                },
+                {
+                    field: 'contactPhone',
+                    title: '联系方式',
+                    align: 'center'
+                },
+                {
+                    field: 'status',
+                    title: '状态',
+                    align: 'center',
+                    formatter: function (value) {
+                        return value === 1 ? '<span class="label label-primary">启用</span>' : '<span class="label label-default">禁用</span>';
+                    }
+                },
+                {
+                    field: 'id',
+                    title: '操作',
+                    align: 'center',
+                    formatter: function (value) {
+                        return '<button type="button" class="btn btn-primary btn-sm" onclick="showEditModal(' + value + ')">编辑</button> ' +
+                            '<button type="button" class="btn btn-danger btn-sm" onclick="deleteJxs(' + value + ')">删除</button>';
+                    },
+                    width: '150px'
+                }
+            ]
+        });
+    }
+
+    // 在initTable()函数之后添加以下代码
+
+    // 导出数据功能实现
+    function exportData() {
+        // 显示加载中提示
+        var loadingIndex = layer.load(1, {
+            shade: [0.2, '#000']
+        });
+
+        // 获取查询条件
+        const jxsCode = $.trim($("#jxsCode").val());
+        const jxsName = $.trim($("#jxsName").val());
+
+        // 构建查询参数
+        const params = {
+            jxsCode: jxsCode,
+            jxsName: jxsName
+        };
+
+        // 发送导出请求
+        $.ajax({
+            url: '${ctx}/jxsNew/exportJxsList',
+            type: 'POST',
+            data: JSON.stringify(params),
+            contentType: 'application/json',
+            success: function (res) {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+
+                if (res.code === 0) {
+                    // 获取导出URL并打开
+                    let exportUrl = res.data;
+                    if (exportUrl) {
+                        // 使用新窗口打开URL进行下载
+                        window.open(exportUrl, '_blank');
+                        layer.msg('导出成功,请在新窗口中查看下载文件', {icon: 1});
+                    } else {
+                        layer.msg('未获取到有效的导出URL', {icon: 5});
+                    }
+                } else {
+                    layer.msg(res.msg || '导出失败', {icon: 5});
+                }
+            },
+            error: function () {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+                layer.msg('导出请求失败', {icon: 5});
+            }
+        });
+    }
+
+    // 导入功能实现
+    function importData() {
+        const importHtml = `
+        <div style="padding: 20px;">
+            <div class="upload-area" style="border: 2px dashed #e0e0e0; padding: 30px; text-align: center; margin-bottom: 20px;">
+                <div style="margin-bottom: 15px;">
+                    <i class="fa fa-cloud-upload" style="font-size: 50px; color: #ccc;"></i>
+                </div>
+                <p style="margin-bottom: 10px;">将文件拖到此处,或 <span style="color: #0066cc; cursor: pointer;" id="clickUpload">点击上传</span></p>
+                <p style="font-size: 12px; color: #999;">仅允许导入xls、xlsx格式文件。<a href="https://hyscancode.oss-cn-hangzhou.aliyuncs.com/jinzaiimport/%E7%BB%8F%E9%94%80%E5%95%86%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF.xlsx" style="color: #0066cc;">下载模板</a></p>
+                <div id="selectedFileName" style="margin-top: 15px; font-size: 12px; color: #333; display: none; justify-content: center; align-items: center;"></div>
+                <input type="file" id="fileUpload" accept=".xlsx, .xls" style="display: none;">
+            </div>
+            <div style="text-align: center;">
+                <button type="button" class="btn btn-warning" style="margin-right: 10px;" onclick="uploadJxsFile()">确定</button>
+                <button type="button" class="btn btn-default" onclick="layer.closeAll()">取消</button>
+            </div>
+        </div>
+    `;
+
+        layer.open({
+            type: 1,
+            title: '导入经销商数据',
+            area: ['500px', '350px'],
+            content: importHtml
+        });
+
+        // 绑定点击上传事件
+        setTimeout(function () {
+            document.getElementById('clickUpload').addEventListener('click', function () {
+                document.getElementById('fileUpload').click();
+            });
+
+            // 监听文件选择事件
+            document.getElementById('fileUpload').addEventListener('change', function () {
+                const fileName = this.files[0]?.name;
+                const fileNameElement = document.getElementById('selectedFileName');
+                if (fileName) {
+                    // 创建包含文件名和关闭按钮的HTML
+                    fileNameElement.innerHTML =
+                        '<span>已选择文件: ' + fileName + '</span>' +
+                        '<span style="margin-left: 8px; cursor: pointer; color: #ff4444;" id="clearFileSelection">×</span>';
+                    fileNameElement.style.display = 'flex';
+
+                    // 绑定清除按钮事件
+                    document.getElementById('clearFileSelection').addEventListener('click', function () {
+                        // 清除文件选择
+                        const fileInput = document.getElementById('fileUpload');
+                        fileInput.value = '';
+
+                        // 隐藏文件名显示
+                        fileNameElement.textContent = '';
+                        fileNameElement.style.display = 'none';
+                    });
+                } else {
+                    fileNameElement.textContent = '';
+                    fileNameElement.style.display = 'none';
+                }
+            });
+
+            // 实现拖拽上传效果
+            const uploadArea = document.querySelector('.upload-area');
+            uploadArea.addEventListener('dragover', function (e) {
+                e.preventDefault();
+                this.style.borderColor = '#0066cc';
+                this.style.backgroundColor = '#f5f9ff';
+            });
+
+            uploadArea.addEventListener('dragleave', function () {
+                this.style.borderColor = '#e0e0e0';
+                this.style.backgroundColor = 'transparent';
+            });
+
+            uploadArea.addEventListener('drop', function (e) {
+                e.preventDefault();
+                this.style.borderColor = '#e0e0e0';
+                this.style.backgroundColor = 'transparent';
+
+                if (e.dataTransfer.files.length) {
+                    document.getElementById('fileUpload').files = e.dataTransfer.files;
+                    // 触发change事件以更新文件名显示
+                    const event = new Event('change');
+                    document.getElementById('fileUpload').dispatchEvent(event);
+                }
+            });
+        }, 100);
+    }
+
+    function uploadJxsFile() {
+        const fileInput = document.getElementById('fileUpload');
+        if (!fileInput.files || fileInput.files.length === 0) {
+            layer.msg('请选择要上传的文件', {icon: 2});
+            return;
+        }
+
+        const formData = new FormData();
+        formData.append('file', fileInput.files[0]);
+
+        $.ajax({
+            url: '${ctx}/jxsNew/importJxs',
+            type: 'POST',
+            data: formData,
+            processData: false,
+            contentType: false,
+            beforeSend: function () {
+                layer.load(1); // 显示加载动画
+            },
+            success: function (result) {
+                layer.closeAll('loading'); // 关闭加载动画
+                if (result.code === 0) {
+                    let successCount = result.data.successCount;
+                    let errorCount = result.data.errorCount;
+                    let errorFileUrl = result.data.errorFileUrl;
+
+                    // 检查是否有错误数据
+                    if (errorCount > 0) {
+                        // 创建错误信息HTML
+                        const errorHtml =
+                            '<div style="padding: 20px;">' +
+                            '<p style="text-align: center; margin-bottom: 15px;">导入结果:成功 ' + successCount + ' 条,失败 ' + errorCount + ' 条</p>' +
+                            '<div style="text-align: center; margin-bottom: 15px;">' +
+                            '<a href="' + errorFileUrl + '" class="btn btn-warning" target="_blank">下载错误数据</a>' +
+                            '</div>' +
+                            '</div>';
+
+                        layer.open({
+                            type: 1,
+                            title: '导入结果',
+                            area: ['400px', '250px'],
+                            content: errorHtml
+                        });
+                    } else {
+                        layer.msg('导入成功,共 ' + successCount + ' 条数据', {icon: 1});
+                    }
+
+                    // 刷新表格数据
+                    search();
+                } else {
+                    layer.msg(result.msg, {icon: 2});
+                }
+            },
+            error: function () {
+                layer.closeAll('loading'); // 关闭加载动画
+                layer.msg('导入失败,请重试', {icon: 2});
+            }
+        });
+    }
+
+    /**
+     * 显示产品详情
+     */
+    function showJxsDetail(jxsId) {
+        // 显示加载中提示
+        var loadingIndex = layer.load(1, {
+            shade: [0.2, '#000']
+        });
+
+        // 发送请求获取产品详情
+        $.ajax({
+            url: '${ctx}/jxsNew/getById',
+            type: 'GET',
+            data: {id: jxsId},
+            dataType: 'json',
+            success: function (data) {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+
+                if (data.code === 0) {
+                    var jxs = data.data;
+
+                    // 填充详情数据
+                    $('#detailJxsCode').text(jxs.code || '');
+                    $('#detailJxsName').text(jxs.jxs || '');
+                    $('#detailContactName').text(jxs.contactName || '');
+                    $('#detailContactPhone').text(jxs.contactPhone || '');
+                    $('#detailAreas').text(jxs.dealerAreas || '');
+                    $('#detailCreateUser').text(jxs.createUser || '');
+                    $('#detailCreateTime').text(jxs.createTime || '');
+
+                    // 状态转换
+                    if (jxs.status === 1) {
+                        $('#detailStatus').html('<span class="label label-success">正常</span>');
+                    } else if (jxs.status === 0) {
+                        $('#detailStatus').html('<span class="label label-default">禁用</span>');
+                    } else {
+                        $('#detailStatus').text('');
+                    }
+                    // 显示模态框
+                    $('#jxsDetailModal').modal('show');
+                } else {
+                    layer.msg(data.msg, {icon: 5});
+                }
+            },
+            error: function () {
+                // 关闭加载提示
+                layer.close(loadingIndex);
+                layer.msg('获取产品详情失败', {icon: 5});
+            }
+        });
+    }
+</script>
+</html>

Разлика између датотеке није приказан због своје велике величине
+ 1002 - 0
src/main/webapp/page/jinzai/productList.jsp