Browse Source

提交修改

main
likunming 2 months ago
parent
commit
a80bbd8a72
  1. 10
      irbs.cust.rating/src/main/java/irbs/cust/rating/enums/BusinessCodeSuffix.java
  2. 111
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/BusinessCode.java
  3. 292
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/RatingQualIndexAddtion.java
  4. 10
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/repository/BusinessCodeRepository.java
  5. 11
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/repository/RatingQualIndexAddtionRepository.java
  6. 72
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/BusinessCodeVo.java
  7. 224
      irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/RatingQualIndexAddtionVo.java
  8. 19
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/BusinessCodeService.java
  9. 9
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/RatingQualIndexAddtionService.java
  10. 57
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/BusinessCodeServiceImpl.java
  11. 12
      irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/RatingQualIndexAddtionServiceImpl.java
  12. 439
      irbs.cust.rating/src/main/resources/liquibase/20250528_DG_KH_DDL.xml
  13. 48
      irbs.cust.rating/src/main/resources/liquibase/20250714_RPT_VIEW__DDL.xml
  14. 3
      irbs.frontend/public/engine.svg
  15. 83
      irbs.frontend/public/webjars/tailwindcss/3.4.16/tailwind.css.js
  16. 8
      irbs.frontend/src/remote-components/remote-components.json
  17. 33
      irbs.frontend/src/views/custRating/company/GrayModelDialog.vue
  18. 68
      irbs.frontend/src/views/custRating/company/components/AdjustItemGrid.vue
  19. 36
      irbs.frontend/src/views/custRating/company/components/AdjustItemIndex.vue
  20. 38
      irbs.frontend/src/views/custRating/company/components/CreditReportGrid.vue
  21. 42
      irbs.frontend/src/views/custRating/company/components/CustBaseInfo.vue
  22. 46
      irbs.frontend/src/views/custRating/company/components/DefaultCognizanceGrid.vue
  23. 45
      irbs.frontend/src/views/custRating/company/components/DefaultRebirthGrid.vue
  24. 49
      irbs.frontend/src/views/custRating/company/components/FinanceProjectCompare.vue
  25. 89
      irbs.frontend/src/views/custRating/company/components/FinanceProjectGrid.vue
  26. 38
      irbs.frontend/src/views/custRating/company/components/FinanceReportTabs.vue
  27. 29
      irbs.frontend/src/views/custRating/company/components/FirstRatingResult.vue
  28. 51
      irbs.frontend/src/views/custRating/company/components/HistRatingGrid.vue
  29. 33
      irbs.frontend/src/views/custRating/company/components/HistTab.vue
  30. 44
      irbs.frontend/src/views/custRating/company/components/OpinionGrid.vue
  31. 77
      irbs.frontend/src/views/custRating/company/components/Overturn.vue
  32. 11
      irbs.frontend/src/views/custRating/company/components/QualAddtionView.vue
  33. 162
      irbs.frontend/src/views/custRating/company/components/QualAnalysis.vue
  34. 51
      irbs.frontend/src/views/custRating/company/components/QuanAnalysis.vue
  35. 61
      irbs.frontend/src/views/custRating/company/components/RatingLevelSlider.vue
  36. 36
      irbs.frontend/src/views/custRating/company/components/ReportIndex.vue
  37. 117
      irbs.frontend/src/views/custRating/company/components/ReportRating.vue
  38. 29
      irbs.frontend/src/views/custRating/company/components/StepTabs.vue
  39. 82
      irbs.frontend/src/views/custRating/company/components/Timeline.vue
  40. 39
      irbs.frontend/src/views/custRating/company/components/UpdateModel.vue
  41. 309
      irbs.frontend/src/views/custRating/company/components/buttons/AnnotationButton.vue
  42. 21
      irbs.frontend/src/views/custRating/company/components/buttons/NextButton.vue
  43. 73
      irbs.frontend/src/views/custRating/company/components/buttons/TestCalcButton.vue
  44. 61
      irbs.frontend/src/views/custRating/company/components/buttons/WorkflowButton.vue
  45. 37
      irbs.frontend/src/views/custRating/company/template/shrcb/Content.vue
  46. 58
      irbs.frontend/src/views/custRating/company/template/shrcb/Index.vue
  47. 40
      irbs.frontend/src/views/custRating/company/template/shrcb/Layout.vue
  48. 18
      irbs.frontend/src/views/custRating/company/template/shrcb/step/adjust-item/AdjustItem.vue
  49. 31
      irbs.frontend/src/views/custRating/company/template/shrcb/step/cust-info/CustInfo.vue
  50. 47
      irbs.frontend/src/views/custRating/company/template/shrcb/step/opinion/Opinion.vue
  51. 20
      irbs.frontend/src/views/custRating/company/template/shrcb/step/quan-qual-analysis/QuanQualAnalysis.vue
  52. 34
      irbs.frontend/src/views/custRating/company/template/shrcb/step/rating-report/ReportInfo.vue
  53. 79
      irbs.frontend/src/views/custRating/company/ts/Addtion.ts
  54. 3
      irbs.shrcb.poc.frontend/public/engine.svg
  55. 83
      irbs.shrcb.poc.frontend/public/webjars/tailwindcss/3.4.16/tailwind.css.js
  56. 8
      irbs.shrcb.poc.frontend/src/remote-components/remote-components.json

10
irbs.cust.rating/src/main/java/irbs/cust/rating/enums/BusinessCodeSuffix.java

@ -0,0 +1,10 @@
package irbs.cust.rating.enums;
/**
* 业务流水号后缀
*/
public enum BusinessCodeSuffix {
YYYYMMDD, //年月日
YYYYMM //年月
;
}

111
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/BusinessCode.java

@ -0,0 +1,111 @@
package irbs.cust.rating.jpa.entity;
import io.sc.platform.orm.entity.BaseEntity;
import irbs.cust.rating.enums.BusinessCodeSuffix;
import irbs.cust.rating.jpa.vo.BusinessCodeVo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.Size;
/**
* 最大业务流水号记录表
* @author likunming
*
*/
@Entity
@Table(name="T_BUSINESS_CODE")
public class BusinessCode extends BaseEntity<BusinessCodeVo> {
// 主键
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name="ID_")
@Size(max=50)
protected String id;
// 前缀(一般为字母,用来标识是什么业务)
@Column(name="PREFIX_")
@Size(max=10)
protected String prefix;
// 后缀(包括:YYYYMMDD,YYYYMM)
@Column(name="SUFFIX_")
@Enumerated(EnumType.STRING)
protected BusinessCodeSuffix suffix;
// 流水号长度(减掉前缀后缀后的长度,长度为4的示例:R202505280001)
@Column(name="LENGTH_")
protected Integer length;
// 最后获取流水号的时间(根据后缀存储)
@Column(name="LAST_DATE_")
@Size(max=20)
protected String lastDate;
// 当前最大序号(每获取一次+1)
@Column(name="MAX_NUM_")
protected Integer maxNum;
@Override
public BusinessCodeVo toVo() {
BusinessCodeVo vo = new BusinessCodeVo();
super.toVo(vo);
vo.setId(this.getId());
vo.setPrefix(this.getPrefix());
vo.setSuffix(this.getSuffix().name());
vo.setLength(this.getLength());
vo.setLastDate(this.getLastDate());
vo.setMaxNum(this.getMaxNum());
return vo;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public BusinessCodeSuffix getSuffix() {
return suffix;
}
public void setSuffix(BusinessCodeSuffix suffix) {
this.suffix = suffix;
}
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public String getLastDate() {
return lastDate;
}
public void setLastDate(String lastDate) {
this.lastDate = lastDate;
}
public Integer getMaxNum() {
return maxNum;
}
public void setMaxNum(Integer maxNum) {
this.maxNum = maxNum;
}
}

292
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/entity/RatingQualIndexAddtion.java

@ -0,0 +1,292 @@
package irbs.cust.rating.jpa.entity;
import io.sc.engine.rule.core.enums.QualitativeAdditionComponentType;
import io.sc.platform.orm.converter.NumericBooleanConverter;
import io.sc.platform.orm.entity.BaseEntity;
import irbs.cust.rating.jpa.vo.RatingQualIndexAddtionVo;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import javax.validation.constraints.Size;
/**
* 定性指标补录表
* @author likunming
*/
@Entity
@Table(name="NS_QUAL_INDEX_ADDTION")
public class RatingQualIndexAddtion extends BaseEntity<RatingQualIndexAddtionVo> {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Column(name="ID")
@Size(max=50)
private String id;
/**
* 问题定义ID
*/
@Column(name= "DEF_ID_")
private String defId;
/**
* 代码
*/
@Column(name= "CODE_")
private String code;
/**
* 名称
*/
@Column(name= "NAME_")
private String name;
/**
* 描述
*/
@Column(name= "DESCRIPTION_")
private String description;
/**
* 组件类型
*/
@Column(name= "COMPONENT_TYPE_")
@Enumerated(EnumType.STRING)
private QualitativeAdditionComponentType componentType;
/**
* 条件
*/
@Column(name= "CONDITION_")
private String condition;
/**
* 是否可用
*/
@Column(name= "ENABLE_")
@Convert(converter= NumericBooleanConverter.class)
private Boolean enable;
/**
* 排序
*/
@Column(name= "ORDER_")
private Integer order;
/**
* 多行文本框行数
*/
@Column(name= "ROWS_")
private Integer rows;
/**
* 提示词
*/
@Column(name= "PROMPT_")
private String prompt;
/**
* 允许上传附件的文件扩展名
*/
@Column(name= "ATTACHMENT_EXT_NAMES_")
private String attachmentExtNames;
/**
* 允许上传附件的最大个数
*/
@Column(name= "ATTACHMENT_MAX_COUNT_")
private Integer attachmentMaxCount;
/**
* 整数值
*/
@Column(name= "INTEGER_VALUE_")
private Integer integerValue;
/**
* 小数值
*/
@Column(name= "DECIMAL_VALUE_")
private Integer decimalValue;
/**
* 文本值
*/
@Column(name= "TEXT_VALUE_")
private String textValue;
/**
* 多行文本值
*/
@Column(name= "TEXTS_VALUE_")
private String textsValue;
public RatingQualIndexAddtion() {
}
public RatingQualIndexAddtion(String id) {
this.id = id;
}
@Override
public RatingQualIndexAddtionVo toVo() {
RatingQualIndexAddtionVo vo = new RatingQualIndexAddtionVo();
vo.setId(this.getId());
vo.setDefId(this.getDefId());
vo.setCode(this.getCode());
vo.setName(this.getName());
vo.setDescription(this.getDescription());
if (this.getComponentType() != null) {
vo.setComponentType(this.getComponentType().name());
}
vo.setEnable(this.getEnable());
vo.setOrder(this.getOrder());
vo.setRows(this.getRows());
vo.setPrompt(this.getPrompt());
vo.setAttachmentExtNames(this.getAttachmentExtNames());
vo.setAttachmentMaxCount(this.getAttachmentMaxCount());
vo.setIntegerValue(this.getIntegerValue());
vo.setDecimalValue(this.getDecimalValue());
vo.setTextValue(this.getTextValue());
vo.setTextsValue(this.getTextsValue());
return vo;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDefId() {
return defId;
}
public void setDefId(String defId) {
this.defId = defId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public QualitativeAdditionComponentType getComponentType() {
return componentType;
}
public void setComponentType(QualitativeAdditionComponentType componentType) {
this.componentType = componentType;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public String getPrompt() {
return prompt;
}
public void setPrompt(String prompt) {
this.prompt = prompt;
}
public String getAttachmentExtNames() {
return attachmentExtNames;
}
public void setAttachmentExtNames(String attachmentExtNames) {
this.attachmentExtNames = attachmentExtNames;
}
public Integer getAttachmentMaxCount() {
return attachmentMaxCount;
}
public void setAttachmentMaxCount(Integer attachmentMaxCount) {
this.attachmentMaxCount = attachmentMaxCount;
}
public Integer getIntegerValue() {
return integerValue;
}
public void setIntegerValue(Integer integerValue) {
this.integerValue = integerValue;
}
public Integer getDecimalValue() {
return decimalValue;
}
public void setDecimalValue(Integer decimalValue) {
this.decimalValue = decimalValue;
}
public String getTextValue() {
return textValue;
}
public void setTextValue(String textValue) {
this.textValue = textValue;
}
public String getTextsValue() {
return textsValue;
}
public void setTextsValue(String textsValue) {
this.textsValue = textsValue;
}
}

10
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/repository/BusinessCodeRepository.java

@ -0,0 +1,10 @@
package irbs.cust.rating.jpa.repository;
import io.sc.platform.orm.repository.DaoRepository;
import irbs.cust.rating.enums.BusinessCodeSuffix;
import irbs.cust.rating.jpa.entity.BusinessCode;
public interface BusinessCodeRepository extends DaoRepository<BusinessCode, String> {
BusinessCode findByPrefixAndSuffixAndLength(String prefix, BusinessCodeSuffix suffix, Integer length);
}

11
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/repository/RatingQualIndexAddtionRepository.java

@ -0,0 +1,11 @@
package irbs.cust.rating.jpa.repository;
import io.sc.platform.orm.repository.DaoRepository;
import irbs.cust.rating.jpa.entity.RatingQualIndexAddtion;
import java.util.List;
public interface RatingQualIndexAddtionRepository extends DaoRepository<RatingQualIndexAddtion, String> {
List<RatingQualIndexAddtion> findByDefIdOrderByOrderAsc(String defId);
}

72
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/BusinessCodeVo.java

@ -0,0 +1,72 @@
package irbs.cust.rating.jpa.vo;
import io.sc.platform.orm.api.vo.BaseVo;
public class BusinessCodeVo extends BaseVo {
// 主键
private String id;
// 前缀(一般为字母,用来标识是什么业务)
private String prefix;
// 后缀(包括:YYYYMMDD,YYYYMM)
private String suffix;
// 流水号长度(减掉前缀后缀后的长度,长度为4的示例:R202505280001)
private Integer length;
// 最后获取流水号的时间(根据后缀存储)
private String lastDate;
// 当前最大序号(每获取一次+1)
private Integer maxNum;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public Integer getLength() {
return length;
}
public void setLength(Integer length) {
this.length = length;
}
public String getLastDate() {
return lastDate;
}
public void setLastDate(String lastDate) {
this.lastDate = lastDate;
}
public Integer getMaxNum() {
return maxNum;
}
public void setMaxNum(Integer maxNum) {
this.maxNum = maxNum;
}
}

224
irbs.cust.rating/src/main/java/irbs/cust/rating/jpa/vo/RatingQualIndexAddtionVo.java

@ -0,0 +1,224 @@
package irbs.cust.rating.jpa.vo;
import io.sc.platform.orm.api.vo.BaseVo;
public class RatingQualIndexAddtionVo extends BaseVo {
private String id;
/**
* 问题定义ID
*/
private String defId;
/**
* 代码
*/
private String code;
/**
* 名称
*/
private String name;
/**
* 描述
*/
private String description;
/**
* 组件类型
*/
private String componentType;
/**
* 条件
*/
private String condition;
/**
* 是否可用
*/
private Boolean enable;
/**
* 排序
*/
private Integer order;
/**
* 多行文本框行数
*/
private Integer rows;
/**
* 提示词
*/
private String prompt;
/**
* 允许上传附件的文件扩展名
*/
private String attachmentExtNames;
/**
* 允许上传附件的最大个数
*/
private Integer attachmentMaxCount;
/**
* 整数值
*/
private Integer integerValue;
/**
* 小数值
*/
private Integer decimalValue;
/**
* 文本值
*/
private String textValue;
/**
* 多行文本值
*/
private String textsValue;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDefId() {
return defId;
}
public void setDefId(String defId) {
this.defId = defId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getComponentType() {
return componentType;
}
public void setComponentType(String componentType) {
this.componentType = componentType;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public Boolean getEnable() {
return enable;
}
public void setEnable(Boolean enable) {
this.enable = enable;
}
public Integer getOrder() {
return order;
}
public void setOrder(Integer order) {
this.order = order;
}
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public String getPrompt() {
return prompt;
}
public void setPrompt(String prompt) {
this.prompt = prompt;
}
public String getAttachmentExtNames() {
return attachmentExtNames;
}
public void setAttachmentExtNames(String attachmentExtNames) {
this.attachmentExtNames = attachmentExtNames;
}
public Integer getAttachmentMaxCount() {
return attachmentMaxCount;
}
public void setAttachmentMaxCount(Integer attachmentMaxCount) {
this.attachmentMaxCount = attachmentMaxCount;
}
public Integer getIntegerValue() {
return integerValue;
}
public void setIntegerValue(Integer integerValue) {
this.integerValue = integerValue;
}
public Integer getDecimalValue() {
return decimalValue;
}
public void setDecimalValue(Integer decimalValue) {
this.decimalValue = decimalValue;
}
public String getTextValue() {
return textValue;
}
public void setTextValue(String textValue) {
this.textValue = textValue;
}
public String getTextsValue() {
return textsValue;
}
public void setTextsValue(String textsValue) {
this.textsValue = textsValue;
}
}

19
irbs.cust.rating/src/main/java/irbs/cust/rating/service/BusinessCodeService.java

@ -0,0 +1,19 @@
package irbs.cust.rating.service;
import io.sc.platform.orm.service.DaoService;
import irbs.cust.rating.enums.BusinessCodeSuffix;
import irbs.cust.rating.jpa.entity.BusinessCode;
import irbs.cust.rating.jpa.repository.BusinessCodeRepository;
public interface BusinessCodeService extends DaoService<BusinessCode, String, BusinessCodeRepository> {
/**
* 获取业务流水号
* @param prefix 前缀
* @param suffix 后缀
* @param length 流水号长度减去前缀后缀后的长度
* @return
* @throws Exception
*/
String getBusinessCode(String prefix, BusinessCodeSuffix suffix, Integer length) throws Exception;
}

9
irbs.cust.rating/src/main/java/irbs/cust/rating/service/RatingQualIndexAddtionService.java

@ -0,0 +1,9 @@
package irbs.cust.rating.service;
import io.sc.platform.orm.service.DaoService;
import irbs.cust.rating.jpa.entity.RatingQualIndexAddtion;
import irbs.cust.rating.jpa.repository.RatingQualIndexAddtionRepository;
public interface RatingQualIndexAddtionService extends DaoService<RatingQualIndexAddtion, String, RatingQualIndexAddtionRepository> {
}

57
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/BusinessCodeServiceImpl.java

@ -0,0 +1,57 @@
package irbs.cust.rating.service.impl;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import irbs.cust.rating.enums.BusinessCodeSuffix;
import irbs.cust.rating.jpa.entity.BusinessCode;
import irbs.cust.rating.jpa.repository.BusinessCodeRepository;
import irbs.cust.rating.service.BusinessCodeService;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service("businessCodeService")
public class BusinessCodeServiceImpl extends DaoServiceImpl<BusinessCode, String, BusinessCodeRepository> implements BusinessCodeService {
@Override
public String getBusinessCode(String prefix, BusinessCodeSuffix suffix, Integer length) throws Exception {
BusinessCode businessCode = repository.findByPrefixAndSuffixAndLength(prefix, suffix, length);
String lastDate = getLastDate(suffix);
Integer currNum = 1;
if (null != businessCode) {
if (businessCode.getLastDate().equals(lastDate)) {
currNum = businessCode.getMaxNum() + 1;
}
} else {
businessCode = new BusinessCode();
businessCode.setPrefix(prefix);
businessCode.setSuffix(suffix);
businessCode.setLength(length);
}
businessCode.setLastDate(lastDate);
businessCode.setMaxNum(currNum);
repository.save(businessCode);
return prefix + lastDate + formatNumber(currNum, length);
}
private String getLastDate(BusinessCodeSuffix suffix) {
String lastDate = "";
Date date = new Date();
SimpleDateFormat sdf = null;
switch (suffix) {
case YYYYMM:
sdf = new SimpleDateFormat("yyyyMM");
lastDate = sdf.format(date);
break;
case YYYYMMDD:
sdf = new SimpleDateFormat("yyyyMMdd");
lastDate = sdf.format(date);
break;
}
return lastDate;
}
public String formatNumber(int number, int length) {
return String.format("%0" + length + "d", number);
}
}

12
irbs.cust.rating/src/main/java/irbs/cust/rating/service/impl/RatingQualIndexAddtionServiceImpl.java

@ -0,0 +1,12 @@
package irbs.cust.rating.service.impl;
import io.sc.platform.orm.service.impl.DaoServiceImpl;
import irbs.cust.rating.jpa.entity.RatingQualIndexAddtion;
import irbs.cust.rating.jpa.repository.RatingQualIndexAddtionRepository;
import irbs.cust.rating.service.RatingQualIndexAddtionService;
import org.springframework.stereotype.Service;
@Service("ratingQualIndexAddtionService")
public class RatingQualIndexAddtionServiceImpl extends DaoServiceImpl<RatingQualIndexAddtion, String, RatingQualIndexAddtionRepository> implements RatingQualIndexAddtionService {
}

439
irbs.cust.rating/src/main/resources/liquibase/20250528_DG_KH_DDL.xml

@ -0,0 +1,439 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="20250528_DG_KH_DDL" author="platform">
<!-- 对公客户基本信息表 -->
<createTable tableName="IRS_DG_KH_BASE_INF" remarks="对公客户基本信息表">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="ID主键">
<constraints primaryKey="true"/>
</column>
<column name="CUST_NO" type="java.sql.Types.NVARCHAR(60)" remarks="客户编号"></column>
<column name="CUST_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="客户名称"></column>
<column name="CUST_TYPE" type="java.sql.Types.NVARCHAR(10)" remarks="客户类别(1:一般公司客户;2:金融机构及发债企业客户)"></column>
<column name="CUSTOMER_CHINESE_NAME" type="java.sql.Types.NVARCHAR(90)" remarks="客户中文名称"></column>
<column name="MANAGER_NAME" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理名称"></column>
<column name="MANAGER_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理编号"></column>
<column name="MANAGER_ORG_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理所在机构编号"></column>
<column name="MANAGER_ORG_NAME" type="java.sql.Types.NVARCHAR(200)" remarks="客户经理所在机构名称"></column>
<column name="LAUNCH_USER" type="java.sql.Types.NVARCHAR(100)" remarks="发起人"></column>
<column name="QUAN_SCORE" type="java.sql.Types.NUMERIC(24, 8)" remarks="定量得分"></column>
<column name="QUAL_SCORE" type="java.sql.Types.NUMERIC(24, 8)" remarks="定性得分"></column>
<column name="MODEL_SCORE" type="java.sql.Types.NUMERIC(24, 8)" remarks="模型得分"></column>
<column name="INIT_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="初始级别"></column>
<column name="ADJ_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="调整项级别"></column>
<column name="SP_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="评级推翻级别"></column>
<column name="FINAL_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="最终认定级别"></column>
<column name="PD" type="java.sql.Types.NUMERIC(24, 8)" remarks="违约概率"></column>
<column name="PROCESS_INSTANCE_ID" type="java.sql.Types.NVARCHAR(50)" remarks="流程实例主键"></column>
<column name="PROCESS_STATUS" type="java.sql.Types.NVARCHAR(50)" remarks="流程状态"></column>
<column name="RATING_STATUS" type="java.sql.Types.NVARCHAR(50)" remarks="评级状态"></column>
<column name="TRIGGER_TYPE" type="java.sql.Types.NVARCHAR(50)" remarks="评级任务触发类型"></column>
<column name="TRIGGER_REA" type="java.sql.Types.NVARCHAR(500)" remarks="评级任务触发原因"></column>
<column name="RATE_TYPE" type="java.sql.Types.NVARCHAR(10)" remarks="评级类型"></column>
<column name="RATE_TYPE_DES" type="java.sql.Types.NVARCHAR(500)" remarks="评级类型描述"></column>
<column name="START_TIME" type="DATETIME" remarks="评级发起日期"></column>
<column name="EFFECTIVE_TIME" type="DATETIME" remarks="评级生效时间"></column>
<column name="MATURE_TIME" type="DATETIME" remarks="评级到期时间"></column>
<column name="MODEL_ID" type="java.sql.Types.NVARCHAR(50)" remarks="评级模型ID"></column>
<column name="MODEL_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="评级模型编号"></column>
<column name="MODEL_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="评级模型名称"></column>
<column name="RATING_CFG_ID" type="java.sql.Types.NVARCHAR(50)" remarks="评级配置ID"></column>
<column name="IS_ADMIT" type="java.sql.Types.SMALLINT" remarks="准入建议"></column>
<column name="IS_TRIAL" type="java.sql.Types.SMALLINT" remarks="是否试算"></column>
<column name="MODEL_LEVEL" type="java.sql.Types.NVARCHAR(50)" remarks="模型评级等级"></column>
<column name="CURRENT_STEP" type="java.sql.Types.NVARCHAR(50)" remarks="当前评级步骤(页面位置)"></column>
<column name="OVER_NUM" type="java.sql.Types.SMALLINT" remarks="意见位置"></column>
<column name="OUT_IMAGE_ID" type="java.sql.Types.NVARCHAR(50)" remarks="外部数据授权标志"></column>
<column name="ACCESS_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="准入级别"></column>
<column name="DEFAULT_IND" type="java.sql.Types.NVARCHAR(10)" remarks="违约标识"></column>
<column name="QUAL_CALC_COUNT" type="java.sql.Types.SMALLINT" remarks="定性计算次数"></column>
<column name="PWH_COMMITTEE_NUM" type="java.sql.Types.SMALLINT" remarks="评级委员会人数"></column>
<column name="GX_END_TIME" type="DATETIME" remarks="评级更新任务到期时间"></column>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
<column name="MODEL_ID_G" type="java.sql.Types.NVARCHAR(50)" remarks="评级模型ID(灰度)"></column>
<column name="MODEL_CODE_G" type="java.sql.Types.NVARCHAR(50)" remarks="评级模型编号(灰度)"></column>
<column name="MODEL_NAME_G" type="java.sql.Types.NVARCHAR(100)" remarks="评级模型名称(灰度)"></column>
<column name="QUAN_SCORE_G" type="java.sql.Types.NUMERIC(24, 8)" remarks="定量得分(灰度)"></column>
<column name="QUAL_SCORE_G" type="java.sql.Types.NUMERIC(24, 8)" remarks="定性得分(灰度)"></column>
<column name="MODEL_SCORE_G" type="java.sql.Types.NUMERIC(24, 8)" remarks="模型得分(灰度)"></column>
<column name="MODEL_LEVEL_G" type="java.sql.Types.NVARCHAR(50)" remarks="模型评级等级(灰度)"></column>
<column name="ACCESS_LEVEL_G" type="java.sql.Types.NVARCHAR(10)" remarks="准入级别(灰度)"></column>
<column name="ADJ_LEVEL_G" type="java.sql.Types.NVARCHAR(10)" remarks="调整项级别(灰度)"></column>
</createTable>
<!-- ESB客户基本信息表 -->
<createTable tableName="ESB_RATING_CUSTOMER" remarks="ESB客户基本信息表">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="CUSTOMER_ID" type="java.sql.Types.NVARCHAR(12)" remarks="客户编号"/>
<column name="CUSTOMER_CHINESE_NAME" type="java.sql.Types.NVARCHAR(90)" remarks="客户中文名称"/>
<column name="CERTIFICATE_TYPE" type="java.sql.Types.NVARCHAR(5)" remarks="证件类型"/>
<column name="CERTIFICATE_NUM" type="java.sql.Types.NVARCHAR(100)" remarks="证件号码"/>
<column name="CUSTOMER_TYPE" type="java.sql.Types.NVARCHAR(1)" remarks="对公客户类型"/>
<column name="CUSTOMER_SIZE" type="java.sql.Types.NVARCHAR(2)" remarks="企业规模"/>
<column name="REGISTERED_TYPE" type="java.sql.Types.NVARCHAR(5)" remarks="企业类型"/>
<column name="GOVER_FINANCE_SIGN" type="java.sql.Types.NVARCHAR(1)" remarks="融资平台标志"/>
<column name="GOVER_FINANCE_TYPE" type="java.sql.Types.NVARCHAR(1)" remarks="政府融资平台类型"/>
<column name="REGISTRATION" type="java.sql.Types.NVARCHAR(2)" remarks="所在行政区域"/>
<column name="NATION" type="java.sql.Types.NVARCHAR(5)" remarks="所在国家地区"/>
<column name="MEMBER_TYPE" type="java.sql.Types.NVARCHAR(2)" remarks="成员类别"/>
<column name="GROUP_CUST_IND" type="java.sql.Types.NVARCHAR(1)" remarks="是否集团客户"/>
<column name="FLAG_FOR_QUOTED_COMPANY" type="java.sql.Types.NVARCHAR(1)" remarks="上市公司标识"/>
<column name="INDUSTRY_TYPE" type="java.sql.Types.NVARCHAR(6)" remarks="国标行业分类"/>
<column name="BUILD_DATE" type="java.sql.Types.NVARCHAR(24)" remarks="成立日期"/>
<column name="CUSTOMER_MANAGER_NO" type="java.sql.Types.NVARCHAR(100)" remarks="经办人编号"/>
<column name="CUSTOMER_MANAGER_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="经办人名称"/>
<column name="CURRENT_PROCESSOR_CODE" type="java.sql.Types.NVARCHAR(36)" remarks="企业类型"/>
<column name="CURRENT_PROCESSOR_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="所在行政区域"/>
<column name="HANDLE_ORG_ID" type="java.sql.Types.NVARCHAR(36)" remarks="经办机构"/>
<column name="HANDLE_TIME" type="DATETIME" remarks="经办时间"/>
<column name="MAIN_BUSI_UNDER_FORTY" type="java.sql.Types.NVARCHAR(1)" remarks="主营业务占比不超过40%"/>
<column name="REPORT_ID" type="java.sql.Types.NVARCHAR(50)" remarks="征信报告主键"/>
<column name="EXTERNAL_FILE_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="外部数据文件传输码"/>
<column name="ACTU_CTRL_YEARS" type="java.sql.Types.SMALLINT" remarks="实际控制人从业年限"/>
<column name="CORPORATE_CUSTOMER_TYPE" type="java.sql.Types.NVARCHAR(3)" remarks="对公客户类型"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 对公客户基本信息 -->
<createTable tableName="IRBS_CUST_CP_INFO" remarks="对公客户基本信息">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="DATA_DT" type="java.sql.Types.NVARCHAR(100)" remarks="数据日期"/>
<column name="CUSTOMER_ID" type="java.sql.Types.NVARCHAR(12)" remarks="客户编号"/>
<column name="CUSTOMER_CHINESE_NAME" type="java.sql.Types.NVARCHAR(90)" remarks="客户中文名称"/>
<column name="CUST_TYPE_CD" type="java.sql.Types.NVARCHAR(100)" remarks="客户类型"/>
<column name="ORGN_CD" type="java.sql.Types.NVARCHAR(100)" remarks="组织机构代码"/>
<column name="LEGA_BOOK_NO" type="java.sql.Types.NVARCHAR(100)" remarks="法人证书号"/>
<column name="ORG_CRDT_CD" type="java.sql.Types.NVARCHAR(100)" remarks="统一信用代码证号"/>
<column name="CUST_SORT_CD" type="java.sql.Types.NVARCHAR(100)" remarks="客户分类"/>
<column name="CORP_SIZE_CD" type="java.sql.Types.NVARCHAR(100)" remarks="企业规模"/>
<column name="INDU_SORT_CD" type="java.sql.Types.NVARCHAR(100)" remarks="国标行业分类"/>
<column name="CHASTEN_CUST_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="是否为联合惩戒名单客户"/>
<column name="FIRST_CRTD_CRDT_RELA_DT" type="java.sql.Types.NVARCHAR(100)" remarks="与我行建立信贷关系时间"/>
<column name="BUILD_DT" type="java.sql.Types.NVARCHAR(100)" remarks="成立日期"/>
<column name="UPDATE_DT" type="java.sql.Types.NVARCHAR(100)" remarks="更新日期"/>
<column name="LEGAL_REP" type="java.sql.Types.NVARCHAR(500)" remarks="法人代表"/>
<column name="RGST_GROUND" type="java.sql.Types.NVARCHAR(300)" remarks="注册地址"/>
<column name="MGER_NO" type="java.sql.Types.NVARCHAR(100)" remarks="管户人编号"/>
<column name="MGER_CNA" type="java.sql.Types.NVARCHAR(100)" remarks="管户人"/>
<column name="MGER_ORG_NM" type="java.sql.Types.NVARCHAR(100)" remarks="管户机构"/>
<column name="MGER_ORG_NO" type="java.sql.Types.NVARCHAR(100)" remarks="管户机构编号"/>
<column name="MGER_ORG_NO_UP" type="java.sql.Types.NVARCHAR(100)" remarks="管户机构上级"/>
<column name="CORP_SUBJ" type="java.sql.Types.NVARCHAR(100)" remarks="企业隶属"/>
<column name="NATION_CD" type="java.sql.Types.NVARCHAR(100)" remarks="所在国家地区"/>
<column name="RGST_GROUND_ADMIN_REGION_CD" type="java.sql.Types.NVARCHAR(100)" remarks="所在行政区域"/>
<column name="LT_TRD_YEAR_INCOME_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="近三年营业收入不大于三亿"/>
<column name="GOVER_FIN_FLT_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="是否政府融资平台"/>
<column name="PRI_RIGHT_LIST_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="是否主权名单"/>
<column name="YEARS3_OVDUE_30_DAY_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内借据逾期超过30天标志"/>
<column name="YEARS3_EXPAND_2_CNT_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内贷款展期次数2次及以上标志"/>
<column name="YEARS3_ADV_MONEY_30_DAY_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内垫款超过30天标志"/>
<column name="YEARS3_BOR_REPAY_2_CNT_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内借新还旧次数2次及以上标志"/>
<column name="YEARS3_MODE_MODIF_OVERDUE_2_CNT_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内结息方式变更后是否出现逾期2次及以上标志"/>
<column name="YEARS3_PRIN_REPAY_PLAN_MODIF_2_CNT_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="3年内合同的本金还款计划是否变更2次及以上标志"/>
<column name="YEARS3_REGROUP_2_CNT_FLAG" type="java.sql.Types.CHAR" remarks="3年内重组2次及以上标志"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 评级步骤表 -->
<createTable tableName="NS_RATING_STEP" remarks="评级步骤表">
<column name="ID_" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="RATING_ID" type="java.sql.Types.NVARCHAR(36)" remarks="评级主键"/>
<column name="STEP_NAME" type="java.sql.Types.NVARCHAR(50)" remarks="步骤名称"/>
<column name="STEP_NO" type="java.sql.Types.NVARCHAR(5)" remarks="步骤编号"/>
<column name="STEP_TYPE" type="java.sql.Types.NVARCHAR(50)" remarks="步骤类型"/>
<column name="MODEL_ID" type="java.sql.Types.NVARCHAR(50)" remarks="模型主键"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 评级配置_评级步骤定义 -->
<createTable tableName="NS_R_CFG_STEPS" remarks="评级配置_评级步骤定义">
<column name="ID_" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="RATING_CFG_ID" type="java.sql.Types.NVARCHAR(36)" remarks="评级配置主表ID"/>
<column name="STEP_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="步骤编号"/>
<column name="STEP_NAME" type="java.sql.Types.NVARCHAR(254)" remarks="步骤名称"/>
<column name="STEP_NUM" type="java.sql.Types.NUMERIC(2, 0)" remarks="步骤序号"/>
<column name="STEP_TYPE" type="java.sql.Types.NVARCHAR(20)" remarks="步骤类型(DL:定量,DX:定性,TZ:调整项,WB:外部支持,TF:评级推翻,OT:其他)"/>
<column name="STEP_SOURCE_PATH" type="java.sql.Types.NVARCHAR(1000)" remarks="步骤资源路径"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 客户评级指标 -->
<createTable tableName="NS_RATING_INDEXES" remarks="客户评级指标">
<column name="ID_" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="STEP_ID" type="java.sql.Types.NVARCHAR(36)" remarks="评级步骤ID"/>
<column name="INDEX_TYPE" type="java.sql.Types.NVARCHAR(20)" remarks="指标类型"/>
<column name="INDEX_CATEGORY" type="java.sql.Types.NVARCHAR(500)" remarks="指标分类"/>
<column name="INDEX_NAME" type="java.sql.Types.NVARCHAR(500)" remarks="指标名称"/>
<column name="CONFIG_ID" type="java.sql.Types.NVARCHAR(36)" remarks="配置ID"/>
<column name="INDEX_ID" type="java.sql.Types.NVARCHAR(36)" remarks="指标ID"/>
<column name="INDEX_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="指标编号"/>
<column name="INDEX_VALUE" type="java.sql.Types.NVARCHAR(50)" remarks="指标值"/>
<column name="WEIGHT" type="java.sql.Types.NUMERIC(9, 6)" remarks="权重"/>
<column name="MODEL_LEVEL" type="java.sql.Types.NVARCHAR(10)" remarks="模型层级"/>
<column name="PARENT_ID" type="java.sql.Types.NVARCHAR(36)" remarks="父ID"/>
<column name="QUALITATIVE_CONTENT" type="java.sql.Types.NVARCHAR(2000)" remarks="定性内容"/>
<column name="QUALITATIVE_OPTIONS" type="java.sql.Types.NVARCHAR(2000)" remarks="定性选项"/>
<column name="INDEX_SCORE" type="java.sql.Types.NUMERIC(20, 4)" remarks="指标得分"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
<column name="INDEX_SCORE_G" type="java.sql.Types.NUMERIC(20, 4)" remarks="指标得分(灰度)"/>
</createTable>
<!-- 评级配置_候选值定义 -->
<createTable tableName="NS_R_CFG_VALUES" 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="DEF_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="问题定义编号"/>
<column name="DEF_NAME" type="java.sql.Types.NVARCHAR(2000)" remarks="问题名称"/>
<column name="ORDER_NUM" type="java.sql.Types.NUMERIC(4, 0)" remarks="选项序号"/>
<column name="TEXT" type="java.sql.Types.NVARCHAR(1000)" remarks="文本内容"/>
<column name="DIS_VAL" type="java.sql.Types.NVARCHAR(1000)" remarks="显示值"/>
<column name="VAL" type="java.sql.Types.NVARCHAR(50)" remarks="使用值"/>
<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="主键">
<constraints primaryKey="true"/>
</column>
<column name="MODEL_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="模型编号"/>
<column name="ADJ_ITEM_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="调整项定义编号"/>
</createTable>
<!-- 评级配置_调整项定义详情 -->
<createTable tableName="NS_R_CFG_ADJ_ITEM_DEF" remarks="评级配置_调整项定义详情">
<column name="ID" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="ADJ_ITEM_TYPE" type="java.sql.Types.NVARCHAR(50)" remarks="调整项类型"/>
<column name="ADJ_ITEM_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="调整项编号"/>
<column name="ADJ_ITEM_NAME" type="java.sql.Types.NVARCHAR(50)" remarks="调整项名称"/>
<column name="ADJ_ITEM_DES" type="java.sql.Types.NVARCHAR(2000)" remarks="调整项描述"/>
<column name="ADJ_ITEM_VALUE" type="java.sql.Types.NVARCHAR(4)" remarks="调整项值"/>
</createTable>
<!-- 评级征信指库结果表 -->
<createTable tableName="NS_ENTERPRISE_CREDIT_INDEX" remarks="评级征信指库结果表">
<column name="REPORT_ID" type="java.sql.Types.NVARCHAR(50)" remarks="报告编号"/>
<column name="INDEX_CODE" type="java.sql.Types.NVARCHAR(20)" remarks="指标代码"/>
<column name="INDEX_NAME" type="java.sql.Types.NVARCHAR(200)" remarks="指标名称"/>
<column name="INDEX_VALUE" type="java.sql.Types.NVARCHAR(50)" remarks="指标值"/>
<column name="CUST_NO" type="java.sql.Types.NVARCHAR(50)" remarks="客户号"/>
</createTable>
<addUniqueConstraint tableName="NS_ENTERPRISE_CREDIT_INDEX" columnNames="REPORT_ID,CUST_NO,INDEX_CODE"></addUniqueConstraint>
<!-- 客户评级试算记录表 -->
<createTable tableName="T_CUST_RATING_TEST_CALC" remarks="客户评级试算记录表">
<column name="ID" type="java.sql.Types.NVARCHAR(50)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="RATING_ID" type="java.sql.Types.NVARCHAR(50)" remarks="评级ID"/>
<column name="TEST_STEP" type="java.sql.Types.NVARCHAR(50)" remarks="试算步骤"/>
<column name="TEST_MAX_NUM" type="java.sql.Types.NUMERIC(8, 0)" remarks="评级时系统配置的最大试算次数"/>
<column name="CURR_NUM" type="java.sql.Types.NUMERIC(8, 0)" remarks="当前试算次数"/>
<column name="CURR_SCORE" type="java.sql.Types.NUMERIC(22, 8)" remarks="当前试算得分"/>
</createTable>
<!-- 对公客户评级推翻记录 -->
<createTable tableName="NS_RATING_OVERTURN" remarks="对公客户评级推翻记录">
<column name="ID_" type="java.sql.Types.NVARCHAR(36)" remarks="主键">
<constraints primaryKey="true"/>
</column>
<column name="RATING_ID" type="java.sql.Types.NVARCHAR(36)" remarks="评级ID"/>
<column name="OVERTURN_TYPE" type="java.sql.Types.NVARCHAR(20)" remarks="推翻类型"/>
<column name="SUGGEST_LEVEL" type="java.sql.Types.NVARCHAR(5)" remarks="建议级别"/>
<column name="ADJ_REASON" type="java.sql.Types.NVARCHAR(2000)" remarks="调整原因"/>
<column name="FILE_COUNT" type="java.sql.Types.NUMERIC(10, 0)" remarks="附件数量"/>
<column name="ORG_ID" type="java.sql.Types.NVARCHAR(36)" remarks="机构"/>
<column name="USER_CODE" type="java.sql.Types.NVARCHAR(254)" remarks="用户编号"/>
<column name="USER_NAME" type="java.sql.Types.NVARCHAR(254)" remarks="用户名称"/>
<column name="ROLE_NAME" type="java.sql.Types.NVARCHAR(254)" remarks="角色名称"/>
<column name="ROLE_CODE" type="java.sql.Types.NVARCHAR(254)" remarks="角色编号"/>
<column name="OVER_NUM" type="java.sql.Types.NUMERIC(10, 0)" remarks="意见位置"/>
<column name="ORG_NAME" type="java.sql.Types.NVARCHAR(254)" remarks="机构名称"/>
<column name="OPERATION_OPINION" type="java.sql.Types.NVARCHAR(10)" remarks="操作意见"/>
<column name="IS_OVERTURN" type="java.sql.Types.NUMERIC(10, 0)" remarks="是否推翻"/>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 债项评级结果 -->
<createTable tableName="P_IRS_CONTR_RAITNG_RESULT" remarks="债项评级结果">
<column name="DATA_DT" type="java.sql.Types.NVARCHAR(10)" remarks="数据日期"/>
<column name="CONT_NO" type="java.sql.Types.NVARCHAR(100)" remarks="合同编号"/>
<column name="LMT_NO" type="java.sql.Types.NVARCHAR(100)" remarks="额度编号"/>
<column name="CUST_NO" type="java.sql.Types.NVARCHAR(100)" remarks="客户编号"/>
<column name="CUST_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="客户名称"/>
<column name="CCY_CD" type="java.sql.Types.NVARCHAR(100)" remarks="币种代码"/>
<column name="LMT_PROD_CD" type="java.sql.Types.NVARCHAR(100)" remarks="业务品种"/>
<column name="CONTR_AMT" type="java.sql.Types.NUMERIC(36, 8)" remarks="合同金额"/>
<column name="CONTR_BAL" type="java.sql.Types.NUMERIC(36, 8)" remarks="合同余额"/>
<column name="OWEINT_BAL" type="java.sql.Types.NUMERIC(36, 8)" remarks="欠息余额"/>
<column name="FEE_BAL" type="java.sql.Types.NUMERIC(36, 8)" remarks="费用余额"/>
<column name="CONT_SIGN_DT" type="java.sql.Types.NVARCHAR(100)" remarks="合同签订日期"/>
<column name="CONT_START_DT" type="java.sql.Types.NVARCHAR(100)" remarks="起始日期"/>
<column name="CONT_END_DT" type="java.sql.Types.NVARCHAR(100)" remarks="到期日期"/>
<column name="CONTR_TERM_CD" type="java.sql.Types.NVARCHAR(100)" remarks="合同期限类型代码"/>
<column name="BLOCK_IND" type="java.sql.Types.NVARCHAR(100)" remarks="冻结标志"/>
<column name="CONT_TYPE_CD" type="java.sql.Types.NVARCHAR(100)" remarks="合同类别代码"/>
<column name="CONT_STATUS_CD" type="java.sql.Types.NVARCHAR(100)" remarks="合同状态代码"/>
<column name="GUAR_WAY_CD" type="java.sql.Types.NVARCHAR(100)" remarks="担保方式"/>
<column name="TEN_CLASS_CD" type="java.sql.Types.NVARCHAR(100)" remarks="十级分类代码"/>
<column name="LOAN_DIRECTION_CD" type="java.sql.Types.NVARCHAR(100)" remarks="贷款行业投向"/>
<column name="CYCLE_FLAG" type="java.sql.Types.NVARCHAR(100)" remarks="循环标志"/>
<column name="EXPENSE_NAME" type="java.sql.Types.NVARCHAR(100)" remarks="费用名称"/>
<column name="EXPENSE_RATE" type="java.sql.Types.NUMERIC(36, 8)" remarks="实际费率"/>
<column name="MONTH_RATE" type="java.sql.Types.NUMERIC(36, 8)" remarks="月利率"/>
<column name="CONTR_OVDUE_DAYS" type="java.sql.Types.NUMERIC(36, 8)" remarks="合同逾期天数"/>
<column name="CONTR_OWEINT_DAYS" type="java.sql.Types.NUMERIC(36, 8)" remarks="合同欠息天数"/>
<column name="OVDUE_POST_REPAY_AMT" type="java.sql.Types.NUMERIC(36, 8)" remarks="折现后还款金额(违约后)"/>
<column name="OPERATE_ORG_NO" type="java.sql.Types.NVARCHAR(100)" remarks="管户机构编号"/>
<column name="OPERATOR_NO" type="java.sql.Types.NVARCHAR(100)" remarks="管户人编号"/>
<column name="IRS_LGD" type="java.sql.Types.NUMERIC(36, 8)" remarks="违约损失率"/>
<column name="IRS_EAD" type="java.sql.Types.NUMERIC(36, 4)" remarks="风险暴露"/>
<column name="IRS_OVDUE" type="java.sql.Types.NVARCHAR(100)" remarks="是否违约认定"/>
<column name="CONT_EXPENSE_FEE_LGD" type="java.sql.Types.NUMERIC(36, 8)" remarks="合同层实际LGD"/>
<column name="IRS_LGD_LEVEL" type="java.sql.Types.NVARCHAR(5)" remarks="LGD等级"/>
<column name="DY_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="抵押VTL"/>
<column name="DBFS_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="主要担保方式VTL"/>
<column name="NPHY_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="内评行业VTL"/>
<column name="YPLX_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="押品类型VTL"/>
<column name="SXFY_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="三项费用比VTL"/>
<column name="JXJL_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="经营活动现金流VTL"/>
<column name="YSZK_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="应收账款增长率VTL"/>
<column name="LDBL_VTL" type="java.sql.Types.NUMERIC(22, 6)" remarks="流动性比率VTL"/>
</createTable>
<addUniqueConstraint tableName="P_IRS_CONTR_RAITNG_RESULT" columnNames="DATA_DT,CONT_NO,CUST_NO"></addUniqueConstraint>
<!-- 重点客户清单表 -->
<createTable tableName="NS_FOCUS_CUSTOMER" remarks="重点客户清单表">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="ID主键">
<constraints primaryKey="true"/>
</column>
<column name="CUST_ID" type="java.sql.Types.NVARCHAR(50)" remarks="客户ID"></column>
<column name="CUST_NO" type="java.sql.Types.NVARCHAR(100)" remarks="客户编号"></column>
<column name="CUST_NAME" type="java.sql.Types.NVARCHAR(200)" remarks="客户中文名称"></column>
<column name="CUST_TYPE" type="java.sql.Types.NVARCHAR(10)" remarks="客户类别(1:一般公司客户;2:金融机构及发债企业客户)"></column>
<column name="MANAGER_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理编号"></column>
<column name="MANAGER_NAME" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理名称"></column>
<column name="MANAGER_ORG_CODE" type="java.sql.Types.NVARCHAR(50)" remarks="客户经理所在机构编号"></column>
<column name="MANAGER_ORG_NAME" type="java.sql.Types.NVARCHAR(200)" remarks="客户经理所在机构名称"></column>
<column name="JPA_VERSION_" type="java.sql.Types.SMALLINT" remarks="JPA乐观锁版本"></column>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<!-- 评级报告允许查看得分详情的审批角色 -->
<createTable tableName="NS_RATING_REPORT_SHOW_SCORE_ROLE" remarks="评级报告允许查看得分详情的审批角色">
<column name="ID_" type="java.sql.Types.NVARCHAR(50)" remarks="ID主键">
<constraints primaryKey="true"/>
</column>
<column name="ROLE_" type="java.sql.Types.NVARCHAR(50)" remarks="角色ID"></column>
<column name="JPA_VERSION_" type="java.sql.Types.SMALLINT" remarks="JPA乐观锁版本"></column>
<column name="DATA_COME_FROM_" type="java.sql.Types.NVARCHAR(10)" remarks="数据来源(INPUT:手工录入,IMPORT:系统自动导入)" defaultValue="INPUT"></column>
<column name="CREATOR_" type="java.sql.Types.NVARCHAR(255)" remarks="创建人"></column>
<column name="CREATE_DATE_" type="DATETIME" remarks="创建日期"></column>
<column name="LAST_MODIFIER_" type="java.sql.Types.NVARCHAR(255)" remarks="最后修改人"></column>
<column name="LAST_MODIFYDATE_" type="DATETIME" remarks="最后修改日期"></column>
<column name="CORP_CODE_" type="java.sql.Types.NVARCHAR(255)" remarks="所属法人代码" defaultValue="_PRIMARY_">
</column>
</createTable>
<addUniqueConstraint tableName="NS_RATING_REPORT_SHOW_SCORE_ROLE" columnNames="ROLE_"></addUniqueConstraint>
</changeSet>
</databaseChangeLog>

48
irbs.cust.rating/src/main/resources/liquibase/20250714_RPT_VIEW__DDL.xml

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="20250714_RPT_VIEW_DDL" author="platform">
<!-- 报表视图 -->
<createView fullDefinition="false" replaceIfExists="true" viewName="VIEW_RPT_BASE_INFO">
SELECT
T.CUSTOMER_ID AS CUST_NO,
IFNULL(T.CUST_TYPE,'1') AS CUST_TYPE,
T.FINAL_LEVEL AS ORIGINAL_LEVEL,
T.INIT_LEVEL AS INIT_LEVEL,
T.ADJ_LEVEL AS ADJ_LEVEL,
CASE WHEN T.DEFAULT_IND = '1' THEN 'D' ELSE T.FINAL_LEVEL END AS FINAL_LEVEL,
S.PD,
CAST(DATE_FORMAT(T.EFFECTIVE_TIME,'%Y%m') AS DECIMAL) AS EFFECTIVE_MONTH,
D.ITEM_VALUE AS EFFECTIVE_Q,
LEFT(D.ITEM_VALUE,4) EFFECTIVE_Y,
IFNULL(T.MANAGER_ORG_CODE, '01002') MANAGER_ORG_CODE,
T.MODEL_CODE,
T.MODEL_NAME,
SUBSTR(IFNULL(C.INDU_SORT_CD, 'X'),1,1) AS INDUSTRY_CODE,
S.ORDER_NUM,
S1.ORDER_NUM AS INIT_ORDER_NUM,
S2.ORDER_NUM AS ADJ_ORDER_NUM,
T.MODEL_SCORE,
T.RATING_STATUS,
T.EFFECTIVE_TIME,
MAX(T.EFFECTIVE_TIME) OVER(PARTITION BY T.CUSTOMER_ID) AS MAX_EFFECTIVE_TIME,
SUM(BORR.BORR_BAL) OVER(PARTITION BY T.CUSTOMER_ID) AS BORR_BAL
FROM NS_COMPANY_RATING T
LEFT JOIN IRBS_CUST_CP_INFO C ON C.CUSTOMER_ID = T.CUSTOMER_ID
LEFT JOIN NS_CFG_MAIN_SCALE S ON S.SCALE_LEVEL = T.FINAL_LEVEL
LEFT JOIN NS_CFG_MAIN_SCALE S1 ON S1.SCALE_LEVEL = T.INIT_LEVEL
LEFT JOIN NS_CFG_MAIN_SCALE S2 ON S2.SCALE_LEVEL = T.ADJ_LEVEL
LEFT JOIN RPT_INIT_DATA D ON D.DATA_TP_CD = 'MONTH2QUARTER'
AND D.ITEM_NAME = LEFT(T.EFFECTIVE_TIME,7)
LEFT JOIN (
select t.CUST_NO, t.BORR_BAL from irbs_loan_borr_info t
) BORR ON BORR.CUST_NO = T.CUSTOMER_ID
WHERE T.RATING_STATUS IN ('010','020','EFFECTIVE','EXPIRED') AND T.FINAL_LEVEL IS NOT NULL
</createView>
</changeSet>
</databaseChangeLog>

3
irbs.frontend/public/engine.svg

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-browser-edge" viewBox="0 0 16 16">
<path d="M3.362 10.11c0 .926-.756 1.681-1.681 1.681S0 11.036 0 10.111.756 8.43 1.68 8.43h1.682zm.846 0c0-.924.756-1.68 1.681-1.68s1.681.756 1.681 1.68v4.21c0 .924-.756 1.68-1.68 1.68a1.685 1.685 0 0 1-1.682-1.68zM5.89 3.362c-.926 0-1.682-.756-1.682-1.681S4.964 0 5.89 0s1.68.756 1.68 1.68v1.682zm0 .846c.924 0 1.68.756 1.68 1.681S6.814 7.57 5.89 7.57H1.68C.757 7.57 0 6.814 0 5.89c0-.926.756-1.682 1.68-1.682zm6.749 1.682c0-.926.755-1.682 1.68-1.682S16 4.964 16 5.889s-.756 1.681-1.68 1.681h-1.681zm-.848 0c0 .924-.755 1.68-1.68 1.68A1.685 1.685 0 0 1 8.43 5.89V1.68C8.43.757 9.186 0 10.11 0c.926 0 1.681.756 1.681 1.68zm-1.681 6.748c.926 0 1.682.756 1.682 1.681S11.036 16 10.11 16s-1.681-.756-1.681-1.68v-1.682h1.68zm0-.847c-.924 0-1.68-.755-1.68-1.68s.756-1.681 1.68-1.681h4.21c.924 0 1.68.756 1.68 1.68 0 .926-.756 1.681-1.68 1.681z"/>
</svg>

After

Width:  |  Height:  |  Size: 970 B

83
irbs.frontend/public/webjars/tailwindcss/3.4.16/tailwind.css.js

File diff suppressed because one or more lines are too long

8
irbs.frontend/src/remote-components/remote-components.json

@ -0,0 +1,8 @@
[
/*
{
"component": "组件名称",
"componentPath": "组件 .vue 文件路径"
}
*/
]

33
irbs.frontend/src/views/custRating/company/GrayModelDialog.vue

@ -0,0 +1,33 @@
<template>
<w-dialog ref="dialogRef" :title="state.dialogTitle" width="80%" height="80%" body-padding="0px 0px 0px 0px" :maximized="true" :buttons="[]"> 1111 </w-dialog>
</template>
<script setup lang="ts">
import { reactive, ref } from '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 show = async (data: any) => {
dialogRef.value.show();
};
const hide = () => {
dialogRef.value.hide();
};
defineExpose({
show,
hide,
});
</script>

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

@ -0,0 +1,68 @@
<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 '@/views/custRating/company/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/components/AdjustItemIndex.vue

@ -0,0 +1,36 @@
<template>
<w-splitter :model-value="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 '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
</script>

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

@ -0,0 +1,38 @@
<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 '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
const creditReportGridRef = ref();
const getCreditReportGridRef = () => {
return creditReportGridRef.value;
};
rating.refs.setCreditReportGridRefFunction(getCreditReportGridRef);
</script>

42
irbs.frontend/src/views/custRating/company/components/CustBaseInfo.vue

@ -0,0 +1,42 @@
<template>
<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>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { Formater, axios, Environment } from 'platform-core';
import { Dictionary } from '@/views/custRating/company/ts/Dictionary';
const props = defineProps({
custId: { type: String, default: '' },
});
const custInfoData = ref({});
const dictionary = new Dictionary();
const loadCustInfo = () => {
axios.get(Environment.apiContextPath('api/irbs/ratingCompanyCustomer/' + props.custId)).then((resp) => {
if (resp && resp.data) {
custInfoData.value = resp.data;
}
});
};
onMounted(() => {
loadCustInfo();
});
await dictionary.load();
</script>

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

@ -0,0 +1,46 @@
<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 '@/views/custRating/company/ts/Constant';
import { Rating } from '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
</script>

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

@ -0,0 +1,45 @@
<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 '@/views/custRating/company/ts/Constant';
import { Rating } from '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
</script>

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

@ -0,0 +1,49 @@
<template>
<div v-if="!Tools.isEmpty(valueComputed)">{{ RatioFormat(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, RatioFormat } from '@/views/custRating/company/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) / 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>

89
irbs.frontend/src/views/custRating/company/components/FinanceProjectGrid.vue

@ -0,0 +1,89 @@
<template>
<w-grid
:dense-body="true"
:pageable="false"
:hide-bottom="true"
:auto-fetch-data="true"
:dense="true"
:stripe="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, Tools } from 'platform-core';
import { Rating } from '@/views/custRating/company/ts/Rating';
import FinanceProjectCompare from '@/views/custRating/company/components/FinanceProjectCompare.vue';
import { formatAmt } from '@/views/custRating/company/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: '科目名称',
title: (title_) => {
return title_;
},
format: (value: any, row: any) => {
if (value) {
if (!Tools.isNill(row.tab)) {
return "<span style='padding-left:" + row.tab * 20 + "px;'>" + value + '</span>';
}
}
return value;
},
},
];
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>

38
irbs.frontend/src/views/custRating/company/components/FinanceReportTabs.vue

@ -0,0 +1,38 @@
<template>
<div class="h-full">
<w-splitter :model-value="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 { FinanceReport } from '@/views/custRating/company/ts/FinanceReport';
import { Rating } from '@/views/custRating/company/ts/Rating';
import FinanceProjectGrid from '@/views/custRating/company/components/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/components/FirstRatingResult.vue

@ -0,0 +1,29 @@
<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 '@/views/custRating/company/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/components/HistRatingGrid.vue

@ -0,0 +1,51 @@
<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 '@/views/custRating/company/ts/Constant';
import { Rating } from '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
</script>

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

@ -0,0 +1,33 @@
<template>
<div class="h-full">
<w-splitter :model-value="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 '@/views/custRating/company/ts/HistGrid';
import HistRatingGrid from '@/views/custRating/company/components/HistRatingGrid.vue';
import DefaultCognizanceGrid from '@/views/custRating/company/components/DefaultCognizanceGrid.vue';
import DefaultRebirthGrid from '@/views/custRating/company/components/DefaultRebirthGrid.vue';
const tab = ref(HistGird.type.histRating.value);
</script>

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

@ -0,0 +1,44 @@
<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 '@/views/custRating/company/ts/Rating';
import { RatingProcessOperationStatus } from '@/views/custRating/company/ts/Utils';
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/components/Overturn.vue

@ -0,0 +1,77 @@
<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 '@/views/custRating/company/ts/Utils';
import { Rating } from '@/views/custRating/company/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>

11
irbs.frontend/src/views/custRating/company/components/QualAddtionView.vue

@ -0,0 +1,11 @@
<template>
<q-icon name="bookmark" size="xs" class="qav-icon" color="orange"></q-icon>
</template>
<style lang="css">
.qav-icon {
position: relative;
top: -7px;
right: -2px;
cursor: inherit;
}
</style>

162
irbs.frontend/src/views/custRating/company/components/QualAnalysis.vue

@ -0,0 +1,162 @@
<template>
<w-splitter :model-value="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="qaMode || allowHideOptions"
v-model="showOptionsModel"
color="blue"
dense
size="40px"
icon="hdr_auto"
label="显示全部选项"
@update:model-value="toggleUpdate"
/>
</div>
</template>
</w-card-panel>
</template>
<template #after>
<w-form 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, shallowRef } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import QualAddtionView from '@/views/custRating/company/components/QualAddtionView.vue';
const QualAddtionViewShallowRef = shallowRef(QualAddtionView);
const qualitativeFormRef = ref();
const rating = <Rating>inject('rating');
const titleSplitterModel = ref(34);
const getQualitativeFormRef = () => {
return qualitativeFormRef.value;
};
rating.refs.setQualitativeFormRefFunction(getQualitativeFormRef);
const props = defineProps({
//
readOnly: { type: Boolean, default: false },
//
qaMode: { type: Boolean, default: false },
// `qaMode``qaMode``qaMode`
allowHideOptions: { type: Boolean, default: true },
// `allowHideOptions`
defaultShowOptions: { type: Boolean, default: false },
});
const showOptionsModel = ref(props.defaultShowOptions);
const existsWaitSelectComputed = computed(() => {
return rating.waitSelectFields.value.length > 0 && !props.readOnly;
});
const qualFormFieldsComputed = computed(() => {
if (props.qaMode) {
let targetName = '';
if (rating.qualFormData.value && rating.waitSelectFields.value && rating.waitSelectFields.value[0]) {
targetName = rating.waitSelectFields.value[0]['field']['name'];
}
rating.qualFormData.value.forEach((item: any) => {
qaModeRecursiveHandle(item, targetName);
});
} else if (props.allowHideOptions) {
rating.qualFormData.value.forEach((item: any) => {
recursiveHandle(item);
});
}
if (props.readOnly) {
rating.qualFormData.value.forEach((item: any) => {
readOnlyRecursiveHandle(item);
});
}
return rating.qualFormData.value;
});
const qaModeRecursiveHandle = (obj: any, targetName: string) => {
if (obj.type === 'w-ext-radio') {
obj.lightNotHideOptionsLabel = true;
if (obj.name === targetName) {
obj.hideOptions = false;
} else {
obj.hideOptions = true;
}
return;
}
if (Array.isArray(obj.fields)) {
obj.fields.forEach((field) => qaModeRecursiveHandle(field, targetName));
}
};
const recursiveHandle = (obj: any) => {
if (obj.type === 'w-ext-radio') {
obj.hideOptions = true;
if (props.defaultShowOptions) {
if (qualitativeFormRef.value) {
const field = qualitativeFormRef.value.getFieldComponent(obj.name);
if (field) {
field.setExpandOptionsModelValue(true);
}
}
}
return;
}
if (Array.isArray(obj.fields)) {
obj.fields.forEach((field) => recursiveHandle(field));
}
};
const toggleUpdate = (value: boolean) => {
rating.qualFormData.value.forEach((item: any) => {
toggleRecursiveHandle(item, value);
});
};
const toggleRecursiveHandle = (obj: any, value: boolean) => {
if (obj.type === 'w-ext-radio') {
obj.hideOptions = true;
if (qualitativeFormRef.value) {
const field = qualitativeFormRef.value.getFieldComponent(obj.name);
if (field) {
field.setExpandOptionsModelValue(value);
}
}
return;
}
if (Array.isArray(obj.fields)) {
obj.fields.forEach((field) => toggleRecursiveHandle(field, value));
}
};
const readOnlyRecursiveHandle = (obj: any) => {
if (obj.type !== 'w-form-group') {
obj.readOnlyIf = true;
obj.hideOptions = true;
return;
}
if (Array.isArray(obj.fields)) {
obj.fields.forEach((field) => readOnlyRecursiveHandle(field));
}
};
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/components/QuanAnalysis.vue

@ -0,0 +1,51 @@
<template>
<w-splitter :model-value="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 '@/views/custRating/company/ts/Rating';
import { round } from '@/views/custRating/company/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>

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

@ -0,0 +1,61 @@
<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 '@/views/custRating/company/ts/Utils';
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>

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

@ -0,0 +1,36 @@
<template>
<div v-if="rating.systemParameter.reportShowScoreDtl.value" class="h-full">
<w-splitter :model-value="20" :separator-color="rating.separatorColor">
<template #before>
<QuanAnalysis></QuanAnalysis>
</template>
<template #after>
<w-splitter v-if="splitComputed" :model-value="75" class="h-full" :separator-color="rating.separatorColor">
<template #before>
<QualAnalysis :qa-mode="false" :read-only="true" :default-show-options="rating.cm.isApplyUserProcessStatus ? false : true"></QualAnalysis>
</template>
<template #after>
<AdjustItemIndex></AdjustItemIndex>
</template>
</w-splitter>
<QualAnalysis v-else :qa-mode="false" :read-only="true"></QualAnalysis>
</template>
</w-splitter>
</div>
</template>
<script setup lang="ts">
import { inject, computed } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import QuanAnalysis from '@/views/custRating/company/components/QuanAnalysis.vue';
import QualAnalysis from '@/views/custRating/company/components/QualAnalysis.vue';
import AdjustItemIndex from '@/views/custRating/company/components/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>

117
irbs.frontend/src/views/custRating/company/components/ReportRating.vue

@ -0,0 +1,117 @@
<template>
<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">{{ 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">{{ 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">{{ 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">{{ 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">{{ 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 '@/views/custRating/company/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>

29
irbs.frontend/src/views/custRating/company/components/StepTabs.vue

@ -0,0 +1,29 @@
<template>
<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"
v-bind="attrs"
@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>
</template>
<script setup lang="ts">
import { inject, useAttrs } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
const attrs = useAttrs();
const rating = <Rating>inject('rating');
</script>

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

@ -0,0 +1,82 @@
<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 '@/views/custRating/company/ts/Rating';
import { RatingProcessOperationStatus } from '@/views/custRating/company/ts/Utils';
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>

39
irbs.frontend/src/views/custRating/company/components/UpdateModel.vue

@ -0,0 +1,39 @@
<template>
<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>
<script setup lang="ts">
import { inject } from 'vue';
import { DialogManager } from 'platform-core';
import { Rating } from '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
const click = () => {
DialogManager.confirm('更改评分卡后流程会经总行进行审批,确认要更改评分卡吗', () => {});
};
</script>

309
irbs.frontend/src/views/custRating/company/components/buttons/AnnotationButton.vue

@ -0,0 +1,309 @@
<template>
<div>
<q-btn-dropdown
split
icon="mark_chat_unread"
color="primary"
label="批注"
class="ab-dropdown-button"
@click="
() => {
annotationInputShowModelValue = true;
}
"
>
<q-list style="max-width: 800px">
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>张三</q-item-label>
<q-item-label caption>企业自身状况选项存疑后续持续跟进</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-18 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item v-close-popup clickable @click="updateAnnotation">
<q-item-section avatar>
<q-avatar icon="person_pin" color="orange" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>admin</q-item-label>
<q-item-label caption>这是我自己加的批注</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item v-close-popup clickable @click="updateAnnotation">
<q-item-section avatar>
<q-avatar icon="person_pin" color="orange" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>admin</q-item-label>
<q-item-label caption>备注一下评级调整项可能需要更改</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-15 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption
>客户财报信 息部分指标取值不准确与客户最新披露的财报存在较大出
入客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入客户财报信息部分指标取值不准确</q-item-label
>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
<q-item>
<q-item-section avatar>
<q-avatar icon="assignment" color="secondary" text-color="white" />
</q-item-section>
<q-item-section>
<q-item-label>李四</q-item-label>
<q-item-label caption>客户财报信息部分指标取值不准确与客户最新披露的财报存在较大出入</q-item-label>
</q-item-section>
<q-item-section side> 2024-04-16 </q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
<q-popup-proxy v-model="annotationInputShowModelValue" no-parent-event>
<div style="height: 170px; width: 500px; padding: 10px; background-color: #fff7d1">
<w-form
:cols-num="1"
:fields="[
{
name: 'annotation',
label: '批注',
type: 'w-textarea',
rows: 5,
},
{
type: 'w-form-group',
align: 'left',
fields: [
{
type: 'q-btn',
label: '保存',
icon: 'save',
color: 'primary',
onClick: () => {
annotationInputShowModelValue = false;
},
},
],
},
]"
></w-form>
</div>
</q-popup-proxy>
<w-drawer ref="addAnnotationRef" title="批注">
<div class="p-2 h-full">
<w-splitter :model-value="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 '@/views/custRating/company/ts/Rating';
const rating = <Rating>inject('rating');
const annotationInputShowModelValue = ref(false);
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;
});
const updateAnnotation = () => {
annotationInputShowModelValue.value = true;
};
</script>

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

@ -0,0 +1,21 @@
<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 '@/views/custRating/company/ts/Rating';
import { Step } from '@/views/custRating/company/ts/Step';
import { Constant } from '@/views/custRating/company/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>

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

@ -0,0 +1,73 @@
<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 '@/views/custRating/company/ts/Rating';
import { Step } from '@/views/custRating/company/ts/Step';
import { Constant } from '@/views/custRating/company/ts/Constant';
import { round } from '@/views/custRating/company/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>

61
irbs.frontend/src/views/custRating/company/components/buttons/WorkflowButton.vue

@ -0,0 +1,61 @@
<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) => {
if (rating.cm.isAwaitSubmitProcessStatus.value && rating.step.currStep.value === Step.type.reportInfo.value) {
rating.opinionData.value = {
transientVariables: {
opaVal: action.transientVariables.goback,
desc: '客户名称:' + rating.ratingData.value['custName'],
},
data: {
adjReason: '申请审核',
},
};
callback(true);
} else {
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 '@/views/custRating/company/ts/Rating';
import { Step } from '@/views/custRating/company/ts/Step';
const rating = <Rating>inject('rating');
const showComputed = computed(() => {
if (rating.cm.isAwaitSubmitProcessStatus.value) {
return rating.step.currStep.value === Step.type.opinion.value || rating.step.currStep.value === Step.type.reportInfo.value;
} else if (rating.ratingData.value['taskId']) {
return true;
}
return false;
});
</script>

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

@ -0,0 +1,37 @@
<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 { PropType, computed } from 'vue';
import type { StepType } from '@/views/custRating/company/ts/type/StepType';
import { Step } from '@/views/custRating/company/ts/Step';
import CustInfo from './step/cust-info/CustInfo.vue';
import QuanQualAnalysis from './step/quan-qual-analysis/QuanQualAnalysis.vue';
import AdjustItem from './step/adjust-item/AdjustItem.vue';
import ReportInfo from './step/rating-report/ReportInfo.vue';
import Opinion from './step/opinion/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>

58
irbs.frontend/src/views/custRating/company/template/shrcb/Index.vue

@ -0,0 +1,58 @@
<template>
<w-splitter :model-value="46" horizontal disable reverse unit="px" style="height: 100%">
<template #before>
<Layout class="h-full"></Layout>
</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 } from 'vue';
import NextButton from '@/views/custRating/company/components/buttons/NextButton.vue';
import Layout from './Layout.vue';
import TestCalcButton from '@/views/custRating/company/components/buttons/TestCalcButton.vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import WorkflowButton from '@/views/custRating/company/components/buttons/WorkflowButton.vue';
import AnnotationButton from '@/views/custRating/company/components/buttons/AnnotationButton.vue';
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();
onMounted(() => {
rating.step.setCurrStep(rating.ratingData.value['currentStep']);
});
//
const instance = getCurrentInstance();
// API
VueTools.expose2Instance(instance);
//
rating.setInstance(instance);
provide('rating', rating);
</script>

40
irbs.frontend/src/views/custRating/company/template/shrcb/Layout.vue

@ -0,0 +1,40 @@
<template>
<w-splitter :model-value="75" class="h-full" unit="px" disable>
<template #before>
<div class="h-full" style="display: flex; align-items: center">
<StepTabs></StepTabs>
</div>
</template>
<template #after>
<!-- 切分窗口 -->
<w-splitter v-if="!rating.cm.isAwaitSubmitProcessStatus.value" :model-value="80" :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 } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import Content from './Content.vue';
import Opinion from './step/opinion/Opinion.vue';
import StepTabs from '@/views/custRating/company/components/StepTabs.vue';
const rating = <Rating>inject('rating');
</script>

18
irbs.frontend/src/views/custRating/company/template/shrcb/step/adjust-item/AdjustItem.vue

@ -0,0 +1,18 @@
<template>
<w-splitter :model-value="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 } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import AdjustItemGrid from '@/views/custRating/company/components/AdjustItemGrid.vue';
import FirstRatingResult from '@/views/custRating/company/components/FirstRatingResult.vue';
const rating = <Rating>inject('rating');
</script>

31
irbs.frontend/src/views/custRating/company/template/shrcb/step/cust-info/CustInfo.vue

@ -0,0 +1,31 @@
<template>
<w-splitter :model-value="48" unit="px" horizontal disable>
<template #before>
<UpdateModel></UpdateModel>
</template>
<template #after>
<w-splitter :model-value="80" :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 { inject, ref } from 'vue';
import { Rating } from '@/views/custRating/company/ts/Rating';
import CreditReportGrid from '@/views/custRating/company/components/CreditReportGrid.vue';
import FinanceReportTabs from '@/views/custRating/company/components/FinanceReportTabs.vue';
import UpdateModel from '@/views/custRating/company/components/UpdateModel.vue';
const rating = <Rating>inject('rating');
const custFormRef = ref();
const getCustFormRef = () => {
return custFormRef.value;
};
rating.refs.setCustFormRefFunction(getCustFormRef);
</script>

47
irbs.frontend/src/views/custRating/company/template/shrcb/step/opinion/Opinion.vue

@ -0,0 +1,47 @@
<template>
<div class="h-full pl-1">
<w-splitter
v-if="!rating.cm.isAwaitSubmitProcessStatus.value"
:model-value="rating.readMode ? 100 : 50"
horizontal
class="h-full"
disable
:show-separator="false"
>
<template #before>
<w-splitter :model-value="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 '@/views/custRating/company/ts/Rating';
import OpinionGrid from '@/views/custRating/company/components/OpinionGrid.vue';
import Overturn from '@/views/custRating/company/components/Overturn.vue';
import Timeline from '@/views/custRating/company/components/Timeline.vue';
const rating = <Rating>inject('rating');
const histTab = ref('timeline');
</script>

20
irbs.frontend/src/views/custRating/company/template/shrcb/step/quan-qual-analysis/QuanQualAnalysis.vue

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

34
irbs.frontend/src/views/custRating/company/template/shrcb/step/rating-report/ReportInfo.vue

@ -0,0 +1,34 @@
<template>
<div class="h-full">
<w-splitter :model-value="splitterSizeComputed" :limits="[0, Infinity]" horizontal unit="px" disable class="h-full">
<template #before>
<ReportRating></ReportRating>
</template>
<template #after>
<w-splitter :model-value="80" 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 '@/views/custRating/company/ts/Rating';
import HistTab from '@/views/custRating/company/components/HistTab.vue';
import ReportRating from '@/views/custRating/company/components/ReportRating.vue';
import ReportIndex from '@/views/custRating/company/components/ReportIndex.vue';
const rating = <Rating>inject('rating');
const splitterSizeComputed = computed(() => {
if (rating.showAllRatingInfoModel.value) {
return 125;
}
return 40;
});
</script>

79
irbs.frontend/src/views/custRating/company/ts/Addtion.ts

@ -0,0 +1,79 @@
import { Tools } from 'platform-core';
export class Addtion {
/**
*
*/
static componentMapping = {
INTEGER: {
key: 'INTEGER',
componentType: 'w-integer',
},
DECIMAL: {
key: 'DECIMAL',
componentType: 'w-number',
},
TEXT: {
key: 'TEXT',
componentType: 'w-text',
},
TEXTS: {
key: 'TEXTS',
componentType: 'w-textarea',
},
ATTACHMENT: {
key: 'ATTACHMENT',
componentType: 'w-file',
},
};
static expression(addtion: any, index: any, value: any) {
const condition = addtion.condition;
const replacedCondition = condition.replace(/\$\{(.*?)\}/g, (match, variable) => {
const values = {};
values[index.indexName] = value;
return values[variable] || match;
});
const result = eval(replacedCondition);
return result;
}
/**
*
* @param addtion
* @param index
*/
static getComponent(addtion: any, index: any) {
const component = {
type: this.componentMapping[addtion.componentType].componentType,
name: addtion.code,
label: addtion.name,
defaultValue: '1111111111',
hint: addtion.prompt,
};
if (!Tools.isEmpty(addtion.condition)) {
component['showIf'] = (args) => {
const value = args.form.getFieldValue(index.indexCode);
if (!Tools.isEmpty(value)) {
return Addtion.expression(addtion, index, value);
}
return false;
};
} else {
component['showIf'] = (args) => {
const field = args.form.getFields()[index.indexCode];
const value = args.form.getFieldValue(index.indexCode);
if (!Tools.isEmpty(value) || (Tools.hasOwnProperty(field, 'hideOptions') && !field.hideOptions)) {
return true;
}
return false;
};
}
switch (addtion.componentType) {
case this.componentMapping.TEXTS.key:
component['rows'] = addtion.rows;
break;
}
return component;
}
}

3
irbs.shrcb.poc.frontend/public/engine.svg

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="white" class="bi bi-browser-edge" viewBox="0 0 16 16">
<path d="M3.362 10.11c0 .926-.756 1.681-1.681 1.681S0 11.036 0 10.111.756 8.43 1.68 8.43h1.682zm.846 0c0-.924.756-1.68 1.681-1.68s1.681.756 1.681 1.68v4.21c0 .924-.756 1.68-1.68 1.68a1.685 1.685 0 0 1-1.682-1.68zM5.89 3.362c-.926 0-1.682-.756-1.682-1.681S4.964 0 5.89 0s1.68.756 1.68 1.68v1.682zm0 .846c.924 0 1.68.756 1.68 1.681S6.814 7.57 5.89 7.57H1.68C.757 7.57 0 6.814 0 5.89c0-.926.756-1.682 1.68-1.682zm6.749 1.682c0-.926.755-1.682 1.68-1.682S16 4.964 16 5.889s-.756 1.681-1.68 1.681h-1.681zm-.848 0c0 .924-.755 1.68-1.68 1.68A1.685 1.685 0 0 1 8.43 5.89V1.68C8.43.757 9.186 0 10.11 0c.926 0 1.681.756 1.681 1.68zm-1.681 6.748c.926 0 1.682.756 1.682 1.681S11.036 16 10.11 16s-1.681-.756-1.681-1.68v-1.682h1.68zm0-.847c-.924 0-1.68-.755-1.68-1.68s.756-1.681 1.68-1.681h4.21c.924 0 1.68.756 1.68 1.68 0 .926-.756 1.681-1.68 1.681z"/>
</svg>

After

Width:  |  Height:  |  Size: 970 B

83
irbs.shrcb.poc.frontend/public/webjars/tailwindcss/3.4.16/tailwind.css.js

File diff suppressed because one or more lines are too long

8
irbs.shrcb.poc.frontend/src/remote-components/remote-components.json

@ -0,0 +1,8 @@
[
/*
{
"component": "组件名称",
"componentPath": "组件 .vue 文件路径"
}
*/
]
Loading…
Cancel
Save