Merge fixes and improvements (#1910)

Co-authored-by: tristanliu <tristanliu@tencent.com>
This commit is contained in:
Jun Zhang
2024-11-16 13:57:54 +08:00
committed by GitHub
parent 5e22b412c6
commit ba1938f04b
40 changed files with 1382 additions and 2784 deletions

View File

@@ -30,11 +30,10 @@ public abstract class BaseSemanticCorrector implements SemanticCorrector {
public void correct(ChatQueryContext chatQueryContext, SemanticParseInfo semanticParseInfo) { public void correct(ChatQueryContext chatQueryContext, SemanticParseInfo semanticParseInfo) {
try { try {
String s2SQL = semanticParseInfo.getSqlInfo().getParsedS2SQL(); String s2SQL = semanticParseInfo.getSqlInfo().getCorrectedS2SQL();
if (Objects.isNull(s2SQL)) { if (Objects.isNull(s2SQL)) {
return; return;
} }
semanticParseInfo.getSqlInfo().setCorrectedS2SQL(s2SQL);
doCorrect(chatQueryContext, semanticParseInfo); doCorrect(chatQueryContext, semanticParseInfo);
log.debug("sqlCorrection:{} sql:{}", this.getClass().getSimpleName(), log.debug("sqlCorrection:{} sql:{}", this.getClass().getSimpleName(),
semanticParseInfo.getSqlInfo()); semanticParseInfo.getSqlInfo());

View File

@@ -6,8 +6,6 @@ import com.tencent.supersonic.headless.api.pojo.SemanticParseInfo;
import com.tencent.supersonic.headless.chat.ChatQueryContext; import com.tencent.supersonic.headless.chat.ChatQueryContext;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.util.Objects;
/** QueryTypeParser resolves query type as either AGGREGATE or DETAIL */ /** QueryTypeParser resolves query type as either AGGREGATE or DETAIL */
@Slf4j @Slf4j
public class QueryTypeParser implements SemanticParser { public class QueryTypeParser implements SemanticParser {
@@ -17,14 +15,12 @@ public class QueryTypeParser implements SemanticParser {
chatQueryContext.getCandidateQueries().forEach(query -> { chatQueryContext.getCandidateQueries().forEach(query -> {
SemanticParseInfo parseInfo = query.getParseInfo(); SemanticParseInfo parseInfo = query.getParseInfo();
String s2SQL = parseInfo.getSqlInfo().getParsedS2SQL(); String s2SQL = parseInfo.getSqlInfo().getParsedS2SQL();
if (Objects.isNull(s2SQL)) {
return;
}
QueryType queryType = QueryType.DETAIL; QueryType queryType = QueryType.DETAIL;
if (SqlSelectFunctionHelper.hasAggregateFunction(s2SQL)) { if (SqlSelectFunctionHelper.hasAggregateFunction(s2SQL)) {
queryType = QueryType.AGGREGATE; queryType = QueryType.AGGREGATE;
} }
parseInfo.setQueryType(queryType); parseInfo.setQueryType(queryType);
}); });
} }

View File

@@ -49,6 +49,7 @@ public class LLMResponseService {
parseInfo.setScore(queryCtx.getRequest().getQueryText().length() * (1 + weight)); parseInfo.setScore(queryCtx.getRequest().getQueryText().length() * (1 + weight));
parseInfo.setQueryMode(semanticQuery.getQueryMode()); parseInfo.setQueryMode(semanticQuery.getQueryMode());
parseInfo.getSqlInfo().setParsedS2SQL(s2SQL); parseInfo.getSqlInfo().setParsedS2SQL(s2SQL);
parseInfo.getSqlInfo().setCorrectedS2SQL(s2SQL);
queryCtx.getCandidateQueries().add(semanticQuery); queryCtx.getCandidateQueries().add(semanticQuery);
} }

View File

@@ -40,9 +40,7 @@ public class RuleSqlParser implements SemanticParser {
auxiliaryParsers.forEach(p -> p.parse(chatQueryContext)); auxiliaryParsers.forEach(p -> p.parse(chatQueryContext));
if (chatQueryContext.needSQL()) { candidateQueries.forEach(query -> query.buildS2Sql(
candidateQueries.forEach(query -> query.buildS2Sql( chatQueryContext.getDataSetSchema(query.getParseInfo().getDataSetId())));
chatQueryContext.getDataSetSchema(query.getParseInfo().getDataSetId())));
}
} }
} }

View File

@@ -1,6 +1,7 @@
package com.tencent.supersonic.headless.chat.query.llm.s2sql; package com.tencent.supersonic.headless.chat.query.llm.s2sql;
import com.tencent.supersonic.headless.api.pojo.DataSetSchema; import com.tencent.supersonic.headless.api.pojo.DataSetSchema;
import com.tencent.supersonic.headless.api.pojo.SqlInfo;
import com.tencent.supersonic.headless.chat.query.QueryManager; import com.tencent.supersonic.headless.chat.query.QueryManager;
import com.tencent.supersonic.headless.chat.query.llm.LLMSemanticQuery; import com.tencent.supersonic.headless.chat.query.llm.LLMSemanticQuery;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -22,5 +23,8 @@ public class LLMSqlQuery extends LLMSemanticQuery {
} }
@Override @Override
public void buildS2Sql(DataSetSchema dataSetSchema) {} public void buildS2Sql(DataSetSchema dataSetSchema) {
SqlInfo sqlInfo = parseInfo.getSqlInfo();
sqlInfo.setCorrectedS2SQL(sqlInfo.getParsedS2SQL());
}
} }

View File

@@ -60,6 +60,7 @@ public abstract class RuleSemanticQuery extends BaseSemanticQuery {
convertBizNameToName(dataSetSchema, queryStructReq); convertBizNameToName(dataSetSchema, queryStructReq);
QuerySqlReq querySQLReq = queryStructReq.convert(); QuerySqlReq querySQLReq = queryStructReq.convert();
parseInfo.getSqlInfo().setParsedS2SQL(querySQLReq.getSql()); parseInfo.getSqlInfo().setParsedS2SQL(querySQLReq.getSql());
parseInfo.getSqlInfo().setCorrectedS2SQL(querySQLReq.getSql());
} }
protected QueryStructReq convertQueryStruct() { protected QueryStructReq convertQueryStruct() {

View File

@@ -147,6 +147,12 @@ public class QueryReqBuilder {
return aggregateType.name(); return aggregateType.name();
} }
private static boolean isDateFieldAlreadyPresent(SemanticParseInfo parseInfo,
String dateField) {
return parseInfo.getDimensions().stream()
.anyMatch(dimension -> dimension.getBizName().equalsIgnoreCase(dateField));
}
public static Set<Order> getOrder(Set<Order> existingOrders, AggregateTypeEnum aggregator, public static Set<Order> getOrder(Set<Order> existingOrders, AggregateTypeEnum aggregator,
SchemaElement metric) { SchemaElement metric) {
if (existingOrders != null && !existingOrders.isEmpty()) { if (existingOrders != null && !existingOrders.isEmpty()) {

View File

@@ -56,13 +56,13 @@ public class S2CompanyDemo extends S2BaseDemo {
ModelResp model_company = addModel_1(domain, demoDatabase); ModelResp model_company = addModel_1(domain, demoDatabase);
ModelResp model_brand = addModel_2(domain, demoDatabase); ModelResp model_brand = addModel_2(domain, demoDatabase);
ModelResp model_company_revenue = addModel_3(domain, demoDatabase); ModelResp company_brand_revenue_proportion = addModel_3(domain, demoDatabase);
ModelResp model_brand_revenue = addModel_4(domain, demoDatabase); ModelResp model_brand_revenue = addModel_4(domain, demoDatabase);
addModelRela_1(domain, model_company_revenue, model_company); addModelRela(domain, company_brand_revenue_proportion, model_company, "company_id");
addModelRela_2(domain, model_brand, model_company); addModelRela(domain, company_brand_revenue_proportion, model_brand, "brand_id");
addModelRela_3(domain, model_brand_revenue, model_brand); addModelRela(domain, model_brand, model_company, "company_id");
addModelRela_4(domain, model_company_revenue, model_brand); addModelRela(domain, model_brand_revenue, model_brand, "brand_id");
DataSetResp dataset = addDataSet(domain); DataSetResp dataset = addDataSet(domain);
addAgent(dataset.getId()); addAgent(dataset.getId());
@@ -85,7 +85,7 @@ public class S2CompanyDemo extends S2BaseDemo {
public DomainResp addDomain() { public DomainResp addDomain() {
DomainReq domainReq = new DomainReq(); DomainReq domainReq = new DomainReq();
domainReq.setName("企业数据"); domainReq.setName("企业数据");
domainReq.setBizName("corporate"); domainReq.setBizName("corporate");
domainReq.setParentId(0L); domainReq.setParentId(0L);
domainReq.setViewers(Arrays.asList("admin", "tom", "jack")); domainReq.setViewers(Arrays.asList("admin", "tom", "jack"));
@@ -188,7 +188,7 @@ public class S2CompanyDemo extends S2BaseDemo {
public ModelResp addModel_3(DomainResp domain, DatabaseResp database) throws Exception { public ModelResp addModel_3(DomainResp domain, DatabaseResp database) throws Exception {
ModelReq modelReq = new ModelReq(); ModelReq modelReq = new ModelReq();
modelReq.setName("公司品牌收入占比"); modelReq.setName("公司品牌收入占比");
modelReq.setBizName("company_revenue"); modelReq.setBizName("company_brand_revenue_proportion");
modelReq.setDatabaseId(database.getId()); modelReq.setDatabaseId(database.getId());
modelReq.setDomainId(domain.getId()); modelReq.setDomainId(domain.getId());
modelReq.setViewers(Arrays.asList("admin", "tom", "jack")); modelReq.setViewers(Arrays.asList("admin", "tom", "jack"));
@@ -210,8 +210,7 @@ public class S2CompanyDemo extends S2BaseDemo {
modelDetail.setIdentifiers(identifiers); modelDetail.setIdentifiers(identifiers);
List<Measure> measures = new ArrayList<>(); List<Measure> measures = new ArrayList<>();
Measure measure = new Measure("营收占比", "revenue_proportion", AggOperatorEnum.MAX.name(), 1); measures.add(new Measure("营收占比", "revenue_proportion", AggOperatorEnum.MAX.name(), 1));
measures.add(measure);
measures.add(new Measure("利润占比", "profit_proportion", AggOperatorEnum.MAX.name(), 1)); measures.add(new Measure("利润占比", "profit_proportion", AggOperatorEnum.MAX.name(), 1));
measures.add(new Measure("支出占比", "expenditure_proportion", AggOperatorEnum.MAX.name(), 1)); measures.add(new Measure("支出占比", "expenditure_proportion", AggOperatorEnum.MAX.name(), 1));
modelDetail.setMeasures(measures); modelDetail.setMeasures(measures);
@@ -268,7 +267,7 @@ public class S2CompanyDemo extends S2BaseDemo {
dataSetReq.setName("企业数据集"); dataSetReq.setName("企业数据集");
dataSetReq.setBizName("CorporateData"); dataSetReq.setBizName("CorporateData");
dataSetReq.setDomainId(domain.getId()); dataSetReq.setDomainId(domain.getId());
dataSetReq.setDescription("互联网企业核心经营数据"); dataSetReq.setDescription("巨头公司核心经营数据");
dataSetReq.setAdmins(Lists.newArrayList("admin")); dataSetReq.setAdmins(Lists.newArrayList("admin"));
List<DataSetModelConfig> dataSetModelConfigs = getDataSetModelConfigs(domain.getId()); List<DataSetModelConfig> dataSetModelConfigs = getDataSetModelConfigs(domain.getId());
@@ -289,10 +288,10 @@ public class S2CompanyDemo extends S2BaseDemo {
return dataSetService.save(dataSetReq, defaultUser); return dataSetService.save(dataSetReq, defaultUser);
} }
public void addModelRela_1(DomainResp domain, ModelResp fromModel, ModelResp toModel) { public void addModelRela(DomainResp domain, ModelResp fromModel, ModelResp toModel,
String joinField) {
List<JoinCondition> joinConditions = Lists.newArrayList(); List<JoinCondition> joinConditions = Lists.newArrayList();
joinConditions joinConditions.add(new JoinCondition(joinField, joinField, FilterOperatorEnum.EQUALS));
.add(new JoinCondition("company_id", "company_id", FilterOperatorEnum.EQUALS));
ModelRela modelRelaReq = new ModelRela(); ModelRela modelRelaReq = new ModelRela();
modelRelaReq.setDomainId(domain.getId()); modelRelaReq.setDomainId(domain.getId());
modelRelaReq.setFromModelId(fromModel.getId()); modelRelaReq.setFromModelId(fromModel.getId());

View File

@@ -51,9 +51,7 @@ public class S2SingerDemo extends S2BaseDemo {
public void doRun() { public void doRun() {
try { try {
DomainResp singerDomain = addDomain(); DomainResp singerDomain = addDomain();
TagObjectResp singerTagObject = addTagObjectSinger(singerDomain); ModelResp singerModel = addModel(singerDomain, demoDatabase);
ModelResp singerModel = addModel(singerDomain, demoDatabase, singerTagObject);
addTags(singerModel);
long dataSetId = addDataSet(singerDomain, singerModel); long dataSetId = addDataSet(singerDomain, singerModel);
addAgent(dataSetId); addAgent(dataSetId);
} catch (Exception e) { } catch (Exception e) {
@@ -83,7 +81,7 @@ public class S2SingerDemo extends S2BaseDemo {
public DomainResp addDomain() { public DomainResp addDomain() {
DomainReq domainReq = new DomainReq(); DomainReq domainReq = new DomainReq();
domainReq.setName("歌手数据"); domainReq.setName("歌手数据");
domainReq.setBizName("singer"); domainReq.setBizName("singer");
domainReq.setParentId(0L); domainReq.setParentId(0L);
domainReq.setStatus(StatusEnum.ONLINE.getCode()); domainReq.setStatus(StatusEnum.ONLINE.getCode());
@@ -95,15 +93,13 @@ public class S2SingerDemo extends S2BaseDemo {
return domainService.createDomain(domainReq, defaultUser); return domainService.createDomain(domainReq, defaultUser);
} }
public ModelResp addModel(DomainResp singerDomain, DatabaseResp s2Database, public ModelResp addModel(DomainResp singerDomain, DatabaseResp s2Database) throws Exception {
TagObjectResp singerTagObject) throws Exception {
ModelReq modelReq = new ModelReq(); ModelReq modelReq = new ModelReq();
modelReq.setName("歌手库"); modelReq.setName("歌手库");
modelReq.setBizName("singer"); modelReq.setBizName("singer");
modelReq.setDescription("歌手库"); modelReq.setDescription("歌手库");
modelReq.setDatabaseId(s2Database.getId()); modelReq.setDatabaseId(s2Database.getId());
modelReq.setDomainId(singerDomain.getId()); modelReq.setDomainId(singerDomain.getId());
modelReq.setTagObjectId(singerTagObject.getId());
modelReq.setViewers(Arrays.asList("admin", "tom", "jack")); modelReq.setViewers(Arrays.asList("admin", "tom", "jack"));
modelReq.setViewOrgs(Collections.singletonList("1")); modelReq.setViewOrgs(Collections.singletonList("1"));
modelReq.setAdmins(Collections.singletonList("admin")); modelReq.setAdmins(Collections.singletonList("admin"));
@@ -128,7 +124,14 @@ public class S2SingerDemo extends S2BaseDemo {
modelDetail.setSqlQuery("select singer_name, act_area, song_name, genre, " modelDetail.setSqlQuery("select singer_name, act_area, song_name, genre, "
+ "js_play_cnt, down_cnt, favor_cnt from singer"); + "js_play_cnt, down_cnt, favor_cnt from singer");
modelReq.setModelDetail(modelDetail); modelReq.setModelDetail(modelDetail);
return modelService.createModel(modelReq, defaultUser); ModelResp modelResp = modelService.createModel(modelReq, defaultUser);
// create dict conf for dimensions
enableDimensionValue(getDimension("act_area", modelResp));
enableDimensionValue(getDimension("genre", modelResp));
enableDimensionValue(getDimension("singer_name", modelResp));
return modelResp;
} }
private void addTags(ModelResp model) { private void addTags(ModelResp model) {

View File

@@ -182,7 +182,7 @@ public class S2VisitsDemo extends S2BaseDemo {
public DomainResp addDomain() { public DomainResp addDomain() {
DomainReq domainReq = new DomainReq(); DomainReq domainReq = new DomainReq();
domainReq.setName("产品数据"); domainReq.setName("产品数据");
domainReq.setBizName("supersonic"); domainReq.setBizName("supersonic");
domainReq.setParentId(0L); domainReq.setParentId(0L);
domainReq.setStatus(StatusEnum.ONLINE.getCode()); domainReq.setStatus(StatusEnum.ONLINE.getCode());

View File

@@ -1044,11 +1044,11 @@ insert INTO artist(artist_name,citizenship,gender,g_name) VALUES ('Michel','英
-------S2CompanyDemo -------S2CompanyDemo
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','微软','西雅图','1975','盖茨','纳德拉',102300000000,40000); insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','微软','西雅图','1975','盖茨','纳德拉',102300000000,210000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','特斯拉','加州','2003','艾伯哈德','马斯克',376800000000,103699); insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','特斯拉','加州','2003','艾伯哈德','马斯克',376800000000,140473);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','谷歌','加州','1998','拉里佩奇','劈柴',321600000000,56310); insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','谷歌','加州','1998','拉里佩奇','劈柴',321600000000,182503);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','亚马逊','加州','1994','贝索斯','贝索斯',28800000000,179000); insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','亚马逊','加州','1994','贝索斯','贝索斯',28800000000,950000);
insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','英伟达','杭州','1993','黄仁勋','黄仁勋',67500000000,20000); insert into company(imp_date,company_id,company_name,headquarter_address,company_established_time,founder,ceo,annual_turnover,employee_count) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','英伟达','杭州','1993','黄仁勋','黄仁勋',67500000000,29000);
insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_131','Office','1990','item_enterprise_13_131','盖茨',50000000); insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_131','Office','1990','item_enterprise_13_131','盖茨',50000000);
insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_132','Windows','1991','item_enterprise_13_131','盖茨',50000000); insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id,legal_representative,registered_capital) VALUES (DATEADD('DAY', -1, CURRENT_DATE()),'item_brand_13_132','Windows','1991','item_enterprise_13_131','盖茨',50000000);
@@ -1063,24 +1063,22 @@ insert into brand(imp_date,brand_id,brand_name,brand_established_time,company_id
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_131',10,10,30); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_131',10,10,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_132',10,10,30); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_131','item_brand_13_132',10,10,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_133',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_133',30,30,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_134',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_132','item_brand_13_134',20,20,30);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_135',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_135',40,50,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_136',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_133','item_brand_13_136',20,30,40);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_137',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_137',10,30,50);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_138',80,80,60); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_134','item_brand_13_138',40,30,60);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_139',10,10,30); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_139',20,10,80);
insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_140',10,10,30); insert into company_revenue(imp_date,company_id,brand_id,revenue_proportion,profit_proportion,expenditure_proportion) VALUES ( DATEADD('DAY', -1, CURRENT_DATE()),'item_enterprise_13_135','item_brand_13_140',20,10,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_131',500000000, 300000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_132',600000000, 300000000,20,20);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_133',700000000, 300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_134',500000000, 300000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_135',600000000, 300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_136',700000000, 300000000,40,40);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_137',800000000, 300000000,50,50);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_138',400000000, 300000000,20,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_139',300000000, 300000000,60,70);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_140',900000000, 300000000,80,100);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_131',500000000, 13100000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_132',600000000, 13200000000,20,20);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_133',700000000, 13300000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_134',500000000, 13400000000,10,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_135',600000000, 13500000000,30,30);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_136',700000000, 13600000000,40,40);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_137',800000000, 13700000000,50,50);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_138',400000000, 13800000000,20,10);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_139',300000000, 13900000000,60,70);
insert into company_brand_revenue(imp_date,year_time,brand_id,revenue,profit,revenue_growth_year_on_year,profit_growth_year_on_year) VALUES (DATEADD('DAY', -1, CURRENT_DATE()), '2024','item_brand_13_140',900000000, 14000000000,80,100);

View File

@@ -21,7 +21,7 @@ s2:
date: true date: true
demo: demo:
names: S2VisitsDemo,S2SingerDemo,S2CompanyDemo,S2SmallTalkDemo, names: S2VisitsDemo,S2SingerDemo,S2CompanyDemo,S2SmallTalkDemo
enableLLM: true enableLLM: true
authentication: authentication:

View File

@@ -27,6 +27,11 @@ import static com.tencent.supersonic.common.pojo.enums.AggregateTypeEnum.SUM;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MetricTest extends BaseTest { public class MetricTest extends BaseTest {
@Test
public void testMetric() throws Exception {
QueryResult actualResult = submitNewChat("超音数 访问次数", DataUtils.metricAgentId);
}
@Test @Test
public void testMetricFilter() throws Exception { public void testMetricFilter() throws Exception {
QueryResult actualResult = submitNewChat("alice的访问次数", DataUtils.metricAgentId); QueryResult actualResult = submitNewChat("alice的访问次数", DataUtils.metricAgentId);

View File

@@ -1,10 +1,12 @@
import { Spin, Switch, Tooltip } from 'antd'; import { Space, Spin, Switch, Tooltip, message } from 'antd';
import { CheckCircleFilled, InfoCircleOutlined } from '@ant-design/icons'; import { CheckCircleFilled, InfoCircleOutlined } from '@ant-design/icons';
import { PREFIX_CLS, MsgContentTypeEnum } from '../../common/constants'; import { PREFIX_CLS, MsgContentTypeEnum } from '../../common/constants';
import { MsgDataType } from '../../common/type'; import { MsgDataType } from '../../common/type';
import ChatMsg from '../ChatMsg'; import ChatMsg from '../ChatMsg';
import WebPage from '../ChatMsg/WebPage'; import WebPage from '../ChatMsg/WebPage';
import Loading from './Loading'; import Loading from './Loading';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { solarizedlight } from 'react-syntax-highlighter/dist/esm/styles/prism';
import React, { ReactNode, useState } from 'react'; import React, { ReactNode, useState } from 'react';
type Props = { type Props = {
@@ -43,10 +45,10 @@ const ExecuteItem: React.FC<Props> = ({
const prefixCls = `${PREFIX_CLS}-item`; const prefixCls = `${PREFIX_CLS}-item`;
const [showMsgContentTable, setShowMsgContentTable] = useState<boolean>(false); const [showMsgContentTable, setShowMsgContentTable] = useState<boolean>(false);
const [msgContentType, setMsgContentType] = useState<MsgContentTypeEnum>(); const [msgContentType, setMsgContentType] = useState<MsgContentTypeEnum>();
const [showErrMsg, setShowErrMsg] = useState<boolean>(false);
const titlePrefix = queryMode === 'PLAIN_TEXT' || queryMode === 'WEB_SERVICE' ? '问答' : '数据'; const titlePrefix = queryMode === 'PLAIN_TEXT' || queryMode === 'WEB_SERVICE' ? '问答' : '数据';
const getNodeTip = (title: ReactNode, tip?: string) => { const getNodeTip = (title: ReactNode, tip?: string | ReactNode) => {
return ( return (
<> <>
<div className={`${prefixCls}-title-bar`}> <div className={`${prefixCls}-title-bar`}>
@@ -65,21 +67,38 @@ const ExecuteItem: React.FC<Props> = ({
return getNodeTip(`${titlePrefix}查询中`); return getNodeTip(`${titlePrefix}查询中`);
} }
const handleCopy = (_: string, result: any) => {
result ? message.success('复制SQL成功', 1) : message.error('复制SQL失败', 1);
};
if (executeTip) { if (executeTip) {
return getNodeTip( return getNodeTip(
<> <>
<span>{titlePrefix}</span> <span>{titlePrefix}</span>
{executeErrorMsg && ( {executeErrorMsg && (
<Tooltip title={executeErrorMsg}> <Space>
<InfoCircleOutlined style={{ marginLeft: 5, color: 'red' }} /> <InfoCircleOutlined style={{ marginLeft: 5, color: 'red' }} />
</Tooltip> <a
onClick={() => {
setShowErrMsg(!showErrMsg);
}}
>
{!showErrMsg ? '查看' : '收起'}
</a>
</Space>
)} )}
{!!data?.queryTimeCost && isDeveloper && ( {!!data?.queryTimeCost && isDeveloper && (
<span className={`${prefixCls}-title-tip`}>(: {data.queryTimeCost}ms)</span> <span className={`${prefixCls}-title-tip`}>(: {data.queryTimeCost}ms)</span>
)} )}
</>, </>,
executeTip
<>
{showErrMsg && (
<SyntaxHighlighter className={`${prefixCls}-code`} language="sql" style={solarizedlight}>
{executeErrorMsg}
</SyntaxHighlighter>
)}
</>
); );
} }

View File

@@ -443,7 +443,6 @@ const ChatItem: React.FC<Props> = ({
: ''} : ''}
</div> </div>
<div className={contentClass}> <div className={contentClass}>
{/* {!isSimpleMode && ( */}
<> <>
{currentAgent?.enableFeedback === 1 && !questionId && showExpandParseTip && ( {currentAgent?.enableFeedback === 1 && !questionId && showExpandParseTip && (
<div style={{ marginBottom: 10 }}> <div style={{ marginBottom: 10 }}>
@@ -489,7 +488,6 @@ const ChatItem: React.FC<Props> = ({
/> />
)} )}
</> </>
{/* )} */}
{executeMode && ( {executeMode && (
<Spin spinning={entitySwitchLoading}> <Spin spinning={entitySwitchLoading}>

View File

@@ -207,6 +207,15 @@
color: var(--text-color); color: var(--text-color);
} }
&-code {
margin-top: 10px !important;
padding: 6px 14px 8px !important;
border: 1px solid var(--border-color-base) !important;
border-radius: 4px !important;
background: #f5f8fb !important;
max-width: calc(100vw - 410px);
}
&-execute-title-bar { &-execute-title-bar {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -13,11 +13,12 @@ import moment from 'moment';
type Props = { type Props = {
data: MsgDataType; data: MsgDataType;
size?: SizeType; size?: SizeType;
question: string;
loading?: boolean; loading?: boolean;
onApplyAuth?: (model: string) => void; onApplyAuth?: (model: string) => void;
}; };
const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => { const Table: React.FC<Props> = ({ data, size, loading, question, onApplyAuth }) => {
const { entityInfo, queryColumns, queryResults } = data; const { entityInfo, queryColumns, queryResults } = data;
const prefixCls = `${CLS_PREFIX}-table`; const prefixCls = `${CLS_PREFIX}-table`;
@@ -27,6 +28,13 @@ const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => {
dataIndex: nameEn, dataIndex: nameEn,
key: nameEn, key: nameEn,
title: name || nameEn, title: name || nameEn,
defaultSortOrder: 'descend',
sorter:
showType === 'NUMBER'
? (a, b) => {
return a[nameEn] - b[nameEn];
}
: undefined,
render: (value: string | number) => { render: (value: string | number) => {
if (!authorized) { if (!authorized) {
return ( return (
@@ -76,9 +84,11 @@ const Table: React.FC<Props> = ({ data, size, loading, onApplyAuth }) => {
const dataSource = dateColumn const dataSource = dateColumn
? queryResults.sort((a, b) => moment(a[dateColumn.nameEn]).diff(moment(b[dateColumn.nameEn]))) ? queryResults.sort((a, b) => moment(a[dateColumn.nameEn]).diff(moment(b[dateColumn.nameEn])))
: queryResults; : queryResults;
return ( return (
<div className={prefixCls}> <div className={prefixCls}>
<div className={`${prefixCls}-top-bar`}>
<div className={`${prefixCls}-indicator-name`}>{question}</div>
</div>
<AntTable <AntTable
pagination={ pagination={
queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] } queryResults.length <= 10 ? false : { defaultPageSize: 10, position: ['bottomCenter'] }

View File

@@ -26,6 +26,22 @@
color: var(--text-color-third); color: var(--text-color-third);
} }
&-top-bar {
display: flex;
align-items: baseline;
flex-wrap: wrap;
column-gap: 8px;
row-gap: 12px;
font-style: italic;
margin-bottom: 15px;
}
&-indicator-name {
font-size: 14px;
color: var(--text-color);
font-weight: 500;
margin-top: 2px;
}
&-filter-item { &-filter-item {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@@ -180,6 +180,7 @@ const ChatMsg: React.FC<Props> = ({
case MsgContentTypeEnum.TABLE: case MsgContentTypeEnum.TABLE:
return ( return (
<Table <Table
question={question}
data={{ ...data, queryColumns: columns, queryResults: dataSource }} data={{ ...data, queryColumns: columns, queryResults: dataSource }}
loading={loading} loading={loading}
/> />
@@ -221,6 +222,7 @@ const ChatMsg: React.FC<Props> = ({
default: default:
return ( return (
<Table <Table
question={question}
data={{ ...data, queryColumns: columns, queryResults: dataSource }} data={{ ...data, queryColumns: columns, queryResults: dataSource }}
loading={loading} loading={loading}
/> />

View File

@@ -18,6 +18,7 @@ export default defineConfig({
API_BASE_URL: '/api/semantic/', // 直接在define中挂载裸露的全局变量还需要配置eslintts相关配置才能导致在使用中不会飘红冗余较高这里挂在进程环境下 API_BASE_URL: '/api/semantic/', // 直接在define中挂载裸露的全局变量还需要配置eslintts相关配置才能导致在使用中不会飘红冗余较高这里挂在进程环境下
CHAT_API_BASE_URL: '/api/chat/', CHAT_API_BASE_URL: '/api/chat/',
AUTH_API_BASE_URL: '/api/auth/', AUTH_API_BASE_URL: '/api/auth/',
SHOW_TAG: false,
...ENV_CONFIG, ...ENV_CONFIG,
}, },
}, },

View File

@@ -115,12 +115,12 @@ const ROUTES = [
}, },
], ],
}, },
{ {
path: '/tag', path: '/tag',
name: 'tag', name: 'tag',
component: './SemanticModel/Insights', component: './SemanticModel/Insights',
envEnableList: [ENV_KEY.SEMANTIC], envEnableList: [ENV_KEY.SEMANTIC],
hideInMenu: process.env.SHOW_TAG ? false : true,
routes: [ routes: [
{ {
path: '/tag', path: '/tag',

View File

@@ -69,7 +69,7 @@
"@umijs/route-utils": "2.2.2", "@umijs/route-utils": "2.2.2",
"ace-builds": "^1.4.12", "ace-builds": "^1.4.12",
"ahooks": "^3.7.7", "ahooks": "^3.7.7",
"antd": "5.11.2", "antd": "^5.17.4",
"classnames": "^2.2.6", "classnames": "^2.2.6",
"compression-webpack-plugin": "^11.0.0", "compression-webpack-plugin": "^11.0.0",
"copy-to-clipboard": "^3.3.1", "copy-to-clipboard": "^3.3.1",

View File

@@ -38,6 +38,7 @@ const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
exportTagButton: { exportTagButton: {
key: 'exportTagButton', key: 'exportTagButton',
label: '导出为标签', label: '导出为标签',
hidden: !!!process.env.SHOW_TAG,
icon: <ExportOutlined />, icon: <ExportOutlined />,
disabled: disabledList?.includes('exportTagButton'), disabled: disabledList?.includes('exportTagButton'),
}, },
@@ -142,9 +143,11 @@ const BatchCtrlDropDownButton: FC<BatchCtrlDropDownButtonProps> = ({
icon: <DeleteOutlined />, icon: <DeleteOutlined />,
disabled: disabledList?.includes('batchDelete'), disabled: disabledList?.includes('batchDelete'),
}, },
].filter((item) => { ]
return !hiddenList.includes(item.key); .filter((item) => {
}); return !hiddenList.includes(item.key);
})
.filter((item) => !!!item.hidden);
const popoverConfig = { const popoverConfig = {
title: '选择下载区间', title: '选择下载区间',

View File

@@ -217,7 +217,11 @@ const MemorySection = ({ agentId }: Props) => {
}; };
const loadMemoryList = async ( const loadMemoryList = async (
{ filtersValue, current }: { filtersValue?: any; current?: number } = {}, {
filtersValue,
current,
pageSize,
}: { filtersValue?: any; current?: number; pageSize?: number } = {},
sort?: any, sort?: any,
) => { ) => {
if (!agentId) { if (!agentId) {
@@ -249,10 +253,11 @@ const MemorySection = ({ agentId }: Props) => {
agentId, agentId,
chatMemoryFilter: filtersValue || filters, chatMemoryFilter: filtersValue || filters,
current: current || 1, current: current || 1,
pageSize,
...sortParams, ...sortParams,
}); });
setLoading(false); setLoading(false);
const { list, total, pageSize, pageNum } = res.data; const { list, total, pageNum } = res.data;
setDataSource(list); setDataSource(list);
setPagination({ setPagination({
pageSize, pageSize,

View File

@@ -35,15 +35,20 @@ export function getMetricList(modelId: number) {
}); });
} }
export function getMemeoryList(data: { agentId: number; chatMemoryFilter: any; current: number }) { export function getMemeoryList(data: {
const { agentId, chatMemoryFilter, current } = data; agentId: number;
chatMemoryFilter: any;
current: number;
pageSize: number;
}) {
const { agentId, chatMemoryFilter, current, pageSize } = data;
return request<Result<{ list: MetricType[] }>>('/api/chat/memory/pageMemories', { return request<Result<{ list: MetricType[] }>>('/api/chat/memory/pageMemories', {
method: 'POST', method: 'POST',
data: { data: {
...data, ...data,
chatMemoryFilter: { agentId, ...chatMemoryFilter }, chatMemoryFilter: { agentId, ...chatMemoryFilter },
current, current,
pageSize: 10, pageSize: pageSize || 10,
sort: 'desc', sort: 'desc',
// orderCondition: 'updatedAt', // orderCondition: 'updatedAt',
}, },

View File

@@ -190,14 +190,14 @@ const ModelBasicForm: React.FC<Props> = ({
<FormItem name="description" label="模型描述"> <FormItem name="description" label="模型描述">
<TextArea placeholder="请输入模型描述" /> <TextArea placeholder="请输入模型描述" />
</FormItem> </FormItem>
<FormItem name={['ext', 'usId']} label="调度任务ID"> {/* <FormItem name={['ext', 'usId']} label="调度任务ID">
<Select <Select
mode="tags" mode="tags"
placeholder="输入ID后回车确认多ID输入、复制粘贴支持英文逗号自动分隔" placeholder="输入ID后回车确认多ID输入、复制粘贴支持英文逗号自动分隔"
tokenSeparators={[',']} tokenSeparators={[',']}
maxTagCount={9} maxTagCount={9}
/> />
</FormItem> </FormItem> */}
</Spin> </Spin>
); );
}; };

View File

@@ -229,7 +229,9 @@ const ModelFieldForm: React.FC<Props> = ({
); );
} }
if (type === EnumDataSourceType.MEASURES) { if (type === EnumDataSourceType.MEASURES) {
const agg = fields.find((field) => field.expr === record.expr)?.agg; const agg = record.expr
? fields.find((field) => field.expr === record.expr)?.agg
: undefined;
return ( return (
<Select <Select
placeholder="度量算子" placeholder="度量算子"
@@ -249,26 +251,52 @@ const ModelFieldForm: React.FC<Props> = ({
</Select> </Select>
); );
} }
if (type === EnumDataSourceType.CATEGORICAL) {
const isTag = fields.find((field) => field.bizName === record.bizName)?.isTag; if (process.env.SHOW_TAG) {
return ( if (type === EnumDataSourceType.CATEGORICAL) {
<Space> const isTag = fields.find((field) => field.bizName === record.bizName)?.isTag;
return (
<Space> <Space>
<span>:</span> <Space>
<Switch <span>:</span>
defaultChecked <Switch
size="small" defaultChecked
checked={!!isTag} size="small"
onChange={(value) => { checked={!!isTag}
handleFieldChange(record, 'isTag', value); onChange={(value) => {
}} handleFieldChange(record, 'isTag', value);
/> }}
<Tooltip title="如果勾选,代表维度的取值都是一种“标签”,可用作对实体的圈选"> />
<ExclamationCircleOutlined /> <Tooltip title="如果勾选,代表维度的取值都是一种“标签”,可用作对实体的圈选">
</Tooltip> <ExclamationCircleOutlined />
</Tooltip>
</Space>
</Space> </Space>
</Space> );
); }
}
if (process.env.SHOW_TAG) {
if (type === EnumDataSourceType.CATEGORICAL) {
const isTag = fields.find((field) => field.bizName === record.bizName)?.isTag;
return (
<Space>
<Space>
<span>:</span>
<Switch
defaultChecked
size="small"
checked={!!isTag}
onChange={(value) => {
handleFieldChange(record, 'isTag', value);
}}
/>
<Tooltip title="如果勾选,代表维度的取值都是一种“标签”,可用作对实体的圈选">
<ExclamationCircleOutlined />
</Tooltip>
</Space>
</Space>
);
}
} }
if ([EnumDataSourceType.TIME, EnumDataSourceType.PARTITION_TIME].includes(type)) { if ([EnumDataSourceType.TIME, EnumDataSourceType.PARTITION_TIME].includes(type)) {
const dateFormat = fields.find((field) => field.bizName === record.bizName)?.dateFormat; const dateFormat = fields.find((field) => field.bizName === record.bizName)?.dateFormat;

View File

@@ -33,14 +33,14 @@ export const modelDataClass = {
}; };
export const DIM_OPTIONS = [ export const DIM_OPTIONS = [
{ // {
label: '主键', // label: '主键',
value: EnumDataSourceType.PRIMARY_KEY, // value: EnumDataSourceType.PRIMARY_KEY,
}, // },
{ // {
label: '外键', // label: '外键',
value: EnumDataSourceType.FOREIGN_KEY, // value: EnumDataSourceType.FOREIGN_KEY,
}, // },
{ {
label: '枚举', label: '枚举',
value: EnumDataSourceType.CATEGORICAL, value: EnumDataSourceType.CATEGORICAL,

View File

@@ -78,6 +78,9 @@ const TagInfoCreateForm: React.FC<CreateFormProps> = ({
const backward = () => setCurrentStep(currentStep - 1); const backward = () => setCurrentStep(currentStep - 1);
const queryModelDetail = async (modelId) => { const queryModelDetail = async (modelId) => {
if (!modelId) {
return;
}
const { code, data } = await getModelDetail({ modelId }); const { code, data } = await getModelDetail({ modelId });
if (code === 200) { if (code === 200) {
if (Array.isArray(data?.modelDetail?.fields)) { if (Array.isArray(data?.modelDetail?.fields)) {

View File

@@ -728,6 +728,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
<FormItem <FormItem
name="isTag" name="isTag"
valuePropName="checked" valuePropName="checked"
hidden={!!!process.env.SHOW_TAG}
getValueFromEvent={(value) => { getValueFromEvent={(value) => {
return value === true ? 1 : 0; return value === true ? 1 : 0;
}} }}
@@ -749,8 +750,9 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
<Switch /> <Switch />
</Col> </Col>
</Row> </Row>
<Divider />
</FormItem> </FormItem>
<Divider />
<FormItem> <FormItem>
<Row gutter={20}> <Row gutter={20}>
<Col flex="1 1 200px"> <Col flex="1 1 200px">

View File

@@ -48,6 +48,9 @@ const ModelRelationFormDrawer: React.FC<ModelRelationFormDrawerProps> = ({
}, [relationData]); }, [relationData]);
const queryModelDetail = async (modelId: number, isSource: boolean) => { const queryModelDetail = async (modelId: number, isSource: boolean) => {
if (!modelId) {
return;
}
const { code, data } = await getModelDetail({ modelId }); const { code, data } = await getModelDetail({ modelId });
if (code === 200) { if (code === 200) {
if (Array.isArray(data?.modelDetail?.identifiers)) { if (Array.isArray(data?.modelDetail?.identifiers)) {

View File

@@ -172,6 +172,7 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
dataIndex: 'isTag', dataIndex: 'isTag',
title: '是否标签', title: '是否标签',
// width: 90, // width: 90,
hideInTable: !!!process.env.SHOW_TAG,
render: (isTag) => { render: (isTag) => {
switch (isTag) { switch (isTag) {
case 0: case 0:
@@ -324,66 +325,69 @@ const ClassDimensionTable: React.FC<Props> = ({}) => {
headerTitle={ headerTitle={
<div style={{ marginLeft: 15 }}> <div style={{ marginLeft: 15 }}>
<TableHeaderFilter <TableHeaderFilter
components={[ components={
{ [
label: '维度搜索', {
component: ( label: '维度搜索',
<Input.Search component: (
style={{ width: 280 }} <Input.Search
placeholder="请输入ID/维度名称/英文名称" style={{ width: 280 }}
onSearch={(value) => { placeholder="请输入ID/维度名称/英文名称"
setFilterParams((preState) => { onSearch={(value) => {
return { setFilterParams((preState) => {
...preState, return {
key: value, ...preState,
}; key: value,
}); };
}} });
/> }}
), />
}, ),
{ },
label: '敏感度', {
component: ( label: '敏感度',
<Select component: (
style={{ width: 140 }} <Select
options={SENSITIVE_LEVEL_OPTIONS} style={{ width: 140 }}
placeholder="请选择敏感度" options={SENSITIVE_LEVEL_OPTIONS}
allowClear placeholder="请选择敏感度"
onChange={(value) => { allowClear
setFilterParams((preState) => { onChange={(value) => {
return { setFilterParams((preState) => {
...preState, return {
sensitiveLevel: value, ...preState,
}; sensitiveLevel: value,
}); };
}} });
/> }}
), />
}, ),
{ },
label: '是否为标签', {
component: ( label: '是否为标签',
<Select hidden: !!!process.env.SHOW_TAG,
style={{ width: 145 }} component: (
placeholder="请选择标签状态" <Select
allowClear style={{ width: 145 }}
onChange={(value) => { placeholder="请选择标签状态"
setFilterParams((preState) => { allowClear
return { onChange={(value) => {
...preState, setFilterParams((preState) => {
isTag: value, return {
}; ...preState,
}); isTag: value,
}} };
options={[ });
{ value: 1, label: '是' }, }}
{ value: 0, label: '否' }, options={[
]} { value: 1, label: '是' },
/> { value: 0, label: '否' },
), ]}
}, />
]} ),
},
].filter((item) => !!!item.hidden) as any
}
/> />
</div> </div>
} }

View File

@@ -177,7 +177,7 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
{ {
dataIndex: 'isTag', dataIndex: 'isTag',
title: '是否标签', title: '是否标签',
// width: 90, hideInTable: !!!process.env.SHOW_TAG,
render: (isTag) => { render: (isTag) => {
switch (isTag) { switch (isTag) {
case 0: case 0:
@@ -353,66 +353,69 @@ const ClassMetricTable: React.FC<Props> = ({ onEmptyMetricData }) => {
headerTitle={ headerTitle={
<div style={{ marginLeft: 15 }}> <div style={{ marginLeft: 15 }}>
<TableHeaderFilter <TableHeaderFilter
components={[ components={
{ [
label: '指标搜索', {
component: ( label: '指标搜索',
<Input.Search component: (
style={{ width: 280 }} <Input.Search
placeholder="请输入ID/指标名称/英文名称/标签" style={{ width: 280 }}
onSearch={(value) => { placeholder="请输入ID/指标名称/英文名称"
setFilterParams((preState) => { onSearch={(value) => {
return { setFilterParams((preState) => {
...preState, return {
key: value, ...preState,
}; key: value,
}); };
}} });
/> }}
), />
}, ),
{ },
label: '敏感度', {
component: ( label: '敏感度',
<Select component: (
style={{ width: 140 }} <Select
options={SENSITIVE_LEVEL_OPTIONS} style={{ width: 140 }}
placeholder="请选择敏感度" options={SENSITIVE_LEVEL_OPTIONS}
allowClear placeholder="请选择敏感度"
onChange={(value) => { allowClear
setFilterParams((preState) => { onChange={(value) => {
return { setFilterParams((preState) => {
...preState, return {
sensitiveLevel: value, ...preState,
}; sensitiveLevel: value,
}); };
}} });
/> }}
), />
}, ),
{ },
label: '是否为标签', {
component: ( label: '是否为标签',
<Select hidden: !!!process.env.SHOW_TAG,
style={{ width: 145 }} component: (
placeholder="请选择标签状态" <Select
allowClear style={{ width: 145 }}
onChange={(value) => { placeholder="请选择标签状态"
setFilterParams((preState) => { allowClear
return { onChange={(value) => {
...preState, setFilterParams((preState) => {
isTag: value, return {
}; ...preState,
}); isTag: value,
}} };
options={[ });
{ value: 1, label: '是' }, }}
{ value: 0, label: '否' }, options={[
]} { value: 1, label: '是' },
/> { value: 0, label: '否' },
), ]}
}, />
]} ),
},
].filter((item) => !!!item.hidden) as any
}
/> />
</div> </div>
} }

View File

@@ -305,6 +305,7 @@ const DimensionInfoModal: React.FC<CreateFormProps> = ({
<InfoTagList /> <InfoTagList />
</FormItem> */} </FormItem> */}
<Form.Item <Form.Item
hidden={!!!process.env.SHOW_TAG}
label={ label={
<FormItemTitle <FormItemTitle
title={`设为标签`} title={`设为标签`}

View File

@@ -73,7 +73,7 @@ const DomainManagerTab: React.FC<Props> = ({
{ {
label: '标签对象管理', label: '标签对象管理',
key: 'tagObjectManage', key: 'tagObjectManage',
hidden: !!domainData?.parentId, hidden: !!!process.env.SHOW_TAG ? true : !!domainData?.parentId,
children: <TagObjectTable />, children: <TagObjectTable />,
}, },
{ {

View File

@@ -53,7 +53,7 @@ const DimensionMetricVisibleTableTransfer: React.FC<Props> = ({
{ {
dataIndex: 'isTag', dataIndex: 'isTag',
title: '是否标签', title: '是否标签',
// hidden: true, hidden: true,
render: (isTag) => { render: (isTag) => {
if (isTag) { if (isTag) {
return <span style={{ color: '#0958d9' }}></span>; return <span style={{ color: '#0958d9' }}></span>;

View File

@@ -213,7 +213,7 @@ const DimensionValueSettingForm: React.FC<Props> = ({
> >
{dimensionVisible && ( {dimensionVisible && (
<Space size={20} style={{ marginBottom: 20 }}> <Space size={20} style={{ marginBottom: 20 }}>
<Tooltip title={`立即将${KnowledgeConfigTypeWordingMap[type]}值导入字典`}> <Tooltip title={`维度值可见后将定期启动导入任务,如果想立即启动可手动触发`}>
<Button <Button
type="link" type="link"
size="small" size="small"

View File

@@ -713,6 +713,7 @@ const MetricInfoCreateForm: React.FC<CreateFormProps> = ({
</FormItem> </FormItem>
<Form.Item <Form.Item
hidden={!!!process.env.SHOW_TAG}
label={ label={
<FormItemTitle <FormItemTitle
title={`设为标签`} title={`设为标签`}

View File

@@ -452,6 +452,9 @@ export function getUnAvailableItem(data: any): Promise<any> {
} }
export function getModelDetail(data: any): Promise<any> { export function getModelDetail(data: any): Promise<any> {
if (!data.modelId) {
return;
}
return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`); return request.get(`${process.env.API_BASE_URL}model/getModel/${data.modelId}`);
} }

3568
webapp/pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff