Browse Source

Merge branch 'dev' into ecp

liyuan 3 weeks ago
parent
commit
19ab697795

+ 0 - 1
blade-ops/blade-xxljob-admin/src/main/java/com/xxl/job/admin/JobAdminApplication.java

@@ -10,7 +10,6 @@ import org.springframework.scheduling.annotation.EnableScheduling;
  * @author xuxueli 2018-10-28 00:38:13
  */
 @SpringBootApplication
-@EnableFeignClients(basePackages = "com.xxl.job.admin.controller.u9cloud.feign") // 扫描Feign客户端所在包
 @EnableScheduling // 若使用Spring定时任务,保留此注解
 public class JobAdminApplication {
 

+ 0 - 11
blade-ops/blade-xxljob-admin/src/main/java/com/xxl/job/admin/controller/u9cloud/config/FeignConfig.java

@@ -1,11 +0,0 @@
-package com.xxl.job.admin.controller.u9cloud.config;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-@Slf4j
-public class FeignConfig {
-
-
-}

+ 0 - 284
blade-ops/blade-xxljob-admin/src/main/java/com/xxl/job/admin/controller/u9cloud/feign/U9CloudTaskJob.java

@@ -1,284 +0,0 @@
-package com.xxl.job.admin.controller.u9cloud.feign;
-
-import com.xxl.job.core.handler.annotation.XxlJob;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springblade.core.tool.api.R;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.function.Supplier;
-
-/**
- * U9同步数据定时任务(通过Feign调用微服务)
- * 每个方法对应一种数据的同步,支持单独调度
- *
- * @author
- */
-@Slf4j
-@Component
-@RequiredArgsConstructor
-public class U9CloudTaskJob {
-
-	// 注入Feign客户端
-	@Autowired
-	private U9CloudFeignClient u9CloudFeignClient;
-
-	/**
-	 * 同步客户数据(单独任务)
-	 */
-	@XxlJob("syncCustomerDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncCustomerData() throws Exception {
-		log.info("XXL-JOB: 开始执行客户数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncCustomerData(),
-			"客户数据"
-		);
-		log.info("XXL-JOB: 客户数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步部门数据(单独任务)
-	 */
-	@XxlJob("syncDepartmentDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncDepartmentData() throws Exception {
-		log.info("XXL-JOB: 开始执行部门数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncDepartmentData(),
-			"部门数据"
-		);
-		log.info("XXL-JOB: 部门数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步物料数据(单独任务)
-	 */
-	@XxlJob("syncItemDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncItemData() throws Exception {
-		log.info("XXL-JOB: 开始执行物料数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncItemData(),
-			"物料数据"
-		);
-		log.info("XXL-JOB: 物料数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步操作员数据(单独任务)
-	 */
-	@XxlJob("syncOperatorsDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncOperatorsData() throws Exception {
-		log.info("XXL-JOB: 开始执行操作员数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncOperatorsData(),
-			"操作员数据"
-		);
-		log.info("XXL-JOB: 操作员数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步物流数据(单独任务)
-	 */
-	@XxlJob("syncShipDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncShipData() throws Exception {
-		log.info("XXL-JOB: 开始执行物流数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncShipData(),
-			"物流数据"
-		);
-		log.info("XXL-JOB: 物流数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步供应商数据(单独任务)
-	 */
-	@XxlJob("syncSupplierDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncSupplierData() throws Exception {
-		log.info("XXL-JOB: 开始执行供应商数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncSupplierData(),
-			"供应商数据"
-		);
-		log.info("XXL-JOB: 供应商数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步库存数据(单独任务)
-	 */
-	@XxlJob("syncWhqohDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncWhqohData() throws Exception {
-		log.info("XXL-JOB: 开始执行库存数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncWhqohData(),
-			"库存数据"
-		);
-		log.info("XXL-JOB: 库存数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步应收单数据(单独任务)
-	 */
-	@XxlJob("syncARBillDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncARBillData() throws Exception {
-		log.info("XXL-JOB: 开始执行应收单数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncARBillData(),
-			"应收单数据"
-		);
-		log.info("XXL-JOB: 应收单数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步收款单数据(单独任务)
-	 */
-	@XxlJob("syncRecBillDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncRecBillData() throws Exception {
-		log.info("XXL-JOB: 开始执行收款单数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncRecBillData(),
-			"收款单数据"
-		);
-		log.info("XXL-JOB: 收款单数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步销售价目表数据(单独任务)
-	 */
-	@XxlJob("syncSalepriceDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncSalepriceData() throws Exception {
-		log.info("XXL-JOB: 开始执行销售价目表数据同步任务");
-		executeSyncTask(
-			() -> u9CloudFeignClient.syncSalepriceData(),
-			"销售价目表数据"
-		);
-		log.info("XXL-JOB: 销售价目表数据同步任务执行完成");
-	}
-
-	/**
-	 * 同步所有U9数据(完整同步)
-	 */
-	@XxlJob("syncAllDataHandler")
-	@Transactional(rollbackFor = Exception.class)
-	public void syncAllData() throws Exception {
-		log.info("XXL-JOB: ===== 开始执行U9数据完整同步 =====");
-
-		long startTime = System.currentTimeMillis();
-
-		try {
-			// 按业务顺序执行同步
-			log.info("XXL-JOB: 开始同步部门数据");
-			syncDepartmentData();
-
-			log.info("XXL-JOB: 开始同步客户数据");
-			syncCustomerData();
-
-			log.info("XXL-JOB: 开始同步物料数据");
-			syncItemData();
-
-			log.info("XXL-JOB: 开始同步操作员数据");
-			syncOperatorsData();
-
-			log.info("XXL-JOB: 开始同步供应商数据");
-			syncSupplierData();
-
-			log.info("XXL-JOB: 开始同步物流数据");
-			syncShipData();
-
-			log.info("XXL-JOB: 开始同步库存数据");
-			syncWhqohData();
-
-			log.info("XXL-JOB: 开始同步应收单数据");
-			syncARBillData();
-
-			log.info("XXL-JOB: 开始同步收款单数据");
-			syncRecBillData();
-
-			log.info("XXL-JOB: 开始同步销售价目表数据");
-			syncSalepriceData();
-
-			long endTime = System.currentTimeMillis();
-			String successMsg = String.format("XXL-JOB: ===== U9数据完整同步完成,耗时:%s ms =====", (endTime - startTime));
-			log.info(successMsg);
-
-		} catch (Exception e) {
-			String errorMsg = "XXL-JOB: U9数据完整同步失败:" + e.getMessage();
-			log.error(errorMsg, e);
-			throw e;
-		}
-	}
-
-	/**
-	 * 通用同步逻辑(通过Feign调用)
-	 *
-	 * @param syncTask 同步任务的具体逻辑
-	 * @param dataName 数据类型名称(用于日志和异常信息)
-	 */
-	private void executeSyncTask(Supplier<R<Boolean>> syncTask, String dataName) {
-		long startTime = System.currentTimeMillis();
-
-		try {
-			String startMsg = "XXL-JOB: 开始通过Feign同步U9【" + dataName + "】";
-			log.info(startMsg);
-
-			// 通过Feign调用远程服务
-			R<Boolean> result = syncTask.get();
-
-			// 独立判断逻辑,不依赖Func工具类
-			if (isSyncSuccess(result)) {
-				long endTime = System.currentTimeMillis();
-				String successMsg = String.format("XXL-JOB: U9【%s】同步成功,耗时:%s ms", dataName, (endTime - startTime));
-				log.info(successMsg);
-			} else {
-				String errorMsg = buildErrorMessage(dataName, result);
-				log.error(errorMsg);
-				throw new RuntimeException(errorMsg);
-			}
-
-		} catch (RuntimeException e) {
-			// 已知的业务异常,直接抛出
-			log.error("XXL-JOB: 业务异常:" + e.getMessage());
-			throw e;
-		} catch (Exception e) {
-			String errorMsg = "XXL-JOB: U9【" + dataName + "】同步失败:" + e.getMessage();
-			log.error(errorMsg, e);
-			throw new RuntimeException(errorMsg, e);
-		}
-	}
-
-	/**
-	 * 判断同步是否成功
-	 */
-	private boolean isSyncSuccess(R<Boolean> result) {
-		return result != null
-			&& result.isSuccess()
-			&& result.getData() != null
-			&& result.getData();
-	}
-
-	/**
-	 * 构建错误信息
-	 */
-	private String buildErrorMessage(String dataName, R<Boolean> result) {
-		if (result == null) {
-			return String.format("XXL-JOB: U9【%s】同步失败:返回结果为空", dataName);
-		} else if (!result.isSuccess()) {
-			return String.format("XXL-JOB: U9【%s】同步失败:%s", dataName, result.getMsg());
-		} else if (result.getData() == null) {
-			return String.format("XXL-JOB: U9【%s】同步失败:返回数据为空", dataName);
-		} else {
-			return String.format("XXL-JOB: U9【%s】同步失败:返回结果为false", dataName);
-		}
-	}
-}

+ 4 - 0
blade-service/blade-u9cloud/pom.xml

@@ -57,6 +57,10 @@
             <version>2.8.2.RELEASE</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>com.xuxueli</groupId>
+            <artifactId>xxl-job-core</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 2 - 1
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/U9cloudApplication.java

@@ -18,7 +18,8 @@ import org.springframework.web.bind.annotation.RestController;
  */
 @EnableFeignClients(basePackages = {
 	"org.springblade.system.user.feign",  // 保留原有的Feign接口包
-	"org.springblade.u9cloud.feign"       // 添加新的Feign接口包(你的IZcrmViewCustomerSel所在包)
+	"org.springblade.u9cloud.feign",       // 添加新的Feign接口包(你的IZcrmViewCustomerSel所在包)
+	"org.springblade.u9cloud.job"
 })
 @BladeCloudApplication
 @SpringCloudApplication

+ 75 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/config/XxlJobConfig.java

@@ -0,0 +1,75 @@
+package org.springblade.u9cloud.config;
+
+
+import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * xxl-job config
+ *
+ * @author xuxueli 2017-04-28
+ */
+@Configuration
+public class XxlJobConfig {
+	private final Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
+
+	@Value("${xxl.job.admin.addresses}")
+	private String adminAddresses;
+
+	@Value("${xxl.job.executor.appname}")
+	private String appName;
+
+	@Value("${xxl.job.executor.ip}")
+	private String ip;
+
+	@Value("${xxl.job.executor.port}")
+	private int port;
+
+	@Value("${xxl.job.accessToken}")
+	private String accessToken;
+
+	@Value("${xxl.job.executor.logpath}")
+	private String logPath;
+
+	@Value("${xxl.job.executor.logretentiondays}")
+	private int logRetentionDays;
+
+
+	@Bean
+	public XxlJobSpringExecutor xxlJobExecutor() {
+		logger.info(">>>>>>>>>>> xxl-job config init.");
+		XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
+		xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
+		xxlJobSpringExecutor.setAppName(appName);
+		xxlJobSpringExecutor.setIp(ip);
+		xxlJobSpringExecutor.setPort(port);
+		xxlJobSpringExecutor.setAccessToken(accessToken);
+		xxlJobSpringExecutor.setLogPath(logPath);
+		xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
+
+		return xxlJobSpringExecutor;
+	}
+
+	/**
+	 * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP;
+	 *
+	 *      1、引入依赖:
+	 *          <dependency>
+	 *             <groupId>org.springframework.cloud</groupId>
+	 *             <artifactId>spring-cloud-commons</artifactId>
+	 *             <version>${version}</version>
+	 *         </dependency>
+	 *
+	 *      2、配置文件,或者容器启动变量
+	 *          spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.'
+	 *
+	 *      3、获取IP
+	 *          String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
+	 */
+
+
+}

+ 3 - 2
blade-ops/blade-xxljob-admin/src/main/java/com/xxl/job/admin/controller/u9cloud/feign/U9CloudFeignClient.java → blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/job/U9CloudFeignClient.java

@@ -1,7 +1,8 @@
-package com.xxl.job.admin.controller.u9cloud.feign;
+package org.springblade.u9cloud.job;
+
 
-import com.xxl.job.admin.controller.u9cloud.config.FeignConfig;
 import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.config.FeignConfig;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.GetMapping;
 

+ 1 - 1
blade-ops/blade-xxljob-admin/src/main/java/com/xxl/job/admin/controller/u9cloud/feign/U9CloudFeignClientFallbackFactory.java → blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/job/U9CloudFeignClientFallbackFactory.java

@@ -1,4 +1,4 @@
-package com.xxl.job.admin.controller.u9cloud.feign;
+package org.springblade.u9cloud.job;
 
 import feign.hystrix.FallbackFactory;
 import lombok.extern.slf4j.Slf4j;

+ 403 - 0
blade-service/blade-u9cloud/src/main/java/org/springblade/u9cloud/job/U9CloudTaskJob.java

@@ -0,0 +1,403 @@
+package org.springblade.u9cloud.job;
+
+import com.xxl.job.core.biz.model.ReturnT;
+import com.xxl.job.core.handler.annotation.XxlJob;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springblade.core.tool.api.R;
+import org.springblade.u9cloud.service.*;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.function.Supplier;
+
+/**
+ * U9同步数据定时任务(通过Feign调用微服务)
+ * 每个方法对应一种数据的同步,支持单独调度
+ *
+ * @author
+ */
+@Slf4j
+@Component
+@RequiredArgsConstructor
+public class U9CloudTaskJob {
+
+	// 注入Feign客户端
+//	@Autowired
+//	private U9CloudFeignClient u9CloudFeignClient;
+
+	@Autowired
+	private final ZcrmViewCustomerSelService zcrmViewCustomerSelService;
+
+	@Autowired
+	private final ZcrmViewDepartmentSelService zcrmViewDepartmentSelService;
+
+	@Autowired
+	private final ZcrmViewItemSelService zcrmViewItemSelService;
+
+	@Autowired
+	private final ZcrmViewOperatorsSelService zcrmViewOperatorsSelService;
+
+	@Autowired
+	private final ZcrmViewShipSelService zcrmViewShipSelService;
+
+	@Autowired
+	private final ZcrmViewSupplierSelService zcrmViewSupplierSelService;
+
+	@Autowired
+	private final ZcrmViewWhqohSelService zcrmViewWhqohSelService;
+
+	@Autowired
+	private final ZcrmViewSalePriceSelService zcrmViewSalePriceSelService;
+
+	@Autowired
+	private final ZcrmViewRecBillHeadSelService zcrmViewRecBillHeadSelService;
+
+	@Autowired
+	private final ZcrmViewARBillHeadSelService zcrmViewARBillHeadSelService;
+
+
+
+	/**
+	 * 同步客户数据(单独任务)
+	 */
+	@XxlJob("syncCustomerDataHandler")
+	public ReturnT<String> syncCustomerData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行客户数据同步任务,参数: {}", param);
+		System.err.println("XXL-JOB: 开始执行客户数据同步任务");
+		try {
+			boolean res1 = zcrmViewCustomerSelService.insertBatchCustomers();
+			if (!res1) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 客户数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步部门数据(单独任务)
+	 */
+	@XxlJob("syncDepartmentDataHandler")
+	public ReturnT<String> syncDepartmentData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行部门数据同步任务,参数: {}", param);
+		try {
+			boolean res2 = zcrmViewDepartmentSelService.insertBatchDepartments();
+			if (!res2) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 部门数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 部门数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步物料数据(单独任务)
+	 */
+	@XxlJob("syncItemDataHandler")
+	public ReturnT<String> syncItemData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行物料数据同步任务,参数: {}", param);
+		try {
+			boolean res3 = zcrmViewItemSelService.insertBatchItems();
+			if (!res3) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 物料数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 物料数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步操作员数据(单独任务)
+	 */
+	@XxlJob("syncOperatorsDataHandler")
+	public ReturnT<String> syncOperatorsData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行操作员数据同步任务,参数: {}", param);
+		try {
+			boolean res4 = zcrmViewOperatorsSelService.insertBatchOperators();
+			if (!res4) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 操作员数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 操作员数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步物流数据(单独任务)
+	 */
+	@XxlJob("syncShipDataHandler")
+	public ReturnT<String> syncShipData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行物流数据同步任务,参数: {}", param);
+		try {
+			boolean res5 = zcrmViewShipSelService.insertBatchShips();
+			if (!res5) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 物流数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 物流数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+
+	}
+
+	/**
+	 * 同步供应商数据(单独任务)
+	 */
+	@XxlJob("syncSupplierDataHandler")
+	public ReturnT<String> syncSupplierData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行供应商数据同步任务,参数: {}", param);
+		try {
+			boolean res6 = zcrmViewSupplierSelService.insertBatchSuppliers();
+			if (!res6) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 供应商数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 供应商数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步库存数据(单独任务)
+	 */
+	@XxlJob("syncWhqohDataHandler")
+	public ReturnT<String> syncWhqohData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行库存数据同步任务,参数: {}", param);
+		try {
+			boolean res7 = zcrmViewWhqohSelService.insertBatchWhqohs();
+			if (!res7) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 库存数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 库存数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+
+	}
+
+	/**
+	 * 同步应收单数据(单独任务)
+	 */
+	@XxlJob("syncARBillDataHandler")
+	public ReturnT<String> syncARBillData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行应收单数据同步任务,参数: {}", param);
+		try {
+			boolean res8 = zcrmViewARBillHeadSelService.insertBatchCustomers();
+			if (!res8) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 应收单数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 应收单数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步收款单数据(单独任务)
+	 */
+	@XxlJob("syncRecBillDataHandler")
+	public ReturnT<String> syncRecBillData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行收款单数据同步任务,参数: {}", param);
+		try {
+			boolean res9 = zcrmViewRecBillHeadSelService.insertBatchOperators();
+			if (!res9) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 收款单数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 收款单数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步销售价目表数据(单独任务)
+	 */
+	@XxlJob("syncSalepriceDataHandler")
+	public ReturnT<String> syncSalepriceData(String param) throws Exception {
+		log.info("XXL-JOB: 开始执行销售价目表数据同步任务,参数: {}", param);
+		try {
+			boolean res10 = zcrmViewSalePriceSelService.insertBatchOperators();
+			if (!res10) {
+				return ReturnT.FAIL;
+			}
+			log.info("XXL-JOB: 销售价目表数据同步任务执行完成");
+			return ReturnT.SUCCESS;
+		} catch (Exception e)
+		{
+			log.error("XXL-JOB: U9 销售价目表数据完整同步失败", e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 同步所有U9数据(完整同步)
+	 */
+	@XxlJob("syncAllDataHandler")
+	public ReturnT<String> syncAllData(String param) throws Exception {
+		log.info("XXL-JOB: ===== 开始执行U9数据完整同步,参数: {} =====", param);
+
+		try {
+			// 1. 执行各服务的数据同步方法,任一方法返回false则抛出异常触发回滚
+			boolean res1 = zcrmViewCustomerSelService.insertBatchCustomers();
+			if (!res1) {
+				System.out.println("客户数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res2 = zcrmViewDepartmentSelService.insertBatchDepartments();
+			if (!res2) {
+				System.out.println("部门数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res3 = zcrmViewItemSelService.insertBatchItems();
+			if (!res3) {
+				System.out.println("物料数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res4 = zcrmViewOperatorsSelService.insertBatchOperators();
+			if (!res4) {
+				System.out.println("操作员数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res5 = zcrmViewShipSelService.insertBatchShips();
+			if (!res5) {
+				System.out.println("物流数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res6 = zcrmViewSupplierSelService.insertBatchSuppliers();
+			if (!res6) {
+				System.out.println("供应商数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res7 = zcrmViewWhqohSelService.insertBatchWhqohs();
+			if (!res7) {
+				System.out.println("库存数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res8 = zcrmViewARBillHeadSelService.insertBatchCustomers();
+			if (!res8) {
+				System.out.println("应收单数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res9 = zcrmViewRecBillHeadSelService.insertBatchOperators();
+			if (!res9) {
+				System.out.println("收款单数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			boolean res10 = zcrmViewSalePriceSelService.insertBatchOperators();
+			if (!res10) {
+				System.out.println("销售价目表数据批量插入失败");
+				return ReturnT.FAIL;
+			}
+
+			return ReturnT.SUCCESS;
+		} catch (Exception e) {
+			String errorMsg = "XXL-JOB: U9数据完整同步失败:" + e.getMessage();
+			log.error(errorMsg, e);
+			return ReturnT.FAIL;
+		}
+	}
+
+	/**
+	 * 通用同步逻辑(通过Feign调用)
+	 *
+	 * @param syncTask 同步任务的具体逻辑
+	 * @param dataName 数据类型名称(用于日志和异常信息)
+	 */
+	private void executeSyncTask(Supplier<R<Boolean>> syncTask, String dataName) {
+		long startTime = System.currentTimeMillis();
+
+		try {
+			String startMsg = "XXL-JOB: 开始通过Feign同步U9【" + dataName + "】";
+			log.info(startMsg);
+
+			// 通过Feign调用远程服务
+			R<Boolean> result = syncTask.get();
+
+			// 独立判断逻辑,不依赖Func工具类
+			if (isSyncSuccess(result)) {
+				long endTime = System.currentTimeMillis();
+				String successMsg = String.format("XXL-JOB: U9【%s】同步成功,耗时:%s ms", dataName, (endTime - startTime));
+				log.info(successMsg);
+			} else {
+				String errorMsg = buildErrorMessage(dataName, result);
+				log.error(errorMsg);
+				throw new RuntimeException(errorMsg);
+			}
+
+		} catch (RuntimeException e) {
+			// 已知的业务异常,直接抛出
+			log.error("XXL-JOB: 业务异常:" + e.getMessage());
+			throw e;
+		} catch (Exception e) {
+			String errorMsg = "XXL-JOB: U9【" + dataName + "】同步失败:" + e.getMessage();
+			log.error(errorMsg, e);
+			throw new RuntimeException(errorMsg, e);
+		}
+	}
+
+	/**
+	 * 判断同步是否成功
+	 */
+	private boolean isSyncSuccess(R<Boolean> result) {
+		return result != null
+			&& result.isSuccess()
+			&& result.getData() != null
+			&& result.getData();
+	}
+
+	/**
+	 * 构建错误信息
+	 */
+	private String buildErrorMessage(String dataName, R<Boolean> result) {
+		if (result == null) {
+			return String.format("XXL-JOB: U9【%s】同步失败:返回结果为空", dataName);
+		} else if (!result.isSuccess()) {
+			return String.format("XXL-JOB: U9【%s】同步失败:%s", dataName, result.getMsg());
+		} else if (result.getData() == null) {
+			return String.format("XXL-JOB: U9【%s】同步失败:返回数据为空", dataName);
+		} else {
+			return String.format("XXL-JOB: U9【%s】同步失败:返回结果为false", dataName);
+		}
+	}
+}

+ 12 - 0
blade-service/blade-u9cloud/src/main/resources/application-dev.yml

@@ -8,3 +8,15 @@ spring:
     url: ${blade.datasource.dev.url}
     username: ${blade.datasource.dev.username}
     password: ${blade.datasource.dev.password}
+
+xxl:
+  job:
+    accessToken: ''
+    admin:
+      addresses: http://127.0.0.1:7009/xxl-job-admin
+    executor:
+      appname: blade-u9cloud
+      ip: 127.0.0.1
+      logpath: applogs/xxl-job/jobhandler
+      logretentiondays: -1
+      port: 8801

+ 12 - 0
blade-service/blade-u9cloud/src/main/resources/application-prod.yml

@@ -8,3 +8,15 @@ spring:
     url: ${blade.datasource.prod.url}
     username: ${blade.datasource.prod.username}
     password: ${blade.datasource.prod.password}
+
+xxl:
+  job:
+    accessToken: ''
+    admin:
+      addresses: http://127.0.0.1:7009/xxl-job-admin
+    executor:
+      appname: blade-u9cloud
+      ip: 127.0.0.1
+      logpath: applogs/xxl-job/jobhandler
+      logretentiondays: -1
+      port: 8801

+ 12 - 0
blade-service/blade-u9cloud/src/main/resources/application-test.yml

@@ -8,3 +8,15 @@ spring:
     url: ${blade.datasource.test.url}
     username: ${blade.datasource.test.username}
     password: ${blade.datasource.test.password}
+
+xxl:
+  job:
+    accessToken: ''
+    admin:
+      addresses: http://127.0.0.1:7009/xxl-job-admin
+    executor:
+      appname: blade-u9cloud
+      ip: 127.0.0.1
+      logpath: applogs/xxl-job/jobhandler
+      logretentiondays: -1
+      port: 8801