diff --git a/.DS_Store b/.DS_Store index 43b5d80..201926e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md b/doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md new file mode 100644 index 0000000..a93257b --- /dev/null +++ b/doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md @@ -0,0 +1,52 @@ +# 上虞对公利率测算字段对齐后端实施计划 + +## 目标 +- 对齐对公创建接口、模型调用入参、流程详情返回、mock 返回和 SQL 基线。 + +## 实施内容 +- 创建请求字段改为 Excel `上传指标` 口径: + - 新增 `repayMethod` + - `isTradeConstruction` 改为 `isTradeBuildEnt` + - 移除对公创建链路中的 `isAgriGuar`、`isTechEnt` +- 流程主表实体补 `repayMethod`,并将 `isTradeBuildEnt` 映射到数据库列 `is_trade_construction` +- 对公模型输出实体补齐: + - `repayMethod` + - `isTradeBuildEnt` + - `loanRateHistory` + - `minRateProduct` + - `smoothRange` + - `finalCalculateRate` + - `referenceRate` +- 对公模型输出实体不再暴露: + - `isAgriGuar` + - `midEntTax` + - `cardOverdue` +- 企业模型入参统一值域: + - `isGreenLoan`、`isTradeBuildEnt`、`collThirdParty` 发送 `0/1` + - `repayMethod` 发送 `分期/不分期` +- 企业流程详情主利率改为 `finalCalculateRate` +- mock 继续保留 `data.mappingOutputFields` 包装层,只更新企业字段集合和值域 + +## SQL 调整 +- `loan_pricing_workflow` 新增 `repay_method` +- `model_corp_output_fields` 新增: + - `repay_method` + - `is_trade_build_ent` + - `loan_rate_history` + - `min_rate_product` + - `smooth_range` + - `final_calculate_rate` + - `reference_rate` +- 已同步更新: + - `sql/loan_pricing_workflow.sql` + - `sql/model_corp.sql` + - `sql/loan_pricing_schema_20260328.sql` + - `sql/loan_pricing_prod_init_20260331.sql` + - `sql/2026-04-16-shangyu-corporate-alignment.sql` + +## 验证 +- 运行后端定向单测,确认对公字段和详情主利率断言通过 +- 使用 `/login/test` 获取 token 后调用对公创建和详情接口,确认: + - 正常场景成功 + - 缺少 `repayMethod` 返回校验错误 + - 详情返回包含新增字段且 `loanRate = finalCalculateRate` diff --git a/doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md b/doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md new file mode 100644 index 0000000..31a4664 --- /dev/null +++ b/doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md @@ -0,0 +1,48 @@ +# 上虞对公利率测算字段对齐前端实施计划 + +## 目标 +- 对齐对公新增弹窗和企业流程详情页展示,严格跟随 Excel `上传指标` 与 `展示指标`。 + +## 实施内容 +- 对公新增弹窗调整为 Excel `上传指标`: + - 新增 `repayMethod` + - `isTradeConstruction` 改为 `isTradeBuildEnt` + - 删除 `省农担担保贷款`、`科技型企业` + - `loanTerm` 文案改为按年 + - `collType` 选项改为 `一类/二类/三类/四类` + - `isGreenLoan`、`isTradeBuildEnt`、`collThirdParty` 提交值改为 `1/0` +- 企业详情左侧关键信息: + - 标签改为 `最终测算利率` + - 读取 `corpOutput.finalCalculateRate` +- 企业流程详情业务信息: + - 新增展示 `repayMethod` + - 新增展示 `isTradeBuildEnt` + - 保留 `isGreenLoan` + - 移除不在本次口径内的企业业务展示 +- 企业模型输出补齐展示: + - `repayMethod` + - `isTradeBuildEnt` + - `loanRateHistory` + - `minRateProduct` + - `smoothRange` + - `finalCalculateRate` + - `referenceRate` +- 企业模型输出移除展示: + - `isAgriGuar` + - `midEntTax` + - `cardOverdue` + +## 测试脚本 +- 新增: + - `ruoyi-ui/tests/corporate-create-input-params.test.js` + - `ruoyi-ui/tests/corporate-display-fields.test.js` +- 更新 `ruoyi-ui/package.json`,补充对应 npm scripts + +## 验证 +- `nvm use default` 后执行两个对公静态断言脚本 +- 执行前端生产构建 +- 启动前端页面并在浏览器中确认: + - 对公新增弹窗字段和选项正确 + - 创建成功后列表刷新 + - 企业详情页显示 `最终测算利率` + - 企业详情页和模型输出出现新增字段 diff --git a/doc/implementation-report-2026-04-16-shangyu-corporate-alignment.md b/doc/implementation-report-2026-04-16-shangyu-corporate-alignment.md new file mode 100644 index 0000000..22b5633 --- /dev/null +++ b/doc/implementation-report-2026-04-16-shangyu-corporate-alignment.md @@ -0,0 +1,38 @@ +# 上虞对公利率测算字段对齐实施记录 + +## 修改时间 +- 2026-04-16 + +## 修改内容 +- 对齐对公创建请求字段,新增 `repayMethod`,将 `isTradeConstruction` 统一为 `isTradeBuildEnt` +- 对齐企业详情返回与页面展示,左侧主利率改为 `finalCalculateRate` +- 对齐对公模型输出字段,补齐 `loanRateHistory`、`minRateProduct`、`smoothRange`、`finalCalculateRate`、`referenceRate` +- 裁剪企业模型输出和页面展示,不再暴露 `isAgriGuar`、`midEntTax`、`cardOverdue` +- 对公新增弹窗中的 `贷款期限(年)` 调整为下拉框,选项固定为 `1-10` 年 +- 更新企业 mock 返回和 SQL 基线、迁移脚本 + +## 文档与脚本 +- `doc/2026-04-16-shangyu-corporate-alignment-backend-plan.md` +- `doc/2026-04-16-shangyu-corporate-alignment-frontend-plan.md` +- `sql/2026-04-16-shangyu-corporate-alignment.sql` + +## 验证记录 +- 后端单测: + - `mvn -pl ruoyi-loan-pricing -Dtest=ModelCorpOutputFieldsTest,LoanPricingModelServiceTest,LoanPricingWorkflowServiceImplTest test` + - 结果:13 个测试全部通过 +- 前端静态断言: + - `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run test:corporate-create-input-params'` + - `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run test:corporate-display-fields'` + - 结果:两个脚本均通过 +- 前端构建: + - `zsh -lic 'nvm use default >/dev/null && npm --prefix ruoyi-ui run build:prod'` + - 结果:构建成功,仅有体积告警 +- 接口联调: + - 使用 `/login/test` 获取 token + - 验证了对公创建正常场景、缺少 `repayMethod` 的参数错误场景、`分期/不分期` 与 `1/0` 分支场景 + - 详情接口确认返回新增字段,且 `loanPricingWorkflow.loanRate = modelCorpOutputFields.finalCalculateRate` +- 浏览器联调: + - 启动前端开发服务并打开流程列表 + - 验证对公新增弹窗字段、选项、提交流程 + - 验证创建后列表新增记录 + - 验证企业详情页出现 `最终测算利率`、`还款方式`、`贸易和建筑业企业`、`历史利率`、`产品最低利率下限`、`平滑幅度`、`参考利率` diff --git a/doc/implementation-report-2026-04-16-workflow-detail-model-output-flat-display.md b/doc/implementation-report-2026-04-16-workflow-detail-model-output-flat-display.md new file mode 100644 index 0000000..d3b6762 --- /dev/null +++ b/doc/implementation-report-2026-04-16-workflow-detail-model-output-flat-display.md @@ -0,0 +1,21 @@ +# 流程详情页模型输出平铺展示实施记录 + +## 改动日期 +- 2026-04-16 + +## 改动范围 +- 前端:`ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue` +- 前端测试:`ruoyi-ui/tests/model-output-flat-display.test.js` +- 前端脚本:`ruoyi-ui/package.json` + +## 改动内容 +- 取消流程详情页“模型输出”区域的 Tab 切换结构。 +- 保留原有分组顺序与字段内容,将“基本信息”“忠诚度分析”“贡献度分析”等分组改为自上而下平铺展示。 +- 按最新要求,将“测算结果”分组前移到“基本信息”下方,优先展示最终测算相关结果。 +- 按最新要求,将“测算结果”中的“最终测算利率”调整到最后一行展示。 +- 移除组件内仅用于 Tab 默认选中的 `activeTab` 和相关监听逻辑。 +- 新增最小回归测试,校验模型输出组件不再包含 `el-tabs`、`el-tab-pane`,并具备平铺分组区块,同时校验“基本信息”后紧跟“测算结果”。 + +## 验证计划 +- 使用 `nvm` 显式切换前端 Node 版本后执行 `npm run test:model-output-flat-display`。 +- 启动前端页面,在浏览器中打开流程详情页,确认模型输出区域已按分组平铺展示,且不再出现 Tab 切换。 diff --git a/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx b/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx new file mode 100644 index 0000000..3c3a794 Binary files /dev/null and b/doc/~$上虞对公利率测算_上传字段与展示字段 .xlsx differ diff --git a/doc/上虞对公利率测算_上传字段与展示字段 .xlsx b/doc/上虞对公利率测算_上传字段与展示字段 .xlsx new file mode 100644 index 0000000..679fcd9 Binary files /dev/null and b/doc/上虞对公利率测算_上传字段与展示字段 .xlsx differ diff --git a/docs/superpowers/plans/2026-04-16-tongweb-access-backend-plan.md b/docs/superpowers/plans/2026-04-16-tongweb-access-backend-plan.md new file mode 100644 index 0000000..bbd638b --- /dev/null +++ b/docs/superpowers/plans/2026-04-16-tongweb-access-backend-plan.md @@ -0,0 +1,27 @@ +# TongWeb 接入后端实施文档 + +## 目标 + +按照 `tongweb/2026-04-16-TongWeb接入全流程通用指南.md` 在当前后端工程中接入东方通 TongWeb,替换默认内嵌 Tomcat,并将 license 文件随 `ruoyi-admin` 启动模块一起打包。 + +## 实施内容 + +1. 在 `ruoyi-admin/pom.xml` 增加 TongWeb Maven 仓库。 +2. 在 `ruoyi-admin/pom.xml` 对 `ruoyi-framework`、`ruoyi-loan-pricing` 依赖排除 `spring-boot-starter-tomcat`。 +3. 在 `ruoyi-admin/pom.xml` 引入 `com.tongweb.springboot:tongweb-spring-boot-starter-3.x:7.0.E.7`。 +4. 将 TongWeb license 复制到 `ruoyi-admin/src/main/resources/license.dat`,并在 `application.yml` 中配置 `server.tongweb.license.path=classpath:license.dat`。 +5. 增加资源存在性测试,验证 `license.dat` 可从 classpath 加载。 +6. 执行后端构建、依赖树、打包产物和测试验证,确认 TongWeb 依赖与 license 已正确接入。 + +## 变更说明 + +- 当前项目基于 Spring Boot 3.5.x,因此实际接入使用 `tongweb-spring-boot-starter-3.x`,版本号延续指南中的 `7.0.E.7`。 +- license 按本次要求保持文件名为 `license.dat`,不改名为 `Tongweb_license.dat`。 +- 现有 `application-dev.yml`、`application-pro.yml`、`application-uat.yml` 中的 `server.tomcat` 参数暂时保留,后续以 TongWeb 实际启动结果为准决定是否继续清理。 + +## 验证步骤 + +1. `mvn -pl ruoyi-admin -Dtest=TongWebLicenseResourceTest test` +2. `mvn -pl ruoyi-admin -am package -DskipTests` +3. `jar tf ruoyi-admin/target/ruoyi-admin.jar | rg 'license.dat|tongweb'` +4. `mvn -pl ruoyi-admin dependency:tree '-Dincludes=com.tongweb.springboot:*,com.tongweb:*,org.springframework.boot:spring-boot-starter-tomcat,org.apache.tomcat.embed:*'` diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 84c510f..13fe9d6 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -15,6 +15,20 @@ web服务入口 + + + tongweb-releases + TongWeb Maven Releases + https://mvn.elitescloud.com/nexus/repository/maven-releases/ + + true + + + false + + + + @@ -40,6 +54,12 @@ com.ruoyi ruoyi-framework + + + org.springframework.boot + spring-boot-starter-tomcat + + @@ -58,6 +78,18 @@ com.ruoyi ruoyi-loan-pricing + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + com.tongweb.springboot + tongweb-spring-boot-starter-3.x + 7.0.E.7 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 7ec4567..be8f1b0 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -1,4 +1,9 @@ # 项目相关配置 +server: + tongweb: + license: + path: classpath:license.dat + ruoyi: # 名称 name: RuoYi diff --git a/ruoyi-admin/src/main/resources/license.dat b/ruoyi-admin/src/main/resources/license.dat new file mode 100755 index 0000000..76964cd --- /dev/null +++ b/ruoyi-admin/src/main/resources/license.dat @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java index 875b8e0..8164ec1 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/CorporateLoanPricingCreateDTO.java @@ -41,24 +41,26 @@ public class CorporateLoanPricingCreateDTO implements Serializable { @NotBlank(message = "申请金额不能为空") private String applyAmt; - @Schema(description = "贷款期限", example = "36") + @Schema(description = "还款方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "分期", allowableValues = {"分期", "不分期"}) + @NotBlank(message = "还款方式不能为空") + @Pattern(regexp = "^(分期|不分期)$", message = "还款方式必须是:分期、不分期之一") + private String repayMethod; + + @Schema(description = "借款期限(年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "3") + @NotBlank(message = "贷款期限不能为空") private String loanTerm; - @Schema(description = "省农担担保贷款", example = "false") - private String isAgriGuar; - - @Schema(description = "绿色贷款", example = "true") + @Schema(description = "绿色贷款", example = "0") private String isGreenLoan; - @Schema(description = "科技型企业", example = "true") - private String isTechEnt; + @Schema(description = "贸易和建筑业企业标识", example = "0") + private String isTradeBuildEnt; - @Schema(description = "贸易和建筑业企业标识", example = "false") - private String isTradeConstruction; - - @Schema(description = "抵质押类型", example = "一类") + @Schema(description = "抵质押类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "一类", allowableValues = {"一类", "二类", "三类", "四类"}) + @NotBlank(message = "抵质押类型不能为空") + @Pattern(regexp = "^(一类|二类|三类|四类)$", message = "抵质押类型必须是:一类、二类、三类、四类之一") private String collType; - @Schema(description = "抵质押物是否三方所有", example = "false") + @Schema(description = "抵质押物是否三方所有", example = "0") private String collThirdParty; } diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java index d65bbfb..a77d866 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/dto/ModelInvokeDTO.java @@ -79,6 +79,12 @@ public class ModelInvokeDTO { */ private String loanTerm; + /** + * 还款方式(非必填) + * 可选值:分期/不分期 + */ + private String repayMethod; + /** * 净身企业(非必填) * 可选值:true/false @@ -98,10 +104,10 @@ public class ModelInvokeDTO { private String isManufacturing; /** - * 省农担担保贷款(非必填) - * 可选值:true/false + * 绿色贷款(非必填) + * 可选值:0/1 */ - private String isAgriGuar; + private String isGreenLoan; /** * 是否纳税信用等级A级(非必填) @@ -137,7 +143,7 @@ public class ModelInvokeDTO { /** * 抵质押类型(非必填) - * 可选值:一类/二类/三类 + * 可选值:一类/二类/三类/四类 */ private String collType; @@ -167,4 +173,10 @@ public class ModelInvokeDTO { */ private String idNum; + /** + * 贸易和建筑业企业(非必填) + * 可选值:0/1 + */ + private String isTradeBuildEnt; + } diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java index 8046e3c..64d47f4 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/LoanPricingWorkflow.java @@ -69,6 +69,11 @@ public class LoanPricingWorkflow implements Serializable */ private String loanTerm; + /** + * 还款方式: 分期/不分期 + */ + private String repayMethod; + /** 净身企业: true/false */ private String isCleanEnt; @@ -78,24 +83,17 @@ public class LoanPricingWorkflow implements Serializable /** 制造业企业: true/false */ private String isManufacturing; - /** 省农担担保贷款: true/false */ - private String isAgriGuar; - /** * 贸易和建筑业企业标识: true/false */ - private String isTradeConstruction; + @TableField("is_trade_construction") + private String isTradeBuildEnt; /** * 绿色贷款: true/false */ private String isGreenLoan; - /** - * 科技型企业: true/false - */ - private String isTechEnt; - /** 是否纳税信用等级A级: true/false */ private String isTaxA; @@ -111,7 +109,7 @@ public class LoanPricingWorkflow implements Serializable /** 循环功能: true/false */ private String loanLoop; - /** 抵质押类型: 一线/一类/二类 */ + /** 抵质押类型: 一类/二类/三类/四类 */ private String collType; /** 抵质押物是否三方所有: true/false */ diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java index c7ec5ad..f5b33d2 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/domain/entity/ModelCorpOutputFields.java @@ -31,6 +31,8 @@ public class ModelCorpOutputFields { private String idType; // 证件号码 private String idNum; + // 还款方式 + private String repayMethod; // 基准利率 private String baseLoanRate; // 我行首贷客户 @@ -65,8 +67,6 @@ public class ModelCorpOutputFields { private String midEntEleDdc; // 中间业务_企业_水费代扣 private String midEntWaterDdc; - // 中间业务_企业_税务代扣 - private String midEntTax; // BP_中间业务 private String bpMid; // 代发工资户数 @@ -79,12 +79,12 @@ public class ModelCorpOutputFields { private String isCleanEnt; // 开立基本结算账户 private String hasSettleAcct; - // 省农担担保贷款 - private String isAgriGuar; // 绿色贷款 private String isGreenLoan; // 科技型企业 private String isTechEnt; + // 贸易和建筑业企业 + private String isTradeBuildEnt; // BP_企业客户类别 private String bpEntType; // TOTAL_BP_关联度 @@ -109,8 +109,6 @@ public class ModelCorpOutputFields { private String prinOverdue; // 利息逾期 private String interestOverdue; - // 信用卡逾期 - private String cardOverdue; // BP_灰名单与逾期 private String bpGreyOverdue; // TOTAL_BP_风险度 @@ -119,6 +117,16 @@ public class ModelCorpOutputFields { private String totalBp; // 测算利率 private String calculateRate; + // 历史利率 + private String loanRateHistory; + // 产品最低利率下限 + private String minRateProduct; + // 平滑幅度 + private String smoothRange; + // 最终测算利率 + private String finalCalculateRate; + // 参考利率 + private String referenceRate; @TableField(fill = FieldFill.INSERT) private Date createTime; diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java index 05517d9..e987db3 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/LoanPricingModelService.java @@ -64,6 +64,10 @@ public class LoanPricingModelService { { normalizePersonalModelInvokeDTO(modelInvokeDTO); } + if ("企业".equals(loanPricingWorkflow.getCustType())) + { + normalizeCorporateModelInvokeDTO(modelInvokeDTO); + } JSONObject response = modelService.invokeModel(modelInvokeDTO); if (loanPricingWorkflow.getCustType().equals("个人")){ // 个人模型 @@ -95,6 +99,13 @@ public class LoanPricingModelService { modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); } + private void normalizeCorporateModelInvokeDTO(ModelInvokeDTO modelInvokeDTO) + { + modelInvokeDTO.setCollThirdParty(toZeroOne(modelInvokeDTO.getCollThirdParty())); + modelInvokeDTO.setIsGreenLoan(toZeroOne(modelInvokeDTO.getIsGreenLoan())); + modelInvokeDTO.setIsTradeBuildEnt(toZeroOne(modelInvokeDTO.getIsTradeBuildEnt())); + } + private String toZeroOne(String value) { if ("true".equals(value) || "1".equals(value)) diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java index 7c2f9a7..2a145da 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImpl.java @@ -181,7 +181,7 @@ public class LoanPricingWorkflowServiceImpl implements ILoanPricingWorkflowServi if (Objects.nonNull(modelCorpOutputFields)) { maskModelCorpOutputBasicInfo(modelCorpOutputFields); - loanPricingWorkflow.setLoanRate(modelCorpOutputFields.getCalculateRate()); + loanPricingWorkflow.setLoanRate(modelCorpOutputFields.getFinalCalculateRate()); } loanPricingWorkflowVO.setModelCorpOutputFields(modelCorpOutputFields); } diff --git a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java index ca0715e..e463dc6 100644 --- a/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java +++ b/ruoyi-loan-pricing/src/main/java/com/ruoyi/loanpricing/util/LoanPricingConverter.java @@ -54,13 +54,11 @@ public class LoanPricingConverter { entity.setIdNum(dto.getIdNum()); entity.setGuarType(dto.getGuarType()); entity.setApplyAmt(dto.getApplyAmt()); + entity.setRepayMethod(dto.getRepayMethod()); entity.setCollType(dto.getCollType()); entity.setCollThirdParty(dto.getCollThirdParty()); - // 映射企业特有字段 - entity.setIsAgriGuar(dto.getIsAgriGuar()); entity.setIsGreenLoan(dto.getIsGreenLoan()); - entity.setIsTechEnt(dto.getIsTechEnt()); - entity.setIsTradeConstruction(dto.getIsTradeConstruction()); + entity.setIsTradeBuildEnt(dto.getIsTradeBuildEnt()); entity.setLoanTerm(dto.getLoanTerm()); return entity; } diff --git a/ruoyi-loan-pricing/src/main/resources/data/corp_output.json b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json index 5752edc..080ea2d 100644 --- a/ruoyi-loan-pricing/src/main/resources/data/corp_output.json +++ b/ruoyi-loan-pricing/src/main/resources/data/corp_output.json @@ -3,66 +3,70 @@ "cost": 2267, "tokenId": "17364055486305E7F4722M8IPFWNL8TOBEB", "mappingOutputFields": { - "custIsn": "CUST20260121001", - "custType": "企业客户", - "guarType": "抵押担保", - "custName": "北京智联科技有限公司", - "idType": "营业执照", - "idNum": "91110108MA00XXXXXX", - "baseLoanRate": "3.45", - "isFirstLoan": "N", - "faithDay": "730", - "bpFirstLoan": "0", - "bpAgeLoan": "5.2", - "totalBpLoyalty": "8.5", - "balanceAvg": "5000000.00", - "loanAvg": "3000000.00", - "derivationRate": "1.8", - "totalBpContribution": "12.3", - "midEntConnect": "100000.00", - "midEntEffect": "50000.00", - "midEntInter": "80000.00", - "midEntAccept": "200000.00", - "midEntDiscount": "150000.00", - "midEntEleDdc": "30000.00", - "midEntWaterDdc": "10000.00", - "midEntTax": "40000.00", - "bpMid": "6.8", - "payroll": "200", - "invLoanAmount": "2500000.00", - "bpPayroll": "4.1", - "isCleanEnt": "Y", - "hasSettleAcct": "Y", - "isAgriGuar": "N", - "isGreenLoan": "Y", - "isTechEnt": "Y", - "bpEntType": "7.5", - "totoalBpRelevance": "9.2", - "loanTerm": "36", - "bpLoanTerm": "3.3", - "applyAmt": "5000000.00", - "bpLoanAmount": "5.8", - "collType": "房产抵押", - "collThirdParty": "N", - "bpCollateral": "4.5", - "greyCust": "N", - "prinOverdue": "N", - "interestOverdue": "N", - "cardOverdue": "N", - "bpGreyOverdue": "0", - "totoalBpRisk": "1.2", - "totalBp": "48.2", - "calculateRate": "3.932" + "custIsn": "CUST20260121001", + "custType": "企业", + "guarType": "抵押", + "custName": "北京智联科技有限公司", + "idType": "统一社会信用代码", + "idNum": "91110108MA00XXXXXX", + "repayMethod": "分期", + "loanTerm": "3", + "isFirstLoan": "0", + "faithDay": "730", + "bpFirstLoan": "0", + "bpAgeLoan": "5.2", + "totalBpLoyalty": "8.5", + "balanceAvg": "5000000.00", + "loanAvg": "3000000.00", + "derivationRate": "1.8", + "totalBpContribution": "12.3", + "midEntConnect": "1", + "midEntEffect": "1", + "midEntInter": "1", + "midEntAccept": "1", + "midEntDiscount": "1", + "midEntEleDdc": "1", + "midEntWaterDdc": "1", + "bpMid": "6.8", + "payroll": "200", + "invLoanAmount": "2500000.00", + "bpPayroll": "4.1", + "isCleanEnt": "1", + "hasSettleAcct": "1", + "isTradeBuildEnt": "0", + "isGreenLoan": "1", + "isTechEnt": "1", + "bpEntType": "7.5", + "totoalBpRelevance": "9.2", + "bpLoanTerm": "3.3", + "applyAmt": "5000000.00", + "bpLoanAmount": "5.8", + "collType": "一类", + "collThirdParty": "0", + "bpCollateral": "4.5", + "greyCust": "0", + "prinOverdue": "0", + "interestOverdue": "0", + "bpGreyOverdue": "0", + "totoalBpRisk": "1.2", + "totalBp": "48.2", + "baseLoanRate": "3.45", + "calculateRate": "3.932", + "loanRateHistory": "4.20", + "minRateProduct": "3.10", + "smoothRange": "-0.20", + "finalCalculateRate": "3.732", + "referenceRate": "3.432" }, "extensionMap": {}, "reasonMessage": "Running successfully", "bizTime": 1736405548630, "outputFields": {}, "workflowCode": "TBKH", - "orgCode": "802000", + "orgCode": "892000", "bizId": "2025010914345", "reasonCode": 200, "workflowVersion": 14, "callTime": 1736405548630, "status": 1 -} \ No newline at end of file +} diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java index e983273..a76133b 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/LoanPricingModelServiceTest.java @@ -87,4 +87,34 @@ class LoanPricingModelServiceTest !Objects.equals("张三", entity.getCustName()) && !Objects.equals("110101199001011234", entity.getIdNum()))); } + + @Test + void shouldNormalizeCorporateUploadParamsBeforeInvokeModel() + { + LoanPricingWorkflow workflow = new LoanPricingWorkflow(); + workflow.setId(3L); + workflow.setCustType("企业"); + workflow.setCustName("cipher-name"); + workflow.setIdNum("cipher-id"); + workflow.setRepayMethod("分期"); + workflow.setIsGreenLoan("true"); + workflow.setIsTradeBuildEnt("false"); + workflow.setCollThirdParty("true"); + + JSONObject response = new JSONObject(); + response.put("calculateRate", "4.15"); + + when(loanPricingWorkflowMapper.selectById(3L)).thenReturn(workflow); + when(sensitiveFieldCryptoService.decrypt("cipher-name")).thenReturn("测试公司"); + when(sensitiveFieldCryptoService.decrypt("cipher-id")).thenReturn("91330000123456789X"); + when(modelService.invokeModel(any())).thenReturn(response); + + loanPricingModelService.invokeModelAsync(3L); + + verify(modelService).invokeModel(argThat((ModelInvokeDTO dto) -> + Objects.equals("分期", dto.getRepayMethod()) + && Objects.equals("1", dto.getIsGreenLoan()) + && Objects.equals("0", dto.getIsTradeBuildEnt()) + && Objects.equals("1", dto.getCollThirdParty()))); + } } diff --git a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java index 542fade..dac8aa5 100644 --- a/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java +++ b/ruoyi-loan-pricing/src/test/java/com/ruoyi/loanpricing/service/impl/LoanPricingWorkflowServiceImplTest.java @@ -216,14 +216,16 @@ class LoanPricingWorkflowServiceImplTest ModelCorpOutputFields corpOutputFields = new ModelCorpOutputFields(); corpOutputFields.setCalculateRate("3.932"); + corpOutputFields.setFinalCalculateRate("3.652"); when(loanPricingWorkflowMapper.selectOne(any())).thenReturn(workflow); when(modelCorpOutputFieldsMapper.selectById(22L)).thenReturn(corpOutputFields); LoanPricingWorkflowVO result = loanPricingWorkflowService.selectLoanPricingBySerialNum("C20260328001"); - assertEquals("3.932", result.getLoanPricingWorkflow().getLoanRate()); + assertEquals("3.652", result.getLoanPricingWorkflow().getLoanRate()); assertEquals("3.932", result.getModelCorpOutputFields().getCalculateRate()); + assertEquals("3.652", result.getModelCorpOutputFields().getFinalCalculateRate()); } @Test diff --git a/ruoyi-ui/package.json b/ruoyi-ui/package.json index 5fbcc8a..c857296 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -11,8 +11,11 @@ "preview": "node build/index.js --preview", "test:password-transfer": "node tests/password-transfer-api.test.js", "test:retail-display-fields": "node tests/retail-display-fields.test.js", + "test:model-output-flat-display": "node tests/model-output-flat-display.test.js", "test:personal-create-input-params": "node tests/personal-create-input-params.test.js", - "test:id-number-validation-removal": "node tests/id-number-validation-removal.test.js" + "test:id-number-validation-removal": "node tests/id-number-validation-removal.test.js", + "test:corporate-create-input-params": "node tests/corporate-create-input-params.test.js", + "test:corporate-display-fields": "node tests/corporate-display-fields.test.js" }, "keywords": [ "vue", diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue index 44f906c..4a07d18 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateCreateDialog.vue @@ -53,8 +53,18 @@ - - + + + + + + + + + + + + @@ -62,26 +72,14 @@ 企业标识 - - - - - - - - - - - - - - + + @@ -92,9 +90,10 @@ - + + @@ -148,8 +147,6 @@ export default { const num = parseInt(value) if (isNaN(num) || num <= 0) { callback(new Error('请输入有效的贷款期限')) - } else if (num > 360) { - callback(new Error('贷款期限不能超过 360 个月')) } else { callback() } @@ -157,6 +154,9 @@ export default { } return { + loanTermOptions: [ + '1', '2', '3', '4', '5', '6', '7', '8', '9', '10' + ], submitting: false, form: { orgCode: '892000', @@ -168,10 +168,9 @@ export default { guarType: undefined, applyAmt: undefined, loanTerm: undefined, - isAgriGuar: false, + repayMethod: undefined, isGreenLoan: false, - isTechEnt: false, - isTradeConstruction: false, + isTradeBuildEnt: false, collType: undefined, collThirdParty: false }, @@ -197,7 +196,10 @@ export default { {required: true, validator: validateApplyAmt, trigger: "blur"} ], loanTerm: [ - {required: true, validator: validateLoanTerm, trigger: "blur"} + {required: true, validator: validateLoanTerm, trigger: "change"} + ], + repayMethod: [ + {required: true, message: "请选择还款方式", trigger: "change"} ], collType: [ {required: true, message: "请选择抵质押类型", trigger: "change"} @@ -235,10 +237,9 @@ export default { guarType: undefined, applyAmt: undefined, loanTerm: undefined, - isAgriGuar: false, + repayMethod: undefined, isGreenLoan: false, - isTechEnt: false, - isTradeConstruction: false, + isTradeBuildEnt: false, collType: undefined, collThirdParty: false } @@ -262,11 +263,9 @@ export default { // 转换开关值为字符串 const data = { ...this.form, - isAgriGuar: this.form.isAgriGuar ? 'true' : 'false', - isGreenLoan: this.form.isGreenLoan ? 'true' : 'false', - isTechEnt: this.form.isTechEnt ? 'true' : 'false', - isTradeConstruction: this.form.isTradeConstruction ? 'true' : 'false', - collThirdParty: this.form.collThirdParty ? 'true' : 'false' + isGreenLoan: this.form.isGreenLoan ? '1' : '0', + isTradeBuildEnt: this.form.isTradeBuildEnt ? '1' : '0', + collThirdParty: this.form.collThirdParty ? '1' : '0' } createCorporateWorkflow(data).then(response => { diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue index fe17473..68b9ffb 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/CorporateWorkflowDetail.vue @@ -19,7 +19,7 @@ {{ getTotalBp() }} - + {{ getCalculateRate() }} % @@ -80,12 +80,9 @@ {{ detailData.guarType }} {{ detailData.applyAmt }} 元 - {{ - formatBoolean(detailData.isAgriGuar) - }} - + {{ detailData.repayMethod || '-' }} {{ formatBoolean(detailData.isGreenLoan) }} - {{ formatBoolean(detailData.isTechEnt) }} + {{ formatBoolean(detailData.isTradeBuildEnt) }} {{ detailData.collType || '-' }} {{ formatBoolean(detailData.collThirdParty) @@ -162,9 +159,9 @@ export default { getTotalBp() { return this.corpOutput?.totalBp || '-' }, - /** 获取测算利率 */ + /** 获取最终测算利率 */ getCalculateRate() { - return this.corpOutput?.calculateRate || '-' + return this.corpOutput?.finalCalculateRate || '-' }, /** 设定执行利率 */ handleSetExecuteRate() { diff --git a/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue b/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue index 4aa649d..25edb02 100644 --- a/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue +++ b/ruoyi-ui/src/views/loanPricing/workflow/components/ModelOutputDisplay.vue @@ -3,11 +3,11 @@
模型输出
- +
- +
@@ -221,24 +225,6 @@ export default { default: null } }, - data() { - return { - activeTab: '' - } - }, - watch: { - custType: { - immediate: true, - handler(val) { - // 根据客户类型设置默认 tab - if (val === '个人') { - this.activeTab = 'retail-basic' - } else if (val === '企业') { - this.activeTab = 'corp-basic' - } - } - } - }, methods: { /** 格式化布尔值为中文 */ formatBoolean(value) { @@ -279,8 +265,15 @@ export default { padding: 20px; } - ::v-deep .el-tabs__header { - margin-bottom: 20px; + .output-section + .output-section { + margin-top: 24px; + } + + .section-title { + margin: 0 0 12px; + font-size: 15px; + font-weight: 500; + color: #303133; } // BP 值样式 diff --git a/sql/2026-04-16-shangyu-corporate-alignment.sql b/sql/2026-04-16-shangyu-corporate-alignment.sql new file mode 100644 index 0000000..41eb101 --- /dev/null +++ b/sql/2026-04-16-shangyu-corporate-alignment.sql @@ -0,0 +1,13 @@ +-- 上虞对公利率测算字段对齐 + +ALTER TABLE `loan_pricing_workflow` + ADD COLUMN `repay_method` varchar(20) DEFAULT NULL COMMENT '还款方式: 分期/不分期' AFTER `loan_term`; + +ALTER TABLE `model_corp_output_fields` + ADD COLUMN `repay_method` varchar(100) DEFAULT NULL COMMENT '还款方式' AFTER `id_num`, + ADD COLUMN `is_trade_build_ent` varchar(100) DEFAULT NULL COMMENT '贸易和建筑业企业' AFTER `is_tech_ent`, + ADD COLUMN `loan_rate_history` varchar(100) DEFAULT NULL COMMENT '历史利率' AFTER `calculate_rate`, + ADD COLUMN `min_rate_product` varchar(100) DEFAULT NULL COMMENT '产品最低利率下限' AFTER `loan_rate_history`, + ADD COLUMN `smooth_range` varchar(100) DEFAULT NULL COMMENT '平滑幅度' AFTER `min_rate_product`, + ADD COLUMN `final_calculate_rate` varchar(100) DEFAULT NULL COMMENT '最终测算利率' AFTER `smooth_range`, + ADD COLUMN `reference_rate` varchar(100) DEFAULT NULL COMMENT '参考利率' AFTER `final_calculate_rate`; diff --git a/sql/loan_pricing_prod_init_20260331.sql b/sql/loan_pricing_prod_init_20260331.sql index 7468d21..3ca837b 100644 --- a/sql/loan_pricing_prod_init_20260331.sql +++ b/sql/loan_pricing_prod_init_20260331.sql @@ -751,7 +751,8 @@ CREATE TABLE `loan_pricing_workflow` ( `mid_ent_ele_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_电费代扣: true/false', `mid_ent_water_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_水费代扣: true/false', `apply_amt` varchar(50) NOT NULL COMMENT '申请金额(元)', - `loan_term` varchar(50) DEFAULT NULL COMMENT '贷款期限', + `loan_term` varchar(50) DEFAULT NULL COMMENT '借款期限(年)', + `repay_method` varchar(20) DEFAULT NULL COMMENT '还款方式: 分期/不分期', `is_clean_ent` varchar(10) DEFAULT NULL COMMENT '净身企业: true/false', `has_settle_acct` varchar(10) DEFAULT NULL COMMENT '开立基本结算账户: true/false', `is_manufacturing` varchar(10) DEFAULT NULL COMMENT '制造业企业: true/false', @@ -764,7 +765,7 @@ CREATE TABLE `loan_pricing_workflow` ( `loan_purpose` varchar(20) DEFAULT NULL COMMENT '贷款用途: consumer-消费/business-经营', `biz_proof` varchar(10) DEFAULT NULL COMMENT '是否有经营佐证: true/false', `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false(贷款合同是否开通循环功能)', - `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一线/一类/二类', + `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一类/二类/三类/四类', `coll_third_party` varchar(10) DEFAULT NULL COMMENT '抵质押物是否三方所有: true/false', `loan_rate` varchar(20) DEFAULT NULL COMMENT '贷款利率', `execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)', @@ -800,6 +801,7 @@ CREATE TABLE `model_corp_output_fields` ( `cust_name` varchar(100) DEFAULT NULL COMMENT '客户名称', `id_type` varchar(100) DEFAULT NULL COMMENT '证件类型', `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码', + `repay_method` varchar(100) DEFAULT NULL COMMENT '还款方式', `base_loan_rate` varchar(100) DEFAULT NULL COMMENT '基准利率', `is_first_loan` varchar(100) DEFAULT NULL COMMENT '我行首贷客户', `faith_day` varchar(100) DEFAULT NULL COMMENT '用信天数', @@ -827,6 +829,7 @@ CREATE TABLE `model_corp_output_fields` ( `is_agri_guar` varchar(100) DEFAULT NULL COMMENT '省农担担保贷款', `is_green_loan` varchar(100) DEFAULT NULL COMMENT '绿色贷款', `is_tech_ent` varchar(100) DEFAULT NULL COMMENT '科技型企业', + `is_trade_build_ent` varchar(100) DEFAULT NULL COMMENT '贸易和建筑业企业', `bp_ent_type` varchar(100) DEFAULT NULL COMMENT 'BP_企业客户类别', `totoal_bp_relevance` varchar(100) DEFAULT NULL COMMENT 'TOTAL_BP_关联度', `loan_term` varchar(100) DEFAULT NULL COMMENT '贷款期限', @@ -844,6 +847,11 @@ CREATE TABLE `model_corp_output_fields` ( `totoal_bp_risk` varchar(100) DEFAULT NULL COMMENT 'TOTAL_BP_风险度', `total_bp` varchar(100) DEFAULT NULL COMMENT '浮动BP', `calculate_rate` varchar(100) DEFAULT NULL COMMENT '测算利率', + `loan_rate_history` varchar(100) DEFAULT NULL COMMENT '历史利率', + `min_rate_product` varchar(100) DEFAULT NULL COMMENT '产品最低利率下限', + `smooth_range` varchar(100) DEFAULT NULL COMMENT '平滑幅度', + `final_calculate_rate` varchar(100) DEFAULT NULL COMMENT '最终测算利率', + `reference_rate` varchar(100) DEFAULT NULL COMMENT '参考利率', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户贷款利率测算表'; diff --git a/sql/loan_pricing_schema_20260328.sql b/sql/loan_pricing_schema_20260328.sql index f02f608..8b33745 100644 --- a/sql/loan_pricing_schema_20260328.sql +++ b/sql/loan_pricing_schema_20260328.sql @@ -333,7 +333,8 @@ CREATE TABLE `loan_pricing_workflow` ( `mid_ent_ele_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_电费代扣: true/false', `mid_ent_water_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_水费代扣: true/false', `apply_amt` varchar(50) NOT NULL COMMENT '申请金额(元)', - `loan_term` varchar(50) DEFAULT NULL COMMENT '贷款期限', + `loan_term` varchar(50) DEFAULT NULL COMMENT '借款期限(年)', + `repay_method` varchar(20) DEFAULT NULL COMMENT '还款方式: 分期/不分期', `is_clean_ent` varchar(10) DEFAULT NULL COMMENT '净身企业: true/false', `has_settle_acct` varchar(10) DEFAULT NULL COMMENT '开立基本结算账户: true/false', `is_manufacturing` varchar(10) DEFAULT NULL COMMENT '制造业企业: true/false', @@ -346,7 +347,7 @@ CREATE TABLE `loan_pricing_workflow` ( `loan_purpose` varchar(20) DEFAULT NULL COMMENT '贷款用途: consumer-消费/business-经营', `biz_proof` varchar(10) DEFAULT NULL COMMENT '是否有经营佐证: true/false', `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false(贷款合同是否开通循环功能)', - `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一线/一类/二类', + `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一类/二类/三类/四类', `coll_third_party` varchar(10) DEFAULT NULL COMMENT '抵质押物是否三方所有: true/false', `loan_rate` varchar(20) DEFAULT NULL COMMENT '贷款利率', `execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)', @@ -382,6 +383,7 @@ CREATE TABLE `model_corp_output_fields` ( `cust_name` varchar(100) DEFAULT NULL COMMENT '客户名称', `id_type` varchar(100) DEFAULT NULL COMMENT '证件类型', `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码', + `repay_method` varchar(100) DEFAULT NULL COMMENT '还款方式', `base_loan_rate` varchar(100) DEFAULT NULL COMMENT '基准利率', `is_first_loan` varchar(100) DEFAULT NULL COMMENT '我行首贷客户', `faith_day` varchar(100) DEFAULT NULL COMMENT '用信天数', @@ -409,6 +411,7 @@ CREATE TABLE `model_corp_output_fields` ( `is_agri_guar` varchar(100) DEFAULT NULL COMMENT '省农担担保贷款', `is_green_loan` varchar(100) DEFAULT NULL COMMENT '绿色贷款', `is_tech_ent` varchar(100) DEFAULT NULL COMMENT '科技型企业', + `is_trade_build_ent` varchar(100) DEFAULT NULL COMMENT '贸易和建筑业企业', `bp_ent_type` varchar(100) DEFAULT NULL COMMENT 'BP_企业客户类别', `totoal_bp_relevance` varchar(100) DEFAULT NULL COMMENT 'TOTAL_BP_关联度', `loan_term` varchar(100) DEFAULT NULL COMMENT '贷款期限', @@ -426,6 +429,11 @@ CREATE TABLE `model_corp_output_fields` ( `totoal_bp_risk` varchar(100) DEFAULT NULL COMMENT 'TOTAL_BP_风险度', `total_bp` varchar(100) DEFAULT NULL COMMENT '浮动BP', `calculate_rate` varchar(100) DEFAULT NULL COMMENT '测算利率', + `loan_rate_history` varchar(100) DEFAULT NULL COMMENT '历史利率', + `min_rate_product` varchar(100) DEFAULT NULL COMMENT '产品最低利率下限', + `smooth_range` varchar(100) DEFAULT NULL COMMENT '平滑幅度', + `final_calculate_rate` varchar(100) DEFAULT NULL COMMENT '最终测算利率', + `reference_rate` varchar(100) DEFAULT NULL COMMENT '参考利率', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户贷款利率测算表'; diff --git a/sql/loan_pricing_workflow.sql b/sql/loan_pricing_workflow.sql index b81fa25..08c6956 100644 --- a/sql/loan_pricing_workflow.sql +++ b/sql/loan_pricing_workflow.sql @@ -14,20 +14,27 @@ CREATE TABLE `loan_pricing_workflow` ( `mid_ent_ele_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_电费代扣: true/false', `mid_ent_water_ddc` varchar(10) DEFAULT NULL COMMENT '中间业务_企业_水费代扣: true/false', `apply_amt` varchar(50) NOT NULL COMMENT '申请金额(元)', + `loan_term` varchar(50) DEFAULT NULL COMMENT '借款期限(年)', + `repay_method` varchar(20) DEFAULT NULL COMMENT '还款方式: 分期/不分期', `is_clean_ent` varchar(10) DEFAULT NULL COMMENT '净身企业: true/false', `has_settle_acct` varchar(10) DEFAULT NULL COMMENT '开立基本结算账户: true/false', `is_manufacturing` varchar(10) DEFAULT NULL COMMENT '制造业企业: true/false', `is_agri_guar` varchar(10) DEFAULT NULL COMMENT '省农担担保贷款: true/false', + `is_tech_ent` varchar(10) DEFAULT NULL COMMENT '科技型企业: true/false(科技型企业最多下降5BP)', + `is_green_loan` varchar(10) DEFAULT NULL COMMENT '绿色贷款: true/false(绿色贷款最多下降5BP)', + `is_trade_construction` varchar(10) DEFAULT NULL COMMENT '贸易和建筑业企业标识: true/false(抵质押类上调20BP)', `is_tax_a` varchar(10) DEFAULT NULL COMMENT '是否纳税信用等级A级: true/false', `is_agri_leading` varchar(10) DEFAULT NULL COMMENT '是否县级及以上农业龙头企业: true/false', `loan_purpose` varchar(20) DEFAULT NULL COMMENT '贷款用途: consumer-消费/business-经营', `biz_proof` varchar(10) DEFAULT NULL COMMENT '是否有经营佐证: true/false', - `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一线/一类/二类', + `loan_loop` varchar(10) DEFAULT NULL COMMENT '循环功能: true/false(贷款合同是否开通循环功能)', + `coll_type` varchar(20) DEFAULT NULL COMMENT '抵质押类型: 一类/二类/三类/四类', `coll_third_party` varchar(10) DEFAULT NULL COMMENT '抵质押物是否三方所有: true/false', - `loan_rate` varchar(20) NOT NULL COMMENT '贷款利率', + `loan_rate` varchar(20) DEFAULT NULL COMMENT '贷款利率', `execute_rate` varchar(20) DEFAULT NULL COMMENT '执行利率(%)', `cust_name` varchar(100) DEFAULT NULL COMMENT '客户名称', `id_type` varchar(50) DEFAULT NULL COMMENT '证件类型', + `id_num` varchar(100) DEFAULT NULL COMMENT '证件号码', `is_inclusive_finance` varchar(10) DEFAULT NULL COMMENT '是否普惠小微借款人: true/false', `create_by` varchar(64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', diff --git a/sql/model_corp.sql b/sql/model_corp.sql index 07ec0ca..c19d7db 100644 --- a/sql/model_corp.sql +++ b/sql/model_corp.sql @@ -3,57 +3,64 @@ */ DROP TABLE IF EXISTS model_corp_output_fields; CREATE TABLE `model_corp_output_fields` ( - `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', - `cust_isn` VARCHAR(100) COMMENT '客户内码', - `cust_type` VARCHAR(100) COMMENT '客户类型', - `guar_type` VARCHAR(100) COMMENT '担保方式', - `cust_name` VARCHAR(100) COMMENT '客户名称', - `id_type` VARCHAR(100) COMMENT '证件类型', - `id_num` VARCHAR(100) COMMENT '证件号码', - `base_loan_rate` VARCHAR(100) COMMENT '基准利率', - `is_first_loan` VARCHAR(100) COMMENT '我行首贷客户', - `faith_day` VARCHAR(100) COMMENT '用信天数', - `bp_first_loan` VARCHAR(100) COMMENT 'BP_首贷', - `bp_age_loan` VARCHAR(100) COMMENT 'BP_贷龄', - `total_bp_loyalty` VARCHAR(100) COMMENT 'TOTAL_BP_忠诚度', - `balance_avg` VARCHAR(100) COMMENT '存款年日均', - `loan_avg` VARCHAR(100) COMMENT '贷款年日均', - `derivation_rate` VARCHAR(100) COMMENT '派生率', - `total_bp_contribution` VARCHAR(100) COMMENT 'TOTAL_BP_贡献度', - `mid_ent_connect` VARCHAR(100) COMMENT '中间业务_企业_企业互联', - `mid_ent_effect` VARCHAR(100) COMMENT '中间业务_企业_有效价值客户', - `mid_ent_inter` VARCHAR(100) COMMENT '中间业务_企业_国际业务', - `mid_ent_accept` VARCHAR(100) COMMENT '中间业务_企业_承兑', - `mid_ent_discount` VARCHAR(100) COMMENT '中间业务_企业_贴现', - `mid_ent_ele_ddc` VARCHAR(100) COMMENT '中间业务_企业_电费代扣', - `mid_ent_water_ddc` VARCHAR(100) COMMENT '中间业务_企业_水费代扣', - `mid_ent_tax` VARCHAR(100) COMMENT '中间业务_企业_税务代扣', - `bp_mid` VARCHAR(100) COMMENT 'BP_中间业务', - `payroll` VARCHAR(100) COMMENT '代发工资户数', - `inv_loan_amount` VARCHAR(100) COMMENT '存量贷款余额', - `bp_payroll` VARCHAR(100) COMMENT 'BP_代发工资', - `is_clean_ent` VARCHAR(100) COMMENT '净身企业', - `has_settle_acct` VARCHAR(100) COMMENT '开立基本结算账户', - `is_agri_guar` VARCHAR(100) COMMENT '省农担担保贷款', - `is_green_loan` VARCHAR(100) COMMENT '绿色贷款', - `is_tech_ent` VARCHAR(100) COMMENT '科技型企业', - `bp_ent_type` VARCHAR(100) COMMENT 'BP_企业客户类别', - `totoal_bp_relevance` VARCHAR(100) COMMENT 'TOTAL_BP_关联度', - `loan_term` VARCHAR(100) COMMENT '贷款期限', - `bp_loan_term` VARCHAR(100) COMMENT 'BP_贷款期限', - `apply_amt` VARCHAR(100) COMMENT '申请金额', - `bp_loan_amount` VARCHAR(100) COMMENT 'BP_贷款额度', - `coll_type` VARCHAR(100) COMMENT '抵质押类型', - `coll_third_party` VARCHAR(100) COMMENT '抵质押物是否三方所有', - `bp_collateral` VARCHAR(100) COMMENT 'BP_抵押物', - `grey_cust` VARCHAR(100) COMMENT '灰名单客户', - `prin_overdue` VARCHAR(100) COMMENT '本金逾期', - `interest_overdue` VARCHAR(100) COMMENT '利息逾期', - `card_overdue` VARCHAR(100) COMMENT '信用卡逾期', - `bp_grey_overdue` VARCHAR(100) COMMENT 'BP_灰名单与逾期', - `totoal_bp_risk` VARCHAR(100) COMMENT 'TOTAL_BP_风险度', - `total_bp` VARCHAR(100) COMMENT '浮动BP', - `calculate_rate` VARCHAR(100) COMMENT '测算利率', - `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户贷款利率测算表'; \ No newline at end of file + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键ID', + `cust_isn` VARCHAR(100) COMMENT '客户内码', + `cust_type` VARCHAR(100) COMMENT '客户类型', + `guar_type` VARCHAR(100) COMMENT '担保方式', + `cust_name` VARCHAR(100) COMMENT '客户名称', + `id_type` VARCHAR(100) COMMENT '证件类型', + `id_num` VARCHAR(100) COMMENT '证件号码', + `repay_method` VARCHAR(100) COMMENT '还款方式', + `base_loan_rate` VARCHAR(100) COMMENT '基准利率', + `is_first_loan` VARCHAR(100) COMMENT '我行首贷客户', + `faith_day` VARCHAR(100) COMMENT '用信天数', + `bp_first_loan` VARCHAR(100) COMMENT 'BP_首贷', + `bp_age_loan` VARCHAR(100) COMMENT 'BP_贷龄', + `total_bp_loyalty` VARCHAR(100) COMMENT 'TOTAL_BP_忠诚度', + `balance_avg` VARCHAR(100) COMMENT '存款年日均', + `loan_avg` VARCHAR(100) COMMENT '贷款年日均', + `derivation_rate` VARCHAR(100) COMMENT '派生率', + `total_bp_contribution` VARCHAR(100) COMMENT 'TOTAL_BP_贡献度', + `mid_ent_connect` VARCHAR(100) COMMENT '中间业务_企业_企业互联', + `mid_ent_effect` VARCHAR(100) COMMENT '中间业务_企业_有效价值客户', + `mid_ent_inter` VARCHAR(100) COMMENT '中间业务_企业_国际业务', + `mid_ent_accept` VARCHAR(100) COMMENT '中间业务_企业_承兑', + `mid_ent_discount` VARCHAR(100) COMMENT '中间业务_企业_贴现', + `mid_ent_ele_ddc` VARCHAR(100) COMMENT '中间业务_企业_电费代扣', + `mid_ent_water_ddc` VARCHAR(100) COMMENT '中间业务_企业_水费代扣', + `mid_ent_tax` VARCHAR(100) COMMENT '中间业务_企业_税务代扣', + `bp_mid` VARCHAR(100) COMMENT 'BP_中间业务', + `payroll` VARCHAR(100) COMMENT '代发工资户数', + `inv_loan_amount` VARCHAR(100) COMMENT '存量贷款余额', + `bp_payroll` VARCHAR(100) COMMENT 'BP_代发工资', + `is_clean_ent` VARCHAR(100) COMMENT '净身企业', + `has_settle_acct` VARCHAR(100) COMMENT '开立基本结算账户', + `is_agri_guar` VARCHAR(100) COMMENT '省农担担保贷款', + `is_green_loan` VARCHAR(100) COMMENT '绿色贷款', + `is_tech_ent` VARCHAR(100) COMMENT '科技型企业', + `is_trade_build_ent` VARCHAR(100) COMMENT '贸易和建筑业企业', + `bp_ent_type` VARCHAR(100) COMMENT 'BP_企业客户类别', + `totoal_bp_relevance` VARCHAR(100) COMMENT 'TOTAL_BP_关联度', + `loan_term` VARCHAR(100) COMMENT '借款期限', + `bp_loan_term` VARCHAR(100) COMMENT 'BP_贷款期限', + `apply_amt` VARCHAR(100) COMMENT '申请金额', + `bp_loan_amount` VARCHAR(100) COMMENT 'BP_贷款额度', + `coll_type` VARCHAR(100) COMMENT '抵质押类型', + `coll_third_party` VARCHAR(100) COMMENT '抵质押物是否三方所有', + `bp_collateral` VARCHAR(100) COMMENT 'BP_抵押物', + `grey_cust` VARCHAR(100) COMMENT '灰名单客户', + `prin_overdue` VARCHAR(100) COMMENT '本金逾期', + `interest_overdue` VARCHAR(100) COMMENT '利息逾期', + `card_overdue` VARCHAR(100) COMMENT '信用卡逾期', + `bp_grey_overdue` VARCHAR(100) COMMENT 'BP_灰名单与逾期', + `totoal_bp_risk` VARCHAR(100) COMMENT 'TOTAL_BP_风险度', + `total_bp` VARCHAR(100) COMMENT '浮动BP', + `calculate_rate` VARCHAR(100) COMMENT '测算利率', + `loan_rate_history` VARCHAR(100) COMMENT '历史利率', + `min_rate_product` VARCHAR(100) COMMENT '产品最低利率下限', + `smooth_range` VARCHAR(100) COMMENT '平滑幅度', + `final_calculate_rate` VARCHAR(100) COMMENT '最终测算利率', + `reference_rate` VARCHAR(100) COMMENT '参考利率', + `create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='客户贷款利率测算表'; diff --git a/tongweb/2026-04-16-TongWeb接入全流程通用指南.md b/tongweb/2026-04-16-TongWeb接入全流程通用指南.md new file mode 100644 index 0000000..1c7d131 --- /dev/null +++ b/tongweb/2026-04-16-TongWeb接入全流程通用指南.md @@ -0,0 +1,410 @@ +# TongWeb接入全流程通用指南 + +## 1. 适用场景 + +本文档用于指导 Spring Boot 2.x 项目接入东方通 TongWeb 内嵌容器,适用于以下场景: + +- 现有项目默认使用 Spring Boot 内嵌 Tomcat。 +- 需要切换为 TongWeb 自启动运行。 +- 需要将 TongWeb license 文件随应用一起打包。 +- 需要沉淀一套可以迁移到其他项目的标准接入步骤。 + +本文以本仓库的接入经验为基础,输出的是一套可复用流程,而不是只面向当前项目的零散记录。 + +## 2. 前置准备 + +接入前需要准备以下信息: + +### 2.1 TongWeb Starter 依赖 + +当前使用的依赖坐标: + +```xml + + com.tongweb.springboot + tongweb-spring-boot-starter-2.x + 7.0.E.7 + +``` + +### 2.2 Maven 仓库 + +如果项目默认只配了 Maven Central 或阿里云公共仓库,TongWeb 依赖通常无法直接解析,需要补充 TongWeb 仓库: + +```xml + + + tongweb-releases + TongWeb Maven Releases + https://mvn.elitescloud.com/nexus/repository/maven-releases/ + + true + + + false + + + +``` + +### 2.3 License 文件 + +需要一份可用的 TongWeb license 文件,例如: + +- `Tongweb_license.dat` + +建议确认以下信息: + +- 许可证版本是否与目标 TongWeb 版本一致。 +- 许可证是否仍在有效期内。 +- 许可证是否允许当前部署规模使用。 + +## 3. 接入总流程 + +TongWeb 接入建议按下面顺序执行: + +1. 确认项目里是谁引入了默认 Tomcat。 +2. 排除默认 Tomcat 依赖。 +3. 引入 TongWeb Starter。 +4. 把 license 文件放入 `resources`。 +5. 在 `application.yml` 中增加 TongWeb 配置。 +6. 执行构建、依赖树、产物检查和启动验证。 +7. 根据日志处理依赖解析、license 不匹配、配置冲突等问题。 + +## 4. 依赖改造 + +### 4.1 找出默认 Tomcat 来源 + +很多项目不是在启动模块直接声明 `spring-boot-starter-web`,而是通过公共框架模块间接引入。因此第一步必须先查清默认 Tomcat 的入口来源。 + +例如: + +```xml + + org.springframework.boot + spring-boot-starter-web + +``` + +如果它出现在公共框架模块里,实际排除 Tomcat 时通常要在应用启动模块对该依赖做 `exclusion`。 + +### 4.2 排除默认 Tomcat + +推荐在最终启动模块中对上游框架模块做排除,避免默认内嵌 Tomcat 和 TongWeb 同时进入运行时: + +```xml + + com.xxx + project-framework + + + org.springframework.boot + spring-boot-starter-tomcat + + + +``` + +### 4.3 引入 TongWeb Starter + +在最终启动模块增加 TongWeb Starter: + +```xml + + com.tongweb.springboot + tongweb-spring-boot-starter-2.x + 7.0.E.7 + +``` + +### 4.4 资源打包 + +如果项目资源打包规则比较严格,建议显式保留 `resources` 配置,避免 `.dat` 文件没有进入产物: + +```xml + + + + src/main/resources + false + + **/* + + + + +``` + +## 5. License 文件接入 + +### 5.1 放置路径 + +将 TongWeb license 文件放到: + +```text +src/main/resources/Tongweb_license.dat +``` + +建议直接随项目源码管理,便于构建产物统一携带。 + +### 5.2 命名原则 + +配置中的文件名必须与实际资源名完全一致。例如资源名是: + +```text +Tongweb_license.dat +``` + +那么配置里也必须写: + +```text +classpath:Tongweb_license.dat +``` + +不要一个地方写 `license.dat`,另一个地方写 `Tongweb_license.dat`,否则运行时会直接出现 license 读取失败。 + +## 6. 配置接入 + +建议把 TongWeb 配置统一放到 `application.yml` 中,便于其他项目直接复用,而不是散落到多个环境文件。 + +推荐配置如下: + +```yml +server: + tongweb: + license: + path: classpath:Tongweb_license.dat +``` + +如果项目本身已经有 `server` 节点,直接挂到其下即可,不需要额外拆配置文件。 + +## 7. 构建与验证 + +接入完成后,至少执行下面几类验证。 + +### 7.1 依赖解析验证 + +```bash +mvn -pl ruoyi-admin -am package -DskipTests +``` + +预期: + +- TongWeb 依赖能够正常下载。 +- 项目可以正常构建。 + +### 7.2 产物检查 + +```bash +jar tf ruoyi-admin/target/ruoyi-admin.jar | rg 'Tongweb_license.dat|tongweb' +``` + +预期: + +- `Tongweb_license.dat` 已进入 `BOOT-INF/classes/` +- TongWeb 相关 jar 已进入 `BOOT-INF/lib/` + +### 7.3 依赖树检查 + +```bash +mvn -pl ruoyi-admin dependency:tree '-Dincludes=com.tongweb.springboot:*,com.tongweb:*,org.apache.tomcat.embed:*' +``` + +预期: + +- 能看到 TongWeb Starter 及相关依赖。 +- 默认 `spring-boot-starter-tomcat` 不应再作为主依赖链出现。 + +注意: + +- 某些项目中仍可能看到 `tomcat-embed-el`,它可能来自 `spring-boot-starter-validation` 等其他依赖。 +- 是否需要继续清理,最终以实际启动结果为准。 + +### 7.4 启动验证 + +建议从应用模块目录直接执行: + +```bash +mvn -f ruoyi-admin/pom.xml spring-boot:run -Dspring-boot.run.profiles=dev +``` + +这样可以避免从聚合工程根目录调用时,Maven 把插件错误落到父 `pom` 上。 + +验证重点: + +- 应用是否成功启动。 +- TongWeb License SDK 日志是否出现。 +- 端口是否成功监听。 +- 是否出现 TongWeb 与 Tomcat 的容器冲突报错。 + +### 7.5 启动后进程清理 + +如果是本地验证,结束测试后需要手动关闭 Java 进程,避免残留服务继续占用端口。 + +例如: + +```bash +lsof -nP -iTCP:63310 -sTCP:LISTEN +kill +``` + +## 8. 推荐自动化测试 + +如果项目有测试体系,建议至少补两类测试。 + +### 8.1 资源存在性测试 + +验证 license 文件能否从 classpath 读取: + +```java +assertNotNull( + TongWebLicenseResourceTest.class.getClassLoader().getResource("Tongweb_license.dat")); +``` + +### 8.2 配置存在性测试 + +验证 `application.yml` 中是否存在: + +```text +server.tongweb.license.path +``` + +这样可以避免后续重构时把 TongWeb 配置误删。 + +## 9. 常见问题 + +### 9.1 TongWeb 依赖下载失败 + +典型现象: + +- Maven 提示找不到 `tongweb-spring-boot-starter-2.x` + +原因: + +- 项目只配置了公共仓库,没有配置 TongWeb 专用仓库。 + +处理方式: + +- 补充 TongWeb Maven 仓库。 + +### 9.2 `spring-boot:run` 找不到插件 + +典型现象: + +- `No plugin found for prefix 'spring-boot'` + +处理方式: + +- 改为从子模块目录执行,或者用 `-f ruoyi-admin/pom.xml` 指向具体模块。 + +### 9.3 `spring-boot:run` 落到父工程 + +典型现象: + +- `Unable to find a suitable main class` + +原因: + +- Spring Boot 插件被执行在聚合父 `pom` 上。 + +处理方式: + +- 使用: + +```bash +mvn -f ruoyi-admin/pom.xml spring-boot:run +``` + +### 9.4 License 不匹配或已过期 + +典型现象: + +- 版本号不匹配告警 +- 有效期已过期 + +这类问题说明 TongWeb 配置链路通常已经生效,真正的问题是授权文件本身不适配当前环境。 + +处理方式: + +- 更换与目标 TongWeb 版本一致、且仍在有效期内的 license 文件。 + +### 9.5 项目里仍保留 `server.tomcat.*` + +如果项目原先已有: + +```yml +server: + tomcat: + ... +``` + +建议先不要大规模重构。 + +处理策略: + +- 若 TongWeb 启动时仅忽略这些配置,则先保留。 +- 只有当日志明确指出这些配置导致启动失败时,再做最小必要调整。 + +## 10. 可复制模板 + +### 10.1 `pom.xml` 最小改造模板 + +```xml + + com.xxx + project-framework + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + + com.tongweb.springboot + tongweb-spring-boot-starter-2.x + 7.0.E.7 + +``` + +### 10.2 `application.yml` 模板 + +```yml +server: + tongweb: + license: + path: classpath:Tongweb_license.dat +``` + +### 10.3 目录模板 + +```text +src/main/resources/Tongweb_license.dat +``` + +## 11. 最终检查清单 + +在其他项目复用时,可以按下面清单逐项确认: + +- 是否已确认默认 Tomcat 的引入来源 +- 是否已排除 `spring-boot-starter-tomcat` +- 是否已引入 TongWeb Starter +- 是否已配置 TongWeb Maven 仓库 +- 是否已将 `Tongweb_license.dat` 放入 `src/main/resources` +- 是否已在 `application.yml` 中加入 `server.tongweb.license.path` +- 是否已通过构建验证 +- 是否已确认产物中包含 TongWeb 相关 jar 与 license 文件 +- 是否已完成启动验证 +- 是否已确认 license 版本、有效期和授权范围可用 + +## 12. 结论 + +TongWeb 接入本质上只包含四件事: + +- 替换默认内嵌容器依赖 +- 接入 TongWeb 仓库与 Starter +- 让 license 文件进入 classpath +- 用启动日志验证 TongWeb 是否真正接管运行 + +只要按这个顺序执行,TongWeb 接入通常可以用最短路径完成,且这套流程可以直接迁移到其他 Spring Boot 项目中。 diff --git a/tongweb/license.dat b/tongweb/license.dat new file mode 100755 index 0000000..76964cd --- /dev/null +++ b/tongweb/license.dat @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/tongweb_63310.properties b/tongweb_63310.properties new file mode 100644 index 0000000..2ee39c0 --- /dev/null +++ b/tongweb_63310.properties @@ -0,0 +1,15 @@ +#TongTech License properties +#Thu Apr 16 16:56:43 CST 2026 +application.location=/Users/wkc/Desktop/loan-pricing/loan-pricing +license.create.date=2024-12-10 +license.customer.name=\u6D59\u6C5F\u519C\u6751\u5546\u4E1A\u8054\u5408\u94F6\u884C\u80A1\u4EFD\u6709\u9650\u516C\u53F8 +license.end.date=-1 +license.extern.properties.name=validateType,order_number,license_info +license.extern.properties.value=file,2024-2121,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 +license.file.content=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 +license.file.path=classpath\:license.dat +license.max.number=-1 +license.project.name=\u6D59\u6C5F\u519C\u6751\u5546\u4E1A\u8054\u5408\u94F6\u884C\u80A1\u4EFD\u6709\u9650\u516C\u53F8\u5173\u4E8E\u56FD\u4EA7\u5316\u5E94\u7528\u670D\u52A1\u5668\u4E2D\u95F4\u4EF6\u91C7\u8D2D +license.type=release +license.validate.type=file +server.number=7.0.E.7