Add Cloud Tour Libo knowledge graph platform

This commit is contained in:
xuelong committed 2026-07-30 10:09:16 +08:00
1 parent 9e05b09a38
commit bae5197d62
103 files changed
+14036 -160

No files matched your search

+50 -6
View File
@@ -9,11 +9,11 @@ import * as echarts from "echarts";
import api, { displayGraphName, getProjectContext } from "../../api";
const CATEGORY_COLORS: Record<string, string> = {
Place: "#00D4AA", Area: "#5B8FF9", Station: "#F6BD16",
Place: "#00D4AA", Area: "#5B8FF9", GeoCell: "#5B8FF9", 片区: "#5B8FF9", Station: "#F6BD16",
BusStop: "#F6BD16", MetroStation: "#1677FF", TransitStop: "#F6BD16",
BusLine: "#9270CA",
地点: "#00D4AA", 景点: "#00D4AA", 美食: "#FF9D4D", 酒店: "#6DC8EC",
商场: "#F6BD16", 公交站: "#F6BD16", 地铁站: "#1677FF", 交通站点: "#F6BD16",
地点: "#00D4AA", 景点: "#1677FF", 景区: "#1677FF", 美食: "#FF5A1F", 酒店: "#722ED1",
交通设施: "#13A8A8", 商场: "#F6BD16", 公交站: "#F6BD16", 地铁站: "#1677FF", 交通站点: "#F6BD16",
RouteTemplate: "#E8684A", ExperienceTag: "#6DC8EC",
Source: "#9270CA", Evidence: "#FF99C3",
TourProduct: "#4C6FFF", ProductDay: "#6DC8EC", RouteStop: "#F6BD16",
@@ -207,6 +207,15 @@ const FULL_GRAPH_LIMIT = 2500;
const FULL_GRAPH_BATCH_SIZE = 1000;
const FULL_GRAPH_BASE_CYPHER = "MATCH (n)-[r]->(m) RETURN n,r,m";
const GENERIC_DEFAULT_CYPHER = `${FULL_GRAPH_BASE_CYPHER} LIMIT ${FULL_GRAPH_LIMIT}`;
const LIBO_DEFAULT_CYPHER = [
"MATCH (n:Hotel)-[r:IN_H3_R9]->(cell:GeoCell)-[areaRel:LOCATED_IN]->(area:Area) RETURN n,r,cell,areaRel,area,null AS parentRel,null AS parent LIMIT 100",
"UNION",
"MATCH (n:FoodPlace)-[r:IN_H3_R9]->(cell:GeoCell)-[areaRel:LOCATED_IN]->(area:Area) RETURN n,r,cell,areaRel,area,null AS parentRel,null AS parent LIMIT 100",
"UNION",
"MATCH (n:TransitFacility)-[r:IN_H3_R9]->(cell:GeoCell)-[areaRel:LOCATED_IN]->(area:Area) RETURN n,r,cell,areaRel,area,null AS parentRel,null AS parent LIMIT 60",
"UNION",
"MATCH (n:ScenicSpot)-[parentRel:PART_OF_SCENIC_AREA]->(parent) MATCH (n)-[r:IN_H3_R9]->(cell:GeoCell)-[areaRel:LOCATED_IN]->(area:Area) RETURN n,r,cell,areaRel,area,parentRel,parent LIMIT 50",
].join(" ");
const TRAVEL_CORE_CYPHER = [
"MATCH (p:TourProduct)-[lineStop:PRODUCT_HAS_ORDERED_STOP]->(s:RouteStop)",
"OPTIONAL MATCH (s)-[next:ROUTE_STOP_NEXT]->(s2:RouteStop)",
@@ -342,8 +351,19 @@ function isAnyTravelGraphName(value?: any): boolean {
return name.includes("travel") || name.includes("旅行社") || name.includes("旅游");
}
function isYunyouLiboGraphName(value?: any): boolean {
const name = String(value || "").toLowerCase();
return name.includes("yunyou_libo") || name.includes("云游荔波");
}
function defaultCypherForGraph(value?: any): string {
return isTravelItemGraphName(value) ? TRAVEL_ITEM_CORE_CYPHER : (isAnyTravelGraphName(value) ? TRAVEL_DEFAULT_CYPHER : GENERIC_DEFAULT_CYPHER);
return isYunyouLiboGraphName(value)
? LIBO_DEFAULT_CYPHER
: isTravelItemGraphName(value)
? TRAVEL_ITEM_CORE_CYPHER
: isAnyTravelGraphName(value)
? TRAVEL_DEFAULT_CYPHER
: GENERIC_DEFAULT_CYPHER;
}
function modeLabel(mode?: string): string {
@@ -1355,7 +1375,25 @@ export default function GraphCanvas() {
const currentGraphName = overview.graph_name || getProjectContext().graphName;
const isTravelGraph = isAnyTravelGraphName(currentGraphName);
const isTravelItemGraph = isTravelItemGraphName(currentGraphName);
const queryTemplates = isTravelItemGraph ? [
const isYunyouLiboGraph = isYunyouLiboGraphName(currentGraphName);
const queryTemplates = isYunyouLiboGraph ? [
{ label: "四类业务全景", cypher: LIBO_DEFAULT_CYPHER },
{ label: "全部关系抽样", cypher: GENERIC_DEFAULT_CYPHER },
{ label: "酒店", cypher: "MATCH (n:Hotel) RETURN n LIMIT 150" },
{ label: "美食", cypher: "MATCH (n:FoodPlace) RETURN n LIMIT 150" },
{ label: "交通设施", cypher: "MATCH (n:TransitFacility) RETURN n LIMIT 150" },
{ label: "景点", cypher: "MATCH (n:ScenicSpot) RETURN n LIMIT 120" },
{ label: "景区", cypher: "MATCH (n:ScenicArea) RETURN n LIMIT 20" },
{ label: "公交线路停靠", cypher: "MATCH (line:BusRoute)-[r:STOPS_AT]->(stop:BusStop) RETURN line,r,stop LIMIT 350" },
{ label: "公交相邻站", cypher: "MATCH (a:BusStop)-[r:NEXT_STOP]->(b:BusStop) RETURN a,r,b LIMIT 320" },
{ label: "景点归属", cypher: "MATCH (spot:ScenicSpot)-[r:PART_OF_SCENIC_AREA]->(parent) RETURN spot,r,parent LIMIT 120" },
{ label: "POI 所在荔波县", cypher: "MATCH (poi:Place)-[r:LOCATED_IN]->(area:Area) WHERE area.adcode = '522722' RETURN poi,r,area LIMIT 300" },
{
label: "POI 所属片区",
cypher: "MATCH (poi:Place)-[r:IN_H3_R9]->(cell:GeoCell)-[areaRel:LOCATED_IN]->(area:Area) RETURN poi,r,cell,areaRel,area LIMIT 50",
},
{ label: "行政区层级", cypher: "MATCH (child:Area)-[r:PART_OF]->(parent:Area) RETURN child,r,parent LIMIT 20" },
] : isTravelItemGraph ? [
{ label: "核心业务图", cypher: TRAVEL_ITEM_CORE_CYPHER },
{ label: "固定线路骨架", cypher: TRAVEL_ITEM_ROUTE_SKELETON_CYPHER },
{ label: "景区附近酒店餐饮", cypher: TRAVEL_ITEM_NEARBY_RESOURCE_CYPHER },
@@ -1408,6 +1446,8 @@ export default function GraphCanvas() {
? "输入自然语言或 Cypher,例如:黄果树天星桥有哪些必付小交通和可选二消?"
: isTravelGraph
? "输入自然语言或 Cypher,例如:一家5人6天想去黄果树小七孔西江梵净山,推荐什么线路?"
: isYunyouLiboGraph
? "输入自然语言或 Cypher,例如:查询荔波县的酒店、美食、交通设施或景点"
: "输入自然语言或 Cypher,例如:花溪公园有哪些历史事件?";
const selectedTrafficInfo = selectedNode ? collectTrafficInfo(selectedNode, dataRef.current) : null;
@@ -1488,7 +1528,11 @@ export default function GraphCanvas() {
<Space split="·" wrap>
{resultInfo && <span style={{ color: "#52c41a", fontSize: 12 }}>{resultInfo}</span>}
<span style={{ color: "#999", fontSize: 12 }}>
{isTravelGraph ? "默认展示固定线路主干;费用/规则/审计关系按需查询" : "支持自然语言和 Cypher"} · 单击看详情 · 双击展开关联 · 滚轮缩放 · 拖拽平移
{isTravelGraph
? "默认展示固定线路主干;费用/规则/审计关系按需查询"
: isYunyouLiboGraph
? "快速查询已按荔波县酒店、美食、交通、景点、公交和空间关系配置"
: "支持自然语言和 Cypher"} · 单击看详情 · 双击展开关联 · 滚轮缩放 · 拖拽平移
</span>
</Space>
{queryMeta?.cypher && (