Browse Source

提交修改

main
likunming 2 months ago
parent
commit
5497e89e2c
  1. 4
      gradle.properties
  2. 1
      irbs.cust.rating/build.gradle
  3. 11
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/RatingIndex.java
  4. 13
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/FinanceReportDetailsVo.java
  5. 11
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/RatingIndexVo.java
  6. 16
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/BusiProcessServiceImpl.java
  7. 8
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/CompanyRatingServiceImpl.java
  8. 163
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/FinanceReportDetailServiceImpl.java
  9. 14
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/FinanceReportIndexServiceImpl.java
  10. 16
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/MainScaleVersionServiceImpl.java
  11. 15
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/ModelLibServiceImpl.java
  12. 62
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/RatingIndexServiceImpl.java
  13. 2
      irbs.cust.rating/src/main/resources/META-INF/platform/plugins/liquibase.json
  14. 2
      irbs.cust.rating/src/main/resources/META-INF/platform/plugins/parameters.json
  15. 36
      irbs.cust.rating/src/main/resources/liquibase/20240321_CUST_RATING_DDL.xml
  16. 16
      irbs.defaultManager/src/main/java/irbs/defaultManager/service/impl/DefaultCognizanceServiceImpl.java
  17. 16
      irbs.defaultManager/src/main/java/irbs/defaultManager/service/impl/DefaultRebirthServiceImpl.java
  18. 16
      irbs.feature/src/main/java/irbs/feature/service/impl/CustFeatureCalcBatchServiceImpl.java
  19. 4
      irbs.frontend/.npmrc
  20. 16
      irbs.frontend/package.json
  21. 62
      irbs.frontend/public/webjars/tailwindcss/3.4.5/tailwind.css.js
  22. 4
      irbs.frontend/src/boostrap.ts
  23. 12
      irbs.frontend/src/components/index.ts
  24. 27
      irbs.frontend/src/routes/routes.json
  25. 167
      irbs.frontend/src/views/custRating/CustRating.ts
  26. 218
      irbs.frontend/src/views/custRating/CustRating.vue
  27. 5
      irbs.frontend/src/views/custRating/CustSeparateRating.vue
  28. 5
      irbs.frontend/src/views/custRating/FinancialRating.vue
  29. 349
      irbs.frontend/src/views/custRating/GrayModelDialog.vue
  30. 186
      irbs.frontend/src/views/custRating/LaunchRatingDialog.vue
  31. 2060
      irbs.frontend/src/views/custRating/RatingDialog.vue
  32. 31
      irbs.frontend/src/views/custRating/RatingLevel.vue
  33. 61
      irbs.frontend/src/views/custRating/RatingLevelSlider.vue
  34. 69
      irbs.frontend/src/views/custRating/company/AnnotationButton.vue
  35. 37
      irbs.frontend/src/views/custRating/company/Content.vue
  36. 21
      irbs.frontend/src/views/custRating/company/NextButton.vue
  37. 45
      irbs.frontend/src/views/custRating/company/RatingDialog.vue
  38. 23
      irbs.frontend/src/views/custRating/company/RatingManager.vue
  39. 71
      irbs.frontend/src/views/custRating/company/RatingPage.vue
  40. 58
      irbs.frontend/src/views/custRating/company/Step.vue
  41. 73
      irbs.frontend/src/views/custRating/company/TestCalcButton.vue
  42. 48
      irbs.frontend/src/views/custRating/company/WorkflowButton.vue
  43. 18
      irbs.frontend/src/views/custRating/company/content/AdjustItem.vue
  44. 68
      irbs.frontend/src/views/custRating/company/content/AdjustItemGrid.vue
  45. 36
      irbs.frontend/src/views/custRating/company/content/AdjustItemIndex.vue
  46. 38
      irbs.frontend/src/views/custRating/company/content/CreditReportGrid.vue
  47. 29
      irbs.frontend/src/views/custRating/company/content/CustBaseInfo.vue
  48. 61
      irbs.frontend/src/views/custRating/company/content/CustInfo.vue
  49. 46
      irbs.frontend/src/views/custRating/company/content/DefaultCognizanceGrid.vue
  50. 45
      irbs.frontend/src/views/custRating/company/content/DefaultRebirthGrid.vue
  51. 49
      irbs.frontend/src/views/custRating/company/content/FinanceProjectCompare.vue
  52. 74
      irbs.frontend/src/views/custRating/company/content/FinanceProjectGrid.vue
  53. 146
      irbs.frontend/src/views/custRating/company/content/FinanceReportGrid.vue
  54. 39
      irbs.frontend/src/views/custRating/company/content/FinanceReportTabs.vue
  55. 29
      irbs.frontend/src/views/custRating/company/content/FirstRatingResult.vue
  56. 51
      irbs.frontend/src/views/custRating/company/content/HistRatingGrid.vue
  57. 33
      irbs.frontend/src/views/custRating/company/content/HistTab.vue
  58. 40
      irbs.frontend/src/views/custRating/company/content/Opinion.vue
  59. 44
      irbs.frontend/src/views/custRating/company/content/OpinionGrid.vue
  60. 77
      irbs.frontend/src/views/custRating/company/content/Overturn.vue
  61. 106
      irbs.frontend/src/views/custRating/company/content/QualAnalysis.vue
  62. 51
      irbs.frontend/src/views/custRating/company/content/QuanAnalysis.vue
  63. 20
      irbs.frontend/src/views/custRating/company/content/QuanQualAnalysis.vue
  64. 36
      irbs.frontend/src/views/custRating/company/content/ReportIndex.vue
  65. 34
      irbs.frontend/src/views/custRating/company/content/ReportInfo.vue
  66. 157
      irbs.frontend/src/views/custRating/company/content/ReportRating.vue
  67. 82
      irbs.frontend/src/views/custRating/company/content/Timeline.vue
  68. 47
      irbs.frontend/src/views/custRating/company/ts/RequestApi.ts
  69. 18
      irbs.frontend/src/views/custRating/company/ts/Step.ts
  70. 80
      irbs.frontend/src/views/custRating/company/ts/Utils.ts
  71. 9
      irbs.frontend/src/views/custRating/mock/MockCmis.vue
  72. 12
      irbs.frontend/src/views/debtRating/LgdQuery.vue
  73. 67
      irbs.frontend/src/views/default/CognizanceApply.vue
  74. 16
      irbs.frontend/src/views/report/RptRatingAdjust.vue
  75. 32
      irbs.frontend/src/views/report/RptRatingChange.vue
  76. 22
      irbs.frontend/src/views/report/RptRatingDistribution.vue
  77. 7
      irbs.frontend/src/views/report/RptRatingIndustryFocusDist.vue
  78. 10
      irbs.frontend/src/views/report/RptRatingLoanBalanceMigrate.vue
  79. 8
      irbs.frontend/src/views/report/RptRatingModelFocusDist.vue
  80. 10
      irbs.frontend/src/views/report/RptRatingNumberMigrate.vue
  81. 8
      irbs.frontend/src/views/report/RptRatingOrgFocusDist.vue
  82. 20
      irbs.frontend/src/views/report/RptRatingOverturn.vue
  83. 11
      irbs.frontend/webpack.config.mf.cjs
  84. 16
      irbs.riskExposure/src/main/java/irbs/riskExposure/service/impl/RiskExposureFlowServiceImpl.java
  85. 2
      irbs.shrcb.poc.frontend/.npmrc
  86. 16
      irbs.shrcb.poc.frontend/package.json
  87. 62
      irbs.shrcb.poc.frontend/public/webjars/tailwindcss/3.4.5/tailwind.css.js
  88. 4
      irbs.shrcb.poc.frontend/src/boostrap.ts
  89. 11
      irbs.shrcb.poc.frontend/webpack.config.mf.cjs

4
gradle.properties

@ -36,9 +36,9 @@ application_version=1.0.1
# platform
###########################################################rwa_version
platform_group=io.sc
platform_version=8.2.11
platform_version=8.2.23
platform_plugin_version=8.2.10
platform_core_frontend_version=8.2.50
platform_core_frontend_version=8.2.84
###########################################################
# product dependencies version

1
irbs.cust.rating/build.gradle

@ -4,6 +4,7 @@ dependencies {
"io.sc:io.sc.engine.rule.client.spring:${platform_version}",
"io.sc:io.sc.platform.flowable:${platform_version}",
"io.sc:io.sc.platform.lcdp:${platform_version}",
"io.sc:io.sc.standard:${platform_version}",
project(":irbs.defaultManager"),
project(":irbs.financialTemplate"),

11
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/RatingIndex.java

@ -91,6 +91,8 @@ public class RatingIndex extends CorporationAuditorEntity<RatingIndexVo> {
@Transient
protected List<RatingSelectValuesConfig> options;
@Transient
protected List<RatingQualIndexAddtion> addtions;
public RatingIndex() {
}
@ -148,6 +150,7 @@ public class RatingIndex extends CorporationAuditorEntity<RatingIndexVo> {
vo.setIndexScore(this.getIndexScore());
vo.setIndexScoreGray(this.getIndexScoreGray());
vo.setOptions(this.getOptions());
vo.setAddtions(this.getAddtions());
return vo;
}
@ -286,4 +289,12 @@ public class RatingIndex extends CorporationAuditorEntity<RatingIndexVo> {
public void setOptions(List<RatingSelectValuesConfig> options) {
this.options = options;
}
public List<RatingQualIndexAddtion> getAddtions() {
return addtions;
}
public void setAddtions(List<RatingQualIndexAddtion> addtions) {
this.addtions = addtions;
}
}

13
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/FinanceReportDetailsVo.java

@ -21,6 +21,11 @@ public class FinanceReportDetailsVo extends BaseVo {
*/
private String name;
/**
* 缩进
*/
private Integer tab;
/**
* 科目本期值
*/
@ -65,6 +70,14 @@ public class FinanceReportDetailsVo extends BaseVo {
this.name = name;
}
public Integer getTab() {
return tab;
}
public void setTab(Integer tab) {
this.tab = tab;
}
public BigDecimal getValue() {
return value;
}

11
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/RatingIndexVo.java

@ -1,6 +1,7 @@
package irbs.cust.rating.jpa.vo;
import io.sc.platform.orm.api.vo.CorporationAuditorVo;
import irbs.cust.rating.jpa.entity.RatingQualIndexAddtion;
import irbs.cust.rating.jpa.entity.RatingSelectValuesConfig;
import javax.persistence.Column;
@ -59,6 +60,8 @@ public class RatingIndexVo extends CorporationAuditorVo {
private List<RatingSelectValuesConfig> options;
private List<RatingQualIndexAddtion> addtions;
public String getId() {
return id;
}
@ -194,4 +197,12 @@ public class RatingIndexVo extends CorporationAuditorVo {
public void setOptions(List<RatingSelectValuesConfig> options) {
this.options = options;
}
public List<RatingQualIndexAddtion> getAddtions() {
return addtions;
}
public void setAddtions(List<RatingQualIndexAddtion> addtions) {
this.addtions = addtions;
}
}

16
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/BusiProcessServiceImpl.java

@ -47,14 +47,14 @@ public class BusiProcessServiceImpl implements BusiProcessService {
@Override
public ProcessTaskWrapper findTaskByProcInstId(String procInstId) throws Exception {
ProcessTaskWrapper taskWrapper = null;
// QueryParameter parameter = new QueryParameter();
// parameter.setPageable(false);
// Equals eq = new Equals();
// eq.setFieldName("processInstanceId");
// eq.setValue(procInstId);
// parameter.addCriteria(eq);
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
Equals eq = new Equals();
eq.setFieldName("processInstanceId");
eq.setValue(procInstId);
parameter.addCriteria(eq);
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
if (null != list && list.size() > 1) {
// 同一个流程实例查找出多个任务则为多实例任务,还需再根据任务处理人匹配。
List<ProcessTaskWrapper> userTaskList = list.stream().filter(task-> SecurityUtil.getLoginName().equals(task.getAssignee())).collect(Collectors.toList());

8
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/CompanyRatingServiceImpl.java

@ -62,6 +62,8 @@ public class CompanyRatingServiceImpl extends DaoServiceImpl<CompanyRating, Stri
private ProcessEngine processEngine;
@Autowired
private MainScaleVersionRepository mainScaleVersionRepository;
@Autowired
private BusinessCodeService businessCodeService;
@Override
public Page<CompanyRatingVo> pageQuery(QueryParameter queryParameter) throws Exception {
@ -104,7 +106,9 @@ public class CompanyRatingServiceImpl extends DaoServiceImpl<CompanyRating, Stri
if(null == companyCustomer.getMgerNo() || "".equals(companyCustomer.getMgerNo())){
throw new RuntimeException("客户经理为空");
}
CompanyRating companyRating = new CompanyRating();
companyRating.setTriggerRea(businessCodeService.getBusinessCode("R", BusinessCodeSuffix.YYYYMMDD, 3));
companyRating.setCustNo(companyCustomer.getCustNo());
companyRating.setCustName(companyCustomer.getCustName());
companyRating.setManagerName(companyCustomer.getMgerCna());
@ -136,7 +140,7 @@ public class CompanyRatingServiceImpl extends DaoServiceImpl<CompanyRating, Stri
}
}
if (RatingStepType.CHECK_FINISH.getText().equals(companyRating.getCurrentStep())){
// TODO 20240329 跳过上述步骤,直接生并启动流程
// TODO 20240329 跳过上述步骤,直接生并启动流程
if(customer == null) {
customer = ratingCompanyCustomerService.findById(companyRating.getCustId());
}
@ -314,6 +318,8 @@ public class CompanyRatingServiceImpl extends DaoServiceImpl<CompanyRating, Stri
// CompanyRatingProcDealImpl.class
);
companyRating.setProcessInstanceId(processInstance.getProcessInstanceId());
ProcessTaskWrapper ptw = busiProcessService.findTaskByProcInstId(processInstance.getId());
companyRating.setTaskId(ptw.getId());
getRepository().save(companyRating);
}

163
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/FinanceReportDetailServiceImpl.java

@ -5,7 +5,13 @@ import io.sc.platform.orm.service.impl.DaoServiceImpl;
import io.sc.platform.orm.service.support.OperatorType;
import io.sc.platform.orm.service.support.QueryParameter;
import io.sc.platform.orm.service.support.criteria.Criteria;
import io.sc.platform.orm.service.support.criteria.impl.Equals;
import io.sc.platform.orm.service.support.criteria.impl.InSet;
import io.sc.standard.api.enums.FinancialReportingStandard;
import io.sc.standard.api.enums.FinancialReportingSubjectCategory;
import io.sc.standard.api.enums.FinancialReportingType;
import io.sc.standard.jpa.entity.FinancialReportingSubjectEntity;
import io.sc.standard.service.FinancialReportingSubjectService;
import irbs.cust.rating.jpa.entity.FinanceReport;
import irbs.cust.rating.jpa.entity.FinanceReportDetail;
import irbs.cust.rating.jpa.entity.RatingCompanyCustomer;
@ -17,9 +23,7 @@ import irbs.cust.rating.service.RatingCompanyCustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
@Service("financeReportDetailService")
@ -29,39 +33,52 @@ public class FinanceReportDetailServiceImpl extends DaoServiceImpl<FinanceReport
private RatingCompanyCustomerService ratingCompanyCustomerService;
@Autowired
private FinanceReportRepository financeReportRepository;
@Autowired
private FinancialReportingSubjectService financialReportingSubjectService;
@Override
public List<FinanceReportDetailsVo> queryDetail(String custId, QueryParameter queryParameter) throws Exception {
List<String> reportIds = getReportIds(custId);
RatingCompanyCustomer customer = ratingCompanyCustomerService.findById(custId);
Equals eq = (Equals) queryParameter.getCriteriaByFieldName("projectType");
String projectType = eq.getValue();
List<FinanceReportDetailsVo> result = new ArrayList<>();
// 获得报告ID集合
List<String> reportIds = getReportIds(customer);
addCriteria(reportIds, queryParameter);
// 查询财报数据
List<FinanceReportDetail> list = this.list(queryParameter);
List<FinanceReportDetailsVo> result = new ArrayList<>();
resultHandler(reportIds, list, result);
// 查询标准财报模板
List<FinancialReportingSubjectEntity> sdSubjectList = listSdSubject(projectType, customer);
// 结果处理
resultHandler(reportIds, list, result, sdSubjectList);
return result;
}
private void resultHandler(List<String> reportIds, List<FinanceReportDetail> list, List<FinanceReportDetailsVo> result) throws Exception {
private void resultHandler(List<String> reportIds, List<FinanceReportDetail> list, List<FinanceReportDetailsVo> result, List<FinancialReportingSubjectEntity> sdSubjectList) throws Exception {
List<FinanceReportDetail> currList = null;
List<FinanceReportDetail> previousPeriodList = new ArrayList<>();
List<FinanceReportDetail> previousPeriod2List = new ArrayList<>();
List<FinanceReportDetail> previousPeriod3List = new ArrayList<>();
if (list!=null && list.size()>0) {
Map<String, List<FinanceReportDetail>> map = list.stream().collect(Collectors.groupingBy(FinanceReportDetail::getReportId));
//以本期值为基础
List<FinanceReportDetail> currList = map.get(reportIds.get(0));
currList = map.get(reportIds.get(0));
// 上期值
List<FinanceReportDetail> previousPeriodList = new ArrayList<>();
if (reportIds.size() > 1 && map.containsKey(reportIds.get(1))) {
previousPeriodList = map.get(reportIds.get(1));
}
// 上2期值
List<FinanceReportDetail> previousPeriod2List = new ArrayList<>();
if (reportIds.size() > 2 && map.containsKey(reportIds.get(2))) {
previousPeriod2List = map.get(reportIds.get(2));
}
// 上3期值
List<FinanceReportDetail> previousPeriod3List = new ArrayList<>();
if (reportIds.size() > 3 && map.containsKey(reportIds.get(3))) {
previousPeriod3List = map.get(reportIds.get(3));
}
list2ListVo(currList, result, previousPeriodList, previousPeriod2List, previousPeriod3List);
}
list2ListVo(currList, result, previousPeriodList, previousPeriod2List, previousPeriod3List, sdSubjectList);
}
private void list2ListVo(
@ -69,30 +86,105 @@ public class FinanceReportDetailServiceImpl extends DaoServiceImpl<FinanceReport
List<FinanceReportDetailsVo> listVo,
List<FinanceReportDetail> previousPeriodList,
List<FinanceReportDetail> previousPeriod2List,
List<FinanceReportDetail> previousPeriod3List
) {
for(FinanceReportDetail frd: list) {
FinanceReportDetailsVo vo = new FinanceReportDetailsVo();
vo.setId(frd.getId());
vo.setCode(frd.getProjectCode());
vo.setName(frd.getProjectName());
vo.setValue(frd.getProjectValue());
if (previousPeriodList.size() > 0) {
FinanceReportDetail tmp = previousPeriodList.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriodvalue(tmp.getProjectValue());
}
if (previousPeriod2List.size() > 0) {
FinanceReportDetail tmp = previousPeriod2List.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriod2value(tmp.getProjectValue());
}
if (previousPeriod3List.size() > 0) {
FinanceReportDetail tmp = previousPeriod3List.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriod3value(tmp.getProjectValue());
List<FinanceReportDetail> previousPeriod3List,
List<FinancialReportingSubjectEntity> sdSubjectList
) throws Exception {
if (sdSubjectList!=null) {
for (FinancialReportingSubjectEntity frse: sdSubjectList) {
FinanceReportDetailsVo vo = new FinanceReportDetailsVo();
if (list!=null) {
Optional<FinanceReportDetail> optionalEntity = list.stream()
.filter(entity -> entity != null && entity.getProjectCode().equals(frse.getMappingCode()))
.findFirst();
optionalEntity.ifPresent(frd -> {
// 处理找到的实体
vo.setId(frd.getId());
vo.setValue(frd.getProjectValue());
if (previousPeriodList.size() > 0) {
FinanceReportDetail tmp = previousPeriodList.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriodvalue(tmp.getProjectValue());
}
if (previousPeriod2List.size() > 0) {
FinanceReportDetail tmp = previousPeriod2List.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriod2value(tmp.getProjectValue());
}
if (previousPeriod3List.size() > 0) {
FinanceReportDetail tmp = previousPeriod3List.stream().filter(entity -> entity.getProjectCode().equals(frd.getProjectCode())).findFirst().get();
vo.setPreviousPeriod3value(tmp.getProjectValue());
}
});
}
vo.setCode(frse.getCode());
vo.setName(frse.getName());
vo.setTab(frse.getTab());
listVo.add(vo);
}
listVo.add(vo);
}
}
/**
* 获取数据标准中财报模板
* @return
* @throws Exception
*/
private List<FinancialReportingSubjectEntity> listSdSubject(String projectType, RatingCompanyCustomer customer) throws Exception {
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
List<String> sortList = new ArrayList();
sortList.add("category");
sortList.add("row");
parameter.setSortBy(sortList);
Equals standard = new Equals<String>();
standard.setFieldName("standard");
standard.setValue(FinancialReportingStandard.NEW.name());
parameter.addCriteria(standard);
Equals type = new Equals<String>();
type.setFieldName("type");
if (!customer.getCustomerType().equals("1")) {
type.setValue(FinancialReportingType.INSTITUTION.name());
} else {
type.setValue(FinancialReportingType.COMPANY.name());
}
parameter.addCriteria(type);
if (projectType.equals("01")) {
String[] values = new String[]{FinancialReportingSubjectCategory.COMPANY_ASSETS.name(), FinancialReportingSubjectCategory.COMPANY_LIABILITIES_AND_OWNERS_EQUITY.name()};
// 企业类资产负债表
InSet categorys = new InSet();
categorys.setFieldName("category");
categorys.setValue(values);
parameter.addCriteria(categorys);
} else if (projectType.equals("02")) {
// 企业类现金流表
Equals category = new Equals<>();
category.setFieldName("category");
category.setValue(FinancialReportingSubjectCategory.COMPANY_CASH_FLOWS.name());
parameter.addCriteria(category);
} else if (projectType.equals("03")) {
// 企业类损益表
Equals category = new Equals<>();
category.setFieldName("category");
category.setValue(FinancialReportingSubjectCategory.COMPANY_PROFIT.name());
parameter.addCriteria(category);
} else if (projectType.equals("11")) {
// 事业类资产负债表
InSet categorys = new InSet();
categorys.setFieldName("category");
categorys.setValue(new String[]{FinancialReportingSubjectCategory.INSTITUTION_ASSETS.name(), FinancialReportingSubjectCategory.INSTITUTION_LIABILITIES_AND_NET_ASSETS.name()});
parameter.addCriteria(categorys);
} else if (projectType.equals("12")) {
// 事业类收入支出表
InSet categorys = new InSet();
categorys.setFieldName("category");
categorys.setValue(new String[]{FinancialReportingSubjectCategory.INSTITUTION_INCOME_AND_EXPENSES.name(), FinancialReportingSubjectCategory.INSTITUTION_CASH_FLOWS.name()});
parameter.addCriteria(categorys);
sortList = new ArrayList();
sortList.add("-category");
sortList.add("row");
parameter.setSortBy(sortList);
}
return financialReportingSubjectService.list(parameter);
}
private void addCriteria(List<String> reportIds, QueryParameter queryParameter) throws Exception {
InSet inSet = new InSet();
inSet.setFieldName("reportId");
@ -107,17 +199,16 @@ public class FinanceReportDetailServiceImpl extends DaoServiceImpl<FinanceReport
/**
* 根据客户ID查询最新多期报表ID企业类3期其他4期
* @param custId
* @param customer
* @return
* @throws Exception
*/
private List<String> getReportIds(String custId) throws Exception {
RatingCompanyCustomer customer = ratingCompanyCustomerService.findById(custId);
private List<String> getReportIds(RatingCompanyCustomer customer) throws Exception {
Integer periodNum = 3;
if (!customer.getCustomerType().equals("1")) {
periodNum = 4;
}
List<FinanceReport> reports = financeReportRepository.findByCustIdOrderByEndDateDesc(custId);
List<FinanceReport> reports = financeReportRepository.findByCustIdOrderByEndDateDesc(customer.getId());
List<String> reportIds = new ArrayList<>();
if (reports!=null && reports.size() > 0) {
if (reports.size() <= periodNum) {

14
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/FinanceReportIndexServiceImpl.java

@ -1,8 +1,9 @@
package irbs.cust.rating.service.impl;
import io.sc.engine.rule.client.spring.service.ExecutorFactoryService;
import io.sc.engine.rule.core.ExecuteResult;
import io.sc.engine.rule.core.ParameterResult;
import io.sc.engine.rule.core.ResourceResult;
import io.sc.engine.rule.core.client.Executor;
import io.sc.platform.mvc.service.SystemParameterService;
import irbs.cust.rating.jpa.entity.FinanceReport;
import irbs.cust.rating.jpa.entity.FinanceReportDetail;
@ -15,9 +16,6 @@ import irbs.cust.rating.service.FinanceReportService;
import liquibase.repackaged.org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.ExecutorBuilder;
import io.sc.engine.rule.client.enums.ExecutorMode;
import java.math.BigDecimal;
import java.util.ArrayList;
@ -88,8 +86,8 @@ public class FinanceReportIndexServiceImpl implements FinanceReportIndexService
}
kiMap.put("QYCB1",lastMap);
// 调用模型引擎
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeByCode("QYCW_ZB",null,kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeByCode("QYCW_ZB",null,kiMap);
if(result != null && CollectionUtils.isNotEmpty(result.getData())) {
List<ParameterResult> results = result.getData();
List<FinanceReportResult> res = new ArrayList<>();
@ -177,8 +175,8 @@ public class FinanceReportIndexServiceImpl implements FinanceReportIndexService
// 调用模型引擎
// String modelResourceUrl = systemParameterService.getParameter("parameter.irbs.engine.remote.config.re.url");
// Executor executor = new ExecutorBuilder().executor(ExecutorMode.REMOTE).url(modelResourceUrl).build();
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeByCode("SYCW_ZB",null,kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeByCode("SYCW_ZB",null,kiMap);
if(result != null && CollectionUtils.isNotEmpty(result.getData())) {
List<ParameterResult> results = result.getData();
List<FinanceReportResult> res = new ArrayList<>();

16
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/MainScaleVersionServiceImpl.java

@ -69,14 +69,14 @@ public class MainScaleVersionServiceImpl extends DaoServiceImpl<MainScaleVersion
@Override
public ProcessTaskWrapper findTaskByProcInstId(String procInstId) throws Exception {
ProcessTaskWrapper taskWrapper = null;
// QueryParameter parameter = new QueryParameter();
// parameter.setPageable(false);
// Equals eq = new Equals();
// eq.setFieldName("processInstanceId");
// eq.setValue(procInstId);
// parameter.addCriteria(eq);
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
Equals eq = new Equals();
eq.setFieldName("processInstanceId");
eq.setValue(procInstId);
parameter.addCriteria(eq);
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
if (null != list && list.size() > 1) {
// 同一个流程实例查找出多个任务则为多实例任务,还需再根据任务处理人匹配。
List<ProcessTaskWrapper> userTaskList = list.stream().filter(task-> SecurityUtil.getLoginName().equals(task.getAssignee())).collect(Collectors.toList());

15
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/ModelLibServiceImpl.java

@ -1,25 +1,20 @@
package irbs.cust.rating.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.sc.engine.rule.client.enums.LoaderMode;
import io.sc.engine.rule.client.spring.service.ExecutorFactoryService;
import io.sc.engine.rule.core.ExecuteResult;
import io.sc.engine.rule.core.ParameterResult;
import io.sc.engine.rule.core.ResourceResult;
import io.sc.engine.rule.core.client.Executor;
import io.sc.engine.rule.core.code.ExecuteUnit;
import io.sc.engine.rule.core.code.ExecuteUnit4Resource;
import io.sc.engine.rule.core.enums.ParameterType;
import io.sc.engine.rule.server.resource.service.support.ResourceWrapper;
import io.sc.platform.mvc.service.SystemParameterService;
import irbs.cust.rating.jpa.entity.RatingCompanyCustomer;
import irbs.cust.rating.service.FinanceReportService;
import irbs.cust.rating.service.ModelLibService;
import irbs.cust.rating.util.DateUtil;
import liquibase.repackaged.org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.ExecutorBuilder;
import io.sc.engine.rule.client.enums.ExecutorMode;
import io.sc.engine.rule.core.po.resource.ModelResource;
import java.util.HashMap;
@ -72,14 +67,14 @@ public class ModelLibServiceImpl implements ModelLibService {
params.put(custCode, ratingCustomer.getId());
// 模型路由结果
ResourceResult result;
ExecuteResult result;
String callModelCode = "";
try {
// Map<String, String> parameterMap = systemParameterService.getParameters(new String[]{"parameter.re.client.remoteApiUrl","parameter.re.client.loaderMode","parameter.re.client.executorMode"});
// ExecutorMode executorMode = ExecutorMode.valueOf(parameterMap.get("parameter.re.client.executorMode"));
// LoaderMode loaderMode = LoaderMode.valueOf(parameterMap.get("parameter.re.client.loaderMode"));
// String remoteApiUrl = parameterMap.get("parameter.re.client.remoteApiUrl");
Executor executor = executorFactoryService.getExecutor();
Executor executor = executorFactoryService.getClientExecutor();
// TODO 灰度模型
if (grayFlag) {
@ -120,7 +115,7 @@ public class ModelLibServiceImpl implements ModelLibService {
public ModelResource getModelResource(String modelCode) throws Exception {
// String modelResourceUrl = systemParameterService.getParameter("parameter.irbs.engine.remote.config.re.url");
// Executor executor = new ExecutorBuilder().executor(ExecutorMode.REMOTE).url(modelResourceUrl).build();
Executor executor = executorFactoryService.getExecutor();
Executor executor = executorFactoryService.getClientExecutor();
ExecuteUnit resourceWrapper = executor.getLoader().load(modelCode, null);
if(resourceWrapper != null) {
if(resourceWrapper instanceof ExecuteUnit4Resource) {

62
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/RatingIndexServiceImpl.java

@ -1,10 +1,16 @@
package irbs.cust.rating.service.impl;
import io.sc.engine.rule.client.spring.service.ExecutorFactoryService;
import io.sc.engine.rule.core.ExecuteResult;
import io.sc.engine.rule.core.ParameterResult;
import io.sc.engine.rule.core.ResourceResult;
import io.sc.engine.rule.core.client.Executor;
import io.sc.engine.rule.core.enums.ParameterType;
import io.sc.engine.rule.core.po.model.Model;
import io.sc.engine.rule.core.po.model.Parameter;
import io.sc.engine.rule.core.po.model.ParameterInOptionAddtion;
import io.sc.engine.rule.core.po.model.ParameterInOptionItem;
import io.sc.engine.rule.core.po.model.parameter.InOptionParameter;
import io.sc.engine.rule.core.po.model.parameter.IndicatorParameter;
import io.sc.platform.jdbc.sql.condition.Condition;
import io.sc.platform.lcdp.form.service.JdbcTemplateService;
import io.sc.platform.mvc.service.SystemParameterService;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
@ -16,6 +22,7 @@ import irbs.cust.rating.enums.ModelReturnCode;
import irbs.cust.rating.enums.RatingStepType;
import irbs.cust.rating.jpa.entity.*;
import irbs.cust.rating.jpa.repository.RatingIndexRepository;
import irbs.cust.rating.jpa.repository.RatingQualIndexAddtionRepository;
import irbs.cust.rating.jpa.repository.RatingStepRepository;
import irbs.cust.rating.service.*;
import irbs.cust.rating.util.CommonUtils;
@ -23,14 +30,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Service;
import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.ExecutorBuilder;
import io.sc.engine.rule.client.enums.ExecutorMode;
import io.sc.engine.rule.core.enums.ParameterType;
import io.sc.engine.rule.core.po.model.Model;
import io.sc.engine.rule.core.po.model.Parameter;
import io.sc.engine.rule.core.po.model.ParameterInOptionItem;
import io.sc.engine.rule.core.po.model.parameter.InOptionParameter;
import java.math.BigDecimal;
import java.util.*;
@ -67,6 +66,8 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
private SystemParameterService systemParameterService;
@Autowired
private JdbcTemplateService jdbcTemplateService;
@Autowired
private RatingQualIndexAddtionRepository ratingQualIndexAddtionRepository;
@Override
public void genRatingIndexByModel(RatingStep step, List<Model> models, String type) {
@ -144,8 +145,8 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
String indexName = parameter.getName();
indexName = indexName.replaceAll("输入值", "");
index.setIndexName(indexName);
InOptionParameter InOptionParameter = (InOptionParameter)parameter;
List<ParameterInOptionItem> options = InOptionParameter.getOptions();
InOptionParameter inOptionParameter = (InOptionParameter)parameter;
List<ParameterInOptionItem> options = inOptionParameter.getOptions();
if(options!=null && options.size()>0) {
for (ParameterInOptionItem option : options) {
RatingSelectValuesConfig selectItem = new RatingSelectValuesConfig();
@ -159,6 +160,25 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
ratingSelectValuesConfigService.getRepository().save(selectItem);
}
}
List<ParameterInOptionAddtion> addtions = inOptionParameter.getAdditons();
if (addtions!=null && addtions.size()>0) {
for (ParameterInOptionAddtion addtion : addtions) {
RatingQualIndexAddtion rqia = new RatingQualIndexAddtion();
rqia.setDefId(defId);
rqia.setCode(addtion.getCode());
rqia.setName(addtion.getName());
rqia.setDescription(addtion.getDescription());
rqia.setComponentType(addtion.getComponentType());
rqia.setCondition(addtion.getCondition());
rqia.setEnable(addtion.getEnable());
rqia.setOrder(addtion.getOrder());
rqia.setRows(3);
rqia.setPrompt(addtion.getPrompt());
rqia.setAttachmentExtNames(addtion.getAttachmentExtendNames());
rqia.setAttachmentMaxCount(addtion.getAttachmentMaxCount());
ratingQualIndexAddtionRepository.save(rqia);
}
}
} else if (ParameterType.INDICATOR.equals(parameter.getType()) && parameter.getCode().endsWith("_SHOW")) {
// TODO 20240717,模型升级,指标类型的数据也存下来
IndicatorParameter indicatorParameter = (IndicatorParameter) parameter;
@ -274,21 +294,21 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
}
}
// 调用模型引擎
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeById(rating.getModelId(), ModelParamCode.DL.getCode(), kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeById(rating.getModelId(), ModelParamCode.DL.getCode(), kiMap);
indexResultHandler(result, ratingIndexs, rating, false);
// TODO 灰度
String grayModelEnable = systemParameterService.getParameter("parameter.irbs.params.gm.enable");
if ("1".equals(grayModelEnable)) {
ResourceResult grayResult = executor.executeById(rating.getModelIdGray(), ModelParamCode.DL.getCode(), kiMap);
ExecuteResult grayResult = executor.executeById(rating.getModelIdGray(), ModelParamCode.DL.getCode(), kiMap);
indexResultHandler(grayResult, ratingIndexs, rating, true);
}
getRepository().saveAll(ratingIndexs);
return rating;
}
public void indexResultHandler(ResourceResult result, List<RatingIndex> ratingIndexs, CompanyRating rating, Boolean grayFlag) throws Exception {
public void indexResultHandler(ExecuteResult result, List<RatingIndex> ratingIndexs, CompanyRating rating, Boolean grayFlag) throws Exception {
if(result != null && null!=result.getData() && result.getData().size() >0 && null!=ratingIndexs && ratingIndexs.size() >0) {
List<ParameterResult> results = result.getData();
for (ParameterResult parameterResult : results) {
@ -355,6 +375,8 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
indices.forEach((idx)->{
List<RatingSelectValuesConfig> listOptions = ratingSelectValuesConfigService.getRepository().findByDefIdOrderByOrderNumAsc(idx.getConfigId());
idx.setOptions(listOptions);
List<RatingQualIndexAddtion> listAddtions = ratingQualIndexAddtionRepository.findByDefIdOrderByOrderAsc(idx.getConfigId());
idx.setAddtions(listAddtions);
});
return indices;
}
@ -390,21 +412,21 @@ public class RatingIndexServiceImpl extends DaoServiceImpl<RatingIndex, String,
}
}
// 调用模型引擎
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeById(rating.getModelId(),kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeById(rating.getModelId(),kiMap);
qualIndexResultHandler(result, qualIndexs, rating, false);
// TODO 灰度
String grayModelEnable = systemParameterService.getParameter("parameter.irbs.params.gm.enable");
if ("1".equals(grayModelEnable)) {
ResourceResult grayResult = executor.executeById(rating.getModelIdGray(),kiMap);
ExecuteResult grayResult = executor.executeById(rating.getModelIdGray(),kiMap);
qualIndexResultHandler(grayResult, qualIndexs, rating, true);
}
getRepository().saveAll(qualIndexs);
return rating;
}
public void qualIndexResultHandler(ResourceResult result, List<RatingIndex> qualIndexs, CompanyRating rating, Boolean grayFlag) throws Exception {
public void qualIndexResultHandler(ExecuteResult result, List<RatingIndex> qualIndexs, CompanyRating rating, Boolean grayFlag) throws Exception {
if(result != null && null!=result.getData() && result.getData().size() >0) {
List<ParameterResult> results = result.getData();
for (ParameterResult parameterResult : results) {

2
irbs.cust.rating/src/main/resources/META-INF/platform/plugins/liquibase.json

@ -44,7 +44,7 @@
"locations":[
"classpath:/liquibase/20240326_ALL_TABLES_DDL.xml",
"classpath:/liquibase/20240401_REPORTS_TABLES_DDL.xml",
"classpath:/liquibase/20240401_REPORTS_VIEW.xml"
"classpath:/liquibase/20250714_RPT_VIEW__DDL.xml"
]
},
{

2
irbs.cust.rating/src/main/resources/META-INF/platform/plugins/parameters.json

@ -95,7 +95,7 @@
"id" : "parameter.irbs.params.ratingUI.totalScore",
"parentId" : "parameter.irbs.params.ratingUI",
"code" : "parameter.irbs.params.ratingUI.totalScore",
"defaultValue" : "show",
"defaultValue" : "hide",
"options" : {
"show": "展示",
"hide": "隐藏"

36
irbs.cust.rating/src/main/resources/liquibase/20240321_CUST_RATING_DDL.xml

@ -7,6 +7,19 @@
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="20240321_CUST_RATING_DDL" author="platform">
<!-- 最大业务流水号记录表 -->
<createTable tableName="T_BUSINESS_CODE" remarks="最大业务流水号记录表">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="ID主键">
<constraints primaryKey="true"/>
</column>
<column name="PREFIX_" type="java.sql.Types.NVARCHAR(10)" remarks="前缀(一般为字母,用来标识是什么业务)"></column>
<column name="SUFFIX_" type="java.sql.Types.NVARCHAR(10)" remarks="后缀(包括:YYYYMMDD,YYYYMM)"></column>
<column name="LENGTH_" type="java.sql.Types.SMALLINT" remarks="流水号长度(减掉前缀后缀后的长度,长度为4的示例:R202505280001)"></column>
<column name="LAST_DATE_" type="java.sql.Types.NVARCHAR(20)" remarks="最后获取流水号的时间"></column>
<column name="MAX_NUM_" type="java.sql.Types.SMALLINT" remarks="当前最大序号(每获取一次+1)"></column>
</createTable>
<addUniqueConstraint tableName="T_BUSINESS_CODE" columnNames="PREFIX_,SUFFIX_,LENGTH_"></addUniqueConstraint>
<!-- 公司客户评级主表 -->
<createTable tableName="NS_COMPANY_RATING" remarks="公司客户评级主表">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="ID主键">
@ -250,6 +263,29 @@
<column name="WEIGHT" type="java.sql.Types.NVARCHAR(50)" remarks="权重"/>
</createTable>
<!-- 定性指标补录表-->
<createTable tableName="NS_QUAL_INDEX_ADDTION" remarks="定性指标补录表">
<column name="ID" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="DEF_ID_" type="java.sql.Types.NVARCHAR(36)" remarks="问题定义ID"/>
<column name="CODE_" type="java.sql.Types.NVARCHAR(50)" remarks="代码"/>
<column name="NAME_" type="java.sql.Types.NVARCHAR(100)" remarks="名称"/>
<column name="DESCRIPTION_" type="java.sql.Types.NVARCHAR(500)" remarks="描述"/>
<column name="COMPONENT_TYPE_" type="java.sql.Types.NVARCHAR(50)" remarks="组件类型(INTEGER:整数;DECIMAL:小数,TEXT:文本;TEXTS:多行文本;ATTACHMENT:附件)"/>
<column name="CONDITION_" type="java.sql.Types.NVARCHAR(1000)" remarks="条件"/>
<column name="ENABLE_" type="java.sql.Types.SMALLINT" remarks="是否可用"/>
<column name="ORDER_" type="java.sql.Types.SMALLINT" remarks="排序"/>
<column name="ROWS_" type="java.sql.Types.SMALLINT" remarks="多行文本框行数"/>
<column name="PROMPT_" type="java.sql.Types.NVARCHAR(1000)" remarks="提示词"/>
<column name="ATTACHMENT_EXT_NAMES_" type="java.sql.Types.NVARCHAR(200)" remarks="允许上传附件的文件扩展名"/>
<column name="ATTACHMENT_MAX_COUNT_" type="java.sql.Types.SMALLINT" remarks="允许上传附件的最大个数"/>
<column name="INTEGER_VALUE_" type="java.sql.Types.SMALLINT" remarks="整数值"/>
<column name="DECIMAL_VALUE_" type="java.sql.Types.NUMERIC(24, 8)" remarks="小数值"/>
<column name="TEXT_VALUE_" type="java.sql.Types.NVARCHAR(200)" remarks="文本值"/>
<column name="TEXTS_VALUE_" type="java.sql.Types.NVARCHAR(1000)" remarks="多行文本值"/>
</createTable>
<!-- 评级配置_调整项定义 -->
<createTable tableName="NS_R_CFG_ADJ_ITEM" remarks="评级配置_调整项定义">
<column name="ID" type="java.sql.Types.NVARCHAR(36)" remarks="主键">

16
irbs.defaultManager/src/main/java/irbs/defaultManager/service/impl/DefaultCognizanceServiceImpl.java

@ -127,14 +127,14 @@ public class DefaultCognizanceServiceImpl extends DaoServiceImpl<DefaultCognizan
public ProcessTaskWrapper findTaskByProcInstId(String procInstId) throws Exception {
ProcessTaskWrapper taskWrapper = null;
// QueryParameter parameter = new QueryParameter();
// parameter.setPageable(false);
// Equals eq = new Equals();
// eq.setFieldName("processInstanceId");
// eq.setValue(procInstId);
// parameter.addCriteria(eq);
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
Equals eq = new Equals();
eq.setFieldName("processInstanceId");
eq.setValue(procInstId);
parameter.addCriteria(eq);
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
if (null != list && list.size() > 1) {
// 同一个流程实例查找出多个任务则为多实例任务,还需再根据任务处理人匹配。
List<ProcessTaskWrapper> userTaskList = list.stream().filter(task-> SecurityUtil.getLoginName().equals(task.getAssignee())).collect(Collectors.toList());

16
irbs.defaultManager/src/main/java/irbs/defaultManager/service/impl/DefaultRebirthServiceImpl.java

@ -67,14 +67,14 @@ public class DefaultRebirthServiceImpl extends DaoServiceImpl<DefaultRebirth, St
public ProcessTaskWrapper findTaskByProcInstId(String procInstId) throws Exception {
ProcessTaskWrapper taskWrapper = null;
// QueryParameter parameter = new QueryParameter();
// parameter.setPageable(false);
// Equals eq = new Equals();
// eq.setFieldName("processInstanceId");
// eq.setValue(procInstId);
// parameter.addCriteria(eq);
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
Equals eq = new Equals();
eq.setFieldName("processInstanceId");
eq.setValue(procInstId);
parameter.addCriteria(eq);
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
if (null != list && list.size() > 1) {
// 同一个流程实例查找出多个任务则为多实例任务,还需再根据任务处理人匹配。
List<ProcessTaskWrapper> userTaskList = list.stream().filter(task-> SecurityUtil.getLoginName().equals(task.getAssignee())).collect(Collectors.toList());

16
irbs.feature/src/main/java/irbs/feature/service/impl/CustFeatureCalcBatchServiceImpl.java

@ -1,11 +1,11 @@
package irbs.feature.service.impl;
import io.sc.engine.rule.client.Executor;
import io.sc.engine.rule.client.runtime.impl.groovy.GroovyScriptEngineService;
import io.sc.engine.rule.client.runtime.impl.groovy.GroovyScriptEngineServiceImpl;
import io.sc.engine.rule.client.spring.service.ExecutorFactoryService;
import io.sc.engine.rule.core.ExecuteResult;
import io.sc.engine.rule.core.ParameterResult;
import io.sc.engine.rule.core.ResourceResult;
import io.sc.engine.rule.core.client.Executor;
import io.sc.engine.rule.core.code.ExecuteUnit;
import io.sc.engine.rule.core.code.SourceCode;
import io.sc.engine.rule.core.code.generator.GroovySourceCodeGenerator;
@ -69,7 +69,7 @@ public class CustFeatureCalcBatchServiceImpl implements CustFeatureCalcBatchServ
if(list != null){
DatabaseType type = DatabaseType.fromMetaData(dataSource);
String dbType = type.getProductName();
Executor executor =executorFactoryService.getExecutor();
Executor executor =executorFactoryService.getClientExecutor();
ExecuteUnit resourceWrapper =executor.getLoader().load(SHRCB_LIB_CODE,null);
SourceCode groovySourceCode =new GroovySourceCodeGenerator().generate(SHRCB_LIB_CODE,null,resourceWrapper);
int i = 1;
@ -87,7 +87,7 @@ public class CustFeatureCalcBatchServiceImpl implements CustFeatureCalcBatchServ
executeParameter.put("executor", executor);
executeParameter.put("subModelCode", null);
executeParameter.put("argument", kiMap);
ResourceResult result =(ResourceResult)groovyScriptEngineService.eval(groovySourceCode.getSource(),"INPUT_PARAMETER",executeParameter);
ExecuteResult result=(ExecuteResult)groovyScriptEngineService.eval(groovySourceCode,"INPUT_PARAMETER",executeParameter);
if(result != null && !CollectionUtils.isEmpty(result.getData())) {
List<ParameterResult> results = result.getData();
List<CustFeatureRet> res = new ArrayList<>();
@ -509,8 +509,8 @@ public class CustFeatureCalcBatchServiceImpl implements CustFeatureCalcBatchServ
setModelValue(kiMap, rptVals);
}
}
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeByCode("QYCW_ZB", null, kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeByCode("QYCW_ZB", null, kiMap);
if(result != null && !CollectionUtils.isEmpty(result.getData())) {
List<ParameterResult> results = result.getData();
List<CustFeatureRet> res = new ArrayList<>();
@ -654,8 +654,8 @@ public class CustFeatureCalcBatchServiceImpl implements CustFeatureCalcBatchServ
setModelValue(kiMap, rptVals);
}
}
Executor executor = executorFactoryService.getExecutor();
ResourceResult result = executor.executeByCode("SYCW_ZB",null,kiMap);
Executor executor = executorFactoryService.getClientExecutor();
ExecuteResult result = executor.executeByCode("SYCW_ZB",null,kiMap);
if(result != null && !CollectionUtils.isEmpty(result.getData())) {
List<ParameterResult> results = result.getData();
List<CustFeatureRet> res = new ArrayList<>();

4
irbs.frontend/.npmrc

@ -1,5 +1,5 @@
# npm 仓库地址, 在 npm install 时使用
registry=http://nexus.sc.io:8000/repository/npm-public/
registry=http://58.33.84.154:8000/repository/npm-public/
# 用户邮箱
email=
@ -10,4 +10,4 @@ git-checks=false
# 登录 npm 仓库的用户认证信息, 在 npm publish 时使用, publish 的 npm registry 在 package.json 文件中 publishConfig 部分配置
# _authToken 可通过以下命令获取
# curl -X PUT -H "Content-Type:application/json" -d '{"_id":"org.couchdb.user:admin","name":"admin","password":"admin"}' http://nexus.sc.io:8000/repository/npm-releases/-/user/org.couchdb.user:admin
//nexus.sc.io:8000/repository/npm-releases/:_authToken=NpmToken.67c99588-56a6-3ce1-9bea-a9a6164f8090
//nexus.sc.io:8000/repository/npm-releases/:_authToken=NpmToken.67c99588-56a6-3ce1-9bea-a9a6164f8090

16
irbs.frontend/package.json

@ -72,18 +72,18 @@
"webpack-merge": "6.0.1"
},
"dependencies": {
"@codemirror/autocomplete": "6.18.4",
"@codemirror/commands": "6.8.0",
"@codemirror/autocomplete": "6.18.6",
"@codemirror/commands": "6.8.1",
"@codemirror/lang-html": "6.4.9",
"@codemirror/lang-java": "6.0.1",
"@codemirror/lang-javascript": "6.2.2",
"@codemirror/lang-javascript": "6.2.3",
"@codemirror/lang-json": "6.0.1",
"@codemirror/lang-sql": "6.8.0",
"@codemirror/lang-xml": "6.1.0",
"@codemirror/language": "6.10.8",
"@codemirror/search": "6.5.8",
"@codemirror/state": "6.5.1",
"@codemirror/view": "6.36.2",
"@codemirror/language": "6.11.0",
"@codemirror/search": "6.5.10",
"@codemirror/state": "6.5.2",
"@codemirror/view": "6.36.5",
"@maxgraph/core": "0.14.0",
"@quasar/extras": "1.16.15",
"@quasar/quasar-ui-qmarkdown": "2.0.5",
@ -111,7 +111,7 @@
"mockjs": "1.1.0",
"node-sql-parser": "5.3.6",
"pinia": "2.3.0",
"platform-core": "v999.999.7",
"platform-core": "8.2.84",
"quasar": "2.17.6",
"sort-array": "5.0.0",
"svg-path-commander": "2.1.7",

62
irbs.frontend/public/webjars/tailwindcss/3.4.5/tailwind.css.js

File diff suppressed because one or more lines are too long

4
irbs.frontend/src/boostrap.ts

@ -15,10 +15,12 @@ import App from './App.vue';
import 'platform-core/dist/css/platform-core.css';
// 导入 tailwind utilities css
import 'tailwindcss/utilities.css';
// 导入 quasar-ui-qmarkdown css
import '@quasar/quasar-ui-qmarkdown/dist/index.css';
// 设置远程组件加载器
// 覆盖 platform-core 包中的 remoteComponentLoader 函数
// 只有在主前端项目中编写如下的 remoteComponentLoader 函数才能实现 webpack MF 的 shared 功能
// 只有在主前端项目中编写如下的 remoteComponentLoader 函数才能实现 webpack Module Federation 的 shared 功能
ComponentManager.setRemoteComponentLoader((moduleName: string, componentName: string): any => {
return async () => {
await __webpack_init_sharing__('default');

12
irbs.frontend/src/components/index.ts

@ -6,9 +6,9 @@ import irbs_irbsHome from '@/views/IrbsHome.vue';
import irbs_todoTask from '@/views/workbench/TodoTask.vue';
import irbs_doneTask from '@/views/workbench/DoneTask.vue';
import irbs_endTask from '@/views/workbench/EndTask.vue';
import irbs_custRating from '@/views/custRating/CustRating.vue';
import irbs_custSeparateRating from '@/views/custRating/CustSeparateRating.vue';
import irbs_financialRating from '@/views/custRating/FinancialRating.vue';
import irbs_company_custRating from '@/views/custRating/company/RatingGrid.vue';
import irbs_company_apply from '@/views/custRating/company/Apply.vue';
import irbs_company_mockCmis from '@/views/custRating/mock/MockCmis.vue';
import irbs_cognizanceApply from '@/views/default/CognizanceApply.vue';
import irbs_rebirthApply from '@/views/default/RebirthApply.vue';
import irbs_lgdQuery from '@/views/debtRating/LgdQuery.vue';
@ -50,9 +50,9 @@ const localComponents = {
'irbs.todoTask': irbs_todoTask,
'irbs.doneTask': irbs_doneTask,
'irbs.endTask': irbs_endTask,
'irbs.custRating': irbs_custRating,
'irbs.custSeparateRating': irbs_custSeparateRating,
'irbs.financialRating': irbs_financialRating,
'irbs.company.custRating': irbs_company_custRating,
'irbs.company.apply': irbs_company_apply,
'irbs.company.mockCmis': irbs_company_mockCmis,
'irbs.cognizanceApply': irbs_cognizanceApply,
'irbs.rebirthApply': irbs_rebirthApply,
'irbs.lgdQuery': irbs_lgdQuery,

27
irbs.frontend/src/routes/routes.json

@ -66,6 +66,7 @@
"children": []
},
{
"force": true,
"parent": "/",
"name": "route.irbs.rating.apply",
"path": "/irbs/rating/apply",
@ -92,32 +93,6 @@
},
"children": []
},
{
"name": "route.irbs.custRating.custSeparateRating",
"path": "irbs/custSeparateRating",
"parent": "/",
"priority": -1,
"component": "irbs.custSeparateRating",
"componentPath": "@/views/custRating/CustSeparateRating.vue",
"redirect": null,
"meta": {
"permissions": ["/example/**/*"]
},
"children": []
},
{
"name": "route.irbs.custRating.financialRating",
"path": "irbs/financialRating",
"parent": "/",
"priority": -1,
"component": "irbs.financialRating",
"componentPath": "@/views/custRating/FinancialRating.vue",
"redirect": null,
"meta": {
"permissions": ["/example/**/*"]
},
"children": []
},
{
"name": "route.irbs.default.cognizance",
"path": "irbs/cognizanceApply",

167
irbs.frontend/src/views/custRating/CustRating.ts

@ -1,167 +0,0 @@
/**
*
*/
export const RatingLevelOptions = [
{ label: 'AAA+', value: 'AAA+', numberValue: 15, color: 'green', denseLabel: false },
{ label: 'AAA', value: 'AAA', numberValue: 14, color: 'green', denseLabel: false },
{ label: 'AA+', value: 'AA+', numberValue: 13, color: 'green', denseLabel: false },
{ label: 'AA', value: 'AA', numberValue: 12, color: 'green', denseLabel: false },
{ label: 'AA-', value: 'AA-', numberValue: 11, color: 'green', denseLabel: false },
{ label: 'A+', value: 'A+', numberValue: 10, color: 'green', denseLabel: false },
{ label: 'A', value: 'A', numberValue: 9, color: 'green', denseLabel: false },
{ label: 'A-', value: 'A-', numberValue: 8, color: 'green', denseLabel: false },
{ label: 'BBB', value: 'BBB', numberValue: 7, color: 'green', denseLabel: false },
{ label: 'BB', value: 'BB', numberValue: 6, color: 'red', denseLabel: false },
{ label: 'B', value: 'B', numberValue: 5, color: 'red', denseLabel: false },
{ label: 'CCC', value: 'CCC', numberValue: 4, color: 'red', denseLabel: false },
{ label: 'CC', value: 'CC', numberValue: 3, color: 'red', denseLabel: false },
{ label: 'C', value: 'C', numberValue: 2, color: 'red', denseLabel: false },
{ label: 'D', value: 'D', numberValue: 1, color: 'red', denseLabel: false },
];
/**
*
*/
export const RatingStep = {
CSWC: 'INIT_FINISH', // 初始化完成
KHXX: 'CUST_INFO', // 客户信息
DLFX: 'QUANTITATIVE', // 定量分析
DXFX: 'QUALITATIVE_EDIT', // 定性分析
CPJG: 'QUALITATIVE_SHOW', // 初评结果
PJTZX: 'ADJUST_ITEM', // 评级调整项
QSYJ: 'OTHER', // 签署意见
PJBG: 'REPORT_INFO', // 评级报告
};
/**
*
*/
export const RatingProcessStatus = {
AWAIT_RATING: 'AWAIT_RATING', // 待评级
AWAIT_SUBMIT: 'AWAIT_SUBMIT', // 待提交
BACK: 'BACK', // 退回
APPROVALING: 'APPROVALING', // 审批中
PASS: 'PASS', // 通过
NEGATIVED: 'NEGATIVED', // 否决
END: 'END', // 已结束
};
/**
*
*/
export const RatingProcessOperationStatus = [
{
label: '提交',
value: '10',
},
{
label: '否决',
value: '20',
},
{
label: '退回',
value: '30',
},
{
label: '撤销',
value: '40',
},
{
label: '批准',
value: '50',
},
{
label: '同意',
value: '60',
},
{
label: '不同意',
value: '70',
},
];
/**
*
*/
export const RatingProcessOperation = {
// 通过
APPROVE: 1,
// 否决
REJECT: 2,
// 同意
AGREE: 4,
// 不同意
DISAGREE: 5,
// 提交下一步
SUBMIT: 6,
// 提交到其他上级(信审会)
UPPER_1: 8,
// 提交到上级
UPPER: 9,
//退回起始步骤
BACK_START: -1,
//退回到某步骤
BACK: -2,
};
/**
*
*/
export const DefaultProcessStatus = {
PASS: '03', // 通过
};
/**
*
*/
export const SelectCustomerFlag = {
RATING: 'rating', // 发起评级
COGNIZANCE: 'cognizance', // 违约认定申请
};
/**
*
*/
export const FinanceReportType = {
QYL: '1', // 企业类
SYL: '2', // 事业类
};
/**
*
*/
export const FinanceReportProjectType = {
QYLZCFZ: '01', // 企业类资产负债
QYLXJL: '02', // 企业类现金流
QYLSY: '03', // 企业类损益
SYLZCFZ: '11', // 事业类资产负债
SYLSRZC: '12', // 事业类收入支出表
};
export const Round = (val: any, precision) => {
if (typeof precision !== 'number' || precision <= 0) return val;
let result = val;
if (val && typeof val === 'string') {
const patt = /^-?[0-9]+.?[0-9]*/;
if (patt.test(val)) {
result = parseFloat(val);
}
}
if (result && typeof result === 'number' && String(result).indexOf('.') > -1) {
let scale = '1';
for (let i = 0; i < precision; i++) {
scale += 0;
}
const pre = 'e' + precision;
const post = 'e-' + precision;
return (+(Math.round(result + pre) + post)).toFixed(precision);
}
return result;
};
export const RatioFormat = (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
}
return val;
};

218
irbs.frontend/src/views/custRating/CustRating.vue

@ -1,218 +0,0 @@
<template>
<div style="height: 100%">
<w-grid
ref="companyRatingGridRef"
title="客户评级列表"
:data-url="Environment.apiContextPath('api/irbs/companyRating')"
:fetch-data-url="Environment.apiContextPath('api/irbs/companyRating/query')"
:sort-no="true"
group-mode="alone"
:checkbox-selection="false"
:query-form-cols-num="4"
:query-form-fields="companyRatingGrid.queryFormFields"
:columns="companyRatingGrid.columns"
:toolbar-actions="companyRatingGrid.buttons"
:query-criteria="{
operator: 'and',
criteria: [
{
fieldName: 'triggerType',
operator: 'equals',
value: 'INDEPENDENT',
},
{
fieldName: 'launchUser',
operator: 'equals',
value: SessionManager.getUser().loginName,
},
],
}"
:sort-by="['-createDate']"
></w-grid>
<LaunchRatingDialog ref="launchRatingdialogRef" :dictionary="dictionary" @refresh="refreshTable"></LaunchRatingDialog>
<RatingDialog ref="ratingdialogRef" @refresh="refreshTable"></RatingDialog>
<GrayModelDialog ref="grayDialogRef" @refresh="refreshTable"></GrayModelDialog>
</div>
</template>
<script setup lang="ts">
import { ref, shallowRef } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager, Tools, SessionManager } from 'platform-core';
import LaunchRatingDialog from './LaunchRatingDialog.vue';
import RatingDialog from './RatingDialog.vue';
import GrayModelDialog from './GrayModelDialog.vue';
import { RatingLevelOptions, RatingProcessStatus, Round } from './CustRating.ts';
import RatingLevel from './RatingLevel.vue';
const $q = useQuasar();
const companyRatingGridRef = ref();
const launchRatingdialogRef = ref();
const ratingdialogRef = ref();
const grayDialogRef = ref();
const RatingStatusEnum = await EnumTools.fetch('irbs.cust.rating.enums.RatingStatus');
const RatingProcessStatusEnum = await EnumTools.fetch('irbs.cust.rating.enums.RatingProcessStatus');
const dictCustomerTypeCd = await DictionaryTools.fetch('CustomerTypeCd');
const optionsCustomerTypeCd = Options.dictionary(dictCustomerTypeCd);
const dictCustomerSizeCd = await DictionaryTools.fetch('CustomerSizeCd');
const optionsCustomerSizeCd = Options.dictionary(dictCustomerSizeCd);
const dictionary = {
dictCustomerTypeCd: dictCustomerTypeCd,
optionsCustomerTypeCd: optionsCustomerTypeCd,
dictCustomerSizeCd: dictCustomerSizeCd,
optionsCustomerSizeCd: optionsCustomerSizeCd,
};
const companyRatingGrid = {
buttons: [
'query',
'reset',
'separator',
{
extend: 'add',
label: '发起评级',
click: () => {
launchRatingdialogRef.value.show();
},
},
{
extend: 'edit',
label: '评级',
enableIf: (args) => {
if (
args.selected &&
(args.selected['processStatus'] === RatingProcessStatus.AWAIT_RATING ||
args.selected['processStatus'] === RatingProcessStatus.AWAIT_SUBMIT ||
args.selected['processStatus'] === RatingProcessStatus.BACK)
) {
return true;
}
return false;
},
click: (args) => {
ratingdialogRef.value.show(args.selected);
},
},
// {
// extend: 'remove',
// label: '',
// click: () => {},
// },
'separator',
{
extend: 'view',
click: (args) => {
ratingdialogRef.value.show(args.selected, true);
},
},
'export',
'separator',
[
{
name: 'otherOp',
label: '其他操作',
icon: 'device_hub',
},
{
name: 'viewGray',
extend: 'view',
label: '查看灰度模型结果',
click: (args) => {
grayDialogRef.value.show(args.selected);
},
},
'separator',
{
extend: 'remove',
name: 'delete',
label: '强制删除',
click: (args) => {
// args._click();
$q.dialog({
title: '询问',
message: '是否确认删除已生成评级信息及流程信息?',
cancel: { noCaps: true },
ok: { noCaps: true },
persistent: true,
}).onOk(() => {
axios
.post(Environment.apiContextPath('api/irbs/companyRating/removeRatingAndProcess/' + args.selected['id']))
.then((resp) => {
if (resp && resp.data) {
NotifyManager.info('删除成功');
companyRatingGridRef.value.refresh();
}
})
.catch((error) => {
console.info('error====', error);
NotifyManager.warn('删除失败');
});
});
},
},
],
'separator',
],
queryFormFields: [
{ label: '申请编号', name: 'id', type: 'w-text' },
{ label: '客户号', name: 'custNo', type: 'w-text' },
{ label: '客户名称', name: 'custName', type: 'w-text' },
{
label: '认定等级',
name: 'finalLevel',
type: 'w-select',
options: RatingLevelOptions,
},
{ label: '流程状态', name: 'processStatus', type: 'w-select', options: Options.enum(RatingProcessStatusEnum) },
{ label: '评级状态', name: 'ratingStatus', type: 'w-select', options: Options.enum(RatingStatusEnum) },
],
columns: [
{ name: 'id', label: '申请编号', align: 'center' },
{ name: 'custNo', label: '客户号', align: 'center' },
{ name: 'custName', label: '客户名称', width: 150 },
{ name: 'industryTypeName', label: '行业类型' },
{ name: 'modelScore', label: '模型得分' },
{ name: 'modelLevel', label: '模型等级' },
{ name: 'adjLevel', label: '调整后等级' },
{ name: 'initLevel', label: '初评等级' },
{
name: 'finalLevel',
label: '认定等级',
format: (val) => {
if (!Tools.isEmpty(val)) {
return {
componentType: RatingLevel,
attrs: {
level: val,
dense: true,
},
};
}
return val;
},
},
{
name: 'pd',
label: '违约概率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
}
return val;
},
},
{ name: 'effectiveTime', label: '评级生效日', format: Formater.dateOnly() },
{ name: 'matureTime', label: '评级失效日', format: Formater.dateOnly() },
{ name: 'ratingStatus', label: '评级状态', format: Formater.enum(RatingStatusEnum) },
{ name: 'launchUser', label: '发起人' },
{ name: 'processStatus', label: '流程状态', format: Formater.enum(RatingProcessStatusEnum) },
{ name: 'currentAssignee', label: '当前处理人' },
],
};
const refreshTable = () => {
companyRatingGridRef.value.refresh();
};
</script>

5
irbs.frontend/src/views/custRating/CustSeparateRating.vue

@ -1,5 +0,0 @@
<template>
<div>111</div>
</template>
<script setup lang="ts"></script>

5
irbs.frontend/src/views/custRating/FinancialRating.vue

@ -1,5 +0,0 @@
<template>
<div>111</div>
</template>
<script setup lang="ts"></script>

349
irbs.frontend/src/views/custRating/GrayModelDialog.vue

@ -1,349 +0,0 @@
<template>
<w-dialog ref="dialogRef" :title="state.dialogTitle" width="80%" height="80%" body-padding="0px 0px 0px 0px" :maximized="true" :buttons="[]">
<div>
<div class="p-[10px]">
<span class="text-3xl text-amber-600"
>{{ state.custInfoObj['custName'] }}<q-badge v-if="state.custInfoObj['marketEnterprisesInd'] === '1'" color="red" align="top">上市</q-badge></span
>
<div class="flex pt-2">
<div class="flex-1 text-center">
<div>客户号</div>
<div class="text-blue-500">
{{ state.custInfoObj['custNo'] }}
</div>
</div>
<div class="flex-1 text-center">
<div>企业规模</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictCustomerSize)(state.custInfoObj['customerSize']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>企业类型</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictRegisteredType)(state.custInfoObj['registeredType']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>融资平台标志</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictGoverFinanceSign)(state.custInfoObj['goverFinanceSign']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>融资平台类型</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictGoverFinanceType)(state.custInfoObj['goverFinanceType']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>所在国家地区</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictNationCd)(state.custInfoObj['nation']) }}
</div>
</div>
</div>
<div class="pt-3"></div>
<div class="flex">
<div class="flex-1 text-center">
<div>注册所在地</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictRegistrationCd)(state.custInfoObj['registration']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>是否集团客户</div>
<div class="text-blue-500">
{{ state.custInfoObj['groupCustInd'] === '1' ? '是' : '否' }}
</div>
</div>
<div class="flex-1 text-center">
<div>成员类别</div>
<div class="text-blue-500">
{{ Formater.dictionary(dictMemberTypeCd)(state.custInfoObj['memberType']) }}
</div>
</div>
<div class="flex-1 text-center">
<div>行业类型国标</div>
<div class="text-blue-500">
{{ state.custInfoObj['industryTypeName'] }}
</div>
</div>
<div class="flex-1 text-center">
<div>成立日期</div>
<div class="text-blue-500">
{{ state.custInfoObj['buildDate'] }}
</div>
</div>
<div class="flex-1 text-center"></div>
</div>
</div>
<q-separator />
<div class="pt-[10px]">
<q-card flat bordered>
<q-item dense class="pl-[8px]">
<q-item-section>
<q-item-label>灰度模型结果</q-item-label>
</q-item-section>
</q-item>
<q-separator />
<q-card-section class="p-[10px]">
<div class="pt-[8px]">
<w-info-panel :dense="state.dense" :info="state.reportCustRatingInfo" :column-num="3"></w-info-panel>
</div>
</q-card-section>
</q-card>
<div class="pt-[8px]">
<q-list bordered class="rounded-borders">
<q-expansion-item default-opened expand-separator icon="bubble_chart" label="得分详情">
<q-separator />
<q-splitter v-model="state.splitterModel">
<template #before>
<div>
<div class="text-center">
<q-chip outline color="orange" text-color="white" :clickable="false" :ripple="false"> 定量得分详情 </q-chip>
</div>
<q-list v-if="state.reportQuantitativeScoreDtl" padding>
<template v-for="(values, key, a) in state.reportQuantitativeScoreDtl" :key="a">
<q-item-label header>{{ key }}</q-item-label>
<template v-for="(dtl, index) in values" :key="index">
<q-item>
<q-item-section>
<q-item-label>{{ dtl['INDEX_NAME'] }}</q-item-label>
<q-item-label caption> {{ Round(dtl['INDEX_VALUE'], 2) }} </q-item-label>
</q-item-section>
<q-item-section v-if="!Tools.isEmpty(dtl['INDEX_SCORE_G'])" side>
<q-chip :clickable="false" :ripple="false" color="green" text-color="white"> {{ Round(dtl['INDEX_SCORE_G'], 2) }} </q-chip>
</q-item-section>
</q-item>
</template>
<q-separator />
</template>
</q-list>
</div>
</template>
<template #after>
<q-splitter v-model="state.afterSplitterModel">
<template #before>
<div>
<div class="text-center">
<q-chip outline color="light-blue" text-color="white" :clickable="false" :ripple="false"> 定性得分详情 </q-chip>
</div>
<q-list v-if="state.reportQualitativeScoreDtl" padding>
<template v-for="(values, key, a) in state.reportQualitativeScoreDtl" :key="a">
<q-item-label header>{{ key }}</q-item-label>
<template v-for="(dtl, index) in values" :key="index">
<q-item>
<q-item-section>
<q-item-label>{{ dtl['INDEX_NAME'] }}</q-item-label>
<q-item-label caption> {{ dtl['TEXT'] }} </q-item-label>
</q-item-section>
<q-item-section v-if="!Tools.isEmpty(dtl['INDEX_SCORE_G'])" side>
<q-chip :clickable="false" :ripple="false" color="green" text-color="white"> {{ Round(dtl['INDEX_SCORE_G'], 2) }} </q-chip>
</q-item-section>
</q-item>
</template>
<q-separator />
</template>
</q-list>
</div>
</template>
<template #after>
<div>
<div class="text-center">
<q-chip outline color="lime" text-color="white" :clickable="false" :ripple="false"> 评级调整项详情 </q-chip>
</div>
<q-list v-if="state.reportAdjustScoreDtl" padding>
<template v-for="(values, key, a) in state.reportAdjustScoreDtl" :key="a">
<q-item-label header>{{ key }}</q-item-label>
<template v-for="(dtl, index) in values" :key="index">
<q-item>
<q-item-section>
<q-item-label>{{ dtl['INDEX_NAME'] }}</q-item-label>
<q-item-label caption> {{ dtl['TEXT'] }} </q-item-label>
</q-item-section>
</q-item>
</template>
<q-separator />
</template>
</q-list>
</div>
</template>
</q-splitter>
</template>
</q-splitter>
</q-expansion-item>
</q-list>
</div>
</div>
</div>
</w-dialog>
</template>
<script setup lang="ts">
import { DictionaryTools, Environment, Formater, axios, Tools } from 'platform-core';
import { nextTick, reactive, ref } from 'vue';
import { RatingStep, Round } from './CustRating.ts';
import RatingLevel from './RatingLevel.vue';
const dialogRef = ref();
const state = reactive({
splitterModel: 30,
afterSplitterModel: 50,
rating: {},
dialogTitle: '灰度模型结果',
dense: false,
custInfoObj: {},
reportCustRatingInfo: <any>[],
reportQuantitativeScoreDtl: <any>null,
reportQualitativeScoreDtl: <any>null,
reportAdjustScoreDtl: <any>null,
});
//
const loadCustInfo = async () => {
//
let customerType = '';
await axios.get(Environment.apiContextPath('api/irbs/ratingCompanyCustomer/' + state.rating['custId'])).then((resp) => {
if (resp && resp.data) {
customerType = resp.data['customerType'];
state.custInfoObj = {};
state.custInfoObj['custNo'] = resp.data['custNo'];
state.custInfoObj['custName'] = resp.data['custName'];
state.custInfoObj['certificateType'] = resp.data['certificateType'];
state.custInfoObj['certificateNum'] = resp.data['certificateNum'];
state.custInfoObj['customerType'] = resp.data['customerType'];
state.custInfoObj['customerSize'] = resp.data['customerSize'];
state.custInfoObj['registeredType'] = resp.data['registeredType'];
state.custInfoObj['goverFinanceSign'] = resp.data['goverFinanceSign'];
state.custInfoObj['goverFinanceType'] = resp.data['goverFinanceType'];
state.custInfoObj['registration'] = resp.data['registration'];
state.custInfoObj['nation'] = resp.data['nation'];
state.custInfoObj['memberType'] = resp.data['memberType'];
state.custInfoObj['groupCustInd'] = resp.data['groupCustInd'];
state.custInfoObj['marketEnterprisesInd'] = resp.data['marketEnterprisesInd'];
state.custInfoObj['industryType'] = resp.data['industryType'];
state.custInfoObj['industryTypeName'] = resp.data['industryTypeName'];
state.custInfoObj['buildDate'] = resp.data['buildDate'];
state.custInfoObj['customerManagerNo'] = resp.data['customerManagerNo'];
state.custInfoObj['customerManagerName'] = resp.data['customerManagerName'];
state.custInfoObj['handleOrgId'] = resp.data['handleOrgId'];
state.custInfoObj['handleTime'] = resp.data['handleTime'];
}
});
};
const groupByProperties = (list, propName) => {
const map = {};
list.forEach((item, index, arr) => {
if (!map[item[propName]]) {
map[item[propName]] = arr.filter((a) => a[propName] == item[propName]);
}
});
return map;
};
const loadRatingReport = async () => {
//
state.reportCustRatingInfo = [];
await axios
.get(Environment.apiContextPath('api/irbs/companyRating/stepRatingReport'), { params: { ratingId: state.rating['id'] } })
.then((resp) => {
if (resp && resp.data) {
state.rating = resp.data;
state.reportCustRatingInfo.push({ label: '模型名称', value: resp.data.modelNameGray });
state.reportCustRatingInfo.push({ label: '定量得分', value: Round(resp.data.quanScoreGray, 2) });
state.reportCustRatingInfo.push({ label: '定性得分', value: Round(resp.data.qualScoreGray, 2) });
state.reportCustRatingInfo.push({ label: '模型得分', value: Round(resp.data.modelScoreGray, 2) });
state.reportCustRatingInfo.push({
label: '模型级别',
value: resp.data.modelLevelGray,
format: () => {
return {
componentType: RatingLevel,
attrs: {
level: resp.data.modelLevelGray,
dense: true,
},
};
},
});
state.reportCustRatingInfo.push({
label: '调整项级别',
value: resp.data.adjLevelGray,
format: () => {
return {
componentType: RatingLevel,
attrs: {
level: resp.data.adjLevelGray,
dense: true,
},
};
},
});
}
})
.catch((error) => {
console.info('error====', error);
});
//
const urlSearchParams = new URLSearchParams({ sortBy: ['INDEX_TYPE', 'INDEX_CATEGORY'] });
urlSearchParams.append('pageable', 'false');
const criteria = {
fieldName: 'RATING_ID',
operator: 'equals',
value: state.rating['id'],
};
urlSearchParams.append('criteria', JSON.stringify(criteria));
await axios
.get(Environment.apiContextPath('api/irbs/ratingIndex/getGrayScoreDetail'), { params: urlSearchParams })
.then((resp) => {
if (resp?.data?.content) {
const groupMap = groupByProperties(resp.data.content, 'INDEX_TYPE');
state.reportQuantitativeScoreDtl = groupByProperties(groupMap[RatingStep.DLFX], 'INDEX_CATEGORY');
state.reportQualitativeScoreDtl = groupByProperties(groupMap[RatingStep.DXFX], 'INDEX_CATEGORY');
state.reportAdjustScoreDtl = groupByProperties(
groupMap[RatingStep.PJTZX].filter((item) => {
return item['INDEX_VALUE'] !== '0';
}),
'INDEX_CATEGORY',
);
}
})
.catch((error) => {
console.info('error====', error);
});
};
const show = async (data: any) => {
dialogRef.value.show();
state.rating = data;
state.dialogTitle = `公司客户灰度评级结果(客户:` + data['custName'] + ``;
loadCustInfo();
await loadRatingReport();
};
const hide = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
});
const dictCustomerSize = await DictionaryTools.fetch('CustomerSizeCd');
const dictRegisteredType = await DictionaryTools.fetch('REGISTERED_TYPE');
const dictGoverFinanceType = await DictionaryTools.fetch('GOVER_FINANCE_TYPE');
const dictGoverFinanceSign = await DictionaryTools.fetch('GOVER_FINANCE_SIGN');
const dictRegistrationCd = await DictionaryTools.fetch('REGISTRATION_CD');
const dictNationCd = await DictionaryTools.fetch('NATION_CD');
const dictMemberTypeCd = await DictionaryTools.fetch('MEMBER_TYPE_CD');
</script>
<style scoped lang="css"></style>

186
irbs.frontend/src/views/custRating/LaunchRatingDialog.vue

@ -1,186 +0,0 @@
<template>
<w-dialog ref="dialogRef" :title="state.dialogTitle" width="80%" height="80%" :buttons="dialogButtons">
<w-grid
ref="customerGridRef"
title="客户列表"
:fetch-data-url="Environment.apiContextPath('api/irbs/companyCustomer/query')"
:sort-no="true"
:checkbox-selection="false"
:config-button="false"
:query-form-cols-num="3"
:query-form-fields="customerGrid.queryFormFields"
:columns="customerGrid.columns"
:toolbar-actions="customerGrid.buttons"
:sort-by="['-lastModifyDate']"
:query-criteria="{
fieldName: 'mgerNo',
operator: 'equals',
value: SessionManager.getUser().loginName,
}"
></w-grid>
</w-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { useI18n } from 'vue-i18n';
import { axios, noErrorAxios, Environment, NotifyManager, Formater, Tools, SessionManager } from 'platform-core';
import { SelectCustomerFlag } from './CustRating.ts';
const { t } = useI18n();
const $q = useQuasar();
const dialogRef = ref();
const customerGridRef = ref();
const props = defineProps({
dictionary: {
type: Object,
default: () => {
return {};
},
},
});
const emit = defineEmits(['refresh']);
const state = reactive({
dialogTitle: '选择客户',
flag: SelectCustomerFlag.RATING, //
});
const generateRating = (rows) => {
showLoading();
const requestParams = {
method: 'POST',
headers: { 'content-type': 'application/json;charset=utf-8;' },
url: Environment.apiContextPath('api/irbs/companyRating/generateRating/' + rows[0]['custNo']),
};
noErrorAxios(requestParams)
.then((resp) => {
hideLoading();
emit('refresh');
dialogRef.value.hide();
NotifyManager.info('发起成功');
})
.catch((error) => {
const response = error?.response;
const status = response?.status;
const data = response?.data;
//
if (status === 500 && data.exception === 'java.lang.RuntimeException' && !Tools.isEmpty(data.errorMessage)) {
NotifyManager.error(data.errorMessage);
} else if (status === 500) {
NotifyManager.error(t(data?.errorMessageI18nKey));
} else {
NotifyManager.error(t(status));
}
});
};
const dialogButtons = [
{
label: '确定',
icon: 'beenhere',
click: async () => {
const rows = customerGridRef.value.getSelectedRows();
if (rows.length === 0) {
NotifyManager.warn('请选择客户');
return;
}
if (state.flag === SelectCustomerFlag.RATING) {
//
const monthLimit = await axios.post(Environment.apiContextPath('api/irbs/companyRating/getMonthRatingLimit/' + rows[0]['custNo']));
console.info('monthLimit====', monthLimit);
if (monthLimit?.data?.result === true && monthLimit?.data?.tactics === '1') {
NotifyManager.warn('该客户当月已达评级次数上限(' + monthLimit?.data?.num + '次),无法再次发起评级');
return;
} else if (monthLimit?.data?.result === true && monthLimit?.data?.tactics === '2') {
$q.dialog({
title: '询问',
message: '该客户当月已发起评级次数超过:' + monthLimit?.data?.num + '次,是否继续发起?',
cancel: { noCaps: true },
ok: { noCaps: true },
persistent: true,
}).onOk(() => {
generateRating(rows);
});
} else {
generateRating(rows);
}
} else if (state.flag === SelectCustomerFlag.COGNIZANCE) {
//
const resp = await axios
.get(Environment.apiContextPath('api/irbs/defaultCognizance/queryDefaCustNo'), { params: { custNo: rows[0]['custNo'] } })
.catch((error) => {
console.info('error-------------', error);
});
if (resp && resp.data === '1') {
NotifyManager.warn('当前客户存在进行中违约认定流程');
return;
} else if (resp && resp.data === '2') {
NotifyManager.warn('当前客户存在已人工认定违约认定结果,无法发起新的人工违约认定流程');
return;
} else if (resp && resp.data === '0') {
//
showLoading();
axios
.post(Environment.apiContextPath('api/irbs/defaultManager/cognizanceApply'), { custNo: rows[0]['custNo'], type: 'F' })
.then((resp) => {
hideLoading();
if (resp && resp['code'] === 200 && resp['data']) {
emit('refresh');
dialogRef.value.hide();
}
})
.catch((error) => {
hideLoading();
console.info('error-------------', error);
});
}
}
},
},
];
const customerGrid = {
queryFormFields: [
{ label: '客户号', name: 'custNo', type: 'w-text' }, //defaultValue: '2100601306'
{ label: '客户名称', name: 'custName', type: 'w-text' },
{ label: '企业规模', name: 'corpSizeCd', type: 'w-select', options: props.dictionary.optionsCustomerSizeCd },
],
buttons: ['query', 'reset'],
columns: [
{ name: 'custNo', label: '客户号' },
{ name: 'custName', label: '客户名称' },
{ name: 'induSortName', label: '行业类型' },
{ name: 'custTypeCd', label: '客户类型', format: Formater.dictionary(props.dictionary.dictCustomerTypeCd) },
{ name: 'buildDt', label: '成立时间' },
{ name: 'corpSizeCd', label: '企业规模', format: Formater.dictionary(props.dictionary.dictCustomerSizeCd) },
],
};
const show = (flag) => {
if (flag) {
state.flag = flag;
}
dialogRef.value.show();
};
const hide = () => {
dialogRef.value.hide();
};
const showLoading = (msg: string = '正在处理,请稍等...') => {
$q.loading.show({
message: msg,
boxClass: 'bg-grey-2 text-grey-9',
spinnerColor: 'primary',
});
};
const hideLoading = () => {
$q.loading.hide();
};
defineExpose({
show,
hide,
});
</script>

2060
irbs.frontend/src/views/custRating/RatingDialog.vue

File diff suppressed because it is too large

31
irbs.frontend/src/views/custRating/RatingLevel.vue

@ -1,31 +0,0 @@
<template>
<div>
<q-knob v-model="value" :min="1" :max="10" readonly show-value :size="size" :color="color" track-color="grey-3" v-bind="attrs">
<span>{{ props.level }}</span>
</q-knob>
</div>
</template>
<script setup lang="ts">
import { ref, useAttrs } from 'vue';
import { RatingLevelOptions } from './CustRating.ts';
const attrs = useAttrs();
const props = defineProps({
level: { type: String, default: '' },
size: { type: String, default: 'md' },
});
const value = ref(0);
const color = ref('teal');
const ratingLevel = RatingLevelOptions.find((item) => {
return item['value'] === props.level;
});
if (ratingLevel) {
value.value = ratingLevel.numberValue;
color.value = ratingLevel.color;
}
</script>
<style scoped lang="css"></style>

61
irbs.frontend/src/views/custRating/RatingLevelSlider.vue

@ -1,61 +0,0 @@
<template>
<q-slider
v-model="ratingLevel"
dense
readonly
color="blue"
:label-always="labelAlwaysComputed"
:label-value="labelValueComputed"
:marker-labels="labelsComputed"
:min="minLevel"
:max="maxLevel"
style="width: 95%"
/>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { RatingLevelOptions } from './CustRating';
const modelValue = defineModel<string>();
const minLevel = ref(RatingLevelOptions.find((item) => item.value === 'D')?.numberValue);
const maxLevel = ref(RatingLevelOptions.find((item) => item.value === 'AAA+')?.numberValue);
const props = defineProps({
// marker-labels
denseLabel: { type: Boolean, default: false },
});
const ratingLevel = computed(() => {
const ratingLevel_ = RatingLevelOptions.find((item) => {
return item['value'] === modelValue.value;
});
if (ratingLevel_) {
return ratingLevel_.numberValue;
}
return 1;
});
const labelsComputed = computed(() => {
const result = <any>[];
RatingLevelOptions.forEach((item) => {
if (props.denseLabel && item.denseLabel) {
result.push({
label: item.label,
value: item.numberValue,
});
} else if (!props.denseLabel) {
result.push({
label: item.label,
value: item.numberValue,
});
}
});
return result;
});
const labelAlwaysComputed = computed(() => {
return props.denseLabel;
});
const labelValueComputed = computed(() => {
return modelValue.value;
});
</script>

69
irbs.frontend/src/views/custRating/company/AnnotationButton.vue

@ -1,69 +0,0 @@
<template>
<div>
<q-btn
v-if="showComputed"
icon="mark_chat_unread"
color="primary"
label="批注"
@click="
() => {
addAnnotationRef.show();
}
"
/>
<w-drawer ref="addAnnotationRef" title="批注">
<div class="p-2 h-full">
<w-splitter :size="205" horizontal unit="px" disable :show-separator="false">
<template #before>
<w-form ref="formRef" :cols-num="1" :fields="[{ label: '批注内容', name: 'annotation', type: 'w-textarea' }]"></w-form>
<br />
<q-btn
icon="add"
color="primary"
label="添加"
@click="
() => {
annotationGridRef.addLocalData({ nr: formRef.getData()['annotation'], sj: currDate() });
}
"
/>
</template>
<template #after>
<div class="h-full">
<w-grid
ref="annotationGridRef"
:auto-fetch-data="false"
:config-button="false"
:toolbar-actions="['refresh', 'remove']"
:columns="[
{ label: '批注内容', name: 'nr' },
{ label: '批注时间', name: 'sj', width: 200 },
]"
>
</w-grid>
</div>
</template>
</w-splitter>
</div>
</w-drawer>
</div>
</template>
<script setup lang="ts">
import { ref, inject, computed } from 'vue';
import { Rating } from './ts/Rating';
import { Step } from './ts/Step';
import { Constant } from './ts/Constant';
const rating = <Rating>inject('rating');
const addAnnotationRef = ref();
const annotationGridRef = ref();
const formRef = ref();
const currDate = () => {
const now = new Date();
const formattedTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;
return formattedTime;
};
const showComputed = computed(() => {
return true;
});
</script>

37
irbs.frontend/src/views/custRating/company/Content.vue

@ -1,37 +0,0 @@
<template>
<CustInfo v-if="custComputed"></CustInfo>
<QuanQualAnalysis v-else-if="qqaComputed"></QuanQualAnalysis>
<AdjustItem v-else-if="aiComputed"></AdjustItem>
<ReportInfo v-else-if="riComputed"></ReportInfo>
<Opinion v-else-if="opinionComputed"></Opinion>
</template>
<script setup lang="ts">
import { ref, PropType, computed } from 'vue';
import type { StepType } from './ts/type/StepType';
import { Step } from './ts/Step';
import CustInfo from './content/CustInfo.vue';
import QuanQualAnalysis from './content/QuanQualAnalysis.vue';
import AdjustItem from './content/AdjustItem.vue';
import ReportInfo from './content/ReportInfo.vue';
import Opinion from './content/Opinion.vue';
const props = defineProps({
step: { type: Object as PropType<StepType>, default: undefined },
});
const custComputed = computed(() => {
return props.step?.value === Step.type.custInfo.value;
});
const qqaComputed = computed(() => {
return props.step?.value === Step.type.quanQualAnalysis.value;
});
const aiComputed = computed(() => {
return props.step?.value === Step.type.adjustItem.value;
});
const riComputed = computed(() => {
return props.step?.value === Step.type.reportInfo.value;
});
const opinionComputed = computed(() => {
return props.step?.value === Step.type.opinion.value;
});
</script>

21
irbs.frontend/src/views/custRating/company/NextButton.vue

@ -1,21 +0,0 @@
<template>
<q-btn v-if="showComputed" icon="next_plan" color="primary" label="下一步" @click="rating.step.nextClick" />
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Rating } from './ts/Rating';
import { Step } from './ts/Step';
import { Constant } from './ts/Constant';
const rating = <Rating>inject('rating');
const showComputed = computed(() => {
if (rating.ratingData.value['processStatus'] === Constant.RATING_PROCESS_STATUS.BACK && rating.step.currStep.value === Step.type.reportInfo.value) {
return false;
} else {
if (rating.cm.isApplyUserProcessStatus.value && rating.step.currStep.value !== Step.type.opinion.value) {
return true;
}
}
return false;
});
</script>

45
irbs.frontend/src/views/custRating/company/RatingDialog.vue

@ -1,38 +1,20 @@
<template>
<w-dialog ref="dialogRef" width="95%" height="95%" body-padding="0px 0px 0px 0px" @hide="hideEvent">
<w-dialog ref="dialogRef" width="98%" height="98%" body-padding="0px 0px 0px 0px" @hide="hideEvent">
<template #title>
<div>
<span class="text-xl">客户评级</span>
<span class="text-3xl">
{{ custInfoData['custName'] }}
<q-badge color="orange" align="top">客户号{{ custInfoData['custNo'] }}</q-badge
>&nbsp; <q-badge color="green" align="top">上市</q-badge>&nbsp;
<q-badge color="red" align="top">{{ Formater.dictionary(dictionary.customerSize)(custInfoData['customerSize']) }}</q-badge
>&nbsp; <q-badge align="top">{{ Formater.dictionary(dictionary.registeredType)(custInfoData['registeredType']) }}</q-badge
>&nbsp; <q-badge color="secondary" align="top">{{ custInfoData['groupCustInd'] === '1' ? '集团客户' : '非集团客户' }}</q-badge
>&nbsp;
<q-badge v-if="custInfoData['groupCustInd'] === '1'" align="top"
>集团成员类别{{ Formater.dictionary(dictionary.memberTypeCd)(custInfoData['memberType']) }}</q-badge
><template v-if="custInfoData['groupCustInd'] === '1'">&nbsp;</template>
<q-badge color="blue" align="top">行业{{ custInfoData['industryTypeName'] }}</q-badge
>&nbsp; <q-badge color="brown" align="top">成立日期{{ custInfoData['buildDate'] }}</q-badge
>&nbsp;
</span>
<CustBaseInfo :cust-id="custId"></CustBaseInfo>
</div>
</template>
<RatingPage :rating-data="props.ratingData" :read-mode="props.readMode" @after-complete="afterComplete"></RatingPage>
<ShrcbIndex :rating-data="props.ratingData" :read-mode="props.readMode" @after-complete="afterComplete"></ShrcbIndex>
</w-dialog>
</template>
<script setup lang="ts">
import { ref, computed, nextTick } from 'vue';
import { axios, Environment, Formater } from 'platform-core';
import RatingPage from './RatingPage.vue';
import { Dictionary } from './ts/Dictionary';
import { ref, nextTick } from 'vue';
import CustBaseInfo from '@/views/custRating/company/components/CustBaseInfo.vue';
import ShrcbIndex from '@/views/custRating/company/template/shrcb/Index.vue';
const dialogRef = ref();
const custInfoData = ref({});
const dictionary = new Dictionary();
const custId = ref('');
const props = defineProps({
ratingData: {
type: Object,
@ -47,22 +29,13 @@ const props = defineProps({
});
const emit = defineEmits(['refresh']);
const titleComputed = computed(() => {
return `公司客户评级 客户:` + props.ratingData['custName'] + ` 评级模型:` + (props.ratingData['modelName'] || '');
});
/**
* 显示评级窗口
*/
const show = () => {
dialogRef.value.show();
nextTick(() => {
const custId = props.ratingData['custId'];
axios.get(Environment.apiContextPath('api/irbs/ratingCompanyCustomer/' + custId)).then((resp) => {
if (resp && resp.data) {
custInfoData.value = resp.data;
}
});
custId.value = props.ratingData['custId'];
});
};
/**
@ -88,6 +61,4 @@ defineExpose({
show,
hide,
});
await dictionary.load();
</script>

23
irbs.frontend/src/views/custRating/company/RatingManager.vue

@ -106,7 +106,7 @@
{ label: '评级状态', name: 'ratingStatus', type: 'w-select', options: Options.enum(RatingStatusEnum) },
]"
:columns="[
{ name: 'id', label: '申请编号', align: 'center' },
{ name: 'triggerRea', label: '申请编号', align: 'center' },
{ name: 'custNo', label: '客户号', align: 'center' },
{ name: 'custName', label: '客户名称', width: 150 },
{ name: 'industryTypeName', label: '行业类型' },
@ -117,25 +117,13 @@
{
name: 'finalLevel',
label: '认定等级',
format: (val) => {
if (!Tools.isEmpty(val)) {
return {
componentType: RatingLevel,
attrs: {
level: val,
dense: true,
},
};
}
return val;
},
},
{
name: 'pd',
label: '违约概率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -156,13 +144,12 @@
</template>
<script setup lang="ts">
import { ref, nextTick, onMounted } from 'vue';
import { ref, onMounted } from 'vue';
import { useQuasar } from 'quasar';
import { axios, EnumTools, Environment, Formater, noErrorAxios, NotifyManager, Options, SessionManager, Tools, ServerExceptionHandler } from 'platform-core';
import { RatingLevelOptions, RatingProcessStatus, Round } from '../CustRating.ts';
import GrayModelDialog from '../GrayModelDialog.vue';
import { RatingLevelOptions, RatingProcessStatus, round } from '@/views/custRating/company/ts/Utils';
import GrayModelDialog from './GrayModelDialog.vue';
import RatingDialog from './RatingDialog.vue';
import RatingLevel from '../RatingLevel.vue';
import CustSelectDialog from './CustSelectDialog.vue';
import LoadingDialog from '@/views/components/LoadingDialog.vue';

71
irbs.frontend/src/views/custRating/company/RatingPage.vue

@ -1,71 +0,0 @@
<template>
<w-splitter :size="46" horizontal disable reverse unit="px" style="height: 100%">
<template #before>
<Step ref="stepRef" class="h-full"></Step>
</template>
<template #after>
<div class="p-1 flex justify-end gap-x-4">
<AnnotationButton></AnnotationButton>
<!-- <TestCalcButton></TestCalcButton> -->
<NextButton></NextButton>
<WorkflowButton></WorkflowButton>
</div>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { VueTools } from 'platform-core';
import { getCurrentInstance, onMounted, provide, ref, shallowRef } from 'vue';
import RatingLevel from '../RatingLevel.vue';
import NextButton from './NextButton.vue';
import Step from './Step.vue';
import TestCalcButton from './TestCalcButton.vue';
import { Rating } from './ts/Rating';
import WorkflowButton from './WorkflowButton.vue';
import AnnotationButton from './AnnotationButton.vue';
const RatingLevelRef = shallowRef(RatingLevel);
const props = defineProps({
ratingData: {
type: Object,
default: () => {
return {};
},
},
readMode: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(['afterComplete']);
const rating = new Rating(props.ratingData, props.readMode);
await rating.dictionary.load();
await rating.enum.load();
await rating.systemParameter.load();
const ratingLevelFormat = (modelLevel: any, size: string) => {
return {
componentType: RatingLevelRef,
attrs: {
level: modelLevel,
dense: true,
size: size,
},
};
};
rating.refs.setRatingLevelFormatFunction(ratingLevelFormat);
onMounted(() => {
rating.step.setCurrStep(rating.ratingData.value['currentStep']);
});
//
const instance = getCurrentInstance();
// API
VueTools.expose2Instance(instance);
//
rating.setInstance(instance);
provide('rating', rating);
</script>

58
irbs.frontend/src/views/custRating/company/Step.vue

@ -1,58 +0,0 @@
<template>
<w-splitter :size="75" class="h-full" unit="px" disable>
<template #before>
<div class="h-full" style="display: flex; align-items: center">
<q-tabs
v-model="rating.step.currStep.value"
vertical
indicator-color="amber"
active-color="amber"
align="left"
:dense="rating.cm.isAwaitSubmitProcessStatus.value"
style="height: auto"
@update:model-value="rating.step.click"
>
<template v-for="(step, index) in rating.step.steps.value" :key="step.value">
<q-tab :name="step.value" :icon="step.icon" :label="step.label" :disable="step.disable" style="padding: 2px">
<q-tooltip v-if="rating.cm.isAwaitSubmitProcessStatus.value" transition-show="rotate" transition-hide="rotate">{{ step.tooltip }}</q-tooltip>
</q-tab>
<div v-if="index !== rating.step.steps.value.length - 1 && rating.cm.isAwaitSubmitProcessStatus.value" style="width: 100%; text-align: center">
<q-icon name="bi-arrow-down-short" size="sm"></q-icon>
</div>
</template>
</q-tabs>
</div>
</template>
<template #after>
<!-- 切分窗口 -->
<w-splitter v-if="!rating.cm.isAwaitSubmitProcessStatus.value" :size="77" :separator-color="rating.separatorColor" class="h-full">
<template #before>
<q-tab-panels v-model="rating.step.currStep.value" class="p-0 h-full">
<q-tab-panel v-for="step in rating.step.steps.value" :key="step.value" :name="step.value" class="p-0 h-full">
<Content :step="step"></Content>
</q-tab-panel>
</q-tab-panels>
</template>
<template #after>
<Opinion></Opinion>
</template>
</w-splitter>
<!-- 不切分 -->
<q-tab-panels v-else v-model="rating.step.currStep.value" class="p-0 h-full">
<q-tab-panel v-for="step in rating.step.steps.value" :key="step.value" :name="step.value" class="p-0 h-full">
<Content :step="step"></Content>
</q-tab-panel>
</q-tab-panels>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { inject, ref, onMounted } from 'vue';
import { Rating } from './ts/Rating';
import Content from './Content.vue';
import { Constant } from './ts/Constant';
import Opinion from './content/Opinion.vue';
const rating = <Rating>inject('rating');
</script>

73
irbs.frontend/src/views/custRating/company/TestCalcButton.vue

@ -1,73 +0,0 @@
<template>
<q-btn v-if="showComputed" icon="calculate" color="primary" label="试算" :disable="testCalcNum < 1" @click="click">
<q-badge :color="testCalcNum > 3 ? 'green' : 'red'" floating
>{{ testCalcNum }}
<q-tooltip> 剩余可试算次数 </q-tooltip>
</q-badge>
</q-btn>
</template>
<script setup lang="ts">
import { ref, inject, computed, onBeforeMount } from 'vue';
import { useQuasar } from 'quasar';
import { axios, Environment, NotifyManager, Tools } from 'platform-core';
import { Rating } from './ts/Rating';
import { Step } from './ts/Step';
import { Constant } from './ts/Constant';
import { round } from './ts/Utils';
const $q = useQuasar();
const rating = <Rating>inject('rating');
const testCalcNum = ref(0);
const getTestCalcNum = async () => {
const resp = await axios.get(Environment.apiContextPath('api/irbs/companyRating/getQualTestCalcNum'), {
params: { ratingId: rating.ratingData.value['id'] },
});
if (resp?.data) {
testCalcNum.value = resp.data;
}
};
const click = async () => {
const result = rating.step.qualFormValidate();
if (!result['result']) {
return;
}
rating.showLoading('正在计算定性得分,请稍等...');
const url = Environment.apiContextPath('api/irbs/companyRating/qualSaveIndices/' + Constant.QUAL_SAVE_OPERATOR.TEST);
const resp = await axios.post(url, result['submitData']).catch((error) => {
rating.hideLoading();
NotifyManager.error('计算出错,请联系管理员');
console.info('error====', error);
});
rating.hideLoading();
if (resp?.data?.success === true) {
rating.ratingData.value['lastQualTestCalcScore'] = round(resp.data.qualScore, 2);
$q.dialog({
title: '消息',
message: '本次试算定性得分为:' + round(resp.data.qualScore, 2),
cancel: false,
persistent: true,
});
//
getTestCalcNum();
} else if (resp?.data?.success === false && !Tools.isEmpty(resp.data.errorMsg)) {
if (rating.ratingData.value['lastQualTestCalcScore']) {
NotifyManager.error(resp.data.errorMsg + ',与最后一次试算结果相同,得分为:' + rating.ratingData.value['lastQualTestCalcScore']);
} else {
NotifyManager.error(resp.data.errorMsg);
}
}
};
const showComputed = computed(() => {
if (rating.cm.isApplyUserProcessStatus.value && rating.step.currStep.value === Step.type.quanQualAnalysis.value) {
return true;
}
return false;
});
onBeforeMount(() => {
getTestCalcNum();
});
</script>

48
irbs.frontend/src/views/custRating/company/WorkflowButton.vue

@ -1,48 +0,0 @@
<template>
<w-workflow-action
v-if="showComputed"
:task-id="rating.ratingData.value['taskId']"
:data="rating.opinionData.value"
:default-submit-button="false"
:action-url="Environment.apiContextPath('/api/irbs/companyRatingProcess/submit')"
@before-submit="
async (action, callback) => {
rating.opinionData.value = {
transientVariables: {
opaVal: action.transientVariables.goback,
desc: '客户名称:' + rating.ratingData.value['custName'],
},
data: rating.refs.overturnFormRefFunction().getData(),
};
const validateResult = await rating.refs.overturnFormRefFunction().validate();
if (validateResult) {
callback(true);
} else {
callback(false);
}
}
"
@after-submit="
() => {
rating.instance.emit('afterComplete');
}
"
>
</w-workflow-action>
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Environment } from 'platform-core';
import { Rating } from './ts/Rating';
import { Step } from './ts/Step';
const rating = <Rating>inject('rating');
const showComputed = computed(() => {
if (rating.cm.isAwaitSubmitProcessStatus.value) {
return rating.step.currStep.value === Step.type.opinion.value;
} else if (rating.ratingData.value['taskId']) {
return true;
}
return false;
});
</script>

18
irbs.frontend/src/views/custRating/company/content/AdjustItem.vue

@ -1,18 +0,0 @@
<template>
<w-splitter :size="45" unit="px" horizontal disable>
<template #before>
<FirstRatingResult></FirstRatingResult>
</template>
<template #after>
<AdjustItemGrid class="px-1"></AdjustItemGrid>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Rating } from '../ts/Rating';
import FirstRatingResult from './FirstRatingResult.vue';
import AdjustItemGrid from './AdjustItemGrid.vue';
const rating = <Rating>inject('rating');
</script>

68
irbs.frontend/src/views/custRating/company/content/AdjustItemGrid.vue

@ -1,68 +0,0 @@
<template>
<w-grid
ref="adjustItemGridRef"
title="评级调整项列表"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="false"
:checkbox-selection="false"
group-mode="alone"
group-by-field="indexCategory"
:stripe="true"
:sort-no="false"
:config-button="false"
:toolbar-actions="['expand']"
:columns="[
{
name: 'value',
label: '符合',
width: 80,
align: 'center',
sortable: false,
format: (val) => {
return {
componentType: 'w-checkbox',
bindModelValue: true,
attrs: {
dense: true,
disableIf: () => {
// if (showNextBtnComputed) {
// return false;
// }
return false;
},
},
};
},
},
{
name: 'indexCategory',
label: '调整项分类',
showIf: false,
},
{
name: 'indexCode',
label: '调整项编码',
sortable: false,
},
{
name: 'adjustItemName',
label: '调整项(<span class=\'text-red-500\'>若客户符合调整项所描述情况,请在【符合】列打勾</span>)',
sortable: false,
},
]"
@row-db-click="() => {}"
></w-grid>
</template>
<script setup lang="ts">
import { inject, ref } from 'vue';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
const adjustItemGridRef = ref();
const getAdjustItemGridRef = () => {
return adjustItemGridRef.value;
};
rating.refs.setAdjustItemGridRefFunction(getAdjustItemGridRef);
</script>

36
irbs.frontend/src/views/custRating/company/content/AdjustItemIndex.vue

@ -1,36 +0,0 @@
<template>
<w-splitter :size="34" horizontal unit="px" disable class="h-full">
<template #before>
<w-card-panel
label="评级调整项详情"
:bordered="false"
:title-mode="true"
icon="build_circle"
:icon-attrs="{ color: 'yellow' }"
color="yellow"
></w-card-panel>
</template>
<template #after>
<q-list v-if="rating.adjustItemScoreDtlData.value" padding>
<template v-for="(values, key, a) in rating.adjustItemScoreDtlData.value" :key="a">
<q-item-label header>{{ key }}</q-item-label>
<template v-for="(dtl, index) in values" :key="index">
<q-item>
<q-item-section>
<q-item-label>{{ index + 1 }}{{ dtl['INDEX_NAME'] }}</q-item-label>
<!-- <q-item-label caption> {{ dtl['TEXT'] }} </q-item-label> -->
</q-item-section>
</q-item>
</template>
<!-- <q-separator /> -->
</template>
</q-list>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { inject } from 'vue';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
</script>

38
irbs.frontend/src/views/custRating/company/content/CreditReportGrid.vue

@ -1,38 +0,0 @@
<template>
<w-grid
ref="creditReportGridRef"
title="征信报告"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="false"
:fetch-data-url="Environment.apiContextPath('api/irbs/creditReport')"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'id', label: '报告号' },
{ name: 'custNo', label: '客户号' },
{ name: 'entName', label: '客户名称' },
{ name: 'reportDate', label: '报告日期', format: Formater.dateOnly() },
{ name: 'expiryDate', label: '征信有效期', format: Formater.dateOnly() },
{ name: 'blankInd', label: '是否白户', slot: 'isValid' },
]"
:query-criteria="{
fieldName: 'custNo',
operator: 'equals',
value: '',
}"
></w-grid>
</template>
<script setup lang="ts">
import { ref, inject } from 'vue';
import { Formater, Environment } from 'platform-core';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
const creditReportGridRef = ref();
const getCreditReportGridRef = () => {
return creditReportGridRef.value;
};
rating.refs.setCreditReportGridRefFunction(getCreditReportGridRef);
</script>

29
irbs.frontend/src/views/custRating/company/content/CustBaseInfo.vue

@ -1,29 +0,0 @@
<template>
<q-card flat bordered>
<q-card-section>
<span class="text-3xl">
{{ rating.custInfoData.value['custName'] }}
<!-- <q-badge v-if="rating.custInfoData.value['marketEnterprisesInd'] === '1'" color="red" align="top">上市</q-badge> -->
<q-badge color="orange" align="top">客户号{{ rating.custInfoData.value['custNo'] }}</q-badge
>&nbsp; <q-badge color="green" align="top">上市</q-badge>&nbsp;
<q-badge color="red" align="top">{{ Formater.dictionary(rating.dictionary.customerSize)(rating.custInfoData.value['customerSize']) }}</q-badge
>&nbsp; <q-badge align="top">{{ Formater.dictionary(rating.dictionary.registeredType)(rating.custInfoData.value['registeredType']) }}</q-badge
>&nbsp; <q-badge color="secondary" align="top">{{ rating.custInfoData.value['groupCustInd'] === '1' ? '集团客户' : '非集团客户' }}</q-badge
>&nbsp;
<q-badge v-if="rating.custInfoData.value['groupCustInd'] === '1'" align="top"
>集团成员类别{{ Formater.dictionary(rating.dictionary.memberTypeCd)(rating.custInfoData.value['memberType']) }}</q-badge
><template v-if="rating.custInfoData.value['groupCustInd'] === '1'">&nbsp;</template>
<q-badge color="blue" align="top">行业{{ rating.custInfoData.value['industryTypeName'] }}</q-badge
>&nbsp; <q-badge color="brown" align="top">成立日期{{ rating.custInfoData.value['buildDate'] }}</q-badge
>&nbsp;
</span>
</q-card-section>
</q-card>
</template>
<script setup lang="ts">
import { Formater } from 'platform-core';
import { inject } from 'vue';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
</script>

61
irbs.frontend/src/views/custRating/company/content/CustInfo.vue

@ -1,61 +0,0 @@
<template>
<w-splitter :size="48" unit="px" horizontal disable>
<template #before>
<div class="py-1 pl-1 flex flex-nowrap items-start gap-x-2">
<div class="flex-1">
<w-form
:cols-num="3"
:fields="[
{
label: '评分卡',
name: 'modelName',
type: 'w-select',
options: ['A评分卡', 'B评分卡', 'K评分卡'],
defaultValue: rating.ratingData.value['modelName'],
},
{
label: '更改评分卡说明',
name: 'updateModelDesc',
type: 'w-text',
colSpan: 2,
},
]"
>
</w-form>
</div>
<div class="flex-none pr-4">
<q-btn icon="task_alt" color="primary" label="更改" @click="click" />
</div>
</div>
</template>
<template #after>
<w-splitter :size="70" :limits="[30, 95]" horizontal :separator-color="rating.separatorColor">
<template #before>
<FinanceReportTabs></FinanceReportTabs>
</template>
<template #after>
<CreditReportGrid class="px-1"></CreditReportGrid>
</template>
</w-splitter>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { ref, inject } from 'vue';
import { DialogManager } from 'platform-core';
import { Rating } from '../ts/Rating';
import FinanceReportGrid from './FinanceReportGrid.vue';
import CreditReportGrid from './CreditReportGrid.vue';
import CustBaseInfo from './CustBaseInfo.vue';
import FinanceReportTabs from './FinanceReportTabs.vue';
const rating = <Rating>inject('rating');
const custFormRef = ref();
const getCustFormRef = () => {
return custFormRef.value;
};
rating.refs.setCustFormRefFunction(getCustFormRef);
const click = () => {
DialogManager.confirm('更改评分卡后流程会经总行进行审批,确认要更改评分卡吗', () => {});
};
</script>

46
irbs.frontend/src/views/custRating/company/content/DefaultCognizanceGrid.vue

@ -1,46 +0,0 @@
<template>
<w-grid
ref="defaultCognizanceGridRef"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:toolbar-actions="[]"
:fetch-data-url="Environment.apiContextPath('api/irbs/defaultCognizance')"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'custNo', label: '客户号' },
{ name: 'custName', label: '客户名称' },
{ name: 'levelHis', label: '违约时评级' },
{ name: 'effectiveDate', label: '违约发起时间' },
{ name: 'creator', label: '违约发起人' },
{ name: 'defaultProcessStatus', label: '违约流程状态' },
{ name: 'defalutType', label: '违约认定类型' },
]"
:query-criteria="{
operator: 'and',
criteria: [
{
fieldName: 'custNo',
operator: 'equals',
value: rating.ratingData.value['custNo'],
},
{
fieldName: 'status',
operator: 'equals',
value: Constant.DEFAULT_PROCESS_STATUS.PASS,
},
],
}"
:sort-by="['-effectiveDate']"
></w-grid>
</template>
<script setup lang="ts">
import { Environment } from 'platform-core';
import { inject } from 'vue';
import { Constant } from '../ts/Constant';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
</script>

45
irbs.frontend/src/views/custRating/company/content/DefaultRebirthGrid.vue

@ -1,45 +0,0 @@
<template>
<w-grid
ref="defaultRebirthGridRef"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:toolbar-actions="[]"
:fetch-data-url="Environment.apiContextPath('api/irbs/defaultRebirth')"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'custNo', label: '客户号' },
{ name: 'custName', label: '客户名称' },
{ name: 'rebirthEffectiveDate', label: '重生生效时间' },
{ name: 'creator', label: '重生发起人' },
{ name: 'rebirthProcessStatus', label: '重生流程状态' },
{ name: 'defalutRebornType', label: '违约重生类型' },
]"
:query-criteria="{
operator: 'and',
criteria: [
{
fieldName: 'custNo',
operator: 'equals',
value: rating.ratingData.value['custNo'],
},
{
fieldName: 'rebirthProcessStatus',
operator: 'equals',
value: Constant.DEFAULT_PROCESS_STATUS.PASS,
},
],
}"
:sort-by="['-rebirthEffectiveDate']"
></w-grid>
</template>
<script setup lang="ts">
import { Environment } from 'platform-core';
import { inject } from 'vue';
import { Constant } from '../ts/Constant';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
</script>

49
irbs.frontend/src/views/custRating/company/content/FinanceProjectCompare.vue

@ -1,49 +0,0 @@
<template>
<div v-if="!Tools.isEmpty(valueComputed)">{{ formatAmt(valueComputed) }} <q-icon :name="iconComputed?.name" :color="iconComputed?.color"></q-icon></div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { Tools } from 'platform-core';
import { formatAmt } from '../ts/Utils';
const props = defineProps({
//
value: { type: Number, default: undefined },
//
previousPeriod: { type: Number, default: undefined },
});
const icon = {
equals: {
name: 'horizontal_rule',
color: 'green',
},
up: {
name: 'arrow_upward',
color: 'blue',
},
down: {
name: 'arrow_downward',
color: 'orange',
},
};
const valueComputed = computed(() => {
if (!Tools.isEmpty(props.value) && !Tools.isEmpty(props.previousPeriod)) {
const result = props.value - props.previousPeriod;
return result;
}
return undefined;
});
const iconComputed = computed(() => {
if (!Tools.isEmpty(valueComputed.value) && valueComputed.value === 0) {
return icon.equals;
} else if (!Tools.isEmpty(valueComputed.value) && valueComputed.value > 0) {
return icon.up;
} else if (!Tools.isEmpty(valueComputed.value) && valueComputed.value < 0) {
return icon.down;
}
return undefined;
});
</script>

74
irbs.frontend/src/views/custRating/company/content/FinanceProjectGrid.vue

@ -1,74 +0,0 @@
<template>
<w-grid
:dense-body="true"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:dense="true"
:fetch-data-url="Environment.apiContextPath('api/irbs/financeReportDetail/query/' + rating.ratingData.value['custId'])"
:checkbox-selection="false"
:sort-no="true"
:config-button="false"
:columns="columnsComputed"
:query-criteria="props.queryCriteria"
:sort-by="['projectCode']"
></w-grid>
</template>
<script setup lang="ts">
import { inject, onMounted, computed } from 'vue';
import { Environment } from 'platform-core';
import { Rating } from '../ts/Rating';
import FinanceProjectCompare from './FinanceProjectCompare.vue';
import { formatAmt } from '../ts/Utils';
const rating = <Rating>inject('rating');
const props = defineProps({
queryCriteria: { type: Object, default: undefined },
});
const columnsComputed = computed(() => {
const columns = <any>[
{ name: 'code', label: '科目编码' },
{ name: 'name', label: '科目名称' },
];
if (rating.financeReport.value.length > 0) {
const columnNames = ['value', 'previousPeriodvalue', 'previousPeriod2value', 'previousPeriod3value'];
rating.financeReport.value.forEach((report: any, index: number) => {
const year = report['endDate'].substring(0, 4);
columns.push({
name: year,
label: year,
columns: [
{
name: columnNames[index],
label: '本期值',
align: 'right',
format: (val, row) => {
return formatAmt(val);
},
},
{
name: year + 'comparePreviousPeriod',
label: '比上期',
align: 'right',
format: (val, row) => {
return {
componentType: FinanceProjectCompare,
attrs: {
value: row[columnNames[index]],
previousPeriod: index === columnNames.length - 1 ? undefined : row[columnNames[index + 1]],
},
};
},
},
],
});
});
}
return columns;
});
onMounted(() => {
rating.api.loadFinanceReport();
});
</script>

146
irbs.frontend/src/views/custRating/company/content/FinanceReportGrid.vue

@ -1,146 +0,0 @@
<template>
<div>
<w-grid
ref="financeReportGridRef"
title="财务报表"
:dense="rating.dense"
:height="150"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="false"
:fetch-data-url="Environment.apiContextPath('api/irbs/financeReport/getReport')"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'endDate', label: '财报日期', format: Formater.dateOnly() },
// { name: 'type', label: '', format: Formater.dictionary(rating.dictionary.financeTypeCd) },
{
name: 'type',
label: '报表类型',
format: Formater.dictionary(rating.dictionary.financeTypeCd),
},
{ name: 'sort', label: '报表类别', format: Formater.dictionary(rating.dictionary.financeSortTypeCd) },
{ name: 'auditedInd', label: '是否审计', format: Formater.dictionary(rating.dictionary.financeStatusCd) },
{ name: 'caliber', label: '报表口径', format: Formater.dictionary(rating.dictionary.caliberCd) },
{ name: 'currency', label: '报表币种', format: Formater.dictionary(rating.dictionary.currencyTypeCd) },
{ name: 'userNo', label: '经办人' },
{ name: 'remarks', label: '备注' },
{
name: 'op',
label: '操作',
format: opFormat,
},
]"
></w-grid>
<w-dialog ref="financeReportDetailDialogRef" title="财报详情" width="80%" height="80%" body-padding="0px 0px 0px 0px">
<w-splitter :size="60" horizontal unit="px" disable class="h-full">
<template #before>
<div class="p-1">
<w-info-panel :info="financeReport.otherInfo" :column-num="5" :label-width="150"></w-info-panel>
</div>
</template>
<template #after>
<div class="flex flex-nowrap items-start h-full">
<div class="flex-none h-full">
<q-tabs v-model="detailTab" vertical indicator-color="amber" active-color="amber">
<template v-for="report in financeReport.tabsComputed.value" :key="report.value">
<q-tab :name="report.value" :icon="report.icon" :label="report.label" />
</template>
</q-tabs>
</div>
<q-separator vertical />
<div class="flex-1 h-full">
<q-tab-panels
v-model="detailTab"
:keep-alive="true"
animated
swipeable
vertical
transition-prev="jump-up"
transition-next="jump-up"
class="h-full"
>
<template v-for="report in financeReport.tabsComputed.value" :key="report.value">
<q-tab-panel :name="report.value" class="h-full p-1">
<FinanceProjectGrid
:query-criteria="{
operator: 'and',
criteria: [
{
fieldName: 'reportId',
operator: 'equals',
value: financeReport.reportId,
},
{
fieldName: 'projectType',
operator: 'equals',
value: report.value,
},
],
}"
></FinanceProjectGrid>
</q-tab-panel>
</template>
</q-tab-panels>
</div>
</div>
</template>
</w-splitter>
</w-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, nextTick, reactive, inject } from 'vue';
import { Formater, Environment } from 'platform-core';
import { Rating } from '../ts/Rating';
import FinanceProjectGrid from './FinanceProjectGrid.vue';
import { FinanceReport, Constant } from '../ts/FinanceReport';
const rating = <Rating>inject('rating');
const financeReportGridRef = ref();
const getFinanceReportGridRef = () => {
return financeReportGridRef.value;
};
rating.refs.setFinanceReportGridRefFunction(getFinanceReportGridRef);
const financeReportDetailDialogRef = ref();
const financeReport = new FinanceReport();
const splitterModel = ref(60);
const detailTab = ref('');
const opFormat = (value, row) => {
if (row && row['sort']) {
return {
componentType: 'q-chip',
attrs: {
dense: true,
color: 'primary',
icon: 'visibility',
textColor: 'white',
square: true,
size: rating.dense ? 'xs' : 'md',
label: '查 看',
onclick: () => {
financeReport.reportType.value = row['sort'];
if (financeReport.reportType.value === Constant.REPORT_TYPE_COMPANY) {
detailTab.value = FinanceReport.reportDetail.c_balance_sheet.value;
} else {
detailTab.value = FinanceReport.reportDetail.p_balance_sheet.value;
}
financeReport.reportId = row['id'];
financeReportDetailDialogRef.value.show();
financeReport.otherInfo = [];
financeReport.otherInfo.push({ label: '财务报表截至日期', value: row['endDate'], format: Formater.dateOnly() });
financeReport.otherInfo.push({ label: '是否经过审计', value: row['auditedInd'], format: Formater.dictionary(rating.dictionary.financeStatusCd) });
financeReport.otherInfo.push({ label: '财务报表类别', value: row['sort'], format: Formater.dictionary(rating.dictionary.financeTypeCd) });
financeReport.otherInfo.push({ label: '财务报表口径', value: row['caliber'], format: Formater.dictionary(rating.dictionary.caliberCd) });
financeReport.otherInfo.push({ label: '财务报表币种', value: row['currency'], format: Formater.dictionary(rating.dictionary.currencyTypeCd) });
},
},
};
} else {
return '';
}
};
</script>

39
irbs.frontend/src/views/custRating/company/content/FinanceReportTabs.vue

@ -1,39 +0,0 @@
<template>
<div class="h-full">
<w-splitter :size="36" horizontal class="h-full" unit="px" disable>
<template #before>
<q-tabs v-model="tab" inline-label dense indicator-color="amber" align="right" active-color="amber">
<template v-for="report in financeReport.tabsComputed.value" :key="report.value">
<q-tab :name="report.value" :icon="report.icon" :label="report.label" />
</template>
</q-tabs>
</template>
<template #after>
<q-tab-panels v-model="tab" :keep-alive="true" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up" class="h-full">
<template v-for="report in financeReport.tabsComputed.value" :key="report.value">
<q-tab-panel :name="report.value" class="h-full p-1">
<FinanceProjectGrid
:query-criteria="{
fieldName: 'projectType',
operator: 'equals',
value: report.value,
}"
></FinanceProjectGrid>
</q-tab-panel>
</template>
</q-tab-panels>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { inject, ref } from 'vue';
import { Environment, Formater } from 'platform-core';
import { Rating } from '../ts/Rating';
import { FinanceReport, Constant } from '../ts/FinanceReport';
import FinanceProjectGrid from './FinanceProjectGrid.vue';
const rating = <Rating>inject('rating');
const financeReport = new FinanceReport();
const tab = ref(FinanceReport.reportDetail.c_balance_sheet.value);
</script>

29
irbs.frontend/src/views/custRating/company/content/FirstRatingResult.vue

@ -1,29 +0,0 @@
<template>
<div v-if="rating.systemParameter.showTotalScore.value">
<span class="pl-[8px]">初评结果</span>
<w-info-panel :info="rating.firstRatingData.value" :column-num="4"></w-info-panel>
</div>
<div v-else>
<q-list dense>
<q-item>
<q-item-section avatar>初评结果</q-item-section>
<q-item-section>
<RatingLevelSlider v-model="firstRatingLevelComputed"></RatingLevelSlider>
</q-item-section>
</q-item>
</q-list>
</div>
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Rating } from '../ts/Rating';
import RatingLevelSlider from '../../RatingLevelSlider.vue';
const rating = <Rating>inject('rating');
const firstRatingLevelComputed = computed(() => {
if (rating.firstRatingData.value && rating.firstRatingData.value.length > 0) {
return rating.firstRatingData.value[0]['value'];
}
return undefined;
});
</script>

51
irbs.frontend/src/views/custRating/company/content/HistRatingGrid.vue

@ -1,51 +0,0 @@
<template>
<w-grid
ref="custHistRatingGridRef"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:toolbar-actions="[]"
:fetch-data-url="Environment.apiContextPath('api/irbs/companyRating')"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'id', label: '申请编号' },
{ name: 'custNo', label: '客户号' },
{ name: 'custName', label: '客户名称' },
// { name: 'modelScore', label: '' },
{ name: 'modelLevel', label: '系统评级等级' },
{ name: 'adjLevel', label: '调整等级' },
{ name: 'initLevel', label: '初评等级' },
{ name: 'finalLevel', label: '最终等级' },
{ name: 'effectiveTime', label: '生效日期', format: Formater.dateOnly() },
{ name: 'matureTime', label: '到期日期', format: Formater.dateOnly() },
{ name: 'ratingStatus', label: '评级状态', format: Formater.enum(rating.enum.ratingStatus) },
{ name: 'launchUser', label: '发起人' },
{ name: 'processStatus', label: '状态', format: Formater.enum(rating.enum.ratingProcessStatus) },
]"
:query-criteria="{
operator: 'and',
criteria: [
{
fieldName: 'custNo',
operator: 'equals',
value: rating.ratingData.value['custNo'],
},
{
fieldName: 'processStatus',
operator: 'equals',
value: Constant.DEFAULT_PROCESS_STATUS.PASS,
},
],
}"
></w-grid>
</template>
<script setup lang="ts">
import { Environment, Formater } from 'platform-core';
import { inject } from 'vue';
import { Constant } from '../ts/Constant';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
</script>

33
irbs.frontend/src/views/custRating/company/content/HistTab.vue

@ -1,33 +0,0 @@
<template>
<div class="h-full">
<w-splitter :size="36" horizontal class="h-full" unit="px" disable>
<template #before>
<q-tabs v-model="tab" inline-label dense indicator-color="amber" align="left" active-color="amber">
<template v-for="item in HistGird.tabs" :key="item.value">
<q-tab :name="item.value" :icon="item.icon" :label="item.label" />
</template>
</q-tabs>
</template>
<template #after>
<q-tab-panels v-model="tab" :keep-alive="true" animated swipeable vertical transition-prev="jump-up" transition-next="jump-up" class="h-full">
<template v-for="item in HistGird.tabs" :key="item.value">
<q-tab-panel :name="item.value" class="h-full p-1">
<HistRatingGrid v-if="item.value === HistGird.type.histRating.value"></HistRatingGrid>
<DefaultCognizanceGrid v-else-if="item.value === HistGird.type.defaultCognizance.value"></DefaultCognizanceGrid>
<DefaultRebirthGrid v-else-if="item.value === HistGird.type.defaultRebirth.value"></DefaultRebirthGrid>
</q-tab-panel>
</template>
</q-tab-panels>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { HistGird } from '../ts/HistGrid';
import HistRatingGrid from './HistRatingGrid.vue';
import DefaultCognizanceGrid from './DefaultCognizanceGrid.vue';
import DefaultRebirthGrid from './DefaultRebirthGrid.vue';
const tab = ref(HistGird.type.histRating.value);
</script>

40
irbs.frontend/src/views/custRating/company/content/Opinion.vue

@ -1,40 +0,0 @@
<template>
<div class="h-full pl-1">
<w-splitter v-if="!rating.cm.isAwaitSubmitProcessStatus.value" :size="rating.readMode ? 100 : 50" horizontal class="h-full" disable :show-separator="false">
<template #before>
<w-splitter :size="36" horizontal class="h-full" unit="px" disable :show-separator="false">
<template #before>
<q-tabs v-model="histTab" dense no-caps inline-label align="right">
<q-tab name="timeline" icon="query_builder" label="审批时间线" />
<q-tab name="grid" icon="grid_on" label="审批列表" />
</q-tabs>
</template>
<template #after>
<q-tab-panels v-model="histTab" class="p-0 h-full">
<q-tab-panel name="timeline" class="p-0 pt-1 px-2 h-full">
<Timeline></Timeline>
</q-tab-panel>
<q-tab-panel name="grid" class="p-0 pt-1 h-full">
<OpinionGrid></OpinionGrid>
</q-tab-panel>
</q-tab-panels>
</template>
</w-splitter>
</template>
<template #after>
<Overturn></Overturn>
</template>
</w-splitter>
<Overturn v-else class="p-1"></Overturn>
</div>
</template>
<script setup lang="ts">
import { inject, ref } from 'vue';
import { Rating } from '../ts/Rating';
import OpinionGrid from './OpinionGrid.vue';
import Overturn from './Overturn.vue';
import Timeline from './Timeline.vue';
const rating = <Rating>inject('rating');
const histTab = ref('timeline');
</script>

44
irbs.frontend/src/views/custRating/company/content/OpinionGrid.vue

@ -1,44 +0,0 @@
<template>
<w-grid
ref="opinionGridRef"
:dense="rating.dense"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:fetch-data-url="histOpinionUrl"
:checkbox-selection="false"
:config-button="false"
:columns="[
{ name: 'roleName', label: '岗位名称', width: 150 },
{ name: 'userCode', label: '操作人工号', width: 100 },
{ name: 'userName', label: '操作人名称', width: 100 },
{ name: 'operationOpinion', label: '操作意见', width: 100, format: Formater.dictionary({ items: RatingProcessOperationStatus }) },
{ name: 'adjReason', label: '意见说明', width: 200 },
{ name: 'lastModifyDate', label: '操作时间', width: 150 },
{ name: 'isOverturn', label: '是否推翻', width: 80, format: Formater.yesNo() },
{ name: 'overturnType', label: '推翻类型', width: 100, format: Formater.dictionary(rating.dictionary.overturnType) },
{ name: 'suggestLevel', label: '建议等级', width: 100 },
{ name: 'fileCount', label: '附件列表', width: 100 },
]"
:query-criteria="{
fieldName: 'ratingId',
operator: 'equals',
value: rating.ratingData.value['id'],
}"
:sort-by="['-lastModifyDate']"
></w-grid>
</template>
<script setup lang="ts">
import { inject, ref } from 'vue';
import { Environment, Formater } from 'platform-core';
import { Rating } from '../ts/Rating';
import { RatingProcessOperationStatus } from '../../CustRating';
const rating = <Rating>inject('rating');
const overturnFormRef = ref();
const getOverturnFormRef = () => {
return overturnFormRef.value;
};
rating.refs.setOverturnFormRefFunction(getOverturnFormRef);
const histOpinionUrl = Environment.apiContextPath('api/irbs/ratingOverturn');
</script>

77
irbs.frontend/src/views/custRating/company/content/Overturn.vue

@ -1,77 +0,0 @@
<template>
<w-card-panel v-bind="panelAttrsComputed">
<div class="flex flex-row gap-4">
<div v-if="rating.cm.isAwaitSubmitProcessStatus.value" class="basis-1/4">
<w-info-panel :info="rating.overturnTipData.value" :column-num="1"></w-info-panel>
</div>
<div :class="rating.cm.isAwaitSubmitProcessStatus.value ? 'basis-2/3' : 'flex-1'">
<w-form
ref="overturnFormRef"
:fields="[
{ label: '附件', name: 'file', type: 'w-file' },
{ label: '是否推翻', name: 'isOverturn', type: 'w-checkbox' },
{
label: '推翻类型',
name: 'overturnType',
type: 'w-select',
options: Options.dictionary(rating.dictionary.overturnType),
requiredIf: true,
showIf: (args) => {
if (args?.form && args.form.getFieldValue('isOverturn')) {
return true;
}
return false;
},
},
{
label: '建议等级',
name: 'suggestLevel',
type: 'w-select',
options: RatingLevelOptions,
requiredIf: true,
showIf: (args) => {
if (args?.form && args.form.getFieldValue('isOverturn')) {
return true;
}
return false;
},
},
{
label: '意见说明',
name: 'adjReason',
type: 'w-textarea',
requiredIf: true,
},
]"
:cols-num="1"
></w-form>
</div>
</div>
</w-card-panel>
</template>
<script setup lang="ts">
import { Options } from 'platform-core';
import { computed, ref, inject } from 'vue';
import { RatingLevelOptions } from '../../CustRating';
import { Rating } from '../ts/Rating';
const rating = <Rating>inject('rating');
const overturnFormRef = ref();
const getOverturnFormRef = () => {
return overturnFormRef.value;
};
rating.refs.setOverturnFormRefFunction(getOverturnFormRef);
const panelAttrsComputed = computed(() => {
if (rating.cm.isAwaitSubmitProcessStatus.value) {
return {
label: '评级推翻',
icon: 'model_training',
};
} else {
return {
label: '审批意见',
icon: 'comment',
};
}
});
</script>

106
irbs.frontend/src/views/custRating/company/content/QualAnalysis.vue

@ -1,106 +0,0 @@
<template>
<w-splitter :size="titleSplitterModel" horizontal unit="px" disable class="h-full">
<template #before>
<w-card-panel :bordered="false" :title-mode="true" icon="scatter_plot" :icon-attrs="{ color: 'green' }" color="green">
<template #label>
<div class="flex justify-between">
<div>
定性分析<q-badge v-if="existsWaitSelectComputed" color="red" floating transparent class="qa-badge">{{
rating.waitSelectFields.value.length
}}</q-badge>
</div>
<q-toggle v-if="showToggleComputed" v-model="qaMode" color="blue" dense size="40px" icon="bi-quora" label="问卷模式" />
<q-toggle v-if="props.readOnly" v-model="showOptionsModel" color="blue" dense size="40px" icon="hdr_auto" label="显示全部选项" />
</div>
</template>
</w-card-panel>
</template>
<template #after>
<w-form
v-show="showQaPanelComputed"
ref="qa-qualFormRef"
:cols-num="1"
:fields="qaFormFieldComputed"
class="px-1 py-1"
@update-value="qaFormUpdateValue"
></w-form>
<w-form
v-show="!showQaPanelComputed"
ref="qualitativeFormRef"
:fields="qualFormFieldsComputed"
:cols-num="1"
:y-gap="10"
class="pl-1 py-1"
@update-value="formUpdateValue"
></w-form>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { inject, ref, computed } from 'vue';
import { Rating } from '../ts/Rating';
const qualitativeFormRef = ref();
const rating = <Rating>inject('rating');
const titleSplitterModel = ref(34);
const getQualitativeFormRef = () => {
return qualitativeFormRef.value;
};
rating.refs.setQualitativeFormRefFunction(getQualitativeFormRef);
const props = defineProps({
//
qualQaMode: { type: Boolean, default: true },
//
readOnly: { type: Boolean, default: false },
//
showOptions: { type: Boolean, default: false },
});
const qaMode = ref(props.readOnly ? false : props.qualQaMode);
const showOptionsModel = ref(props.showOptions);
const qaFormFieldComputed = computed(() => {
const result = <any>[];
if (rating.waitSelectFields.value?.length > 0) {
result.push({
type: 'w-form-group',
label: rating.waitSelectFields.value[0]['group'],
mode: 'card',
fields: [rating.waitSelectFields.value[0]['field']],
});
}
return result;
});
const showQaPanelComputed = computed(() => {
return showToggleComputed.value && qaMode.value;
});
const showToggleComputed = computed(() => {
return props.qualQaMode && existsWaitSelectComputed.value;
});
const existsWaitSelectComputed = computed(() => {
return rating.waitSelectFields.value.length > 0 && !props.readOnly;
});
const qualFormFieldsComputed = computed(() => {
if (showOptionsModel.value) {
return rating.qualFormData.value;
}
return rating.qualSimpleOptionData.value;
});
const qaFormUpdateValue = (args) => {
qualitativeFormRef.value.setFieldValue(args.fieldName, args.fieldValue);
rating.waitSelectFields.value = rating.waitSelectFields.value.slice(1);
};
const formUpdateValue = (args) => {
const result = rating.waitSelectFields.value.filter((field) => field.field['name'] !== args.fieldName);
rating.waitSelectFields.value = result;
};
</script>
<style lang="css">
.qa-badge {
position: relative;
top: -7px;
right: -2px;
cursor: inherit;
}
</style>

51
irbs.frontend/src/views/custRating/company/content/QuanAnalysis.vue

@ -1,51 +0,0 @@
<template>
<w-splitter :size="34" horizontal unit="px" disable class="h-full">
<template #before>
<w-card-panel label="定量分析" :bordered="false" :title-mode="true" icon="bar_chart" :icon-attrs="{ color: 'teal' }" color="teal"></w-card-panel>
</template>
<template #after>
<div v-if="rating.systemParameter.showTotalScore.value" class="p-1">
<w-card-panel :info="rating.quanData.value"></w-card-panel>
</div>
<div v-if="rating.systemParameter.showIndex.value" class="rating-quan">
<q-list>
<template v-for="(values, key, a) in rating.quanScoreDtlData.value" :key="a">
<!-- <q-item-label header><q-icon name="toc" size="25px" />定量指标详情</q-item-label> -->
<template v-for="(dtl, index) in values" :key="index">
<q-item>
<q-item-section>
<q-item-label>{{ dtl['INDEX_NAME'] }}</q-item-label>
<q-item-label caption>
{{ round(dtl['INDEX_VALUE'], 2) }}
</q-item-label>
</q-item-section>
<q-item-section v-if="rating.systemParameter.showIndexScore.value && !Tools.isEmpty(dtl['INDEX_SCORE'])" side>
<q-chip :clickable="false" :ripple="false" color="green" text-color="white">
{{ round(dtl['INDEX_SCORE'], 2) }}
</q-chip>
</q-item-section>
</q-item>
</template>
</template>
</q-list>
</div>
</template>
</w-splitter>
</template>
<script setup lang="ts">
import { Tools } from 'platform-core';
import { inject } from 'vue';
import { Rating } from '../ts/Rating';
import { round } from '../ts/Utils';
const rating = <Rating>inject('rating');
</script>
<style lang="css">
.rating-quan {
padding-top: 10px;
}
.rating-quan .text-caption {
font-size: 1rem;
color: #2196f3;
}
</style>

20
irbs.frontend/src/views/custRating/company/content/QuanQualAnalysis.vue

@ -1,20 +0,0 @@
<template>
<div class="h-full">
<w-splitter :size="25" :separator-color="rating.separatorColor" class="h-full">
<template #before>
<QuanAnalysis></QuanAnalysis>
</template>
<template #after>
<QualAnalysis :qual-qa-mode="rating.systemParameter.qualQaMode.value" :show-options="true"></QualAnalysis>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { inject } from 'vue';
import { Rating } from '../ts/Rating';
import QuanAnalysis from './QuanAnalysis.vue';
import QualAnalysis from './QualAnalysis.vue';
const rating = <Rating>inject('rating');
</script>

36
irbs.frontend/src/views/custRating/company/content/ReportIndex.vue

@ -1,36 +0,0 @@
<template>
<div v-if="rating.systemParameter.reportShowScoreDtl.value" class="h-full">
<w-splitter :size="25" :separator-color="rating.separatorColor">
<template #before>
<QuanAnalysis></QuanAnalysis>
</template>
<template #after>
<w-splitter v-if="splitComputed" :size="65" class="h-full" :separator-color="rating.separatorColor">
<template #before>
<QualAnalysis :qual-qa-mode="false" :read-only="true"></QualAnalysis>
</template>
<template #after>
<AdjustItemIndex></AdjustItemIndex>
</template>
</w-splitter>
<QualAnalysis v-else :qual-qa-mode="false" :read-only="true"></QualAnalysis>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Rating } from '../ts/Rating';
import QuanAnalysis from './QuanAnalysis.vue';
import QualAnalysis from './QualAnalysis.vue';
import AdjustItemIndex from './AdjustItemIndex.vue';
const rating = <Rating>inject('rating');
const splitComputed = computed(() => {
if (rating.adjustItemScoreDtlData.value && Object.keys(rating.adjustItemScoreDtlData.value).length > 0) {
return true;
}
return false;
});
</script>

34
irbs.frontend/src/views/custRating/company/content/ReportInfo.vue

@ -1,34 +0,0 @@
<template>
<div class="h-full">
<w-splitter :size="splitterSizeComputed" :limits="[0, Infinity]" horizontal unit="px" disable class="h-full">
<template #before>
<ReportRating></ReportRating>
</template>
<template #after>
<w-splitter :size="70" horizontal :separator-color="rating.separatorColor">
<template #before>
<ReportIndex></ReportIndex>
</template>
<template #after>
<HistTab></HistTab>
</template>
</w-splitter>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { computed, inject } from 'vue';
import { Rating } from '../ts/Rating';
import HistTab from './HistTab.vue';
import ReportIndex from './ReportIndex.vue';
import ReportRating from './ReportRating.vue';
const rating = <Rating>inject('rating');
const splitterSizeComputed = computed(() => {
if (rating.showAllRatingInfoModel.value) {
return 125;
}
return 40;
});
</script>

157
irbs.frontend/src/views/custRating/company/content/ReportRating.vue

@ -1,157 +0,0 @@
<template>
<!-- <w-card-panel label="评级结果" :bordered="false">
<div class="flex">
<div class="flex-1 text-center">
<div>模型名称</div>
<div :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['modelName']" />
</div>
</div>
<div class="flex-1 text-center">
<div>模型级别</div>
<div :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['modelLevel']" />
</div>
</div>
<div class="flex-1 text-center">
<div>调整后级别</div>
<div v-if="rating.ratingData.value['adjLevel']" :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['adjLevel']" />
</div>
</div>
<div class="flex-1 text-center">
<div>推翻级别</div>
<div v-if="rating.ratingData.value['tf']" :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['tf']" />
</div>
</div>
<div class="flex-1 text-center">
<div>最终认定级别</div>
<div v-if="rating.ratingData.value['finalLevel']" :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['finalLevel']" />
</div>
</div>
<div class="flex-1 text-center">
<div>客户经理</div>
<div v-if="rating.ratingData.value['managerName']" :class="valueClassComputed">
<q-chip outline square size="md" :clickable="false" :ripple="false" :label="rating.ratingData.value['managerName']" />
</div>
</div>
</div>
</w-card-panel> -->
<div class="flex">
<div class="flex-1">
<div :class="classComputed">
<div :class="itemClassComputed">
<div :class="labelClassComputed">模型名称</div>
<div :class="valueClassComputed">{{ rating.ratingData.value['modelName'] }}</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">模型评级等级</div>
<div :class="valueClassComputed" @mouseover="handleHover('.rr-modelLevel', rating.ratingData.value['modelLevel'])" @mouseout="handleOut">
<span class="rr-modelLevel underline">{{ rating.ratingData.value['modelLevel'] }}</span>
</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">调整后级别</div>
<div :class="valueClassComputed" @mouseover="handleHover('.rr-adjLevel', rating.ratingData.value['adjLevel'])" @mouseout="handleOut">
<span class="rr-adjLevel underline">{{ rating.ratingData.value['adjLevel'] }}</span>
</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">最终认定级别</div>
<div :class="valueClassComputed" @mouseover="handleHover('.rr-finalLevel', rating.ratingData.value['finalLevel'])" @mouseout="handleOut">
<span class="rr-finalLevel underline">{{ rating.ratingData.value['finalLevel'] }}</span>
</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">客户经理</div>
<div :class="valueClassComputed">{{ rating.ratingData.value['managerName'] }}</div>
</div>
<template v-if="rating.showAllRatingInfoModel.value">
<div :class="itemClassComputed">
<div :class="labelClassComputed">初始级别</div>
<div :class="valueClassComputed" @mouseover="handleHover('.rr-initLevel', rating.ratingData.value['initLevel'])" @mouseout="handleOut">
<span class="rr-initLevel underline">{{ rating.ratingData.value['initLevel'] }}</span>
</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">上一次建议级别</div>
<div :class="valueClassComputed" @mouseover="handleHover('.rr-spLevel', rating.ratingData.value['spLevel'])" @mouseout="handleOut">
<span class="rr-spLevel underline">{{ rating.ratingData.value['spLevel'] }}</span>
</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">评级发起日期</div>
<div :class="valueClassComputed" v-html="Formater.dateOnly()(rating.ratingData.value['startTime'])"></div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">评级生效日期</div>
<div :class="valueClassComputed" v-html="Formater.dateOnly()(rating.ratingData.value['effectiveTime'])"></div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">评级到期日期</div>
<div :class="valueClassComputed" v-html="Formater.dateOnly()(rating.ratingData.value['matureTime'])"></div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">评级状态</div>
<div :class="valueClassComputed">{{ Formater.enum(rating.enum.ratingStatus)(rating.ratingData.value['ratingStatus']) }}</div>
</div>
<div :class="itemClassComputed">
<div :class="labelClassComputed">流程状态</div>
<div :class="valueClassComputed">{{ Formater.enum(rating.enum.ratingProcessStatus)(rating.ratingData.value['processStatus']) }}</div>
</div>
</template>
</div>
</div>
<div class="flex-none pr-1 pt-1">
<q-btn
flat
round
color="primary"
size="sm"
:icon="rating.showAllRatingInfoModel.value ? 'bi-arrow-up-circle-fill' : 'bi-arrow-down-circle-fill'"
@click="rating.showAllRatingInfoModel.value = !rating.showAllRatingInfoModel.value"
/>
</div>
<q-popup-proxy v-model="ratingLevelShowModel" :target="ratingLevelTarget" no-parent-event>
<div style="height: 80px; width: 650px; padding: 20px 10px 10px 20px">
<RatingLevelSlider v-model="ratingLevel"></RatingLevelSlider>
</div>
</q-popup-proxy>
</div>
</template>
<script setup lang="ts">
import { ref, inject, computed } from 'vue';
import { Formater } from 'platform-core';
import { Rating } from '../ts/Rating';
import RatingLevelSlider from '../../RatingLevelSlider.vue';
const ratingLevelShowModel = ref(false);
const ratingLevel = ref('');
const ratingLevelTarget = ref('');
const rating = <Rating>inject('rating');
const itemClassComputed = computed(() => {
return 'flex items-center';
});
const labelClassComputed = computed(() => {
return 'flex-none text-gray-500';
});
const valueClassComputed = computed(() => {
return 'flex-1 text-2xl';
});
const classComputed = computed(() => {
if (rating.showAllRatingInfoModel) {
return 'grid grid-cols-5 gap-3 pl-3 pt-1';
}
return 'grid grid-cols-5 gap-x-3 pl-3 pt-1';
});
const handleHover = (target_, ratingLevel_: any) => {
ratingLevel.value = ratingLevel_;
ratingLevelTarget.value = target_;
ratingLevelShowModel.value = true;
};
const handleOut = () => {
ratingLevelShowModel.value = false;
};
</script>

82
irbs.frontend/src/views/custRating/company/content/Timeline.vue

@ -1,82 +0,0 @@
<template>
<div class="rating-timeline">
<div v-if="timelineData.length < 1" style="display: flex; justify-content: center; align-items: center; height: 100%">
<q-icon size="2em" name="info" />{{ $t('tip.noData') }}
</div>
<q-timeline v-else layout="dense" side="right" color="secondary">
<template v-for="(opinion, index) in timelineData" :key="index">
<q-timeline-entry side="left" :color="timelineEntryColor(opinion)">
<div style="background-color: #f9f9f9">
{{ opinion['adjReason'] }}
</div>
<template #subtitle>
<div class="flex justify-between">
<span class="text-sm">{{ timelineTitleFormat(opinion) }}</span>
<div class="flex gap-x-2">
<span>{{ opinion['userName'] }}</span>
<span class="text-blue-grey-6">7分钟以前</span>
</div>
</div>
</template>
</q-timeline-entry>
</template>
</q-timeline>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, inject } from 'vue';
import { $t, axios, Environment } from 'platform-core';
import { Rating } from '../ts/Rating';
import { RatingProcessOperationStatus } from '../../CustRating';
const timelineData = ref([]);
const rating = <Rating>inject('rating');
const histOpinionUrl = Environment.apiContextPath('api/irbs/ratingOverturn');
const timelineTitleFormat = (opinion: any) => {
const findResult = RatingProcessOperationStatus.find((item) => item['value'] === opinion['operationOpinion']);
if (findResult) {
return findResult['label'];
}
return '';
};
const timelineSubTitleFormat = (opinion: any) => {
return opinion['userName'] + ' ' + timelineTitleFormat(opinion) + ' ' + '7分钟以前';
};
const timelineEntryColor = (opinion: any) => {
const operator = opinion['operationOpinion'];
if (operator === '20') {
return 'red';
} else if (operator === '30' || operator === '40') {
return 'orange';
}
return 'secondary';
};
onMounted(() => {
const urlSearchParams = new URLSearchParams({ sortBy: ['-lastModifyDate'] });
urlSearchParams.append('pageable', 'false');
const criteria = {
fieldName: 'ratingId',
operator: 'equals',
value: rating.ratingData.value['id'],
};
urlSearchParams.append('criteria', JSON.stringify(criteria));
axios.get(histOpinionUrl, { params: urlSearchParams }).then((resp) => {
if (resp['code'] === 200) {
timelineData.value = resp.data.content;
}
});
});
</script>
<style lang="css">
.rating-timeline .q-timeline--dense--right .q-timeline__entry {
padding-left: 25px;
}
.rating-timeline .q-timeline__title {
margin-top: 0;
margin-bottom: 0px;
}
.rating-timeline .q-timeline__content {
padding-bottom: 10px;
}
</style>

47
irbs.frontend/src/views/custRating/company/ts/RequestApi.ts

@ -4,6 +4,8 @@ import { Constant } from './Constant';
import { round, groupBy } from './Utils';
import { Step } from './Step';
import { StepType } from './type/StepType';
import { Addtion } from './Addtion';
import { group } from 'console';
/**
* api
@ -95,6 +97,13 @@ export class RequestApi {
this.rating.qualFormData.value.push(group);
this.rating.qualSimpleOptionData.value.push(simpleGroup);
});
const formValue = {};
if (resp.data.indices) {
resp.data.indices.forEach((item) => {
formValue[item.indexCode] = item.indexValue;
});
this.rating.refs.qualitativeFormRefFunction().setData(formValue);
}
}
})
.catch((error) => {
@ -113,12 +122,10 @@ export class RequestApi {
for (let i = 0; i < arr.length; i++) {
const index = arr[i];
const indexOptions = <any>[];
// 选项处理
if (index.options && index.options.length > 0) {
index.options.forEach((item, index_) => {
index.options.forEach((item) => {
const option = { label: item.text, value: item.disVal };
if (index_ === 0) {
option['desc'] = { label: '选项说明' };
}
if (allOptions || (!Tools.isEmpty(index.indexValue) && index.indexValue === item.disVal)) {
indexOptions.push(option);
}
@ -133,13 +140,37 @@ export class RequestApi {
selectedColor: 'blue',
selectedLabelColor: '#2196f3',
};
if (i !== 0) {
radio['class'] = 'pt-1';
}
if (!Tools.isEmpty(index.indexValue)) {
radio['defaultValue'] = index.indexValue;
}
resultArr.push(radio);
// 补录处理
let field = {};
if (index.addtions && index.addtions.length > 0) {
const addtions = <any>[];
index.addtions.forEach((addtion: any) => {
addtions.push(Addtion.getComponent(addtion, index));
});
field = {
type: 'w-form-group',
layout: 'form',
colsNum: 2,
fields: [
radio,
{
type: 'w-form-group',
layout: 'form',
colsNum: 1,
fields: addtions,
},
],
};
} else {
field = radio;
}
if (i !== 0) {
field['class'] = 'pt-1';
}
resultArr.push(field);
if (allOptions) {
this.rating.waitSelectFields.value.push({ group: index.indexCategory, field: radio });
this.rating.qualFormObj.value[index.indexCode] = [i + 1 + '、' + index.indexName, index];

18
irbs.frontend/src/views/custRating/company/ts/Step.ts

@ -56,11 +56,11 @@ export class Step {
disable: false,
},
/**
*
*
*/
opinion: <StepType>{
label: '签署意见',
tooltip: '评级推翻提交审核',
label: '评级推翻',
tooltip: '评级推翻提交审核',
value: 'OTHER',
icon: 'bi-5-circle-fill',
order: 5,
@ -191,7 +191,7 @@ export class Step {
const errorRows = <any>[];
const keys = Object.keys(formData);
for (let i = 0; i < keys.length; i++) {
if (Tools.isEmpty(formData[keys[i]])) {
if (Tools.isEmpty(formData[keys[i]]) && this.rating.qualFormObj.value[keys[i]]) {
result = false;
errorRows.push({
label: this.rating.qualFormObj.value[keys[i]][0],
@ -204,8 +204,10 @@ export class Step {
dense: true,
});
} else {
this.rating.qualFormObj.value[keys[i]][1].indexValue = formData[keys[i]];
submitData.push(this.rating.qualFormObj.value[keys[i]][1]);
if (this.rating.qualFormObj.value[keys[i]]) {
this.rating.qualFormObj.value[keys[i]][1].indexValue = formData[keys[i]];
submitData.push(this.rating.qualFormObj.value[keys[i]][1]);
}
}
}
if (!result) {
@ -264,7 +266,7 @@ export class Step {
const value_ = value === 'INIT_FINISH' ? Step.type.custInfo.value : value;
if (value_) {
this.currStep.value = value_;
nextTick(() => {
nextTick(async () => {
switch (value_) {
case Step.type.custInfo.value:
this.rating.api.loadCustInfo();
@ -277,7 +279,7 @@ export class Step {
break;
case Step.type.reportInfo.value:
this.rating.api.loadCustInfo();
this.rating.api.loadQuanQualInfo();
await this.rating.api.loadQuanQualInfo();
this.rating.api.loadRatingReport();
break;
case Step.type.opinion.value:

80
irbs.frontend/src/views/custRating/company/ts/Utils.ts

@ -19,13 +19,21 @@ export const round = (val: any, precision: any) => {
return result;
};
export const groupBy = (arr, prop) =>
arr.reduce((acc, item) => {
export const RatioFormat = (val) => {
if (val && typeof val === 'number') {
return round(val * 100, 2) + '%';
}
return val;
};
export const groupBy = (arr, prop) => {
return arr.reduce((acc, item) => {
const key = item[prop];
if (!acc[key]) acc[key] = [];
acc[key].push(item);
return acc;
}, {});
};
export const formatAmt = (num: any) => {
if (num) {
@ -39,3 +47,71 @@ export const formatAmt = (num: any) => {
}
return num;
};
/**
*
*/
export const RatingLevelOptions = [
{ label: 'AAA+', value: 'AAA+', numberValue: 15, color: 'green', denseLabel: false },
{ label: 'AAA', value: 'AAA', numberValue: 14, color: 'green', denseLabel: false },
{ label: 'AA+', value: 'AA+', numberValue: 13, color: 'green', denseLabel: false },
{ label: 'AA', value: 'AA', numberValue: 12, color: 'green', denseLabel: false },
{ label: 'AA-', value: 'AA-', numberValue: 11, color: 'green', denseLabel: false },
{ label: 'A+', value: 'A+', numberValue: 10, color: 'green', denseLabel: false },
{ label: 'A', value: 'A', numberValue: 9, color: 'green', denseLabel: false },
{ label: 'A-', value: 'A-', numberValue: 8, color: 'green', denseLabel: false },
{ label: 'BBB', value: 'BBB', numberValue: 7, color: 'green', denseLabel: false },
{ label: 'BB', value: 'BB', numberValue: 6, color: 'red', denseLabel: false },
{ label: 'B', value: 'B', numberValue: 5, color: 'red', denseLabel: false },
{ label: 'CCC', value: 'CCC', numberValue: 4, color: 'red', denseLabel: false },
{ label: 'CC', value: 'CC', numberValue: 3, color: 'red', denseLabel: false },
{ label: 'C', value: 'C', numberValue: 2, color: 'red', denseLabel: false },
{ label: 'D', value: 'D', numberValue: 1, color: 'red', denseLabel: false },
];
/**
*
*/
export const RatingProcessStatus = {
AWAIT_RATING: 'AWAIT_RATING', // 待评级
AWAIT_SUBMIT: 'AWAIT_SUBMIT', // 待提交
BACK: 'BACK', // 退回
APPROVALING: 'APPROVALING', // 审批中
PASS: 'PASS', // 通过
NEGATIVED: 'NEGATIVED', // 否决
END: 'END', // 已结束
};
/**
*
*/
export const RatingProcessOperationStatus = [
{
label: '提交',
value: '10',
},
{
label: '否决',
value: '20',
},
{
label: '退回',
value: '30',
},
{
label: '撤销',
value: '40',
},
{
label: '批准',
value: '50',
},
{
label: '同意',
value: '60',
},
{
label: '不同意',
value: '70',
},
];

9
irbs.frontend/src/views/custRating/mock/MockCmis.vue

@ -38,6 +38,7 @@
<script setup lang="ts">
import { ref } from 'vue';
import { Environment } from 'platform-core';
import CustSelectGrid from '../company/CustSelectGrid.vue';
const tabsSplitterModel = ref(36);
@ -45,6 +46,12 @@ const customerGridRef = ref();
const tabsModel = ref('mockApply');
const mockApply = (args) => {
const custNo = args.selected['custNo'];
window.open('http://localhost:3000/#/irbs/rating/apply?custNo=' + custNo, '_blank');
const frontendScenario = Environment.getFontendScenario();
let url = Environment.getWebContextPath() + '#/irbs/rating/apply?custNo=' + custNo;
// if (frontendScenario === 'backend') {
// url = Environment.apiContextPath('#/irbs/rating/apply?custNo=' + custNo);
// }
console.info('url====', url);
window.open(url, '_blank');
};
</script>

12
irbs.frontend/src/views/debtRating/LgdQuery.vue

@ -20,7 +20,7 @@
import { ref } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round } from '@/views/custRating/CustRating.ts';
import { round } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const appDebtRatingGridRef = ref();
@ -43,7 +43,7 @@ const appDebtRatingGrid = {
label: '产品回收率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -71,7 +71,7 @@ const appDebtRatingGrid = {
label: '借款人整体回收率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -81,7 +81,7 @@ const appDebtRatingGrid = {
label: '保证人整体回收率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -91,7 +91,7 @@ const appDebtRatingGrid = {
label: '押品整体回收率',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -101,7 +101,7 @@ const appDebtRatingGrid = {
label: 'LGD',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},

67
irbs.frontend/src/views/default/CognizanceApply.vue

@ -17,37 +17,26 @@
}"
:sort-by="['-lastModifyDate']"
></w-grid>
<LaunchRatingDialog ref="launchRatingDialog" :dictionary="dictionary" @refresh="refreshTable"></LaunchRatingDialog>
<CustSelectDialog ref="launchRatingDialog" @submit-handler="selectCustSubmit" @refresh="refreshTable"></CustSelectDialog>
<CognizanceDialog ref="cognizanceDialogRef" @refresh="refreshTable"></CognizanceDialog>
<LoadingDialog ref="loadingDialogRef"></LoadingDialog>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import LaunchRatingDialog from '@/views/custRating/LaunchRatingDialog.vue';
import { Environment, EnumTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import CustSelectDialog from '@/views/custRating/company/CustSelectDialog.vue';
import CognizanceDialog from './CognizanceDialog.vue';
import { RatingLevelOptions, RatingProcessStatus, SelectCustomerFlag } from '@/views/custRating/CustRating.ts';
import { DefaultProcessStatus } from './DefaultManager.ts';
import LoadingDialog from '@/views/components/LoadingDialog.vue';
const $q = useQuasar();
const loadingDialogRef = ref();
const cognizanceGridRef = ref();
const launchRatingDialog = ref();
const cognizanceDialogRef = ref();
const DefaultProcessStatusEnum = await EnumTools.fetch('irbs.defaultManager.enums.DefaultProcessStatus');
const dictCustomerTypeCd = await DictionaryTools.fetch('CustomerTypeCd');
const optionsCustomerTypeCd = Options.dictionary(dictCustomerTypeCd);
const dictCustomerSizeCd = await DictionaryTools.fetch('CustomerSizeCd');
const optionsCustomerSizeCd = Options.dictionary(dictCustomerSizeCd);
const dictionary = {
dictCustomerTypeCd: dictCustomerTypeCd,
optionsCustomerTypeCd: optionsCustomerTypeCd,
dictCustomerSizeCd: dictCustomerSizeCd,
optionsCustomerSizeCd: optionsCustomerSizeCd,
};
const cognizanceGrid = {
buttons: [
@ -58,7 +47,7 @@ const cognizanceGrid = {
extend: 'add',
label: '新增申请',
click: () => {
launchRatingDialog.value.show(SelectCustomerFlag.COGNIZANCE);
launchRatingDialog.value.show();
},
},
{
@ -115,6 +104,48 @@ const cognizanceGrid = {
],
};
const showLoading = (msg: string = '正在处理,请稍等...') => {
loadingDialogRef.value.show(msg);
};
const hideLoading = () => {
loadingDialogRef.value.hide();
};
const selectCustSubmit = async (data: any) => {
showLoading();
//
const resp = await axios
.get(Environment.apiContextPath('api/irbs/defaultCognizance/queryDefaCustNo'), { params: { custNo: data['custNo'] } })
.catch((error) => {
hideLoading();
console.info('error-------------', error);
});
if (resp && resp.data === '1') {
hideLoading();
NotifyManager.warn('当前客户存在进行中违约认定流程');
return;
} else if (resp && resp.data === '2') {
hideLoading();
NotifyManager.warn('当前客户存在已人工认定违约认定结果,无法发起新的人工违约认定流程');
return;
} else if (resp && resp.data === '0') {
//
axios
.post(Environment.apiContextPath('api/irbs/defaultManager/cognizanceApply'), { custNo: data['custNo'], type: 'F' })
.then((resp) => {
hideLoading();
if (resp && resp['code'] === 200 && resp['data']) {
refreshTable();
launchRatingDialog.value.hide();
}
})
.catch((error) => {
hideLoading();
console.info('error-------------', error);
});
}
};
const refreshTable = () => {
cognizanceGridRef.value.refresh();
};

16
irbs.frontend/src/views/report/RptRatingAdjust.vue

@ -203,11 +203,9 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingAdjustGridRef = ref();
const state = reactive({
@ -242,11 +240,11 @@ const afterRequestData = (args) => {
state.xData.push(item['ratingMonth']);
state.custData.ratingCnt.push(item['custCnt']);
state.custData.overturnCnt.push(item['adjCnt']);
state.custData.overturnRatio.push(item['adjRatio'] && typeof item['adjRatio'] === 'number' ? Round(item['adjRatio'] * 100, 2) : 0);
state.range.l1.push(item['oneLvlRatio'] && typeof item['oneLvlRatio'] === 'number' ? Round(item['oneLvlRatio'] * 100, 2) : 0);
state.range.l2.push(item['twoLvlRatio'] && typeof item['twoLvlRatio'] === 'number' ? Round(item['twoLvlRatio'] * 100, 2) : 0);
state.range.l3.push(item['threeLvlRatio'] && typeof item['threeLvlRatio'] === 'number' ? Round(item['threeLvlRatio'] * 100, 2) : 0);
state.range.ln.push(item['threeMoreLvlRatio'] && typeof item['threeMoreLvlRatio'] === 'number' ? Round(item['threeMoreLvlRatio'] * 100, 2) : 0);
state.custData.overturnRatio.push(item['adjRatio'] && typeof item['adjRatio'] === 'number' ? round(item['adjRatio'] * 100, 2) : 0);
state.range.l1.push(item['oneLvlRatio'] && typeof item['oneLvlRatio'] === 'number' ? round(item['oneLvlRatio'] * 100, 2) : 0);
state.range.l2.push(item['twoLvlRatio'] && typeof item['twoLvlRatio'] === 'number' ? round(item['twoLvlRatio'] * 100, 2) : 0);
state.range.l3.push(item['threeLvlRatio'] && typeof item['threeLvlRatio'] === 'number' ? round(item['threeLvlRatio'] * 100, 2) : 0);
state.range.ln.push(item['threeMoreLvlRatio'] && typeof item['threeMoreLvlRatio'] === 'number' ? round(item['threeMoreLvlRatio'] * 100, 2) : 0);
});
}
};

32
irbs.frontend/src/views/report/RptRatingChange.vue

@ -16,12 +16,10 @@
</template>
<script setup lang="ts">
import { Round } from '@/views/custRating/CustRating.ts';
import { axios, Environment, Formater } from 'platform-core';
import { useQuasar } from 'quasar';
import { round } from '@/views/custRating/company/ts/Utils';
import { axios, Environment } from 'platform-core';
import { reactive, ref } from 'vue';
const $q = useQuasar();
const rptRatingChangeGridRef = ref();
const state = reactive({
splitterModel: 55,
@ -54,13 +52,13 @@ const afterRequestData = () => {
rows.forEach((item) => {
state.xData.push(item['ratingLevel']);
state.custData.number.push(item['custCnt']);
state.custData.ratio.push(item['custRatio'] && typeof item['custRatio'] === 'number' ? Round(item['custRatio'] * 100, 2) : 0);
state.custData.ratio.push(item['custRatio'] && typeof item['custRatio'] === 'number' ? round(item['custRatio'] * 100, 2) : 0);
state.custData.addNumber.push(item['currInctCnt']);
state.custData.addRatio.push(item['currInctRatio'] && typeof item['currInctRatio'] === 'number' ? Round(item['currInctRatio'] * 100, 2) : 0);
state.custData.addRatio.push(item['currInctRatio'] && typeof item['currInctRatio'] === 'number' ? round(item['currInctRatio'] * 100, 2) : 0);
state.custData.defaultNumber.push(item['defCustCnt']);
state.custData.defaultRatio.push(item['defCustRatio'] && typeof item['defCustRatio'] === 'number' ? Round(item['defCustRatio'] * 100, 2) : 0);
state.custData.defaultRatio.push(item['defCustRatio'] && typeof item['defCustRatio'] === 'number' ? round(item['defCustRatio'] * 100, 2) : 0);
state.custData.creditBalance.push(item['borrBal']);
state.custData.creditRatio.push(item['borrBalRatio'] && typeof item['borrBalRatio'] === 'number' ? Round(item['borrBalRatio'] * 100, 2) : 0);
state.custData.creditRatio.push(item['borrBalRatio'] && typeof item['borrBalRatio'] === 'number' ? round(item['borrBalRatio'] * 100, 2) : 0);
});
};
@ -156,7 +154,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -179,7 +177,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -198,7 +196,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -217,7 +215,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -236,7 +234,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -261,7 +259,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -280,7 +278,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -299,7 +297,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -318,7 +316,7 @@ const rptRatingChangeGrid = {
align: 'center',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},

22
irbs.frontend/src/views/report/RptRatingDistribution.vue

@ -246,12 +246,10 @@
<script setup lang="ts">
import { reactive, ref } from 'vue';
import { useQuasar } from 'quasar';
import { axios, Environment, Formater } from 'platform-core';
import { axios, Environment } from 'platform-core';
import { formatNumber } from './Common.ts';
import { Round } from '@/views/custRating/CustRating.ts';
import { round } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingDistributionGridRef = ref();
const state = reactive({
splitterModel: 55,
@ -284,13 +282,13 @@ const afterRequestData = () => {
rows.forEach((item) => {
state.xData.push(item['ratingLevel']);
state.custData.number.push(item['custCnt']);
state.custData.ratio.push(item['custRatio'] && typeof item['custRatio'] === 'number' ? Round(item['custRatio'] * 100, 2) : 0);
state.custData.ratio.push(item['custRatio'] && typeof item['custRatio'] === 'number' ? round(item['custRatio'] * 100, 2) : 0);
state.custData.addNumber.push(item['currInctCnt']);
state.custData.addRatio.push(item['currInctRatio'] && typeof item['currInctRatio'] === 'number' ? Round(item['currInctRatio'] * 100, 2) : 0);
state.custData.addRatio.push(item['currInctRatio'] && typeof item['currInctRatio'] === 'number' ? round(item['currInctRatio'] * 100, 2) : 0);
state.custData.defaultNumber.push(item['defCustCnt']);
state.custData.defaultRatio.push(item['defCustRatio'] && typeof item['defCustRatio'] === 'number' ? Round(item['defCustRatio'] * 100, 2) : 0);
state.custData.defaultRatio.push(item['defCustRatio'] && typeof item['defCustRatio'] === 'number' ? round(item['defCustRatio'] * 100, 2) : 0);
state.custData.creditBalance.push(item['borrBal']);
state.custData.creditRatio.push(item['borrBalRatio'] && typeof item['borrBalRatio'] === 'number' ? Round(item['borrBalRatio'] * 100, 2) : 0);
state.custData.creditRatio.push(item['borrBalRatio'] && typeof item['borrBalRatio'] === 'number' ? round(item['borrBalRatio'] * 100, 2) : 0);
});
};
@ -386,7 +384,7 @@ const rptRatingDistributionGrid = {
align: 'right',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -404,7 +402,7 @@ const rptRatingDistributionGrid = {
align: 'right',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -422,7 +420,7 @@ const rptRatingDistributionGrid = {
align: 'right',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},
@ -447,7 +445,7 @@ const rptRatingDistributionGrid = {
align: 'right',
format: (val) => {
if (val && typeof val === 'number') {
return Round(val * 100, 2) + '%';
return round(val * 100, 2) + '%';
}
return val;
},

7
irbs.frontend/src/views/report/RptRatingIndustryFocusDist.vue

@ -197,9 +197,8 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const rptRatingIndustryFocusDistGridRef = ref();
@ -235,7 +234,7 @@ const afterRequestData = (args) => {
Object.keys(totalData).forEach((key) => {
if (key.indexOf('Ratio') > -1) {
totalData[key].push(item[key] && typeof item[key] === 'number' ? Round(item[key] * 100, 2) : 0);
totalData[key].push(item[key] && typeof item[key] === 'number' ? round(item[key] * 100, 2) : 0);
} else {
totalData[key].push(item[key] ? item[key] : 0);
}

10
irbs.frontend/src/views/report/RptRatingLoanBalanceMigrate.vue

@ -244,12 +244,10 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { formatNumber } from './Common.ts';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingLoanBalanceMigrateRef = ref();
const state = reactive({
@ -292,7 +290,7 @@ const afterRequestData = (args) => {
Object.keys(totalData).forEach((key) => {
if (key.indexOf('Ratio') > -1) {
totalData[key].push(item[key] && typeof item[key] === 'number' ? Round(item[key] * 100, 2) : 0);
totalData[key].push(item[key] && typeof item[key] === 'number' ? round(item[key] * 100, 2) : 0);
} else {
totalData[key].push(item[key] ? item[key] : 0);
}
@ -566,7 +564,7 @@ const rptRatingLoanBalanceMigrateGrid = {
align: 'right',
format: (val) => {
if (val) {
return Round(val, 2);
return round(val, 2);
}
return val;
},

8
irbs.frontend/src/views/report/RptRatingModelFocusDist.vue

@ -195,11 +195,9 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingModelFocusDistGridRef = ref();
const state = reactive({
@ -235,7 +233,7 @@ const afterRequestData = (args) => {
Object.keys(totalData).forEach((key) => {
if (key.indexOf('Ratio') > -1) {
totalData[key].push(item[key] && typeof item[key] === 'number' ? Round(item[key] * 100, 2) : 0);
totalData[key].push(item[key] && typeof item[key] === 'number' ? round(item[key] * 100, 2) : 0);
} else {
totalData[key].push(item[key] ? item[key] : 0);
}

10
irbs.frontend/src/views/report/RptRatingNumberMigrate.vue

@ -244,11 +244,9 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingNumberMigrateRef = ref();
const state = reactive({
@ -288,7 +286,7 @@ const afterRequestData = (args) => {
Object.keys(totalData).forEach((key) => {
if (key.indexOf('Ratio') > -1) {
totalData[key].push(item[key] && typeof item[key] === 'number' ? Round(item[key] * 100, 2) : 0);
totalData[key].push(item[key] && typeof item[key] === 'number' ? round(item[key] * 100, 2) : 0);
} else {
totalData[key].push(item[key] ? item[key] : 0);
}
@ -435,7 +433,7 @@ const rptRatingNumberMigrateGrid = {
align: 'center',
format: (val) => {
if (val) {
return Round(val, 2);
return round(val, 2);
}
return val;
},

8
irbs.frontend/src/views/report/RptRatingOrgFocusDist.vue

@ -195,11 +195,9 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingOrgFocusDistGridRef = ref();
const state = reactive({
splitterModel: 55,
@ -233,7 +231,7 @@ const afterRequestData = (args) => {
Object.keys(totalData).forEach((key) => {
if (key.indexOf('Ratio') > -1) {
totalData[key].push(item[key] && typeof item[key] === 'number' ? Round(item[key] * 100, 2) : 0);
totalData[key].push(item[key] && typeof item[key] === 'number' ? round(item[key] * 100, 2) : 0);
} else {
totalData[key].push(item[key] ? item[key] : 0);
}

20
irbs.frontend/src/views/report/RptRatingOverturn.vue

@ -259,11 +259,9 @@
<script setup lang="ts">
import { ref, reactive } from 'vue';
import { useQuasar } from 'quasar';
import { Environment, EnumTools, DictionaryTools, Options, Formater, axios, NotifyManager } from 'platform-core';
import { Round, RatioFormat } from '@/views/custRating/CustRating.ts';
import { Environment, axios } from 'platform-core';
import { round, RatioFormat } from '@/views/custRating/company/ts/Utils';
const $q = useQuasar();
const rptRatingOverturnGridRef = ref();
const state = reactive({
@ -304,13 +302,13 @@ const afterRequestData = (args) => {
state.xData.push(item['ratingMonth']);
state.custData.ratingCnt.push(item['custCnt']);
state.custData.overturnCnt.push(item['overturnCnt']);
state.custData.overturnRatio.push(item['overturnRatio'] && typeof item['overturnRatio'] === 'number' ? Round(item['overturnRatio'] * 100, 2) : 0);
state.position.down.push(item['upOverturnRatio'] && typeof item['upOverturnRatio'] === 'number' ? Round(item['upOverturnRatio'] * 100, 2) : 0);
state.position.up.push(item['downOverturnRatio'] && typeof item['downOverturnRatio'] === 'number' ? Round(item['downOverturnRatio'] * 100, 2) : 0);
state.range.l1.push(item['oneLvlRatio'] && typeof item['oneLvlRatio'] === 'number' ? Round(item['oneLvlRatio'] * 100, 2) : 0);
state.range.l2.push(item['twoLvlRatio'] && typeof item['twoLvlRatio'] === 'number' ? Round(item['twoLvlRatio'] * 100, 2) : 0);
state.range.l3.push(item['threeLvlRatio'] && typeof item['threeLvlRatio'] === 'number' ? Round(item['threeLvlRatio'] * 100, 2) : 0);
state.range.ln.push(item['threeMoreLvlRatio'] && typeof item['threeMoreLvlRatio'] === 'number' ? Round(item['threeMoreLvlRatio'] * 100, 2) : 0);
state.custData.overturnRatio.push(item['overturnRatio'] && typeof item['overturnRatio'] === 'number' ? round(item['overturnRatio'] * 100, 2) : 0);
state.position.down.push(item['upOverturnRatio'] && typeof item['upOverturnRatio'] === 'number' ? round(item['upOverturnRatio'] * 100, 2) : 0);
state.position.up.push(item['downOverturnRatio'] && typeof item['downOverturnRatio'] === 'number' ? round(item['downOverturnRatio'] * 100, 2) : 0);
state.range.l1.push(item['oneLvlRatio'] && typeof item['oneLvlRatio'] === 'number' ? round(item['oneLvlRatio'] * 100, 2) : 0);
state.range.l2.push(item['twoLvlRatio'] && typeof item['twoLvlRatio'] === 'number' ? round(item['twoLvlRatio'] * 100, 2) : 0);
state.range.l3.push(item['threeLvlRatio'] && typeof item['threeLvlRatio'] === 'number' ? round(item['threeLvlRatio'] * 100, 2) : 0);
state.range.ln.push(item['threeMoreLvlRatio'] && typeof item['threeMoreLvlRatio'] === 'number' ? round(item['threeMoreLvlRatio'] * 100, 2) : 0);
});
}
};

11
irbs.frontend/webpack.config.mf.cjs

@ -9,13 +9,20 @@ const projectName = packageJson.name; // 项目名称
const deps = packageJson.dependencies; // 项目依赖
// 读取本地路由配置, 通过其中 component 和 componentPath 两个属性构建 webpack 模块联邦的 exposes 属性值
const data = fs.readFileSync('./src/routes/routes.json', 'utf8');
const routes = Json5.parse(data);
const routesJson = fs.readFileSync('./src/routes/routes.json', 'utf8');
const routes = Json5.parse(routesJson);
const mfExposes = {};
for (const route of routes) {
mfExposes[route.component] = route.componentPath;
}
// 读取远程组件配置, 通过其中 component 和 componentPath 两个属性构建 webpack 模块联邦的 exposes 属性值
const remoteComponentsJson = fs.readFileSync('./src/remote-components/remote-components.json', 'utf8');
const remoteComponents = Json5.parse(remoteComponentsJson);
for (const remoteComponent of remoteComponents) {
mfExposes[remoteComponent.component] = remoteComponent.componentPath;
}
// 导出 webapck 配置的模块联邦部分
module.exports = {
plugins: [

16
irbs.riskExposure/src/main/java/irbs/riskExposure/service/impl/RiskExposureFlowServiceImpl.java

@ -33,14 +33,14 @@ public class RiskExposureFlowServiceImpl implements RiskExposureFlowService {
@Override
public ProcessTaskWrapper findTaskByProcInstId(String procInstId) throws Exception {
ProcessTaskWrapper taskWrapper = null;
// QueryParameter parameter = new QueryParameter();
// parameter.setPageable(false);
// Equals eq = new Equals();
// eq.setFieldName("processInstanceId");
// eq.setValue(procInstId);
// parameter.addCriteria(eq);
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
QueryParameter parameter = new QueryParameter();
parameter.setPageable(false);
Equals eq = new Equals();
eq.setFieldName("processInstanceId");
eq.setValue(procInstId);
parameter.addCriteria(eq);
List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(parameter).getContent();
// List<ProcessTaskWrapper> list = processQueryService.queryProcessTasks(procInstId, null);
if (null != list && list.size() > 1) {
// 同一个流程实例查找出多个任务则为多实例任务,还需再根据任务处理人匹配。
List<ProcessTaskWrapper> userTaskList = list.stream().filter(task-> SecurityUtil.getLoginName().equals(task.getAssignee())).collect(Collectors.toList());

2
irbs.shrcb.poc.frontend/.npmrc

@ -10,4 +10,4 @@ git-checks=false
# 登录 npm 仓库的用户认证信息, 在 npm publish 时使用, publish 的 npm registry 在 package.json 文件中 publishConfig 部分配置
# _authToken 可通过以下命令获取
# curl -X PUT -H "Content-Type:application/json" -d '{"_id":"org.couchdb.user:admin","name":"admin","password":"admin"}' http://nexus.sc.io:8000/repository/npm-releases/-/user/org.couchdb.user:admin
//nexus.sc.io:8000/repository/npm-releases/:_authToken=NpmToken.67c99588-56a6-3ce1-9bea-a9a6164f8090
//nexus.sc.io:8000/repository/npm-releases/:_authToken=NpmToken.67c99588-56a6-3ce1-9bea-a9a6164f8090

16
irbs.shrcb.poc.frontend/package.json

@ -73,18 +73,18 @@
"webpack-merge": "6.0.1"
},
"dependencies": {
"@codemirror/autocomplete": "6.18.4",
"@codemirror/commands": "6.8.0",
"@codemirror/autocomplete": "6.18.6",
"@codemirror/commands": "6.8.1",
"@codemirror/lang-html": "6.4.9",
"@codemirror/lang-java": "6.0.1",
"@codemirror/lang-javascript": "6.2.2",
"@codemirror/lang-javascript": "6.2.3",
"@codemirror/lang-json": "6.0.1",
"@codemirror/lang-sql": "6.8.0",
"@codemirror/lang-xml": "6.1.0",
"@codemirror/language": "6.10.8",
"@codemirror/search": "6.5.8",
"@codemirror/state": "6.5.1",
"@codemirror/view": "6.36.2",
"@codemirror/language": "6.11.0",
"@codemirror/search": "6.5.10",
"@codemirror/state": "6.5.2",
"@codemirror/view": "6.36.5",
"@maxgraph/core": "0.14.0",
"@quasar/extras": "1.16.15",
"@quasar/quasar-ui-qmarkdown": "2.0.5",
@ -112,7 +112,7 @@
"mockjs": "1.1.0",
"node-sql-parser": "5.3.6",
"pinia": "2.3.0",
"platform-core": "8.2.50",
"platform-core": "8.2.78",
"quasar": "2.17.6",
"sort-array": "5.0.0",
"svg-path-commander": "2.1.7",

62
irbs.shrcb.poc.frontend/public/webjars/tailwindcss/3.4.5/tailwind.css.js

File diff suppressed because one or more lines are too long

4
irbs.shrcb.poc.frontend/src/boostrap.ts

@ -15,10 +15,12 @@ import App from './App.vue';
import 'platform-core/dist/css/platform-core.css';
// 导入 tailwind utilities css
import 'tailwindcss/utilities.css';
// 导入 quasar-ui-qmarkdown css
import '@quasar/quasar-ui-qmarkdown/dist/index.css';
// 设置远程组件加载器
// 覆盖 platform-core 包中的 remoteComponentLoader 函数
// 只有在主前端项目中编写如下的 remoteComponentLoader 函数才能实现 webpack MF 的 shared 功能
// 只有在主前端项目中编写如下的 remoteComponentLoader 函数才能实现 webpack Module Federation 的 shared 功能
ComponentManager.setRemoteComponentLoader((moduleName: string, componentName: string): any => {
return async () => {
await __webpack_init_sharing__('default');

11
irbs.shrcb.poc.frontend/webpack.config.mf.cjs

@ -9,13 +9,20 @@ const projectName = packageJson.name; // 项目名称
const deps = packageJson.dependencies; // 项目依赖
// 读取本地路由配置, 通过其中 component 和 componentPath 两个属性构建 webpack 模块联邦的 exposes 属性值
const data = fs.readFileSync('./src/routes/routes.json', 'utf8');
const routes = Json5.parse(data);
const routesJson = fs.readFileSync('./src/routes/routes.json', 'utf8');
const routes = Json5.parse(routesJson);
const mfExposes = {};
for (const route of routes) {
mfExposes[route.component] = route.componentPath;
}
// 读取远程组件配置, 通过其中 component 和 componentPath 两个属性构建 webpack 模块联邦的 exposes 属性值
const remoteComponentsJson = fs.readFileSync('./src/remote-components/remote-components.json', 'utf8');
const remoteComponents = Json5.parse(remoteComponentsJson);
for (const remoteComponent of remoteComponents) {
mfExposes[remoteComponent.component] = remoteComponent.componentPath;
}
// 导出 webapck 配置的模块联邦部分
module.exports = {
plugins: [

Loading…
Cancel
Save