diff --git a/client/pom.xml b/client/pom.xml new file mode 100644 index 00000000..8c99599a --- /dev/null +++ b/client/pom.xml @@ -0,0 +1,126 @@ + + + 4.0.0 + + com.small + client + v1 + jar + + org.springframework.boot + spring-boot-starter-parent + 2.3.0.RELEASE + + + + + UTF-8 + UTF-8 + 8 + 8 + 5.8.20 + + + + org.springframework.boot + spring-boot-starter-web + + + org.apache.commons + commons-text + 1.10.0 + + + org.projectlombok + lombok + + + io.springfox + springfox-swagger2 + 2.9.2 + + + + com.microsoft.sqlserver + mssql-jdbc + 9.4.1.jre8 + + + ch.qos.logback + logback-classic + + + + cn.hutool + hutool-all + ${hutool.version} + + + + + + + + ali-maven + https://maven.aliyun.com/repository/central + + true + + + true + always + fail + + + + repo.maven.apache.org + https://repo.maven.apache.org/maven2 + + true + + + true + always + fail + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + + + + repackage + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + \ No newline at end of file diff --git a/client/readme.txt b/client/readme.txt new file mode 100644 index 00000000..7bcd7ded --- /dev/null +++ b/client/readme.txt @@ -0,0 +1,21 @@ +本系统主要安装在客户端 +主要有以下几个功能 + +第一阶段 +1、通过http获取远程数据小发服务配置,基础数据包括主要包括数据库地址ip,数据库名称,数据库密码,以及同步定时时间 + +2.采集本地数据库,通过多线程调用同步接口,同步商品,种类,会员 + +第二阶段 +由于系统的数据同步存在性能瓶颈,需要使用文件传输的方式同步数据, +文件采用分页形式同步数据,每一页使用一个文件,服务器解析文件采用多线程解析方式解析 + + + +打包功能更,需要写一个shell脚本自动打包放到服务器供给下载和java的jkd安装包,这些下载放到后端的网页端,暴露下载地址 + +todo +1、通过http获取dataInfo没有写 +2、文件传输没有写 +3.商品同步没有写 +4.商品分类同步没有写 diff --git a/client/src/main/java/com/small/client/Cache/CommonCache.java b/client/src/main/java/com/small/client/Cache/CommonCache.java new file mode 100644 index 00000000..d90da612 --- /dev/null +++ b/client/src/main/java/com/small/client/Cache/CommonCache.java @@ -0,0 +1,48 @@ +package com.small.client.Cache; + +import cn.hutool.cache.Cache; +import cn.hutool.cache.impl.FIFOCache; +import cn.hutool.core.date.DateUnit; +import com.small.client.dto.BrandModel; +import com.small.client.dto.SpecPriceDto; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 用于本地缓存 + */ +@Component +public class CommonCache { + public final static String CACHE_CATEGROY = "CACHE_CATEGROY";//分类缓存 + + private Cache cache =new FIFOCache<>(20000); + + private Cache> spriceCache =new FIFOCache<>(20); + + private Cache> brandCahce =new FIFOCache<>(20); + + public void put(String key, String value) { + cache.put(key, value, DateUnit.MINUTE.getMillis()*20); + } + + public String get(String key) { + return cache.get(key); + } + + public void putSpecPrice(String key, List value) { + spriceCache.put(key, value, DateUnit.MINUTE.getMillis()*20); + } + + public List getSpecPrice(String key) { + return spriceCache.get(key); + } + + public List getBrandCahce(String key) { + return brandCahce.get(key); + } + + public void setBrandCahce(String key, List value) { + brandCahce.put(key, value, DateUnit.MINUTE.getMillis()*20); + } +} diff --git a/client/src/main/java/com/small/client/ClientApplication.java b/client/src/main/java/com/small/client/ClientApplication.java new file mode 100644 index 00000000..1a61fead --- /dev/null +++ b/client/src/main/java/com/small/client/ClientApplication.java @@ -0,0 +1,27 @@ +package com.small.client; + +import com.small.client.Utils.JarPathUtil; +import com.small.client.service.SxDataService; +import com.small.client.service.WebClientService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +import javax.annotation.Resource; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +@SpringBootApplication +@Slf4j +public class ClientApplication{ + public static void main(String[] args) { + SpringApplication.run(ClientApplication.class, args); + } + +} \ No newline at end of file diff --git a/client/src/main/java/com/small/client/Schedule/DynamicTaskScheduler.java b/client/src/main/java/com/small/client/Schedule/DynamicTaskScheduler.java new file mode 100644 index 00000000..56d0c47c --- /dev/null +++ b/client/src/main/java/com/small/client/Schedule/DynamicTaskScheduler.java @@ -0,0 +1,103 @@ +package com.small.client.Schedule; + +import com.small.client.dto.CommentModel; +import com.small.client.dto.DataBaseInfo; +import com.small.client.service.SxDataService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.time.Duration; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; + +@Service +@Slf4j +public class DynamicTaskScheduler { + private final TaskScheduler taskScheduler; + private final SxDataService sxDataService; + private final Map> scheduledTasks = new ConcurrentHashMap<>(); + + private boolean isRuning =false; + + @Autowired + public DynamicTaskScheduler(TaskScheduler taskScheduler, SxDataService sxDataService) { + this.taskScheduler = taskScheduler; + this.sxDataService = sxDataService; + } + + @PostConstruct + public void initTasks() { + refreshTasks(); + // 每5分钟检查一次数据库更新 + taskScheduler.scheduleAtFixedRate(this::refreshTasks, Duration.ofHours(1)); + } + + public void refreshTasks() { + if(!isRuning){ + sxDataService.checkForUpdates();//检查app更新 + } + CommentModel commentModel =sxDataService.getCommentModel(); + DataBaseInfo enabledTask = sxDataService.getDataBaseInfo(commentModel); + + List enabledTasks=new ArrayList<>(); + enabledTasks.add(enabledTask); + // 移除已禁用或删除的任务 + scheduledTasks.keySet().removeIf(taskKey -> + enabledTasks.stream().noneMatch(task -> task.getDataBaseName().equals(taskKey))); + + // 新增或更新任务 + enabledTasks.forEach(task -> { + if (!scheduledTasks.containsKey(task.getDataBaseName()) || + isCronModified(task)) { + cancelExistingTask(task.getDataBaseName()); + scheduleTask(task,commentModel); + } + }); + } + + private void scheduleTask(DataBaseInfo task, CommentModel commentModel) { + ScheduledFuture future = taskScheduler.schedule( + () -> executeTask(task.getDataBaseName(),commentModel), + new CronTrigger(task.getCronExpression()) + ); + scheduledTasks.put(task.getDataBaseName(), future); + } + + /** + * 业务逻辑执行 + * @param taskKey + */ + private void executeTask(String taskKey, CommentModel commentModel) { + isRuning=true; + log.info("execute task key:{}, commentModel:{}", taskKey, commentModel); + if(commentModel==null){ + commentModel =sxDataService.getCommentModel(); + } + if(StringUtils.isEmpty(commentModel.getSyncTime())){ + commentModel =sxDataService.getCommentModel(); + } + DataBaseInfo dataBaseInfo=sxDataService.getDataBaseInfo(commentModel); + sxDataService.SyncBranchList(dataBaseInfo,commentModel); + sxDataService.SyncCategory(dataBaseInfo,commentModel); + sxDataService.SyncGoods(dataBaseInfo,commentModel);//todo 暂时同步全部的商品如果后期修改,需要增加服务器的字段test + sxDataService.SyncVipList(dataBaseInfo,commentModel); + isRuning=false; + } + + private void cancelExistingTask(String taskKey) { + Optional.ofNullable(scheduledTasks.remove(taskKey)) + .ifPresent(future -> future.cancel(false)); + } + + private boolean isCronModified(DataBaseInfo newTask) { + DataBaseInfo dataBaseInfo= sxDataService.getDataBaseInfo(sxDataService.getCommentModel()); + return scheduledTasks.containsKey(newTask.getDataBaseName()) && + !dataBaseInfo.getCronExpression().equals(newTask.getCronExpression()); + } +} diff --git a/client/src/main/java/com/small/client/Utils/CommonUtil.java b/client/src/main/java/com/small/client/Utils/CommonUtil.java new file mode 100644 index 00000000..4f8db7e3 --- /dev/null +++ b/client/src/main/java/com/small/client/Utils/CommonUtil.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.small.client.Utils; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.http.HttpUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; + +public class CommonUtil { + + private final static String apiUrl = "http://4ei8850868ux.vicp.fun"; + + public static JSONObject sendPostRequestToSiXun(String urlPath, JSONObject params) { + String resp = HttpUtil.post(apiUrl + urlPath, params.toString()); + if (StrUtil.isBlank(resp)) { + return null; + } + + JSONObject respObj = JSONUtil.parseObj(resp); + + return respObj; + } + + /** + * 根据总条数和分页大小,求页数 + * + * @param total + * @param pageSize + * @return + */ + public static Integer getPagesCount(Integer total, Integer pageSize) { + if (total == null || pageSize == null || pageSize <= 0 || total <= 0) { + return 0; + } + + int pagesCount = 0; + pagesCount = total / pageSize; + + if (total % pageSize > 0) { + // 有余数 + pagesCount++; + } else { + if (pagesCount == 0) { + pagesCount = 1; + } + } + + return pagesCount; + } + + /** + * 接口是否成功执行返回 + * + * @param jsonObject + * @return + */ + public static Boolean isSuccess(JSONObject jsonObject) { + if (jsonObject == null) { + return false; + } + + return jsonObject.get("code") != null && jsonObject.getStr("code").equals("0"); + } + + /** + * 接口是否成功执行返回 + * + * @param jsonObject + * @return + */ + public static Boolean hasSuccessData(JSONObject jsonObject) { + if (jsonObject == null) { + return false; + } + + return jsonObject.get("code") != null && jsonObject.getStr("code").equals("0") && jsonObject.get("data") != null; + } + + /** + * 通过json节点表达式,获取节点json字符串,注:驼峰命名改成下划线命名 + * + * @param jsonObject + * @param expression json 节点表达式比如: data.list, msg, code + * @return + */ + public static String toUnderlineJson(JSONObject jsonObject, String expression) { + return StrUtil.toUnderlineCase(jsonObject.getByPath(expression, String.class)); + } + + +} diff --git a/client/src/main/java/com/small/client/Utils/CryptoUtils.java b/client/src/main/java/com/small/client/Utils/CryptoUtils.java new file mode 100644 index 00000000..6c99f73d --- /dev/null +++ b/client/src/main/java/com/small/client/Utils/CryptoUtils.java @@ -0,0 +1,110 @@ +package com.small.client.Utils; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +public class CryptoUtils { + private static final String ALGORITHM = "AES"; + private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding"; + private static final String SECRET_KEY = "9f823ea6ab22785caf040e4cc3930619"; // 必须16/24/32字符 + + private static final String HASH_ALGORITHM_KEY = "appKey=a&sign=b&storeId=c"; + + /** + * 打包并加密字段 + */ + public static String packAndEncrypt(String appKey, String sign, String storeId) throws Exception { + String combined = String.format("appKey=%s&sign=%s&storeId=%s", appKey, sign, storeId); + return encrypt(combined); + } + + /** + * 32位字符串生成 + * @param input + * @return + * @throws NoSuchAlgorithmException + */ + public static String generate32CharMD5(String input) throws NoSuchAlgorithmException { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] hashBytes = md.digest(input.getBytes()); + + StringBuilder hexString = new StringBuilder(); + for (byte b : hashBytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + + return hexString.toString(); + } + + /** + * 解密并解包字段 + */ + public static Map decryptAndUnpack(String encryptedData) throws Exception { + String decrypted = decrypt(encryptedData); + Map result = new HashMap<>(); + String[] pairs = decrypted.split("&"); + for (String pair : pairs) { + String[] keyValue = pair.split("="); + if (keyValue.length == 2) { + result.put(keyValue[0], keyValue[1]); + } + } + return result; + } + + /** + * 加密 + * @param value + * @return + * @throws Exception + */ + private static String encrypt(String value) throws Exception { + SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM); + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + byte[] encryptedBytes = cipher.doFinal(value.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(encryptedBytes); + } + + /** + * 解密 + * @param encryptedValue + * @return + * @throws Exception + */ + private static String decrypt(String encryptedValue) throws Exception { + SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM); + Cipher cipher = Cipher.getInstance(TRANSFORMATION); + cipher.init(Cipher.DECRYPT_MODE, secretKey); + byte[] decodedBytes = Base64.getDecoder().decode(encryptedValue); + byte[] decryptedBytes = cipher.doFinal(decodedBytes); + return new String(decryptedBytes, StandardCharsets.UTF_8); + } + + + // 示例用法 + public static void main(String[] args) throws Exception { + + String appKey = "d68397c4fb671bc024e24e1964b067cc35388818"; + String sign = "d68397c4fb671bc024e24e1964b067cc35388818"; + String storeId = "1"; + + // 打包加密 + String encrypted = packAndEncrypt(appKey, sign, storeId); + System.out.println("加密结果: " + encrypted); + + // 解密解包 + Map result = decryptAndUnpack(encrypted); + System.out.println("解密结果: " + result); + } +} diff --git a/client/src/main/java/com/small/client/Utils/FileUtils.java b/client/src/main/java/com/small/client/Utils/FileUtils.java new file mode 100644 index 00000000..b865a8da --- /dev/null +++ b/client/src/main/java/com/small/client/Utils/FileUtils.java @@ -0,0 +1,176 @@ +package com.small.client.Utils; + + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.Calendar; +import java.util.Date; + +@Slf4j +public class FileUtils { + + public static final String pathSeparator = System.getProperty("file.separator"); + public static final String FOLDER = System.getProperty("user.home") + pathSeparator+"uploaded"+pathSeparator; + public static final String GOODS = pathSeparator+"goods"+pathSeparator;//商品 + public static final String CATEGORY= pathSeparator+ "category"+pathSeparator;//分类 + public static final String BRAND = pathSeparator+"brand/"+pathSeparator;//品牌 + public static final String MEMBER= pathSeparator+"member"+pathSeparator;//会员 + + public static final String CLIENTSTALLPATH = System.getProperty("user.home") + pathSeparator+"cientStorePath"+pathSeparator; + + public static final String REFLESHDATE="refleshdate.txt"; + public static final String PRIMARYKEY="primaryKey.txt"; + + public static final String GOODS_TYPE = "goods";//商品 + public static final String CATEGORY_TYPE= "category";//分类 + public static final String BRAND_TYPE = "brand";//品牌 + public static final String MEMBER_TYPE= "member";//会员 + + public static final String okEnd = "ok";//后缀 + public static final String txtEnd = "txt";//后缀 + + public static String fileFormat = "%s_%s.%s";//good_1 + + public static String getSyncTypeFlag(String syncType){ + Calendar calendar=Calendar.getInstance(); + int year=calendar.get(Calendar.YEAR); + int month=calendar.get(Calendar.MONTH)+1; + int date=calendar.get(Calendar.DAY_OF_MONTH); + String result =FOLDER; + switch (syncType){ + case "1": + result=GOODS; + break; + case "2": + result=CATEGORY; + break; + case "3": + result=BRAND; + break; + case "4": + result=MEMBER; + break; + default: + break; + } + return result+year+pathSeparator+month+pathSeparator+date+pathSeparator; + } + + /** + * 创建文件 + * @param syncType + * @param page + * @return + */ + public File createFile(String syncType,Integer page){ + String path= getSyncTypeFlag(syncType+pathSeparator+page+pathSeparator); + File file=new File(path); + if(!file.exists()){ + file.mkdirs(); + } + return file; + } + + /** + * 创建文件 + * @param path + * @return + */ + public File createFile(String path){ + File file=new File(path); + if(!file.exists()){ + file.mkdirs(); + } + return file; + } + + /** + * 文件写入 + * @param filePath + */ + public void writeFile(String filePath,String fileName,String content){ + try { + FileWriter writer = new FileWriter(filePath+pathSeparator+fileName); + writer.write(content); + writer.close(); + log.info("文件写入成功!"); + } catch (IOException e) { + log.info("文件写入失败:{}", e.getMessage()); + } + } + + /** + * 根据类型获取文件名称 + * @param syncType + * @param page + * @return + */ + public String getFileName(String syncType ,Integer page,String endFix){ + String result=""; + switch (syncType){ + case "1": + result=GOODS_TYPE; + break; + case "2": + result=CATEGORY_TYPE; + break; + case "3": + result=BRAND_TYPE; + break; + case "4": + result=MEMBER_TYPE; + break; + default: + break; + } + return String.format(fileFormat, result,page,endFix); + } + + /** + * 创建文件 + * @param folderPath + * @param filePath + */ + public static void createFolderAndFileUsingFile(String folderPath, String filePath) { + File folder = new File(folderPath); + if (!folder.exists()) { + folder.mkdir(); + } + + File file = new File(filePath); + try { + if (!file.exists()) { + file.createNewFile(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + public static void copyFile(String srcFile, String destFile) { + String path= JarPathUtil.getRuntimePath(); + Path sourceFile = Paths.get(srcFile); + Path targetDir =Paths.get(destFile); + try { + Files.copy(sourceFile, targetDir.resolve(sourceFile.getFileName()), + StandardCopyOption.REPLACE_EXISTING); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public static void main(String[] args) { + FileUtils fileUtils= new FileUtils(); + File file=fileUtils.createFile("1",1); + System.out.printf("--"+file.getAbsoluteFile()); + fileUtils.writeFile(file.getAbsolutePath(),fileUtils.getFileName("1",2,txtEnd),"456"); + } + +} diff --git a/client/src/main/java/com/small/client/Utils/HttpUtils.java b/client/src/main/java/com/small/client/Utils/HttpUtils.java new file mode 100644 index 00000000..5bf17681 --- /dev/null +++ b/client/src/main/java/com/small/client/Utils/HttpUtils.java @@ -0,0 +1,107 @@ +package com.small.client.Utils; + +import cn.hutool.json.JSON; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.small.client.dto.StoreDbConfig; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.util.Map; + +@Slf4j +public class HttpUtils { + + public static final String SUCCESSCODE="0";//上传文件 + + public static final String URL_UPLOUP="/shop/sync/third/uploudSxData";//上传文件 + + + public static final String URL_SYNC_CATEGORY="/shop/sync/third/goods/category";//商品分类数据同步 + + public static final String URL_SYNC_BRAND="/shop/sync/third/goods/brand";//商品品牌数据同步 + + public static final String URL_SYNC_GOODS="/shop/sync/third/goods";//商品数据同步 + + public static final String URL_SYNC_MEMBER="/shop/sync/third/member"; + + public static final String URL_SYNC_GOODS_READ="/shop/sync/third/readSxData";//商品数据同步 + + public static final String URL_SYNC_GET_APPSIGN="/shop/sync/third/getAppSign";//获取密文 + + public static final String URL_SYNC_GET_DOWNCLIENTJAR="/shop/sync/app/downClientJar";//文件下载 + + public static final String URL_SYNC_GET_STOREdBCONFIG="/shop/sync/third/getStoreDbConfig";//文件下载 + + public static String postData(RestTemplate restTemplate, String url,Object modelObject){ + // 创建表单参数 +// MultiValueMap map = new LinkedMultiValueMap<>(); +// map.add("key1", "value1"); +// map.add("key2", "value2"); + + // 设置Content-Type为application/x-www-form-urlencoded + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + log.info(modelObject.toString()); + HttpEntity request = new HttpEntity<>(modelObject, headers); + + // 发送POST请求 + JSONObject jsonObject = restTemplate.postForObject(url, request, JSONObject.class); + assert jsonObject != null; + log.info(jsonObject.toString()); + return jsonObject.getStr("error_code"); + } + + public static String postData(RestTemplate restTemplate, String url,Object modelObject,String contentName){ + // 创建表单参数 +// MultiValueMap map = new LinkedMultiValueMap<>(); +// map.add("key1", "value1"); +// map.add("key2", "value2"); + + // 设置Content-Type为application/x-www-form-urlencoded + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + log.info(modelObject.toString()); + HttpEntity request = new HttpEntity<>(modelObject, headers); + + // 发送POST请求 + JSONObject jsonObject = restTemplate.postForObject(url, request, JSONObject.class); + assert jsonObject != null; + log.info(jsonObject.toString()); + if("OK".equals(jsonObject.get("resultCode"))){ + return jsonObject.getStr(contentName); + } + return null; + } + + public static StoreDbConfig postDataGetConfig(RestTemplate restTemplate, String url, Object modelObject){ + // 创建表单参数 +// MultiValueMap map = new LinkedMultiValueMap<>(); +// map.add("key1", "value1"); +// map.add("key2", "value2"); + + // 设置Content-Type为application/x-www-form-urlencoded + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + log.info(modelObject.toString()); + HttpEntity request = new HttpEntity<>(modelObject, headers); + + // 发送POST请求 + JSONObject jsonObject = restTemplate.postForObject(url, request, JSONObject.class); + assert jsonObject != null; + log.info(jsonObject.toString()); + if(0==jsonObject.getInt("error_code")){ + JSONObject object= jsonObject.getJSONObject("result"); + if(null!=object){ + return JSONUtil.toBean(object,StoreDbConfig.class); + } + } + return null; + } + +} diff --git a/client/src/main/java/com/small/client/Utils/JarPathUtil.java b/client/src/main/java/com/small/client/Utils/JarPathUtil.java new file mode 100644 index 00000000..78bc506f --- /dev/null +++ b/client/src/main/java/com/small/client/Utils/JarPathUtil.java @@ -0,0 +1,70 @@ +package com.small.client.Utils; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +@Slf4j +public class JarPathUtil { + /** + * 更健壮的获取JAR路径方法 + */ + public static String getJarPath() { + try { + // 获取当前类的URI + String jarPath = JarPathUtil.class + .getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI() + .getPath(); + + // 处理Windows路径问题 + if (jarPath.startsWith("/") && System.getProperty("os.name").contains("Windows")) { + jarPath = jarPath.substring(1); + } + + return new File(jarPath).getAbsolutePath(); + } catch (URISyntaxException e) { + throw new RuntimeException("无法解析JAR文件URI", e); + } + } + + /** + * 使用NIO获取JAR所在目录 + */ + public static String getJarParentPath() { + try { + Path path = Paths.get(JarPathUtil.class.getProtectionDomain() + .getCodeSource() + .getLocation() + .toURI()); + return path.getParent().toString(); + } catch (URISyntaxException e) { + throw new RuntimeException("无法解析JAR文件URI", e); + } + } + public static String getRuntimePath() { + URL location = JarPathUtil.class.getProtectionDomain() + .getCodeSource() + .getLocation(); + String path = location.getPath(); + + // 判断是否在IDE中运行(class文件) + if (path.endsWith(".jar")) { + // JAR运行模式 + return new File(path).getParent(); + } else { + // IDE运行模式,返回项目目录 + return new File("").getAbsolutePath(); + } + } + + public static void main(String[] args) { + log.info(getRuntimePath()); + } +} diff --git a/client/src/main/java/com/small/client/comment/DicEnum.java b/client/src/main/java/com/small/client/comment/DicEnum.java new file mode 100644 index 00000000..a88f1031 --- /dev/null +++ b/client/src/main/java/com/small/client/comment/DicEnum.java @@ -0,0 +1,30 @@ +package com.small.client.comment; + +import lombok.Getter; + +public enum DicEnum { + //1-品牌,2-分类,3-商品,4-会员 + SYNCTYPE_1("1","品牌","syncType","同步类型"), + SYNCTYPE_2("2","分类","syncType","同步类型"), + SYNCTYPE_3("3","商品","syncType","同步类型"), + SYNCTYPE_4("4","会员","syncType","同步类型"), + ; + + @Getter + private String code; + @Getter + private String name; + @Getter + private String dicType; + @Getter + private String description; + + DicEnum(String code, String name, String dicType, String description) { + this.code = code; + this.name = name; + this.dicType = dicType; + this.description = description; + } + + +} diff --git a/client/src/main/java/com/small/client/comment/UrlComment.java b/client/src/main/java/com/small/client/comment/UrlComment.java new file mode 100644 index 00000000..2c02301c --- /dev/null +++ b/client/src/main/java/com/small/client/comment/UrlComment.java @@ -0,0 +1,11 @@ +package com.small.client.comment; + +public class UrlComment { + + public static String url="";//获取shop的数据库基本信息 todo + + public static String UrlSynShop="";//商品同步接口 + public static String UrlSynCategory="";//商品种类同步接口 + + public static String UrlSynProduct=""; +} diff --git a/client/src/main/java/com/small/client/config/ClientConfig.java b/client/src/main/java/com/small/client/config/ClientConfig.java new file mode 100644 index 00000000..c062e31c --- /dev/null +++ b/client/src/main/java/com/small/client/config/ClientConfig.java @@ -0,0 +1,14 @@ +package com.small.client.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class ClientConfig { + + @Bean + public RestTemplate restTemplate() { + return new RestTemplate(); + } +} diff --git a/client/src/main/java/com/small/client/config/TaskConfig.java b/client/src/main/java/com/small/client/config/TaskConfig.java new file mode 100644 index 00000000..a4f41f72 --- /dev/null +++ b/client/src/main/java/com/small/client/config/TaskConfig.java @@ -0,0 +1,18 @@ +package com.small.client.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.TaskScheduler; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler; + +import java.util.concurrent.Executors; + +@Configuration +@EnableScheduling +public class TaskConfig { + @Bean + public TaskScheduler taskScheduler() { + return new ConcurrentTaskScheduler(Executors.newScheduledThreadPool(10)); // 使用默认线程池 + } +} diff --git a/client/src/main/java/com/small/client/controller/WebController.java b/client/src/main/java/com/small/client/controller/WebController.java new file mode 100644 index 00000000..737b0be9 --- /dev/null +++ b/client/src/main/java/com/small/client/controller/WebController.java @@ -0,0 +1,79 @@ +package com.small.client.controller; + +import com.small.client.Utils.HttpUtils; +import com.small.client.dto.DataBaseInfo; +import com.small.client.dto.SyncGoodsSearchModel; +import com.small.client.service.SxDataService; +import com.small.client.service.WebClientService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/client") +@Slf4j +public class WebController { + @Autowired + private WebClientService webClientService; + @Autowired + private SxDataService sxDataService; + + @RequestMapping("/upload") + public void upload(){ + System.out.println("upload"); + //webClientService.uploudSxData(); + } + + @RequestMapping("/synBrand") + public void synBrand(){ + log.info("synBrand"); + sxDataService.getAppSign(); + + sxDataService.SyncBranchList(new DataBaseInfo(),sxDataService.getCommentModel()); + } + + @RequestMapping("/syncCategory") + public void syncCategory(){ + log.info("syncCategory"); + sxDataService.getAppSign(); + sxDataService.SyncCategory(new DataBaseInfo(),sxDataService.getCommentModel()); + } + + @RequestMapping("/syncGoods") + public void syncGoods(){ + log.info("syncGoods"); + sxDataService.getAppSign(); + sxDataService.SyncGoods(new DataBaseInfo(),sxDataService.getCommentModel()); + } + + @RequestMapping("/synvip") + public void synvip(){ + log.info("synvip"); + sxDataService.getAppSign(); + sxDataService.SyncVipList(new DataBaseInfo(),sxDataService.getCommentModel()); + } + + @RequestMapping("/getAppSign") + public void getAppSign(){ + log.info("getAppSign"); + sxDataService.getAppSign(); + } + + @RequestMapping("/downLoadClient") + public void downLoadClient(){ + log.info("downLoadClient"); + sxDataService.downLoadClient(); + } + + @RequestMapping("/udpateAndStart") + public void updateAndStart(){ + sxDataService.checkForUpdates(); + } + + @RequestMapping("/getDataBaseInfo") + public void getDataBaseInfo(){ + sxDataService.getDataBaseInfo(sxDataService.getCommentModel()); + } + +} diff --git a/client/src/main/java/com/small/client/dao/BaseDao.java b/client/src/main/java/com/small/client/dao/BaseDao.java new file mode 100644 index 00000000..d9d3e948 --- /dev/null +++ b/client/src/main/java/com/small/client/dao/BaseDao.java @@ -0,0 +1,246 @@ +package com.small.client.dao; + +import com.microsoft.sqlserver.jdbc.SQLServerDataSource; +import com.microsoft.sqlserver.jdbc.SQLServerException; + +import com.small.client.dto.ResultDto; +import lombok.extern.slf4j.Slf4j; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +@Slf4j +public class BaseDao { + + private final static String DEFAULT_IP="127.0.0.1"; + private final static String DEFAULT_DATABASE="hbposev9"; + private final static String DEFAULT_USERNAME="sa"; + private final static String DEFAULT_PWD="123456"; + private final static int PortNumber=1433; + private final static int LoginTimeout=10; + /** + * + * 动态获取数据库连接 + * @param ip 数据库ip+ + * @param username 用户名 + * @param password 密码 todo 需要加密 + * @param dataBaseName 数据库名称 + * @return + */ + public Connection getConnection(String ip, String username, String password,Integer port, String dataBaseName){ + Connection conn=null; + SQLServerDataSource sqlServerDataSource=new SQLServerDataSource(); + sqlServerDataSource.setDatabaseName(dataBaseName==null?DEFAULT_DATABASE:dataBaseName); + sqlServerDataSource.setServerName(ip==null?DEFAULT_IP:ip); + sqlServerDataSource.setPortNumber(port==null?PortNumber:port); + sqlServerDataSource.setLoginTimeout(LoginTimeout); + sqlServerDataSource.setPassword(password==null?DEFAULT_PWD:password); + sqlServerDataSource.setUser(username==null?DEFAULT_USERNAME:username); + try { + conn=sqlServerDataSource.getConnection(); + } catch (SQLServerException e) { + log.info("数据库连接异常方法{}异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.getConnection",e.getMessage()); + throw new RuntimeException(e); + } + + return conn; + } + + /** + * 关闭数据库连接 + * @param conn + */ + public void Close(Connection conn){ + if(conn!=null){ + try { + conn.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + /** + * 返回游标和连接 减少服务器的占用内存 + * @param ip + * @param username + * @param password + * @param dataBaseName + * @return ResultDto + */ + public ResultDto baseFindList(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String where){ + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + String sql="select * from %s %s"; + sql=String.format(sql, table,where); + ResultDto resultDto=new ResultDto(); + ResultSet rs=null; + log.info(sql); + try { + PreparedStatement ps= connection.prepareStatement(sql); + rs = ps.executeQuery(); + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.baseFindList",e.getMessage()); + throw new RuntimeException(e); + } + resultDto.setResultSet(rs); + resultDto.setConnection(connection); + return resultDto; + + } + + /** + * 带分页数据 + * @param ip + * @param username + * @param password + * @param dataBaseName + * @param table + * @return + */ + public ResultDto baseFindListPage(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String orderColumn, int pageNo, int pageSize,String where){ + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + int start=(pageNo-1)*pageSize+1; + int end=pageNo*pageSize; + String sql=" select * from( " + + " select ROW_NUMBER() OVER(ORDER BY %s) as rowId,* from %s %s" + + " ) as r where rowId between %s and %s"; + sql=String.format(sql, orderColumn,table,where,start,end); + log.info(sql); + ResultDto resultDto=new ResultDto(); + ResultSet rs=null; + try { + PreparedStatement ps= connection.prepareStatement(sql); + rs = ps.executeQuery(); + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.baseFindListPage",e.getMessage()); + throw new RuntimeException(e); + } + resultDto.setResultSet(rs); + resultDto.setConnection(connection); + return resultDto; + } + + public Integer getBaseTotal(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String where){ + int total=0; + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + try { + String sql="select count(*) from %s %s"; + sql=String.format(sql, table,where); + log.info(sql); + PreparedStatement ps= connection.prepareStatement(sql); + ResultSet rs=ps.executeQuery(); + while (rs.next()){ + total=rs.getInt(1); + } + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.getBaseTotal",e.getMessage()); + throw new RuntimeException(e); + } + finally { + try { + connection.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return total; + } + + + public Integer getBaseJoinTotal(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String joinTable,String onLeft,String onRight,String orderColumn,String rightSelect,String where){ + int total=0; + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + try { + String sql=" select COUNT(*) from( " + + " select ROW_NUMBER() OVER(ORDER BY b.%s) as rowId,b.*,%s from %s b left join %s t on b.%s=t.%s %s" + + " ) r"; + sql=String.format(sql, orderColumn,rightSelect,table,joinTable,onLeft,onRight,where); + log.info(sql); + PreparedStatement ps= connection.prepareStatement(sql); + ResultSet rs=ps.executeQuery(); + while (rs.next()){ + total=rs.getInt(1); + } + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.getBaseTotal",e.getMessage()); + throw new RuntimeException(e); + } + finally { + try { + connection.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return total; + } + + + /** + * 带分页数据关联分页查询 + * @param ip + * @param username + * @param password + * @param dataBaseName + * @param table + * @return + */ + public ResultDto baseFindListJoinPage(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String joinTable,String onLeft,String onRight,String orderColumn,String rightSelect, int pageNo, int pageSize,String where){ + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + int start=(pageNo-1)*pageSize+1; + int end=pageNo*pageSize; + String sql=" select * from( " + + " select ROW_NUMBER() OVER(ORDER BY b.%s) as rowId,b.*,%s from %s b left join %s t on b.%s=t.%s %s" + + " ) as r where rowId between %s and %s"; + sql=String.format(sql, orderColumn,rightSelect,table,joinTable,onLeft,onRight,where,start,end); + log.info(sql); + ResultDto resultDto=new ResultDto(); + ResultSet rs=null; + try { + PreparedStatement ps= connection.prepareStatement(sql); + rs = ps.executeQuery(); + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.baseFindListJoinPage",e.getMessage()); + throw new RuntimeException(e); + } + resultDto.setResultSet(rs); + resultDto.setConnection(connection); + return resultDto; + } + + /** + * + * @param ip + * @param username + * @param password + * @param dataBaseName + * @param table + * @param joinTable + * @param onLeft + * @param onRight + * @param rightSelect + * @param where + * @return + */ + public ResultDto baseFindListJoin(String ip, String username, String password,Integer portNumber, String dataBaseName, String table,String joinTable,String onLeft,String onRight,String rightSelect, String where){ + Connection connection=getConnection(ip,username,password,portNumber,dataBaseName); + String sql= "select b.*,%s from %s b left join %s t on b.%s=t.%s %s " ; + sql=String.format(sql,rightSelect,table,joinTable,onLeft,onRight,where); + log.info(sql); + ResultDto resultDto=new ResultDto(); + ResultSet rs=null; + try { + PreparedStatement ps= connection.prepareStatement(sql); + rs = ps.executeQuery(); + } catch (SQLException e) { + log.info("数据库查询异常方法{},异常信息{}","com.suisung.mall.shop.sixun.dao.BaseDao.baseFindListJoin",e.getMessage()); + throw new RuntimeException(e); + } + resultDto.setResultSet(rs); + resultDto.setConnection(connection); + return resultDto; + } + +} diff --git a/client/src/main/java/com/small/client/dao/SxDataDao.java b/client/src/main/java/com/small/client/dao/SxDataDao.java new file mode 100644 index 00000000..85fc645e --- /dev/null +++ b/client/src/main/java/com/small/client/dao/SxDataDao.java @@ -0,0 +1,448 @@ +package com.small.client.dao; + + +import com.small.client.dto.*; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.nio.charset.Charset; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * 考虑到每个思迅软件都是自己的数据,所以采用动态获取的方式获取数据 + * 数据库为MS SQL + * todo 如果考虑到数据量需要分页多线程 + */ +@Service +@Slf4j +public class SxDataDao extends BaseDao{ + + private final static String T_BD_ITEM_CLS="t_bd_item_cls";//商品分类 + private final static String T_BD_ITEM_INFO="t_bd_item_info";//商品表 + private final static String T_RM_VIP_INFO="t_rm_vip_info";//会员表 + + private final static String ITEM_CLSNO="item_clsno";//商品分类排序字段 + private final static String ITEM_NO="item_no";//商品排序字段 + private final static String CARD_ID="card_id";//会员表排序字段 + + + private final static String T_BD_BASE_CODE="t_bd_base_code";//品牌表 + private final static String T_BD_BASECODE_TYPE="t_bd_basecode_type";//品牌表 + private final static String TYPE_NO="type_no";//品牌排序字段 + + private final static String T_IM_BRANCH_STOCK="t_im_branch_stock";//库存表 + + private final static String T_RM_SPEC_PRICE="t_rm_spec_price";//活动表 + + public final static Integer PAGESIZE=500; + + public final static String DEFALTWHERE="where 1=1"; + + public final static String DEFAULT_IMG="https://digitalassets.tesla.com/tesla-contents/image/upload/f_auto,q_auto/Homepage-Model-Y-2-Promo-Hero-Tablet-CN.png"; + + + /** + * 查找商品分类数据 + * @param dataBaseInfo + */ + public List findTBdItemClsList(DataBaseInfo dataBaseInfo){ + ResultDto resultDto=baseFindList(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_BD_ITEM_CLS,DEFALTWHERE); + ResultSet rs= resultDto.getResultSet(); + List sxSyncCategories=new ArrayList<>(); + SxSyncCategory sxSyncCategory=null; + try { + while (rs.next()) { + sxSyncCategory=new SxSyncCategory(); + sxSyncCategory.setItem_clsname(rs.getString("item_clsname").trim());//分类名称 + if(null!=rs.getString("cls_parent")){ + sxSyncCategory.setCls_parent(rs.getString("cls_parent").trim());//父级编码 + } + sxSyncCategory.setItem_clsno(rs.getString("item_clsno").trim());//分类编码 +// System.out.printf(rs.getString("item_clsno"));//分类编码 +// System.out.printf(rs.getString("item_clsname")+"\t");//分类名称 +// System.out.print(rs.getString("cls_parent")+"\t");//父级编码 +// System.out.print(rs.getString("item_flag")+"\t" + "\n");//显示标识 + sxSyncCategories.add(sxSyncCategory); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return sxSyncCategories; + } + + /** + * 分页查找商品分类数据 + * @param dataBaseInfo + * @param pageNo + * @param pageSize + */ + public List findTBdItemClsListPage(DataBaseInfo dataBaseInfo, int pageNo, int pageSize){ + ResultDto resultDto=baseFindListPage(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_BD_ITEM_CLS,ITEM_CLSNO,pageNo,pageSize,DEFALTWHERE); + ResultSet rs= resultDto.getResultSet(); + List sxSyncCategories=new ArrayList<>(); + SxSyncCategory sxSyncCategory=null; + try { + while (rs.next()) { + sxSyncCategory=new SxSyncCategory(); + sxSyncCategory.setItem_clsname(rs.getString("item_clsname"));//分类名称 + sxSyncCategory.setCls_parent(rs.getString("cls_parent"));//父级编码 + sxSyncCategory.setItem_clsno(rs.getString("item_clsno"));//分类编码 +// System.out.printf(rs.getString("item_clsno"));//分类编码 + // log.info(rs.getString("item_clsname")+"\t");//分类名称 + //log.info(rs.getString("cls_parent")+"\t");//父级编码 + //log.info(rs.getString("item_flag")+"\t" + "\n");//显示标识 + sxSyncCategories.add(sxSyncCategory); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return sxSyncCategories; + } + + /** + * 获取商品分类TBdItemCls表的数量 + * @param dataBaseInfo + * @return + */ + public Integer getTBdItemClsTotal(DataBaseInfo dataBaseInfo){ + return getBaseTotal(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_BD_ITEM_CLS,DEFALTWHERE); + } + + /** + * 获取商品表t_bd_item_info表的数量 + * @param dataBaseInfo + * @return + */ + public int getTBditemInfoTotal(DataBaseInfo dataBaseInfo){ +// String where =DEFALTWHERE; +// if(syncGoodsSearchModel!=null){ +// if(dataBaseInfo.getWhere()!=null){ +// where+= dataBaseInfo.getWhere(); +// } +// } + return getBaseTotal(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_BD_ITEM_INFO,dataBaseInfo.getWhere()); + } + + /** + * 获取商品表t_bd_item_info表的数量 + * @param dataBaseInfo + * @return + */ + public int getTBditemInfoJoninTotal(DataBaseInfo dataBaseInfo){ + return getBaseJoinTotal(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName() + , T_BD_ITEM_INFO + ,T_IM_BRANCH_STOCK + ,"item_no" + ,"item_no" + ,ITEM_CLSNO + ,"t.stock_qty,t.oper_date" + ,dataBaseInfo.getWhere()==null?DEFALTWHERE:dataBaseInfo.getWhere()); + } + + /** + * 获取会员表t_rm_vip_info表的数量 + * @param dataBaseInfo + * @return + */ + public int getTrmVipInfoTotal(DataBaseInfo dataBaseInfo){ + return getBaseTotal(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_RM_VIP_INFO,dataBaseInfo.getWhere()); + } + + + /** + * 分页查找商品数据 + * 表T_BD_ITEM_INFO + * @param dataBaseInfo + * @param pageNo + * @param pageSize + */ + public List findBditemInfoListPage(DataBaseInfo dataBaseInfo,int pageNo,int pageSize){ + ResultDto resultDto=baseFindListJoinPage(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName() + , T_BD_ITEM_INFO + ,T_IM_BRANCH_STOCK + ,"item_no" + ,"item_no" + ,ITEM_CLSNO + ,"t.stock_qty,t.oper_date" + ,pageNo,pageSize,dataBaseInfo.getWhere()==null?DEFALTWHERE:dataBaseInfo.getWhere()); + ResultSet rs= resultDto.getResultSet(); + List sxSyncGoodses=new ArrayList<>(); + SxSyncGoods sxSyncGoods=null; + try { + while (rs.next()) { + sxSyncGoods=new SxSyncGoods(); + BigDecimal price=new BigDecimal(rs.getString("price")); + BigDecimal salePrice=new BigDecimal(rs.getString("sale_price")); + if(salePrice.compareTo(new BigDecimal("0"))>0){ + try{ + BigDecimal gross= salePrice.subtract(price).divide(salePrice,4, RoundingMode.HALF_UP); + sxSyncGoods.setGross_margin(gross);//毛利率 + }catch (RuntimeException e){ + log.info("运行错误:{}",e.getMessage()); + log.info(String.valueOf(rs.getString("sale_price"))); + } + + }else { + sxSyncGoods.setGross_margin(new BigDecimal("0"));//毛利率 + } + sxSyncGoods.setItem_no(rs.getString("item_no"));//货号 + sxSyncGoods.setItem_subname(rs.getString("item_subname"));//商品名称 + sxSyncGoods.setItem_subno(rs.getString("item_subno"));//商品条码 + + sxSyncGoods.setBig_cls_name("9999");//商品大类 todo 如何关联 + sxSyncGoods.setSmall_cls_name(rs.getString("item_clsno").trim());//商品小类 todo 如何关联 + + sxSyncGoods.setItem_size(rs.getString("item_size"));//规格 + sxSyncGoods.setUnit_no(rs.getString("unit_no"));//单位 todo + sxSyncGoods.setStock(rs.getBigDecimal("stock_qty"));//库存数量 todo item_stock? + + sxSyncGoods.setPrice(rs.getBigDecimal("price"));//进货价 + sxSyncGoods.setSale_price(rs.getBigDecimal("sale_price"));//零售价 + + sxSyncGoods.setVip_price(rs.getBigDecimal("vip_price"));//会员价 + sxSyncGoods.setVip_acc_flag(rs.getBigDecimal("vip_acc_flag"));//允许积分 + sxSyncGoods.setVip_acc_num(rs.getBigDecimal("vip_acc_num"));//积分值 + sxSyncGoods.setSale_flag(rs.getInt("main_Sale_flag"));//商品状态 todo 是main_Sale_flag? + sxSyncGoods.setItem_rem(rs.getString("item_rem"));//助记码 + sxSyncGoods.setBuild_date(rs.getString("build_date"));//生产日期 todo + sxSyncGoods.setValid_days(getStopDate(rs));//保质期 todo stop_date-build_date? + + sxSyncGoods.setItem_brand_name(rs.getString("item_brandname")); + sxSyncGoods.setItemBrand(rs.getString("item_brand")); + sxSyncGoods.setItem_clsno(rs.getString("item_clsno").trim()); + sxSyncGoods.setItem_size(rs.getString("item_size")); + + sxSyncGoodses.add(sxSyncGoods); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return sxSyncGoodses; + } + + private static String getStopDate(ResultSet rs) throws SQLException { + return rs.getString("stop_date"); + } + + + /** + * 分页查找会员数据 + * RM_VIP_INFO + * @param dataBaseInfo + * @param pageNo + * @param pageSize + */ + public List findRmVipInfoListPage(DataBaseInfo dataBaseInfo, int pageNo, int pageSize){ + ResultDto resultDto=baseFindListPage(dataBaseInfo.getIp(),dataBaseInfo.getUserName(),dataBaseInfo.getPassword(),dataBaseInfo.getDbPort(),dataBaseInfo.getDataBaseName(),T_RM_VIP_INFO,CARD_ID,pageNo,pageSize,dataBaseInfo.getWhere()); + ResultSet rs= resultDto.getResultSet(); + List sxSyncVips=new ArrayList<>(); + SxSyncVip sxSyncVip=null; + try { + while (rs.next()) { + sxSyncVip = new SxSyncVip(); + int cardStatus=rs.getInt("card_status"); + if(cardStatus!=1){ + sxSyncVip.setVip_name(rs.getString("vip_name"));//会员名称 + sxSyncVip.setVip_sex(rs.getString("vip_sex"));//会员名称 + sxSyncVip.setMobile(rs.getString("mobile"));//会员名称 + sxSyncVip.setBirthday(rs.getString("birthday"));//会员生日 + sxSyncVip.setCard_type(rs.getString("card_type")==null?"v1":rs.getString("card_type"));//会员生日 + sxSyncVip.setCard_no(rs.getString("card_no"));//会员卡号 + sxSyncVip.setCard_no(rs.getString("now_acc_num"));//会员积分 + sxSyncVip.setCard_no(rs.getString("residual_amt"));//储值余额 + sxSyncVip.setCard_no(rs.getString("vip_start_date"));//建档日期 + + log.info(rs.getString("vip_name"));//会员名称 + log.info(rs.getString("mobile"));//会员手机号 + log.info(rs.getString("vip_sex"));//会员性别 + log.info(rs.getString("birthday"));//会员生日 + log.info(rs.getString("card_no"));//会员卡号 + log.info(rs.getString("card_type"));//会员等级 + log.info("{}",rs.getBigDecimal("residual_amt"));//储值余额 + log.info("{}",rs.getBigDecimal("now_acc_num"));//会员积分 + log.info(rs.getString("vip_start_date"));//建档日期 + log.info("{}",rs.getInt("card_status"));//会员状态 + } + + sxSyncVips.add(sxSyncVip); + } + }catch (SQLException e){ + throw new RuntimeException(e); + } + return sxSyncVips; + } + + /** + * 获取品牌数据 + * @param dataBaseInfo + */ + public List getBdBrandList(DataBaseInfo dataBaseInfo) { + String where="where t.type_name='品牌'"; + ResultDto resultDto=baseFindListJoin(dataBaseInfo.getIp() + ,dataBaseInfo.getUserName() + ,dataBaseInfo.getPassword() + ,dataBaseInfo.getDbPort() + ,dataBaseInfo.getDataBaseName() + ,T_BD_BASE_CODE + ,"t_bd_basecode_type" + ,"type_no" + ,"type_no" + ,"t.type_name" + ,where); + ResultSet rs= resultDto.getResultSet(); + List brandModels=new ArrayList<>(); + try { + while (rs.next()) { + BrandModel brandModel=new BrandModel(); + brandModel.setBrand_name(rs.getString("code_name")); + brandModel.setBrand_desc(rs.getString("code_name")); + brandModel.setCodeId(rs.getString("code_id")); + brandModel.setBrand_image(""); + brandModel.setCategory("0"); + brandModel.setBrand_recommend("0");//是否推荐 + brandModels.add(brandModel); + // log.info(rs.getString("type_no")+"--"+rs.getString("code_name"));//分类编码-分类名称 + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return brandModels; + } + + /** + * 获取库存数据 + * @return + */ + public List getImBranchStockList(DataBaseInfo dataBaseInfo,String where){ + ResultDto resultDto=baseFindList(dataBaseInfo.getIp() + ,dataBaseInfo.getUserName() + ,dataBaseInfo.getPassword() + ,dataBaseInfo.getDbPort() + ,dataBaseInfo.getDataBaseName() + ,T_IM_BRANCH_STOCK + ,where); + ResultSet rs= resultDto.getResultSet(); + List branchStocks=new ArrayList<>(); + try { + while (rs.next()) { + ImBranchStock brandModel=new ImBranchStock(); + brandModel.setBranchNo(rs.getString("branch_no")); + brandModel.setStockQty(rs.getBigDecimal("stock_qty")); + brandModel.setItemNo(rs.getString("item_no")); + brandModel.setPerDate(rs.getString("oper_date")); + branchStocks.add(brandModel); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return branchStocks; + } + + /** + *获取促销活动价格 时段特价单 + * @param dataBaseInfo + * @return + */ + public List getSpecPriceList(DataBaseInfo dataBaseInfo){ + ResultDto resultDto=baseFindList(dataBaseInfo.getIp() + ,dataBaseInfo.getUserName() + ,dataBaseInfo.getPassword() + ,dataBaseInfo.getDbPort() + ,dataBaseInfo.getDataBaseName() + ,"T_RM_SPEC_PRICE" + ,"where special_type ='0'"); + ResultSet rs= resultDto.getResultSet(); + List specPriceDtos=new ArrayList<>(); + try { + while (rs.next()) { + SpecPriceDto specPriceDto=new SpecPriceDto(); + specPriceDto.setItemNo(rs.getString("item_no"));// + specPriceDto.setOldPrice(rs.getBigDecimal("old_price"));//原价 + specPriceDto.setSpecPrice(rs.getBigDecimal("spe_price"));//特价 + specPriceDto.setSpecPrice(rs.getBigDecimal("sale_qty"));//限购 + specPriceDto.setDiscountType("0"); + specPriceDtos.add(specPriceDto); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return specPriceDtos; + } + + /** + * 折扣商品 + * @param dataBaseInfo + * @return + */ + public List getDiscountPriceList(DataBaseInfo dataBaseInfo){ + ResultDto resultDto=baseFindList(dataBaseInfo.getIp() + ,dataBaseInfo.getUserName() + ,dataBaseInfo.getPassword() + ,dataBaseInfo.getDbPort() + ,dataBaseInfo.getDataBaseName() + ,T_RM_SPEC_PRICE + ,"where special_type in('6','G')"); + ResultSet rs= resultDto.getResultSet(); + List specPriceDtos=new ArrayList<>(); + try { + while (rs.next()) { + SpecPriceDto specPriceDto=new SpecPriceDto(); + specPriceDto.setItemNo(rs.getString("item_no"));// + specPriceDto.setDiscount(rs.getBigDecimal("discount"));//原价 + specPriceDto.setDiscountType("1"); + specPriceDtos.add(specPriceDto); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } finally { + try { + resultDto.getConnection().close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + return specPriceDtos; + } + +} diff --git a/client/src/main/java/com/small/client/dto/BrandModel.java b/client/src/main/java/com/small/client/dto/BrandModel.java new file mode 100644 index 00000000..dbfaf276 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/BrandModel.java @@ -0,0 +1,27 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class BrandModel implements Serializable { + @ApiModelProperty("品牌名称") + private String brand_name; + + @ApiModelProperty("品牌编号") + private String codeId; + + @ApiModelProperty("品牌描述") + private String brand_desc; + + @ApiModelProperty("品牌分类") + private String category; + + @ApiModelProperty("图片") + private String brand_image; + + @ApiModelProperty("是否推荐") + private String brand_recommend; +} diff --git a/client/src/main/java/com/small/client/dto/CommentModel.java b/client/src/main/java/com/small/client/dto/CommentModel.java new file mode 100644 index 00000000..2b39159e --- /dev/null +++ b/client/src/main/java/com/small/client/dto/CommentModel.java @@ -0,0 +1,17 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class CommentModel { + @ApiModelProperty("店铺的key") + private String appKey; + @ApiModelProperty("店铺的密钥") + private String sign; + @ApiModelProperty("店铺的id") + private String storeId; + + @ApiModelProperty(value = "同步时间-用于增量同步,大于这个时间证明是增量") + private String syncTime;//同步时间 +} diff --git a/client/src/main/java/com/small/client/dto/DataBaseInfo.java b/client/src/main/java/com/small/client/dto/DataBaseInfo.java new file mode 100644 index 00000000..422ff5de --- /dev/null +++ b/client/src/main/java/com/small/client/dto/DataBaseInfo.java @@ -0,0 +1,33 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class DataBaseInfo { + @ApiModelProperty("数据库IP") + private String ip; + @ApiModelProperty("用户名") + private String userName; + @ApiModelProperty("密码") + private String password; + @ApiModelProperty("数据库名称") + private String dataBaseName; + @ApiModelProperty("条件") + private String where; + @ApiModelProperty(value = "数据库端口") + private Integer dbPort; + @ApiModelProperty(value = "定时同步的cron表达式") + private String cronExpression; + @ApiModelProperty(value = "同步模式(1:定时同步,2:间隔同步)") + private String syncMode; + + @ApiModelProperty(value = "商品分类") + private String categoryName; + + @ApiModelProperty(value = "01全量,02增量") + private String syncType; + + @ApiModelProperty(value = "操作时间") + private String operDate; +} diff --git a/client/src/main/java/com/small/client/dto/ImBranchStock.java b/client/src/main/java/com/small/client/dto/ImBranchStock.java new file mode 100644 index 00000000..836a55ac --- /dev/null +++ b/client/src/main/java/com/small/client/dto/ImBranchStock.java @@ -0,0 +1,18 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class ImBranchStock { + @ApiModelProperty("商品编号") + private String itemNo; + @ApiModelProperty("商标编号") + private String branchNo; + @ApiModelProperty("库存") + private BigDecimal stockQty; + @ApiModelProperty("操作时间") + private String perDate; +} diff --git a/client/src/main/java/com/small/client/dto/ProductImage.java b/client/src/main/java/com/small/client/dto/ProductImage.java new file mode 100644 index 00000000..ff28ae69 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/ProductImage.java @@ -0,0 +1,17 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class ProductImage { + @ApiModelProperty("图片路径") + private String image_url; + @ApiModelProperty("推荐值") + private String seq; + @ApiModelProperty("介绍") + private String desc; + @ApiModelProperty("是否默认") + private String is_default; + +} diff --git a/client/src/main/java/com/small/client/dto/PromotionDetail.java b/client/src/main/java/com/small/client/dto/PromotionDetail.java new file mode 100644 index 00000000..bad64429 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/PromotionDetail.java @@ -0,0 +1,17 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +public class PromotionDetail { + + @ApiModelProperty("活动id") + private String activity_id; + @ApiModelProperty("活动名称") + private String activity_name; + @ApiModelProperty("价格") + private String price; + @ApiModelProperty("介绍") + private String intro; +} diff --git a/client/src/main/java/com/small/client/dto/ResultDto.java b/client/src/main/java/com/small/client/dto/ResultDto.java new file mode 100644 index 00000000..a5cd2057 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/ResultDto.java @@ -0,0 +1,15 @@ +package com.small.client.dto; + +import lombok.Data; + +import java.sql.Connection; +import java.sql.ResultSet; + +@Data +public class ResultDto { + + private Connection connection; + + private ResultSet resultSet; + +} diff --git a/client/src/main/java/com/small/client/dto/SpecPriceDto.java b/client/src/main/java/com/small/client/dto/SpecPriceDto.java new file mode 100644 index 00000000..e03dd15b --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SpecPriceDto.java @@ -0,0 +1,19 @@ +package com.small.client.dto; + +import lombok.Data; + +import java.math.BigDecimal; + +@Data +public class SpecPriceDto { + + private String itemNo; + private BigDecimal oldPrice;//原价 + private BigDecimal specPrice;//折后价 + + private BigDecimal discount;//折扣('6','G') + + private Integer saleQty;//限购 + + private String discountType;//折扣类型 0-特价,1打折 +} diff --git a/client/src/main/java/com/small/client/dto/StoreDbConfig.java b/client/src/main/java/com/small/client/dto/StoreDbConfig.java new file mode 100644 index 00000000..1678039a --- /dev/null +++ b/client/src/main/java/com/small/client/dto/StoreDbConfig.java @@ -0,0 +1,64 @@ +package com.small.client.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +public class StoreDbConfig implements Serializable { + + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "主键ID") + private Long id; + + @ApiModelProperty(value = "店铺ID") + private String storeId; + + @ApiModelProperty(value = "数据库类型(mysql/oracle/sqlserver等)") + private String dbType = "sqlserver"; + + @ApiModelProperty(value = "数据库名称") + private String dbName; + + @ApiModelProperty(value = "数据库IP地址") + private String dbIp; + + @ApiModelProperty(value = "数据库端口") + private Integer dbPort; + + @ApiModelProperty(value = "数据库用户名") + private String dbUsername; + + @ApiModelProperty(value = "数据库密码(建议加密存储)") + private String dbPassword; + + @ApiModelProperty(value = "是否有外网访问(0:无,1:有)") + private String hasInternet; + + @ApiModelProperty(value = "同步模式(1:定时同步,2:间隔同步)") + private String syncMode; + + @ApiModelProperty(value = "是否启用(0:否,1:是)") + private String hasStart; + + @ApiModelProperty(value = "定时同步的cron表达式") + private String cronExpression; + + @ApiModelProperty(value = "商品分类") + private String categoryName; + + @ApiModelProperty(value = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + @ApiModelProperty(value = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; + + @ApiModelProperty(value = "备注信息") + private String remark; +} diff --git a/client/src/main/java/com/small/client/dto/SxCategoryModel.java b/client/src/main/java/com/small/client/dto/SxCategoryModel.java new file mode 100644 index 00000000..168e5b9b --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SxCategoryModel.java @@ -0,0 +1,32 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 模型对应 + */ +@Data +public class SxCategoryModel { + //模型对应ShopBaseProductCategory start + private String parent_name;//暂时不用 + @ApiModelProperty(value = "商品分类名称") + private String category_name; + @ApiModelProperty(value = "分类图片") + private String category_image; + @ApiModelProperty(value = "是否允许虚拟商品(ENUM):1-是; 0-否") + private Integer category_virtual_enable; + @ApiModelProperty(value = "分佣比例-百分比") + private BigDecimal category_commission_rate; + // private String type_name;//todo 看代码没有用,使用的是product_type + //模型对应ShopBaseProductCategory end + @ApiModelProperty(value = "产品类型") + private String product_type; + @ApiModelProperty(value = "第一级父类") + private String first_category_name; + @ApiModelProperty(value = "第二级父类") + private String second_category_name; + +} diff --git a/client/src/main/java/com/small/client/dto/SxGoosModel.java b/client/src/main/java/com/small/client/dto/SxGoosModel.java new file mode 100644 index 00000000..ed570893 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SxGoosModel.java @@ -0,0 +1,103 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.List; + +/** + * 思迅同步商品数据入口数据 + */ +@Data +public class SxGoosModel { + + @ApiModelProperty("商品名称") + private String product_name; + + @ApiModelProperty("商品货号") + private String product_number; + + @ApiModelProperty("商品条形码") + private String product_barcode; + + @ApiModelProperty("一级分类") + private String first_category_name; + + @ApiModelProperty("二级分类") + private String second_category_name; + + @ApiModelProperty("三级分类") + private String three_category_name; + + @ApiModelProperty("产品类型") + private String product_type; + + @ApiModelProperty("商品种类") + private String product_kind; + + @ApiModelProperty("成本价") + private BigDecimal cost_price; + + @ApiModelProperty("零售价") + private BigDecimal price; + + @ApiModelProperty("原价") + private BigDecimal original_price; + + @ApiModelProperty("商品价格") + private BigDecimal retail_price; + + @ApiModelProperty("会员价") + private BigDecimal member_price; + + @ApiModelProperty("库存") + private BigDecimal stock; + + @ApiModelProperty("毛利率") + private BigDecimal gross_margin; + + @ApiModelProperty("规格单位") + private String unit; + + @ApiModelProperty("可用积分") + private BigDecimal can_piont; + + @ApiModelProperty("总积分") + private BigDecimal points; + + @ApiModelProperty("助记码") + private String mnemonic; + + + @ApiModelProperty("最大购买商品量") + private Integer buy_limit; + + @ApiModelProperty("品牌名称") + private String brand_name; + + @ApiModelProperty("标签") + private String tags; + + @ApiModelProperty("辅助属性") + private List product_assist; + + @ApiModelProperty("规格(JSON)-规格、规格值、goods_id 规格不需要全选就可以添加对应数据[") + private List product_spec; + + @ApiModelProperty("商品卖点特征") + private String product_value; + + @ApiModelProperty("商品视频") + private String product_video; + + @ApiModelProperty("产品描述") + private String product_desc; + + @ApiModelProperty("商品图片库") + private List product_images; + + + @ApiModelProperty("商品详情") + private List promotion_detail; +} diff --git a/client/src/main/java/com/small/client/dto/SxSyncCategory.java b/client/src/main/java/com/small/client/dto/SxSyncCategory.java new file mode 100644 index 00000000..40e24a9d --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SxSyncCategory.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.small.client.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +/** + * 思迅同步的商品分类表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +@ApiModel(value = "商品分类表", description = "商品分类表") +public class SxSyncCategory implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "自增ID") + private Long id; + + @ApiModelProperty(value = "店铺Id") + private String store_id; + + @ApiModelProperty(value = "分类编码") + private String item_clsno; + + @ApiModelProperty(value = "分类名称") + private String item_clsname; + + @ApiModelProperty(value = "父类编号") + private String cls_parent; + + @ApiModelProperty(value = "分类排序") + private Integer item_order; + + @ApiModelProperty(value = "是否显示:1-前台显示 0-前台不显示") + private Integer display_flag; + + @ApiModelProperty(value = "状态") + private Integer status; + + @ApiModelProperty(value = "同步时间戳") + private Long sync_time; + + @ApiModelProperty(value = "新增时间") + private Date created_at; + + @ApiModelProperty(value = "更新时间") + private Date updated_at; + + @ApiModelProperty(value = "子节点") + List children; +} diff --git a/client/src/main/java/com/small/client/dto/SxSyncGoods.java b/client/src/main/java/com/small/client/dto/SxSyncGoods.java new file mode 100644 index 00000000..ff437912 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SxSyncGoods.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.small.client.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 思迅同步的商品表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +@ApiModel(value = "商品信息表", description = "商品信息表") +public class SxSyncGoods implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "自增ID") + private Long id; + + @ApiModelProperty(value = "店铺Id") + private String store_id; + + @ApiModelProperty(value = "商品编号") + private String item_no; + + @ApiModelProperty(value = "商品名称") + private String item_subname; + + @ApiModelProperty(value = "商品条码") + private String item_subno; + + @ApiModelProperty(value = "小分类编号") + private String item_clsno; + + @ApiModelProperty(value = "大分类名称") + private String big_cls_name; + + @ApiModelProperty(value = "小分类名称") + private String small_cls_name; + + @ApiModelProperty(value = "规格") + private String item_size; + + @ApiModelProperty(value = "单位") + private String unit_no; + + @ApiModelProperty(value = "库存") + private BigDecimal stock; + + @ApiModelProperty(value = "毛利率") + private BigDecimal gross_margin; + + @ApiModelProperty(value = "进货价") + private BigDecimal price; + + @ApiModelProperty(value = "零售价") + private BigDecimal sale_price; + + @ApiModelProperty(value = "会员价") + private BigDecimal vip_price; + + @ApiModelProperty(value = "允许积分") + private BigDecimal vip_acc_flag; + + @ApiModelProperty(value = "积分值") + private BigDecimal vip_acc_num; + + @ApiModelProperty(value = "商品状态") + private Integer sale_flag; + + @ApiModelProperty(value = "品牌名称") + private String item_brand_name; + + @ApiModelProperty(value = "商品助记号") + private String item_rem; + + @ApiModelProperty(value = "生产日期") + private String build_date; + + @ApiModelProperty(value = "质保期") + private String valid_days; + + @ApiModelProperty(value = "状态") + private Integer status; + + @ApiModelProperty(value = "同步时间戳") + private Long sync_time; + + @ApiModelProperty(value = "同步备注") + private String remark; + + @ApiModelProperty(value = "新增时间") + private Date created_at; + + @ApiModelProperty(value = "更新时间") + private Date updated_at; + + @ApiModelProperty(value = "品牌") + private String itemBrand; + +} + diff --git a/client/src/main/java/com/small/client/dto/SxSyncVip.java b/client/src/main/java/com/small/client/dto/SxSyncVip.java new file mode 100644 index 00000000..ff2d1fb4 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SxSyncVip.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.small.client.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 思迅同步的商品表 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode +@ApiModel(value = "会员表", description = "会员表") +public class SxSyncVip implements Serializable { + private static final long serialVersionUID = 1L; + + @ApiModelProperty(value = "自增ID") + private Long id; + + @ApiModelProperty(value = "店铺Id") + private String store_id; + + @ApiModelProperty(value = "会员名称") + private String vip_name; + + @ApiModelProperty(value = "手机号") + private String mobile; + + @ApiModelProperty(value = "会员性别") + private String vip_sex; + + @ApiModelProperty(value = "会员生日") + private String birthday; + + @ApiModelProperty(value = "会员卡号(唯一键)") + private String card_no; + + @ApiModelProperty(value = "会员等级") + private String card_type; + + @ApiModelProperty(value = "储值余额") + private BigDecimal residual_amt; + + @ApiModelProperty(value = "会员积分") + private BigDecimal now_acc_num; + + @ApiModelProperty(value = "加入时间") + private String vip_date; + + @ApiModelProperty(value = "会员状态") + private Integer card_status; + + @ApiModelProperty(value = "同步时间") + private Long sync_time; + + @ApiModelProperty(value = "状态") + private Integer status; + + @ApiModelProperty(value = "新增时间") + private Date created_at; + + @ApiModelProperty(value = "更新时间") + private Date updated_at; +} diff --git a/client/src/main/java/com/small/client/dto/SyncGoodsSearchModel.java b/client/src/main/java/com/small/client/dto/SyncGoodsSearchModel.java new file mode 100644 index 00000000..67f03145 --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SyncGoodsSearchModel.java @@ -0,0 +1,22 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class SyncGoodsSearchModel implements Serializable { + + @ApiModelProperty(value = "分类名称") + private String categoryName;//分类名称 + + @ApiModelProperty(value = "同步分类编号") + private String itemClsno; + + @ApiModelProperty(value = "操作时间") + private String operDate; + + @ApiModelProperty(value = "01全量,02增量") + private String syncType; +} diff --git a/client/src/main/java/com/small/client/dto/SyncThirdMemberReq.java b/client/src/main/java/com/small/client/dto/SyncThirdMemberReq.java new file mode 100644 index 00000000..41e500cd --- /dev/null +++ b/client/src/main/java/com/small/client/dto/SyncThirdMemberReq.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.small.client.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@JsonInclude(JsonInclude.Include.NON_NULL) +@ApiModel(description = "第三方会员同步请求参数") +public class SyncThirdMemberReq{ + private static final long serialVersionUID = 1L; + + @ApiModelProperty("会员手机号") + private String user_mobile; + @ApiModelProperty("会员昵称") + private String user_nickname; + @ApiModelProperty("会员真实姓名") + private String user_realname; + @ApiModelProperty("会员性别:1-男;2-女;") + private Integer user_gender; + @ApiModelProperty("会员生日 yyyy-MM-dd") + private String user_birthday; + @ApiModelProperty("会员等级:v1...v9") + private String user_level; + @ApiModelProperty("会员卡号") + private String user_level_card; + @ApiModelProperty("会员积分值") + private BigDecimal user_points; + @ApiModelProperty("会员余额") + private BigDecimal user_money; + @ApiModelProperty("加入时间") + private Date join_time; + @ApiModelProperty("秒级别时间戳") + private Long time_stamp; + @ApiModelProperty("随机字符串") + private String nonce_str; +} diff --git a/client/src/main/java/com/small/client/dto/UploadModel.java b/client/src/main/java/com/small/client/dto/UploadModel.java new file mode 100644 index 00000000..8a1c967f --- /dev/null +++ b/client/src/main/java/com/small/client/dto/UploadModel.java @@ -0,0 +1,15 @@ +package com.small.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@EqualsAndHashCode(callSuper = true) +@Data +public class UploadModel extends CommentModel{ + @ApiModelProperty("页数作为路径") + private String page; + @ApiModelProperty("同步类型1商品,2分类,3品牌,4会员") + private String syncType; + +} diff --git a/client/src/main/java/com/small/client/enums/DicEnum.java b/client/src/main/java/com/small/client/enums/DicEnum.java new file mode 100644 index 00000000..514156cd --- /dev/null +++ b/client/src/main/java/com/small/client/enums/DicEnum.java @@ -0,0 +1,72 @@ +package com.small.client.enums; + + + +public enum DicEnum { + + SYNCTYPE_01("01","全量","syncType","同步类型","全量同步"), + SYNCTYPE_02("02","增量","syncType","同步类型","增量同步"), + + MUAL_1("1","商品","mual","商品","全量同步"), + MUAL_2("2","分类","mual","分类","分类"), + MUAL_3("3","品牌","mual","品牌","品牌"), + MUAL_4("4","会员","mual","会员","会员"), + ; + private String code; + + private String value; + + private String dicType; + + private String dicName; + + private String desc; + + DicEnum(String code, String value, String dicType, String dicName, String desc) { + this.code = code; + this.value = value; + this.dicType = dicType; + this.dicName = dicName; + this.desc = desc; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getDicType() { + return dicType; + } + + public void setDicType(String dicType) { + this.dicType = dicType; + } + + public String getDicName() { + return dicName; + } + + public void setDicName(String dicName) { + this.dicName = dicName; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/client/src/main/java/com/small/client/service/SxDataAbst/SxDataAbstService.java b/client/src/main/java/com/small/client/service/SxDataAbst/SxDataAbstService.java new file mode 100644 index 00000000..6b1e5284 --- /dev/null +++ b/client/src/main/java/com/small/client/service/SxDataAbst/SxDataAbstService.java @@ -0,0 +1,180 @@ +package com.small.client.service.SxDataAbst; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.CollectionUtil; +import com.small.client.Cache.CommonCache; +import com.small.client.dao.SxDataDao; +import com.small.client.dto.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.time.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.text.ParseException; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@Slf4j +public abstract class SxDataAbstService { + @Autowired + private CommonCache commonCache; + + /** + * List 转换为 List + * @param sxSyncVipList + * @return + */ + public List ConverList(List sxSyncVipList){ + List syncThirdMemberReqList=new ArrayList<>(); + if(CollUtil.isNotEmpty(sxSyncVipList)){ + SyncThirdMemberReq syncThirdMemberReq=null; + for (SxSyncVip sxSyncVip : sxSyncVipList) { + syncThirdMemberReq = new SyncThirdMemberReq(); + syncThirdMemberReq.setUser_nickname(sxSyncVip.getVip_name()); + syncThirdMemberReq.setUser_realname(sxSyncVip.getVip_name()); + if ("男".equals(sxSyncVip.getVip_name())) {//todo 需要确认数据是不是这样判断 + syncThirdMemberReq.setUser_gender(1); + } + if ("男".equals(sxSyncVip.getVip_name())) { + syncThirdMemberReq.setUser_gender(2); + } + syncThirdMemberReq.setUser_mobile(sxSyncVip.getMobile()); + syncThirdMemberReq.setUser_birthday(sxSyncVip.getBirthday()); + syncThirdMemberReq.setUser_level(sxSyncVip.getCard_type());//todo 涉及会员等级字典转换 + syncThirdMemberReq.setUser_level_card(sxSyncVip.getCard_no()); + syncThirdMemberReq.setUser_points(sxSyncVip.getNow_acc_num()); + syncThirdMemberReq.setUser_money(sxSyncVip.getResidual_amt()); + if(sxSyncVip.getVip_date()!=null){ + try { + syncThirdMemberReq.setJoin_time(DateUtils.parseDate(sxSyncVip.getVip_date())); + } catch (ParseException e) { + log.info("时间转换异常{0}",e); + throw new RuntimeException(e); + } + } + syncThirdMemberReqList.add(syncThirdMemberReq); + } + } + return syncThirdMemberReqList; + } + + /** + * + * @param sxSyncCategories + * @param allSxSyncCategories 所有分类 + * @return + */ + public List ConVToSxCategoryModel(List sxSyncCategories,List allSxSyncCategories) { + if(CollectionUtil.isEmpty(sxSyncCategories)){ + return new ArrayList<>(); + } + Iterator iterator= sxSyncCategories.iterator(); + List sxCategoryModels=new ArrayList<>(); + SxCategoryModel sxCategoryModel=null; + while (iterator.hasNext()){ + SxSyncCategory sxSyncCategory= iterator.next(); + sxCategoryModel=new SxCategoryModel(); + sxCategoryModel.setCategory_image(SxDataDao.DEFAULT_IMG); + sxCategoryModel.setCategory_name(sxSyncCategory.getItem_clsname()); + //寻找父级 + if(null!=sxSyncCategory.getCls_parent()){ + SxSyncCategory firstNode=getParentNode(allSxSyncCategories,sxSyncCategory.getCls_parent()); + sxCategoryModel.setParent_name(firstNode.getItem_clsname());//todo 暂时无用 + //如何存在上级的上级,则上级为第二层,上上及为第一层 + if(null!=firstNode.getCls_parent()) {//还存在上级 + SxSyncCategory secondNode=getParentNode(allSxSyncCategories,sxSyncCategory.getCls_parent()); + sxCategoryModel.setFirst_category_name(secondNode.getItem_clsname()); + sxCategoryModel.setSecond_category_name(firstNode.getItem_clsname()); + }else { + sxCategoryModel.setFirst_category_name(firstNode.getItem_clsname()); + } + } + sxCategoryModels.add(sxCategoryModel); + } + return sxCategoryModels; + } + + /** + * 通过流查找父节点 + * @param sxSyncCategories + * @param parentId + */ + private SxSyncCategory getParentNode(List sxSyncCategories,String parentId){ + List list= sxSyncCategories.stream().filter(cc-> + cc.getItem_clsno().trim().equals(parentId.trim())) + .collect(Collectors.toList()); + return CollectionUtil.isNotEmpty(list)?list.get(0):new SxSyncCategory(); + } + + /** + * 将List转换为List + * @param sxSyncGoods + * @return + */ + public List CvtToGoosModel(List sxSyncGoods,List specPriceDtoList){ + if(CollectionUtil.isEmpty(sxSyncGoods)){ + return null; + } + List sxGoosModelList=new ArrayList<>(); + SxGoosModel sxGoosModel=null; + for (SxSyncGoods sxSyncGood:sxSyncGoods){ + sxGoosModel=new SxGoosModel(); + sxGoosModel.setProduct_name(sxSyncGood.getItem_subname()); + sxGoosModel.setProduct_number(sxSyncGood.getItem_no().trim());// todo + sxGoosModel.setProduct_barcode(sxSyncGood.getItem_subno());// todo + + sxGoosModel.setFirst_category_name(commonCache.get(sxSyncGood.getSmall_cls_name()));// todo + sxGoosModel.setSecond_category_name("");// todo + + sxGoosModel.setThree_category_name("");// todo + sxGoosModel.setProduct_type("");// todo + sxGoosModel.setProduct_kind("");// todo + sxGoosModel.setCost_price(sxSyncGood.getPrice());//成本价 todo + sxGoosModel.setOriginal_price(sxSyncGood.getSale_price());//原价 todo + sxGoosModel.setPrice(sxSyncGood.getSale_price());// + sxGoosModel.setMember_price(sxSyncGood.getVip_price());//会员价 + sxGoosModel.setStock(sxSyncGood.getStock());//库存 todo + sxGoosModel.setGross_margin(sxSyncGood.getGross_margin()); //毛利率 todo + sxGoosModel.setUnit(sxSyncGood.getUnit_no());//单位 + sxGoosModel.setCan_piont(new BigDecimal(0));//可用积分 todo + sxGoosModel.setPoints(sxSyncGood.getVip_acc_num());//总积分 todo + sxGoosModel.setMnemonic(sxSyncGood.getItem_rem());//助记码 todo + sxGoosModel.setRetail_price(sxSyncGood.getSale_price()); + // sxGoosModel.setBuy_limit(10);//最大购买商品量 todo + sxGoosModel.setBrand_name(commonCache.get(sxSyncGood.getItemBrand()));//品牌 todo + sxGoosModel.setTags("");//标签 todo + + sxGoosModel.setProduct_assist(Arrays.asList(sxSyncGood.getItem_subname()));//帮助 todo + + sxGoosModel.setProduct_spec(Collections.singletonList(sxSyncGood.getItem_size()==null?"":sxSyncGood.getItem_size()));//规格 + + sxGoosModel.setProduct_value("");//商品卖点特征 todo + + sxGoosModel.setProduct_video("");//商品视频 todo + + sxGoosModel.setProduct_desc("");//商品描述 todo + + sxGoosModel.setProduct_images(new ArrayList<>());//介绍图片 todo + + sxGoosModel.setPromotion_detail(new ArrayList<>());//活动列表 todo + + SxGoosModel finalSxGoosModel = sxGoosModel; + specPriceDtoList.forEach(m->{ + if(sxSyncGood.getItem_no().equals(m.getItemNo())){ + String type=m.getDiscountType(); + if(type.equals("1")){ + finalSxGoosModel.setPrice(m.getSpecPrice()); + finalSxGoosModel.setBuy_limit(m.getSaleQty());//最大购买商品量 todo + } + if(type.equals("2")){ + finalSxGoosModel.setPrice(finalSxGoosModel.getPrice().multiply(m.getDiscount())); + } + } + }); + sxGoosModelList.add(sxGoosModel); + } + return sxGoosModelList; + } +} diff --git a/client/src/main/java/com/small/client/service/SxDataService.java b/client/src/main/java/com/small/client/service/SxDataService.java new file mode 100644 index 00000000..3c3cc48d --- /dev/null +++ b/client/src/main/java/com/small/client/service/SxDataService.java @@ -0,0 +1,53 @@ +package com.small.client.service; + + +import com.small.client.dto.*; + + +public interface SxDataService { + + /** + * 同步商品分类数据 + * @param dataBaseInfo + * @param commentModel + */ + void SyncCategory(DataBaseInfo dataBaseInfo, CommentModel commentModel); + + /** + * 同步商品数据 + * @param dataBaseInfo + * @param commentModel + */ + void SyncGoods(DataBaseInfo dataBaseInfo, CommentModel commentModel); + + /** + * 品牌同步 + * @param dataBaseInfo + * @return + */ + void SyncBranchList(DataBaseInfo dataBaseInfo, CommentModel commentModel); + + /** + * 同步会员数据 + * @param dataBaseInfo + */ + void SyncVipList(DataBaseInfo dataBaseInfo, CommentModel commentModel); + + + CommentModel getCommentModel(); + + void getAppSign(); + + String downLoadClient(); + + void checkForUpdates(); + + /** + * 获取服务器配置 + * @param commentModel + * @return + */ + DataBaseInfo getDataBaseInfo(CommentModel commentModel); + + +} diff --git a/client/src/main/java/com/small/client/service/WebClientService.java b/client/src/main/java/com/small/client/service/WebClientService.java new file mode 100644 index 00000000..b94a63dc --- /dev/null +++ b/client/src/main/java/com/small/client/service/WebClientService.java @@ -0,0 +1,88 @@ +package com.small.client.service; + +import cn.hutool.json.JSONObject; +import com.small.client.Utils.FileUtils; +import com.small.client.Utils.HttpUtils; +import com.small.client.dto.CommentModel; +import com.small.client.dto.UploadModel; +import lombok.extern.slf4j.Slf4j; +import netscape.javascript.JSObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +@Service +@Slf4j +@Component +public class WebClientService { + @Value("${remoteIp}") + private String remoteIp; + + private final RestTemplate restTemplate; + + public WebClientService(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + public String get(String url) { + return restTemplate.getForObject(url, String.class); + } + + /** + * 文件上传 + */ + public String uploudSxData(String filePath, CommentModel commentModel,String page,String syncType){ + UploadModel uploadModel=new UploadModel(); + uploadModel.setAppKey(commentModel.getAppKey()); + uploadModel.setSign(commentModel.getSign()); + uploadModel.setPage(page); + uploadModel.setSyncType(syncType); + //"C:\\Users\\Administrator\\uploaded\\2025\\3\\25\\goods_1.txt" + return this.uploadFile(filePath, remoteIp+HttpUtils.URL_UPLOUP,uploadModel); + } + + + public String uploadFile(String filePath, String url, UploadModel uploadModel) { + // 创建MultiValueMap来封装文件数据和请求参数(如果有的话) + MultiValueMap body = new LinkedMultiValueMap<>(); + FileSystemResource file = new FileSystemResource(filePath); // 文件路径 + body.add("file", file); // "file"是与服务器期望的表单字段名称相对应的键,例如在Spring Controller中用@RequestParam("file") String file接收文件数据 + body.add("appKey",uploadModel.getAppKey()); + body.add("sign",uploadModel.getSign()); + body.add("page",uploadModel.getPage());//页数 + body.add("syncType",uploadModel.getSyncType());//商品类型 + // 设置请求头,指定为multipart/form-data类型,并设置boundary(可选) + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + // 创建HttpEntity对象,它将用于POST请求体中包含文件数据和请求头信息 + HttpEntity> requestEntity = new HttpEntity<>(body, headers); + + // 执行POST请求进行文件上传 + JSONObject jsonObject= restTemplate.exchange(url, HttpMethod.POST, requestEntity, JSONObject.class).getBody(); + log.info(jsonObject.toString()); + log.info(jsonObject.getStr("error_msg")); + log.info(jsonObject.getStr("error_code")); + return jsonObject.getStr("error_code"); + } + + public static void main(String[] args) { + + // String responseStr= new WebClientService(new RestTemplate()).get("http://localhost:8088/mobile/account/login/testcase"); + +// String responseStr= new WebClientService(new RestTemplate()).get("http://localhost:8088/mobile/account/login/testcase"); +// System.out.printf(responseStr); + // new WebClientService(new RestTemplate()).uploudSxData(); + log.info("测试"); + } + +} diff --git a/client/src/main/java/com/small/client/service/imp/SxDataServiceImp.java b/client/src/main/java/com/small/client/service/imp/SxDataServiceImp.java new file mode 100644 index 00000000..1aea50fd --- /dev/null +++ b/client/src/main/java/com/small/client/service/imp/SxDataServiceImp.java @@ -0,0 +1,645 @@ +package com.small.client.service.imp; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.small.client.Cache.CommonCache; +import com.small.client.Utils.*; +import com.small.client.dao.SxDataDao; +import com.small.client.dto.*; +import com.small.client.enums.DicEnum; +import com.small.client.service.SxDataAbst.SxDataAbstService; +import com.small.client.service.SxDataService; + +import com.small.client.service.WebClientService; +import lombok.extern.slf4j.Slf4j; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.util.StreamUtils; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.*; +import java.util.stream.Collectors; + +import static com.small.client.Utils.FileUtils.copyFile; + + +@Service +@Slf4j +public class SxDataServiceImp extends SxDataAbstService implements SxDataService { + @Autowired + private SxDataDao sxDataDao; + + @Autowired + private RestTemplate restTemplate; + + @Value("${remoteIp}") + private String remoteIp; + + @Autowired + private CommonCache commonCache; + + @Autowired + private WebClientService webClientService; + + + /** + * 同步商品分类数据 + * @param dataBaseInfo + * @param commentModel + */ + @Override + public void SyncCategory(DataBaseInfo dataBaseInfo, CommentModel commentModel) { + dataBaseInfo= getDataBaseInfo(commentModel); + // 记录总数 + Integer total = sxDataDao.getTBdItemClsTotal(dataBaseInfo); + if(total==0){ + log.info("暂无商品分类同步"); + return; + } + // 总页数 + int pages = CommonUtil.getPagesCount(total, SxDataDao.PAGESIZE); + List allSxSyncCategories= sxDataDao.findTBdItemClsList(dataBaseInfo); + int syncCount =0; + for (int i = 1; i <=pages; i++) { + List sxSyncCategories= sxDataDao.findTBdItemClsListPage(dataBaseInfo,i,SxDataDao.PAGESIZE); + List sxCategoryModelList= ConVToSxCategoryModel(sxSyncCategories,allSxSyncCategories); + JSONArray jsonArray =null; + String jsonString=""; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonString = objectMapper.writeValueAsString(sxCategoryModelList); + jsonArray = JSONUtil.parseArray(jsonString); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_CATEGORY + +"?appKey="+commentModel.getAppKey() + +"&sign="+commentModel.getSign(),jsonArray);//todo 后期改为文件传输 + if (!HttpUtils.SUCCESSCODE.equals(code)) { + continue; + } + syncCount+=sxCategoryModelList.size(); + } + log.info("商品分类总共有{}条数据,同步完成{}条",total,syncCount); + } + + /** + * 同步商品数据 + * @param dataBaseInfo + * @param commentModel + */ + @Override + public void SyncGoods(DataBaseInfo dataBaseInfo, CommentModel commentModel) { + //dataBaseInfo= getDataBaseInfo(commentModel); + String syncType ="01"; + if(StringUtils.isNotEmpty(commentModel.getSyncTime())){//如果有同步时间,则为增量 + syncType="02"; + dataBaseInfo.setSyncType("02"); + } + if(StringUtils.isEmpty(syncType)){ + syncType="01"; + dataBaseInfo.setSyncType("01"); + } + switch (syncType) { + case "01"://全量 + syncAllGoods(dataBaseInfo, commentModel); + break; + case "02"://增量 todo test + syncIncrementAddGoods(dataBaseInfo, commentModel); + syncIncrementModifyGoods(dataBaseInfo, commentModel); + syncIncrementStock(dataBaseInfo, commentModel); + break; + } + + } + + /** + * 同步品牌数据 + * @param dataBaseInfo + * @param commentModel + */ + @Override + public void SyncBranchList(DataBaseInfo dataBaseInfo, CommentModel commentModel) { + dataBaseInfo= getDataBaseInfo(commentModel); + List brandModels= sxDataDao.getBdBrandList(dataBaseInfo); + if(brandModels!=null&&brandModels.size()>0){ + String jsonString =""; + JSONArray jsonArray =new JSONArray(); + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonString = objectMapper.writeValueAsString(brandModels); + jsonArray = JSONUtil.parseArray(jsonString); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_BRAND + +"?appKey="+commentModel.getAppKey() + +"&sign="+commentModel.getSign(),jsonArray);//todo 后期改为文件传输 + if(code!=null){ + log.info("品牌总共有{}条数据,同步完成{}条",brandModels.size(),brandModels.size()); + } + }else { + log.info("品牌数据为空"); + } + + } + + /** + * 同步会员数据 + * @param dataBaseInfo + * @param commentModel + */ + @Override + public void SyncVipList(DataBaseInfo dataBaseInfo, CommentModel commentModel) { + dataBaseInfo= getDataBaseInfo(commentModel); + String where="where 1=1 "; + if(StringUtils.isNotEmpty(commentModel.getSyncTime())){ + where+="and oper_date > '"+commentModel.getSyncTime()+"'"; + } + dataBaseInfo.setWhere(where); + // 记录总数 + Integer total = sxDataDao.getTrmVipInfoTotal(dataBaseInfo); + if(total==0){ + log.info("暂无会员数据同步"); + return; + } + // 总页数 + int pages = CommonUtil.getPagesCount(total, SxDataDao.PAGESIZE); + List memberList=new ArrayList<>(); + int syncCount =0; + for (int i = 1; i <=pages; i++) { + memberList.clear(); + List sxSyncVipList= sxDataDao.findRmVipInfoListPage(dataBaseInfo,i,SxDataDao.PAGESIZE); + //处理数据转换SxSyncVip>SyncThirdMemberReq + memberList=ConverList(sxSyncVipList); + String jsonString =""; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonString = objectMapper.writeValueAsString(memberList); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_MEMBER + +"?appKey="+commentModel.getAppKey() + +"&sign="+commentModel.getSign(),memberList);//todo 后期改为文件传输 + if (!HttpUtils.SUCCESSCODE.equals(code)) { + continue; + } + syncCount+=memberList.size(); + } + log.info("vip会员总共有{}条数据,同步完成{}条",total,syncCount); + } + + /** + * 获取并缓存父节点的根节点,用户查找数据 + * @param dataBaseInfo + * @param parentName + */ + public String getAndCacheTree(DataBaseInfo dataBaseInfo,String parentName){ + List sxSyncCategories=new SxDataDao().findTBdItemClsList(dataBaseInfo); + String parentId= sxSyncCategories.stream().filter(m->m.getItem_clsname().equals(parentName)). + map(SxSyncCategory::getItem_clsno).collect(Collectors.joining()); + getBdBrandCacheList(dataBaseInfo); + String childrens=commonCache.get(CommonCache.CACHE_CATEGROY+parentId); + if(childrens==null){ + log.info(JSONUtil.toJsonStr(buildTree(sxSyncCategories,parentId))); + } + return parentId; + } + + /** + * 构建树节点 + * @param sxSyncCategories + * @return + */ + public List buildTree(List sxSyncCategories,String parentId){ + List treeNodes=new ArrayList<>(); + List rootSxSyncCategory=getRootNode(sxSyncCategories); + for (SxSyncCategory node : rootSxSyncCategory) { + node=buildChildTree(node,sxSyncCategories,parentId); + treeNodes.add(node); + } + return treeNodes; + } + + /** + * 获取所有的根节点 + * @param sxSyncCategories + * @return + */ + public List getRootNode(List sxSyncCategories){ + List rootNodeList=new ArrayList<>(); + for (SxSyncCategory node : sxSyncCategories) { + if (null==node.getCls_parent()) { + rootNodeList.add(node); + } + } + return rootNodeList; + } + + /** + * 构建子节点 + * @param root + * @param sxSyncCategories + * @return + */ + public SxSyncCategory buildChildTree(SxSyncCategory root,List sxSyncCategories,String findByParentId) { + List children = new ArrayList<>(); + for (SxSyncCategory node : sxSyncCategories) { + commonCache.put(node.getItem_clsno(),node.getItem_clsname());//把数据加入缓存 + if (root.getItem_clsno().equals(node.getCls_parent())) { + children.add(buildChildTree(node,sxSyncCategories,findByParentId)); + } + } + if(root.getItem_clsno().equals(findByParentId)){ + commonCache.put(CommonCache.CACHE_CATEGROY+findByParentId,children.stream().map(SxSyncCategory::getItem_clsno).collect(Collectors.joining(","))); + } + root.setChildren(children); + return root; + } + + /** + *同步所有商品 + * @param dataBaseInfo + * @param commentModel + */ + private void syncAllGoods(DataBaseInfo dataBaseInfo, CommentModel commentModel){ + String where="where 1=1"; + Integer total =0; + if(DicEnum.SYNCTYPE_02.getCode().equals(dataBaseInfo.getSyncType())){ + if (StringUtils.isNotEmpty(dataBaseInfo.getCategoryName())) { + String parentId=getAndCacheTree(dataBaseInfo,dataBaseInfo.getCategoryName()); + String childrens= commonCache.get(CommonCache.CACHE_CATEGROY+parentId); + //syncGoodsSearchModel.setItemClsno(childrens); + where += " and b.item_clsno in ('" + childrens + "')"; + } + if(StringUtils.isNotEmpty(commentModel.getSyncTime())){ + where+=" and b.modify_date>'"+commentModel.getSyncTime()+"' "; + where+=" or b.build_date>'"+commentModel.getSyncTime()+"' "; + } + if(StringUtils.isNotEmpty(dataBaseInfo.getOperDate())){ + where+=" and t.oper_date>'"+dataBaseInfo.getOperDate()+"' "; + } + dataBaseInfo.setWhere(where); + // 记录总数 + total = sxDataDao.getTBditemInfoJoninTotal(dataBaseInfo); + }else { + dataBaseInfo.setWhere(where); + total = sxDataDao.getTBditemInfoTotal(dataBaseInfo); + } + if(total==0){ + log.info("暂无商品同步"); + return; + } + + // 总页数 + int pages = CommonUtil.getPagesCount(total, SxDataDao.PAGESIZE); + int syncCount =0; + + List discountList= getDiscountFromCache(dataBaseInfo); + List specPriceDtoList= getSpecPriceFromCache(dataBaseInfo); + specPriceDtoList.addAll(discountList); + + List folders=new ArrayList<>(); + for (int i = 1; i <=pages; i++) { + List sxSyncGoods= sxDataDao.findBditemInfoListPage(dataBaseInfo,i,SxDataDao.PAGESIZE); + List sxGoosModelList= CvtToGoosModel(sxSyncGoods,specPriceDtoList); + String jsonString=""; + ObjectMapper objectMapper = new ObjectMapper(); + try { + jsonString = objectMapper.writeValueAsString(sxGoosModelList); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + String code= writeToFileAndUploud(i,jsonString,commentModel,DicEnum.MUAL_1.getCode()); + if (!HttpUtils.SUCCESSCODE.equals(code)) { + continue; + } + folders.add(String.valueOf(i)); + syncCount+=sxSyncGoods.size(); + } + // folders.add(String.valueOf(2)); + //folders.add(String.valueOf(4)); + //folders.add(String.valueOf(5)); + log.info("商品分类总共有{}条数据,同步完成{}条",total,syncCount); + String code= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_GOODS_READ + +"?appKey="+commentModel.getAppKey() + +"&sign="+commentModel.getSign() + +"&syncType="+DicEnum.MUAL_1.getCode(), + JSONUtil.parseArray(folders)); + if (HttpUtils.SUCCESSCODE.equals(code)) { + log.info("思迅商品同步完成,通知服务器处理数据相应成功"); + //记录同步时间 + createDateFile(); + } + } + + /** + * 文件上传到服务器 + * @param page + * @param content + * @param commentModel + * @return + */ + private String writeToFileAndUploud(Integer page,String content,CommentModel commentModel,String syncType){ + FileUtils fileUtils= new FileUtils(); + File file=fileUtils.createFile(syncType,page); + String fileName=fileUtils.getFileName(syncType,page,FileUtils.txtEnd); + String filePath=file.getAbsolutePath(); + fileUtils.writeFile(filePath,fileName,content); + return webClientService.uploudSxData(filePath+FileUtils.pathSeparator+fileName,commentModel,page.toString(),syncType); + } + + /** + * 记录同步时间 + */ + private void createDateFile(){ + String path=JarPathUtil.getRuntimePath(); + FileUtils fileUtils= new FileUtils(); + File file=fileUtils.createFile(path); + String filePath=file.getAbsolutePath(); + String date= DateUtil.format(new Date(),"yyyy-MM-dd"); + fileUtils.writeFile(filePath,FileUtils.REFLESHDATE,date); + } + + /** + * 增量新增数据,新增商品数据 + * @param dataBaseInfo + * @param commentModel + */ + private void syncIncrementAddGoods(DataBaseInfo dataBaseInfo, CommentModel commentModel){ + syncAllGoods(dataBaseInfo,commentModel); + } + + /** + * 增量同步 商品内容变化 + * @param dataBaseInfo + * @param commentModel + */ + private void syncIncrementModifyGoods(DataBaseInfo dataBaseInfo, CommentModel commentModel){ + syncAllGoods(dataBaseInfo,commentModel); + } + + /** + * 增量同步 库存变化 + */ + private void syncIncrementStock(DataBaseInfo dataBaseInfo, CommentModel commentModel){ + dataBaseInfo.setOperDate(commentModel.getSyncTime()); + commentModel.setSyncTime(""); + syncAllGoods(dataBaseInfo,commentModel); + } + + /** + *获取特价商品 + * @param dataBaseInfo + * @return + */ + public List getDiscountFromCache(DataBaseInfo dataBaseInfo){ + List specPriceDtos= commonCache.getSpecPrice("specDiscountCache"); + if (null!=specPriceDtos){ + return specPriceDtos; + }else { + specPriceDtos= sxDataDao.getSpecPriceList(dataBaseInfo); + commonCache.putSpecPrice("specDiscountCache",specPriceDtos); + } + return specPriceDtos; + } + + + /** + *获取促销产品数据 + * @param dataBaseInfo + * @return + */ + public List getSpecPriceFromCache(DataBaseInfo dataBaseInfo){ + List specPriceDtos= commonCache.getSpecPrice("specPriceCache"); + if(null!=specPriceDtos){ + return specPriceDtos; + }else { + specPriceDtos= sxDataDao.getDiscountPriceList(dataBaseInfo); + commonCache.putSpecPrice("specDiscountCache",specPriceDtos); + } + return specPriceDtos; + } + + /** + * 获取品牌数据并加入到缓存 + * @param dataBaseInfo + * @return + */ + public void getBdBrandCacheList(DataBaseInfo dataBaseInfo){ + List specPriceDtos= commonCache.getBrandCahce("brandCache"); + if(null==specPriceDtos){ + specPriceDtos= sxDataDao.getBdBrandList(dataBaseInfo); + if(CollectionUtil.isNotEmpty(specPriceDtos)){ + for (BrandModel brandModel : specPriceDtos) { + commonCache.put(brandModel.getCodeId(),brandModel.getBrand_name()); + } + commonCache.setBrandCahce("brandCache",specPriceDtos); + } + + } + } + + @Override + public CommentModel getCommentModel() { + String path=JarPathUtil.getRuntimePath(); + log.info(JarPathUtil.getRuntimePath()); + File folder = new File(path); + //读取文件 + try { + String encryptedData = getPrimaryKey(); + Map result= CryptoUtils.decryptAndUnpack(encryptedData); + CommentModel commentModel=new CommentModel(); + commentModel.setSign(result.get("sign")); + commentModel.setAppKey(result.get("appKey")); + commentModel.setStoreId(result.get("storeId")); + //获取上次同步的最大时间 + File[] lastDateJsonFile = folder.listFiles((dir, name) -> name.endsWith(FileUtils.REFLESHDATE)); + if(lastDateJsonFile!=null&&lastDateJsonFile.length>0){ + String lastDate = new String(Files.readAllBytes(lastDateJsonFile[0].toPath()), StandardCharsets.UTF_8).trim(); + commentModel.setSyncTime(lastDate); + } + return commentModel; + } catch (RuntimeException | IOException e) { + throw new RuntimeException("密钥获取失败"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void getAppSign() { + String encryptedData= getPrimaryKey(); + JSONObject jsonObject=new JSONObject(); + jsonObject.putOnce("primaryKey",encryptedData); + String primaryKey= HttpUtils.postData(restTemplate,remoteIp+HttpUtils.URL_SYNC_GET_APPSIGN + +"?primaryKey="+encryptedData, jsonObject,"primaryKey"); + if(null!=primaryKey){ + String path=JarPathUtil.getRuntimePath(); + FileUtils fileUtils= new FileUtils(); + File file=fileUtils.createFile(path); + String filePath=file.getAbsolutePath(); + fileUtils.writeFile(filePath,FileUtils.PRIMARYKEY,primaryKey); + }else { + log.info("获取服务器密钥失败"); + } + } + + + /** + * 获取文本密钥 + * @return + */ + private String getPrimaryKey(){ + String path=JarPathUtil.getRuntimePath(); + log.info("RuntimePath:{}",JarPathUtil.getRuntimePath()); + File folder = new File(path); + File[] jsonFiles = folder.listFiles((dir, name) -> name.endsWith(FileUtils.PRIMARYKEY)); + if(null!=jsonFiles&&jsonFiles.length>0){ + try { + return new String(Files.readAllBytes(jsonFiles[0].toPath()), StandardCharsets.UTF_8); + }catch (RuntimeException | IOException e){ + throw new RuntimeException("读取[fileName]文件错误"); + } + + } + return null; + } + + @Override + public String downLoadClient() { + String downloadDirectory=FileUtils.CLIENTSTALLPATH; + String originalFileName = ""; + try { + File file= new File(downloadDirectory); + if(!file.exists()){ + file.mkdirs(); // 确保目录存在 + } + log.info("文件下载目录: {}", downloadDirectory); + HttpHeaders headers = new HttpHeaders(); + HttpEntity requestEntity = new HttpEntity<>(headers); + String encryptedData = getPrimaryKey(); + + ResponseEntity response = restTemplate.exchange( + remoteIp+HttpUtils.URL_SYNC_GET_DOWNCLIENTJAR+"?primaryKey="+encryptedData, + HttpMethod.GET, + requestEntity, + Resource.class); + if(response.getStatusCode().is2xxSuccessful() && null!= response.getHeaders().getFirst("error")){ + String error=response.getHeaders().getFirst("error"); + switch (Objects.requireNonNull(error)){ + case "noVersion": + log.info("没有版本更新"); + break; + case "noFile": + log.info("系统错误:文件不存在"); + break; + case "500":; + log.info("系统错误:系统内部错误"); + break; + case "noValid": + log.info("密钥校验失败:密钥过期"); + break; + } + return null; + } + if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) { + // 从Content-Disposition头获取文件名 + String contentDisposition = response.getHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION); + if (contentDisposition != null && contentDisposition.contains("filename=")) { + originalFileName = contentDisposition + .split("filename=")[1] + .replace("\"", ""); // 去除引号 + } + // 如果无法从header获取,使用默认名 + if (originalFileName == null || originalFileName.isEmpty()) { + originalFileName = "new_client" + System.currentTimeMillis()+".jar"; + } + File outputFile = new File(downloadDirectory + originalFileName); + try (FileOutputStream outputStream = new FileOutputStream(outputFile)) { + StreamUtils.copy(response.getBody().getInputStream(), outputStream); + log.info("文件下载成功: {}" , outputFile.getAbsolutePath()); + }catch (Exception e){ + log.error("下载失败,下载流异常:{}",e.getMessage()); + return null; + } + } else { + log.error("文件下载失败: {}", response.getStatusCode()); + return null; + } + }catch (Exception e){ + log.error("文件下载失败:{}",e.getMessage()); + return null; + } + return downloadDirectory+originalFileName; + } + + @Override + public void checkForUpdates() { + log.info("curentPath:{}",JarPathUtil.getRuntimePath()); + File classDirFile = new File(JarPathUtil.getRuntimePath()); + File parentDir = classDirFile.getParentFile(); + String filePath= this.downLoadClient(); + if (filePath != null) { + copyFile(filePath,parentDir.getAbsolutePath()+"/lib"); + applyUpdate(); + } + } + + private void applyUpdate() { + try { + File classDirFile = new File(JarPathUtil.getRuntimePath()); + File parentDir = classDirFile.getParentFile(); + // 执行脚本并退出当前应用 + log.info(parentDir.getAbsolutePath()+"/bin/run.bat"); + Runtime.getRuntime().exec(parentDir.getAbsolutePath()+"/bin/run.bat"); + log.info(parentDir.getAbsolutePath()+"/bin/run.bat"); + System.exit(0); + } catch (IOException e) { + log.error("异常{}", e.getMessage()); + } + } + + + @Override + public DataBaseInfo getDataBaseInfo(CommentModel commentModel) { + JSONObject jsonObject=new JSONObject(); + jsonObject.putOnce("appKey",commentModel.getAppKey()); + jsonObject.putOnce("sign",commentModel.getSign()); + StoreDbConfig storeDbConfig= HttpUtils.postDataGetConfig(restTemplate,remoteIp+HttpUtils.URL_SYNC_GET_STOREdBCONFIG + +"?appKey="+commentModel.getAppKey() + +"&sign="+commentModel.getSign(), jsonObject); + DataBaseInfo dataBaseInfo=new DataBaseInfo(); + if(null!=storeDbConfig){ + dataBaseInfo.setIp(storeDbConfig.getDbIp()); + dataBaseInfo.setPassword(storeDbConfig.getDbPassword()); + dataBaseInfo.setDataBaseName(storeDbConfig.getDbName()); + dataBaseInfo.setDbPort(storeDbConfig.getDbPort()); + dataBaseInfo.setSyncMode(storeDbConfig.getSyncMode()); + dataBaseInfo.setCronExpression(storeDbConfig.getCronExpression()); + dataBaseInfo.setCategoryName(storeDbConfig.getCategoryName()); + return dataBaseInfo; + } + return new DataBaseInfo(); + } + +} diff --git a/client/src/main/resources/application.yml b/client/src/main/resources/application.yml new file mode 100644 index 00000000..6b48c137 --- /dev/null +++ b/client/src/main/resources/application.yml @@ -0,0 +1,15 @@ +server: + port: 9099 + servlet: + encoding: + charset: UTF-8 + enabled: true + force: true + +#配置远程模板信息 +#服务器地址 +logging: + charset: + console: UTF-8 + +remoteIp: https://mall.gpxscs.cn \ No newline at end of file diff --git a/client/src/main/resources/logback.xml b/client/src/main/resources/logback.xml new file mode 100644 index 00000000..79a5a80e --- /dev/null +++ b/client/src/main/resources/logback.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + UTF-8 + %d{yyyy-MM-dd HH:mm:ss} - %msg%n + + + + + +