1
This commit is contained in:
parent
0eedbfc113
commit
66500f66b7
140
src/App.tsx
140
src/App.tsx
@ -12,7 +12,7 @@ import {
|
|||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import type { AgCartesianChartOptions } from 'ag-charts-community';
|
import type { AgCartesianChartOptions } from 'ag-charts-community';
|
||||||
import { ModuleRegistry } from 'ag-charts-community';
|
import { ModuleRegistry } from 'ag-charts-community';
|
||||||
import { Building2, CalendarRange, Construction, House, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, Ruler, Waypoints } from 'lucide-react';
|
import { Building2, CalendarRange, Construction, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, Ruler, Waypoints } from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
AnnotationsModule,
|
AnnotationsModule,
|
||||||
ContextMenuModule,
|
ContextMenuModule,
|
||||||
@ -30,9 +30,9 @@ const API_BASE_URL = 'https://nest.zwgczx.com/api/v1';
|
|||||||
// const API_BASE_URL = 'http://127.0.0.1:9089/api/v1';
|
// const API_BASE_URL = 'http://127.0.0.1:9089/api/v1';
|
||||||
|
|
||||||
const API_ROUTES = {
|
const API_ROUTES = {
|
||||||
filterTree: '/zw/getBuildingFacilityObjectFilterTree',
|
filterTree: '/zw/getBuildingFunctionCostFilterTree',
|
||||||
filterTreeSearch: '/zw/getBuildingFacilityObjectFilterTreeSearch',
|
filterTreeSearch: '/zw/getBuildingFunctionCostFilterTreeSearch',
|
||||||
statsBatch: '/zw/getBuildingFacilityObjectStatsBatch',
|
statsBatch: '/zw/getBuildingFunctionCostStatsBatch',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const statisticOptions = [
|
const statisticOptions = [
|
||||||
@ -73,7 +73,6 @@ const filterOptions = [
|
|||||||
{ key: 'region', label: '省市区', icon: MapPinned },
|
{ key: 'region', label: '省市区', icon: MapPinned },
|
||||||
{ key: 'geoLocation', label: '自然地理区位', icon: LocateFixed },
|
{ key: 'geoLocation', label: '自然地理区位', icon: LocateFixed },
|
||||||
{ key: 'facilityType', label: '设施类别', icon: Building2 },
|
{ key: 'facilityType', label: '设施类别', icon: Building2 },
|
||||||
{ key: 'buildingNature', label: '建筑性质', icon: House },
|
|
||||||
{ key: 'constructionStage', label: '建设阶段', icon: Construction },
|
{ key: 'constructionStage', label: '建设阶段', icon: Construction },
|
||||||
{ key: 'planningForm', label: '规划形式', icon: LayoutGrid },
|
{ key: 'planningForm', label: '规划形式', icon: LayoutGrid },
|
||||||
{ key: 'time', label: '时间', icon: CalendarRange },
|
{ key: 'time', label: '时间', icon: CalendarRange },
|
||||||
@ -128,26 +127,6 @@ const contentTreeConfigs = {
|
|||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const buildingNatureBrowserConfig = {
|
|
||||||
conditionEndpoint: '/api/public/browser/condition/256',
|
|
||||||
dataEndpoint: '/api/public/browser/data/256',
|
|
||||||
treeid: '95504',
|
|
||||||
fieldid: '316390',
|
|
||||||
searchbrowserid: '36523',
|
|
||||||
browserParams: {
|
|
||||||
requestid: '',
|
|
||||||
isshowsearchtab: '1',
|
|
||||||
workflowid: '182028',
|
|
||||||
wfid: '182028',
|
|
||||||
billid: '-1815',
|
|
||||||
f_weaver_belongto_userid: '',
|
|
||||||
f_weaver_belongto_usertype: '',
|
|
||||||
wf_isagent: '',
|
|
||||||
wf_beagenter: '',
|
|
||||||
wfCreater: '',
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const chartLineColors = ['#0078a8', '#d14d72', '#1f8f4d', '#d96f23', '#6b5cc8', '#0d7680', '#9a6b12', '#b24b38'];
|
const chartLineColors = ['#0078a8', '#d14d72', '#1f8f4d', '#d96f23', '#6b5cc8', '#0d7680', '#9a6b12', '#b24b38'];
|
||||||
const defaultTemplateFilterNode = {
|
const defaultTemplateFilterNode = {
|
||||||
id: '3',
|
id: '3',
|
||||||
@ -610,10 +589,6 @@ function isIndicatorTreeFilterKey(filterKey: FilterKey): filterKey is 'indicator
|
|||||||
return filterKey === 'indicatorTree';
|
return filterKey === 'indicatorTree';
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBuildingNatureFilterKey(filterKey: FilterKey): filterKey is 'buildingNature' {
|
|
||||||
return filterKey === 'buildingNature';
|
|
||||||
}
|
|
||||||
|
|
||||||
function isRangeFilterKey(filterKey: FilterKey): filterKey is RangeFilterKey {
|
function isRangeFilterKey(filterKey: FilterKey): filterKey is RangeFilterKey {
|
||||||
return filterKey === 'time' || filterKey === 'area';
|
return filterKey === 'time' || filterKey === 'area';
|
||||||
}
|
}
|
||||||
@ -781,7 +756,6 @@ function App() {
|
|||||||
region: false,
|
region: false,
|
||||||
geoLocation: false,
|
geoLocation: false,
|
||||||
facilityType: false,
|
facilityType: false,
|
||||||
buildingNature: false,
|
|
||||||
constructionStage: false,
|
constructionStage: false,
|
||||||
planningForm: false,
|
planningForm: false,
|
||||||
time: false,
|
time: false,
|
||||||
@ -827,7 +801,6 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
buildingNature: [],
|
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -839,7 +812,6 @@ function App() {
|
|||||||
region: false,
|
region: false,
|
||||||
geoLocation: false,
|
geoLocation: false,
|
||||||
facilityType: false,
|
facilityType: false,
|
||||||
buildingNature: false,
|
|
||||||
constructionStage: false,
|
constructionStage: false,
|
||||||
planningForm: false,
|
planningForm: false,
|
||||||
time: false,
|
time: false,
|
||||||
@ -851,7 +823,6 @@ function App() {
|
|||||||
region: null,
|
region: null,
|
||||||
geoLocation: null,
|
geoLocation: null,
|
||||||
facilityType: null,
|
facilityType: null,
|
||||||
buildingNature: null,
|
|
||||||
constructionStage: null,
|
constructionStage: null,
|
||||||
planningForm: null,
|
planningForm: null,
|
||||||
time: null,
|
time: null,
|
||||||
@ -863,7 +834,6 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
buildingNature: [],
|
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -875,7 +845,6 @@ function App() {
|
|||||||
region: false,
|
region: false,
|
||||||
geoLocation: false,
|
geoLocation: false,
|
||||||
facilityType: false,
|
facilityType: false,
|
||||||
buildingNature: false,
|
|
||||||
constructionStage: false,
|
constructionStage: false,
|
||||||
planningForm: false,
|
planningForm: false,
|
||||||
time: false,
|
time: false,
|
||||||
@ -887,7 +856,6 @@ function App() {
|
|||||||
region: null,
|
region: null,
|
||||||
geoLocation: null,
|
geoLocation: null,
|
||||||
facilityType: null,
|
facilityType: null,
|
||||||
buildingNature: null,
|
|
||||||
constructionStage: null,
|
constructionStage: null,
|
||||||
planningForm: null,
|
planningForm: null,
|
||||||
time: null,
|
time: null,
|
||||||
@ -899,7 +867,6 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
buildingNature: [],
|
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -917,7 +884,6 @@ function App() {
|
|||||||
region: 0,
|
region: 0,
|
||||||
geoLocation: 0,
|
geoLocation: 0,
|
||||||
facilityType: 0,
|
facilityType: 0,
|
||||||
buildingNature: 0,
|
|
||||||
constructionStage: 0,
|
constructionStage: 0,
|
||||||
planningForm: 0,
|
planningForm: 0,
|
||||||
time: 0,
|
time: 0,
|
||||||
@ -1241,7 +1207,6 @@ function App() {
|
|||||||
.filter((filter) => filter.nodes.length > 0),
|
.filter((filter) => filter.nodes.length > 0),
|
||||||
[
|
[
|
||||||
appliedFilters.area,
|
appliedFilters.area,
|
||||||
appliedFilters.buildingNature,
|
|
||||||
appliedFilters.constructionStage,
|
appliedFilters.constructionStage,
|
||||||
appliedFilters.facilityType,
|
appliedFilters.facilityType,
|
||||||
appliedFilters.geoLocation,
|
appliedFilters.geoLocation,
|
||||||
@ -1300,65 +1265,6 @@ function App() {
|
|||||||
return normalizeTreeRows(rows);
|
return normalizeTreeRows(rows);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchBuildingNatureFilterTree = async (nodeId?: string, signal?: AbortSignal) => {
|
|
||||||
const treeParams = {
|
|
||||||
...browserTreeDefaults,
|
|
||||||
...buildingNatureBrowserConfig.browserParams,
|
|
||||||
treeid: buildingNatureBrowserConfig.treeid,
|
|
||||||
cube_treeid: buildingNatureBrowserConfig.treeid,
|
|
||||||
searchbrowserid: buildingNatureBrowserConfig.searchbrowserid,
|
|
||||||
fieldid: buildingNatureBrowserConfig.fieldid,
|
|
||||||
};
|
|
||||||
const requestOptions: RequestInit = {
|
|
||||||
credentials: 'include',
|
|
||||||
signal,
|
|
||||||
headers: {
|
|
||||||
'X-Requested-With': 'XMLHttpRequest',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!nodeId) {
|
|
||||||
const conditionResponse = await fetch(
|
|
||||||
`${buildingNatureBrowserConfig.conditionEndpoint}?${buildQuery(treeParams)}`,
|
|
||||||
requestOptions,
|
|
||||||
);
|
|
||||||
if (!conditionResponse.ok) {
|
|
||||||
throw new Error(`建筑性质浏览条件加载失败:HTTP ${conditionResponse.status}`);
|
|
||||||
}
|
|
||||||
const conditionPayload = await conditionResponse.json() as { status?: boolean; msg?: string };
|
|
||||||
if (conditionPayload.status === false) {
|
|
||||||
throw new Error(conditionPayload.msg || '建筑性质浏览条件加载失败');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const dataParams = nodeId
|
|
||||||
? {
|
|
||||||
...treeParams,
|
|
||||||
type: '2',
|
|
||||||
id: nodeId,
|
|
||||||
isVirtual: '',
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
...treeParams,
|
|
||||||
pageSize: '10',
|
|
||||||
current: '1',
|
|
||||||
min: '1',
|
|
||||||
max: '10',
|
|
||||||
};
|
|
||||||
const dataResponse = await fetch(
|
|
||||||
`${buildingNatureBrowserConfig.dataEndpoint}?${buildQuery(dataParams)}`,
|
|
||||||
requestOptions,
|
|
||||||
);
|
|
||||||
if (!dataResponse.ok) {
|
|
||||||
throw new Error(`建筑性质浏览数据加载失败:HTTP ${dataResponse.status}`);
|
|
||||||
}
|
|
||||||
const dataPayload = await dataResponse.json() as { status?: boolean; msg?: string };
|
|
||||||
if (dataPayload.status === false) {
|
|
||||||
throw new Error(dataPayload.msg || '建筑性质浏览数据加载失败');
|
|
||||||
}
|
|
||||||
return normalizeTreeRows(pickArray(dataPayload));
|
|
||||||
};
|
|
||||||
|
|
||||||
const normalizeBackendTree = (nodes: TreeNode[]): TreeNode[] => nodes.map((node) => ({
|
const normalizeBackendTree = (nodes: TreeNode[]): TreeNode[] => nodes.map((node) => ({
|
||||||
...node,
|
...node,
|
||||||
hasChildren: node.children.length > 0 || node.hasChildren,
|
hasChildren: node.children.length > 0 || node.hasChildren,
|
||||||
@ -1472,12 +1378,6 @@ function App() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loadFilterTree = async (filterKey: FilterKey, keyword?: string, signal?: AbortSignal) => {
|
const loadFilterTree = async (filterKey: FilterKey, keyword?: string, signal?: AbortSignal) => {
|
||||||
if (isBuildingNatureFilterKey(filterKey)) {
|
|
||||||
const nodes = filterTreeByKey.buildingNature.length > 0
|
|
||||||
? filterTreeByKey.buildingNature
|
|
||||||
: await fetchBuildingNatureFilterTree(undefined, signal);
|
|
||||||
return keyword?.trim() ? filterTreeNodesByKeyword(nodes, keyword) : nodes;
|
|
||||||
}
|
|
||||||
if (filterKey === 'region') {
|
if (filterKey === 'region') {
|
||||||
const nodes = await fetchRegionFilterTree(signal);
|
const nodes = await fetchRegionFilterTree(signal);
|
||||||
return keyword?.trim() ? filterTreeNodesByKeyword(nodes, keyword) : nodes;
|
return keyword?.trim() ? filterTreeNodesByKeyword(nodes, keyword) : nodes;
|
||||||
@ -1684,7 +1584,7 @@ function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTemplateFilterKey(filterKey) || filterKey === 'indicatorTree' || isBuildingNatureFilterKey(filterKey)) {
|
if (isTemplateFilterKey(filterKey) || filterKey === 'indicatorTree') {
|
||||||
filterSearchTimerRef.current = window.setTimeout(() => {
|
filterSearchTimerRef.current = window.setTimeout(() => {
|
||||||
setFilterSearchLoadingByKey((current) => ({ ...current, [filterKey]: true }));
|
setFilterSearchLoadingByKey((current) => ({ ...current, [filterKey]: true }));
|
||||||
setFilterSearchErrorByKey((current) => ({ ...current, [filterKey]: null }));
|
setFilterSearchErrorByKey((current) => ({ ...current, [filterKey]: null }));
|
||||||
@ -1741,12 +1641,10 @@ function App() {
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (node.loaded || (!isContentFilterKey(filterModalKey) && !isBuildingNatureFilterKey(filterModalKey))) return;
|
if (node.loaded || !isContentFilterKey(filterModalKey)) return;
|
||||||
|
|
||||||
const currentFilterKey = filterModalKey;
|
const currentFilterKey = filterModalKey;
|
||||||
const childRequest = isBuildingNatureFilterKey(currentFilterKey)
|
const childRequest = fetchContentTree(currentFilterKey, nodeId);
|
||||||
? fetchBuildingNatureFilterTree(nodeId)
|
|
||||||
: fetchContentTree(currentFilterKey, nodeId);
|
|
||||||
childRequest
|
childRequest
|
||||||
.then((children) => {
|
.then((children) => {
|
||||||
setFilterTreeByKey((current) => ({
|
setFilterTreeByKey((current) => ({
|
||||||
@ -2002,13 +1900,6 @@ function App() {
|
|||||||
setLoadingHint('正在加载数据');
|
setLoadingHint('正在加载数据');
|
||||||
setLoadError(null);
|
setLoadError(null);
|
||||||
try {
|
try {
|
||||||
const hasAnyMissingNode = selectedContentNodes.some((node) => !chartDataBySelection[getSelectionKey(node.contentKey, node.id)]);
|
|
||||||
if (selectedContentNodes.length > 0 && !hasAnyMissingNode && chartSummaryBySelection[overallSummaryKey]) {
|
|
||||||
setLoading(false);
|
|
||||||
setLoadingHint('');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}${API_ROUTES.statsBatch}`, {
|
const response = await fetch(`${API_BASE_URL}${API_ROUTES.statsBatch}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
@ -2032,21 +1923,19 @@ function App() {
|
|||||||
}
|
}
|
||||||
const payload = (await response.json()) as { data?: ApiBuildingFunctionStatBatchItem[] };
|
const payload = (await response.json()) as { data?: ApiBuildingFunctionStatBatchItem[] };
|
||||||
const results = (payload.data ?? [])
|
const results = (payload.data ?? [])
|
||||||
.filter((item) => item.key)
|
.filter((item) => item.key && item.key !== overallSummaryKey)
|
||||||
.map((item) => [item.key as string, (item.data ?? []).map(normalizeStat).slice(0, 36)] as const);
|
.map((item) => [item.key as string, (item.data ?? []).map(normalizeStat).slice(0, 36)] as const);
|
||||||
const summaries = (payload.data ?? [])
|
const summaries = (payload.data ?? [])
|
||||||
.filter((item) => item.key && item.summary)
|
.filter((item) => item.key && item.summary)
|
||||||
.map((item) => [item.key as string, normalizeStat(item.summary as ApiBuildingFunctionStat)] as const);
|
.map((item) => [item.key as string, normalizeStat(item.summary as ApiBuildingFunctionStat)] as const);
|
||||||
const overallSummary = (payload.data ?? []).find((item) => item.summary)?.summary;
|
const overallSummary = (payload.data ?? [])
|
||||||
setChartDataBySelection((current) => ({
|
.find((item) => item.key === overallSummaryKey)?.summary
|
||||||
...current,
|
?? (payload.data ?? []).find((item) => item.summary)?.summary;
|
||||||
...Object.fromEntries(results),
|
setChartDataBySelection(Object.fromEntries(results));
|
||||||
}));
|
setChartSummaryBySelection({
|
||||||
setChartSummaryBySelection((current) => ({
|
|
||||||
...current,
|
|
||||||
...Object.fromEntries(summaries),
|
...Object.fromEntries(summaries),
|
||||||
...(overallSummary ? { [overallSummaryKey]: normalizeStat(overallSummary) } : {}),
|
...(overallSummary ? { [overallSummaryKey]: normalizeStat(overallSummary) } : {}),
|
||||||
}));
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (controller.signal.aborted) return;
|
if (controller.signal.aborted) return;
|
||||||
setLoadError(error instanceof Error ? error.message : '接口请求失败');
|
setLoadError(error instanceof Error ? error.message : '接口请求失败');
|
||||||
@ -2551,7 +2440,6 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
buildingNature: [],
|
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user