1
This commit is contained in:
parent
66500f66b7
commit
f0dd3b830c
103
src/App.tsx
103
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, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, Ruler, Waypoints } from 'lucide-react';
|
import { Building2, CalendarRange, Construction, House, LayoutGrid, Library, LocateFixed, MapPinned, PanelRightClose, PanelRightOpen, Ruler, Waypoints } from 'lucide-react';
|
||||||
import {
|
import {
|
||||||
AnnotationsModule,
|
AnnotationsModule,
|
||||||
ContextMenuModule,
|
ContextMenuModule,
|
||||||
@ -73,6 +73,7 @@ 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 },
|
||||||
@ -127,6 +128,18 @@ 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',
|
||||||
@ -589,12 +602,16 @@ 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';
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSingleSelectFilterKey(filterKey: FilterKey) {
|
function isSingleSelectFilterKey(filterKey: FilterKey) {
|
||||||
return isTemplateFilterKey(filterKey) || isIndicatorTreeFilterKey(filterKey);
|
return isTemplateFilterKey(filterKey) || isIndicatorTreeFilterKey(filterKey) || isBuildingNatureFilterKey(filterKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDefaultTemplateFilterNodes(): SelectedFilterNode[] {
|
function getDefaultTemplateFilterNodes(): SelectedFilterNode[] {
|
||||||
@ -756,6 +773,7 @@ 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,
|
||||||
@ -801,6 +819,7 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
|
buildingNature: [],
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -812,6 +831,7 @@ 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,
|
||||||
@ -823,6 +843,7 @@ 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,
|
||||||
@ -834,6 +855,7 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
|
buildingNature: [],
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -845,6 +867,7 @@ 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,
|
||||||
@ -856,6 +879,7 @@ 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,
|
||||||
@ -867,6 +891,7 @@ function App() {
|
|||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
|
buildingNature: [],
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
@ -884,6 +909,7 @@ 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,
|
||||||
@ -938,7 +964,10 @@ function App() {
|
|||||||
);
|
);
|
||||||
const indicatorSelectionLabel = appliedFilters.indicatorTree[0]?.label ?? defaultIndicatorTreeNodes[0]?.label ?? '';
|
const indicatorSelectionLabel = appliedFilters.indicatorTree[0]?.label ?? defaultIndicatorTreeNodes[0]?.label ?? '';
|
||||||
const activeFilterCount = Object.entries(appliedFilters).reduce((total, [key, nodes]) => (
|
const activeFilterCount = Object.entries(appliedFilters).reduce((total, [key, nodes]) => (
|
||||||
key === 'templateLibrary' && isDefaultTemplateSelection(nodes) ? total : total + nodes.length
|
(key === 'templateLibrary' && isDefaultTemplateSelection(nodes))
|
||||||
|
|| (key === 'indicatorTree' && isDefaultIndicatorTreeSelection(nodes, filterTreeByKey.indicatorTree))
|
||||||
|
? total
|
||||||
|
: total + nodes.length
|
||||||
), 0);
|
), 0);
|
||||||
const chartEmptyText = selectedContentNodes.length === 0
|
const chartEmptyText = selectedContentNodes.length === 0
|
||||||
? '请选择右侧分类项'
|
? '请选择右侧分类项'
|
||||||
@ -1197,6 +1226,15 @@ function App() {
|
|||||||
() => new Set(draftFilterNodes.map((node) => getFilterSelectionKey(node.filterKey, node.id))),
|
() => new Set(draftFilterNodes.map((node) => getFilterSelectionKey(node.filterKey, node.id))),
|
||||||
[draftFilterNodes],
|
[draftFilterNodes],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (defaultIndicatorTreeNodes.length === 0) return;
|
||||||
|
setAppliedFilters((current) => {
|
||||||
|
if (current.indicatorTree.length > 0) return current;
|
||||||
|
return { ...current, indicatorTree: defaultIndicatorTreeNodes };
|
||||||
|
});
|
||||||
|
}, [defaultIndicatorTreeNodes]);
|
||||||
|
|
||||||
const appliedFilterPayload = useMemo(
|
const appliedFilterPayload = useMemo(
|
||||||
() => filterOptions
|
() => filterOptions
|
||||||
.filter((option) => option.key !== 'time')
|
.filter((option) => option.key !== 'time')
|
||||||
@ -1207,6 +1245,7 @@ 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,
|
||||||
@ -1265,6 +1304,28 @@ 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 dataParams = nodeId
|
||||||
|
? { ...treeParams, type: '2', id: nodeId, isVirtual: '' }
|
||||||
|
: { ...treeParams, pageSize: '10', current: '1', min: '1', max: '10' };
|
||||||
|
const response = await fetch(`${buildingNatureBrowserConfig.dataEndpoint}?${buildQuery(dataParams)}`, requestOptions);
|
||||||
|
if (!response.ok) throw new Error(`建筑性质浏览数据加载失败:HTTP ${response.status}`);
|
||||||
|
return normalizeTreeRows(pickArray(await response.json()));
|
||||||
|
};
|
||||||
|
|
||||||
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,
|
||||||
@ -1378,6 +1439,12 @@ 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;
|
||||||
@ -1584,7 +1651,7 @@ function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTemplateFilterKey(filterKey) || filterKey === 'indicatorTree') {
|
if (isTemplateFilterKey(filterKey) || filterKey === 'indicatorTree' || isBuildingNatureFilterKey(filterKey)) {
|
||||||
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 }));
|
||||||
@ -1641,10 +1708,12 @@ function App() {
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
if (node.loaded || !isContentFilterKey(filterModalKey)) return;
|
if (node.loaded || (!isContentFilterKey(filterModalKey) && !isBuildingNatureFilterKey(filterModalKey))) return;
|
||||||
|
|
||||||
const currentFilterKey = filterModalKey;
|
const currentFilterKey = filterModalKey;
|
||||||
const childRequest = fetchContentTree(currentFilterKey, nodeId);
|
const childRequest = isBuildingNatureFilterKey(currentFilterKey)
|
||||||
|
? fetchBuildingNatureFilterTree(nodeId)
|
||||||
|
: fetchContentTree(currentFilterKey, nodeId);
|
||||||
childRequest
|
childRequest
|
||||||
.then((children) => {
|
.then((children) => {
|
||||||
setFilterTreeByKey((current) => ({
|
setFilterTreeByKey((current) => ({
|
||||||
@ -1737,22 +1806,18 @@ function App() {
|
|||||||
if (nextDraftNodes.length === 0) {
|
if (nextDraftNodes.length === 0) {
|
||||||
nextDraftNodes = defaultIndicatorTreeNodes;
|
nextDraftNodes = defaultIndicatorTreeNodes;
|
||||||
}
|
}
|
||||||
if (isDefaultIndicatorTreeSelection(nextDraftNodes, filterTreeByKey.indicatorTree)) {
|
|
||||||
nextDraftNodes = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const shouldReloadIndicatorTree = isTemplateFilterKey(filterModalKey) && !isSameFilterSelection(appliedFilters.templateLibrary, nextDraftNodes);
|
|
||||||
setAppliedFilters((current) => {
|
setAppliedFilters((current) => {
|
||||||
const nextFilters = {
|
const nextFilters = {
|
||||||
...current,
|
...current,
|
||||||
[filterModalKey]: nextDraftNodes,
|
[filterModalKey]: nextDraftNodes,
|
||||||
};
|
};
|
||||||
if (shouldReloadIndicatorTree) {
|
if (isTemplateFilterKey(filterModalKey)) {
|
||||||
nextFilters.indicatorTree = [];
|
nextFilters.indicatorTree = [];
|
||||||
}
|
}
|
||||||
return nextFilters;
|
return nextFilters;
|
||||||
});
|
});
|
||||||
if (shouldReloadIndicatorTree) {
|
if (isTemplateFilterKey(filterModalKey)) {
|
||||||
resetIndicatorTreeState();
|
resetIndicatorTreeState();
|
||||||
}
|
}
|
||||||
setChartDataBySelection({});
|
setChartDataBySelection({});
|
||||||
@ -1876,13 +1941,6 @@ function App() {
|
|||||||
});
|
});
|
||||||
}, [activeContentKey, treeByContent]);
|
}, [activeContentKey, treeByContent]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (filterModalKey !== 'indicatorTree') return;
|
|
||||||
if (draftFilterNodes.length > 0) return;
|
|
||||||
if (defaultIndicatorTreeNodes.length === 0) return;
|
|
||||||
setDraftFilterNodes(defaultIndicatorTreeNodes);
|
|
||||||
}, [defaultIndicatorTreeNodes, draftFilterNodes.length, filterModalKey]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
|
|
||||||
@ -2430,16 +2488,13 @@ function App() {
|
|||||||
type="button"
|
type="button"
|
||||||
title="清空全部筛选"
|
title="清空全部筛选"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const shouldReloadIndicatorTree = !isDefaultTemplateSelection(appliedFilters.templateLibrary);
|
|
||||||
if (shouldReloadIndicatorTree) {
|
|
||||||
resetIndicatorTreeState();
|
|
||||||
}
|
|
||||||
setAppliedFilters({
|
setAppliedFilters({
|
||||||
templateLibrary: getDefaultTemplateFilterNodes(),
|
templateLibrary: getDefaultTemplateFilterNodes(),
|
||||||
indicatorTree: [],
|
indicatorTree: defaultIndicatorTreeNodes,
|
||||||
region: [],
|
region: [],
|
||||||
geoLocation: [],
|
geoLocation: [],
|
||||||
facilityType: [],
|
facilityType: [],
|
||||||
|
buildingNature: [],
|
||||||
constructionStage: [],
|
constructionStage: [],
|
||||||
planningForm: [],
|
planningForm: [],
|
||||||
time: [],
|
time: [],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user