feat(map): support to filter other blocks (#1691)
* feat(Map): support to filter other blocks * feat: highlight marker when selected * feat: clear filter params when cancel connect * feat: support line and polygon
This commit is contained in:
parent
e8bb962389
commit
06d67a93ab
@ -203,11 +203,11 @@ export const useCreateActionProps = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
interface FilterTarget {
|
export interface FilterTarget {
|
||||||
targets?: {
|
targets?: {
|
||||||
/** field uid */
|
/** field uid */
|
||||||
uid: string;
|
uid: string;
|
||||||
/** associated fields */
|
/** associated field */
|
||||||
field?: string;
|
field?: string;
|
||||||
}[];
|
}[];
|
||||||
uid?: string;
|
uid?: string;
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
import React, { createContext, useEffect, useRef } from 'react';
|
import React, { createContext, useEffect, useRef } from 'react';
|
||||||
import { useBlockRequestContext } from '../block-provider';
|
import { useBlockRequestContext } from '../block-provider';
|
||||||
import { SharedFilter } from '../block-provider/SharedFilterProvider';
|
import { SharedFilter, mergeFilter } from '../block-provider/SharedFilterProvider';
|
||||||
import { CollectionFieldOptions, useCollection } from '../collection-manager';
|
import { CollectionFieldOptions, useCollection } from '../collection-manager';
|
||||||
|
import { removeNullCondition } from '../schema-component';
|
||||||
import { useAssociatedFields } from './utils';
|
import { useAssociatedFields } from './utils';
|
||||||
|
|
||||||
type Collection = ReturnType<typeof useCollection>;
|
type Collection = ReturnType<typeof useCollection>;
|
||||||
@ -16,6 +17,8 @@ export interface DataBlock {
|
|||||||
collection: Collection;
|
collection: Collection;
|
||||||
/** 根据提供的参数执行该方法即可刷新数据区块的数据 */
|
/** 根据提供的参数执行该方法即可刷新数据区块的数据 */
|
||||||
doFilter: (params: any, params2?: any) => Promise<void>;
|
doFilter: (params: any, params2?: any) => Promise<void>;
|
||||||
|
/** 清除筛选区块设置的筛选参数 */
|
||||||
|
clearFilter: (uid: string) => void;
|
||||||
/** 数据区块表中所有的关系字段 */
|
/** 数据区块表中所有的关系字段 */
|
||||||
associatedFields?: CollectionFieldOptions[];
|
associatedFields?: CollectionFieldOptions[];
|
||||||
/** 通过右上角菜单设置的过滤条件 */
|
/** 通过右上角菜单设置的过滤条件 */
|
||||||
@ -72,6 +75,24 @@ export const FilterBlockRecord = ({
|
|||||||
defaultFilter: params?.filter || {},
|
defaultFilter: params?.filter || {},
|
||||||
service,
|
service,
|
||||||
dom: container.current,
|
dom: container.current,
|
||||||
|
clearFilter(uid: string) {
|
||||||
|
const param = this.service.params?.[0] || {};
|
||||||
|
const storedFilter = this.service.params?.[1]?.filters || {};
|
||||||
|
delete storedFilter[uid];
|
||||||
|
const mergedFilter = mergeFilter([
|
||||||
|
...Object.values(storedFilter).map((filter) => removeNullCondition(filter)),
|
||||||
|
params?.filter || {},
|
||||||
|
]);
|
||||||
|
|
||||||
|
this.service.run(
|
||||||
|
{
|
||||||
|
...param,
|
||||||
|
page: 1,
|
||||||
|
filter: mergedFilter,
|
||||||
|
},
|
||||||
|
{ filters: storedFilter },
|
||||||
|
);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
3
packages/core/client/src/filter-provider/index.ts
Normal file
3
packages/core/client/src/filter-provider/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from './FilterProvider';
|
||||||
|
export * from './utils';
|
||||||
|
|
@ -1,6 +1,11 @@
|
|||||||
import { Schema, useFieldSchema } from '@formily/react';
|
import { Schema, useFieldSchema } from '@formily/react';
|
||||||
import { isPlainObject, isEmpty } from '@nocobase/utils/client';
|
import { isEmpty, isPlainObject } from '@nocobase/utils/client';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { mergeFilter } from '../block-provider';
|
||||||
|
import { FilterTarget, findFilterTargets } from '../block-provider/hooks';
|
||||||
import { Collection, FieldOptions, useCollection } from '../collection-manager';
|
import { Collection, FieldOptions, useCollection } from '../collection-manager';
|
||||||
|
import { removeNullCondition } from '../schema-component';
|
||||||
import { findFilterOperators } from '../schema-component/antd/form-item/SchemaSettingOptions';
|
import { findFilterOperators } from '../schema-component/antd/form-item/SchemaSettingOptions';
|
||||||
import { useFilterBlock } from './FilterProvider';
|
import { useFilterBlock } from './FilterProvider';
|
||||||
|
|
||||||
@ -87,3 +92,78 @@ export const isAssocField = (field?: FieldOptions) => {
|
|||||||
export const isSameCollection = (c1: Collection, c2: Collection) => {
|
export const isSameCollection = (c1: Collection, c2: Collection) => {
|
||||||
return c1.name === c2.name;
|
return c1.name === c2.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useFilterAPI = () => {
|
||||||
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { getDataBlocks } = useFilterBlock();
|
||||||
|
const { targets, uid } = findFilterTargets(fieldSchema);
|
||||||
|
const dataBlocks = getDataBlocks();
|
||||||
|
const [isConnected, setIsConnected] = useState(() => {
|
||||||
|
return targets && targets.some((target) => dataBlocks.some((dataBlock) => dataBlock.uid === target.uid));
|
||||||
|
});
|
||||||
|
const targetsKeys = Object.keys(targets || {});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsConnected(targets && targets.some((target) => dataBlocks.some((dataBlock) => dataBlock.uid === target.uid)));
|
||||||
|
}, [targetsKeys.length, dataBlocks]);
|
||||||
|
|
||||||
|
const doFilter = useCallback(
|
||||||
|
(
|
||||||
|
value,
|
||||||
|
field: string | ((target: FilterTarget['targets'][0]) => string) = 'id',
|
||||||
|
operator: string | ((target: FilterTarget['targets'][0]) => string) = '$eq',
|
||||||
|
) => {
|
||||||
|
dataBlocks.forEach((block) => {
|
||||||
|
const target = targets.find((target) => target.uid === block.uid);
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
|
if (_.isFunction(field)) {
|
||||||
|
field = field(target);
|
||||||
|
}
|
||||||
|
if (_.isFunction(operator)) {
|
||||||
|
operator = operator(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
const param = block.service.params?.[0] || {};
|
||||||
|
// 保留原有的 filter
|
||||||
|
const storedFilter = block.service.params?.[1]?.filters || {};
|
||||||
|
|
||||||
|
if (value !== undefined) {
|
||||||
|
storedFilter[uid] = {
|
||||||
|
$and: [
|
||||||
|
{
|
||||||
|
[field]: {
|
||||||
|
[operator]: value,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
delete storedFilter[uid];
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedFilter = mergeFilter([
|
||||||
|
...Object.values(storedFilter).map((filter) => removeNullCondition(filter)),
|
||||||
|
block.defaultFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
|
block.doFilter(
|
||||||
|
{
|
||||||
|
...param,
|
||||||
|
page: 1,
|
||||||
|
filter: mergedFilter,
|
||||||
|
},
|
||||||
|
{ filters: storedFilter },
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[dataBlocks],
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
/** 当前区块是否已连接其它区块 */
|
||||||
|
isConnected,
|
||||||
|
/** 调用该方法进行过滤 */
|
||||||
|
doFilter,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
@ -11,6 +11,7 @@ export * from './board';
|
|||||||
export * from './china-region';
|
export * from './china-region';
|
||||||
export * from './collection-manager';
|
export * from './collection-manager';
|
||||||
export * from './document-title';
|
export * from './document-title';
|
||||||
|
export * from './filter-provider';
|
||||||
export * from './formula';
|
export * from './formula';
|
||||||
export * from './i18n';
|
export * from './i18n';
|
||||||
export * from './icon';
|
export * from './icon';
|
||||||
|
@ -496,6 +496,7 @@ SchemaSettings.ConnectDataBlocks = (props: { type: FilterBlockType; emptyDescrip
|
|||||||
targets.push({ uid: block.uid });
|
targets.push({ uid: block.uid });
|
||||||
} else {
|
} else {
|
||||||
targets = targets.filter((target) => target.uid !== block.uid);
|
targets = targets.filter((target) => target.uid !== block.uid);
|
||||||
|
block.clearFilter(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFilterTargets(fieldSchema, targets);
|
updateFilterTargets(fieldSchema, targets);
|
||||||
@ -537,6 +538,7 @@ SchemaSettings.ConnectDataBlocks = (props: { type: FilterBlockType; emptyDescrip
|
|||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
targets = targets.filter((target) => target.uid !== block.uid);
|
targets = targets.filter((target) => target.uid !== block.uid);
|
||||||
|
block.clearFilter(uid);
|
||||||
} else {
|
} else {
|
||||||
targets = targets.filter((target) => target.uid !== block.uid);
|
targets = targets.filter((target) => target.uid !== block.uid);
|
||||||
targets.push({ uid: block.uid, field: value });
|
targets.push({ uid: block.uid, field: value });
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { useCollection, useProps, ActionContext, RecordProvider, useRecord, useCompile } from '@nocobase/client';
|
import { CheckOutlined, EnvironmentOutlined, ExpandOutlined } from '@ant-design/icons';
|
||||||
import React, { useState, useRef, useEffect, useMemo } from 'react';
|
|
||||||
import AMap, { AMapForwardedRefProps } from '../components/AMap';
|
|
||||||
import { RecursionField, useFieldSchema, Schema } from '@formily/react';
|
|
||||||
import { useMemoizedFn } from 'ahooks';
|
|
||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
|
import { RecursionField, Schema, useFieldSchema } from '@formily/react';
|
||||||
|
import { ActionContext, RecordProvider, useCollection, useCompile, useFilterAPI, useProps } from '@nocobase/client';
|
||||||
|
import { useMemoizedFn } from 'ahooks';
|
||||||
import { Button, Space } from 'antd';
|
import { Button, Space } from 'antd';
|
||||||
import { ExpandOutlined, EnvironmentOutlined, CheckOutlined } from '@ant-design/icons';
|
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import AMap, { AMapForwardedRefProps } from '../components/AMap';
|
||||||
import { useMapTranslation } from '../locale';
|
import { useMapTranslation } from '../locale';
|
||||||
|
|
||||||
const selectedImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAA/CAMAAAC7OkrPAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEJQTFRFAAAA8Yti8Yti8Itj8Iti74tj8Itj8YtiKwADKwADKhw5Kh07KwADKwADKwADKwAD4odn1YBlKwADKwADKwADKwAD/5y7LQAAABZ0Uk5TAP/8/f/B/PYOHjY3CCozLP3XCSkvMhA05K4AAAC4SURBVHic7dXLDoIwEIXhwSsoLSrw/q8qbSAiMy3/oivj2czmS5omnVORdapVJJFKBSEL2mrrUurbpdXa5dTH5dXi9tTsGNtX0TFG1OT+7PdY2YdEGd0FuFmUwXWm5UAZbCTKYA3SUrXZQTHLHbUy2OlsMO0ultLsajLlbEWZMEUZ+ig5E6YKM2GqMBOmGKubW1D3ps6g1nnvA5uGa5Os85E9nmF2ebYkzeKhc9wre4V+GMeh317hDfXgCWigIGJbAAAAAElFTkSuQmCC'
|
const selectedImage =
|
||||||
const defaultImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAA/CAYAAACM5Lr9AAAFkklEQVR42s3VaWxUVRjG8ddiEKPRxAQTCVSWLnZaWmjpTgulpYUBExP9Agou4IKAogUKAgItlNJCgUIXINFPfsFoDCjibkQRI0QIICAQWUpZugKtpcv0+DxyYqaTe2/vTLf58Etu7znnPf+0k44opQw5i5qsjIFs2APHoBZatFq+02vZeq94yyKs0dOjsAzOTCtuVtNKWtX0UpeaXqHU07tgt4ZnvuMa93Avz/CsniE2WIQV3iEaCDnQ8F/MTgZ4h2d4ljNgmZ4pFszDpmIRIuFP57YWDMcFu7uHMziLMyEKxJBl2MbbM6DZub2NQ3sUZ3K2vkMMGIdNKbi1ADqcZe1q2i7VKzibd8BCEE8GUQ3PQ4ez3KWcGNCbeAfv0neKm85hWRvqo+Hu1LJ2HuwTvAt3tkAciKbDIDO/7iE4l7X9rpqCA30pa3uLwt3nYRAIuIfV5mcWN6msnapf8G405IGQMGry+prB0DiloqPfwng3G3SLDltXnTt5S6PK3NnRr9jAFhDJyLsZAJcz8SGcjOr+xAa0XGGTpOfeSMrYUKcyKlx+gS1oSkbY9VXpm2+rjHKXX2ALm2TS2qq96duaVHp5u19gC5skbc3V05N23FWT8NIfsIVNkra6siGttE2llbX7h9JWhaZ6mfj+lfaJZW3Kn6DJJRNWXWqbgN+Y39jRqtDUKKkrL15PxfdjammrfyhpVmiqlNQVfx9KwX/cFJT6A7awSVLeu1CeUlinxu9o8QsphbUKTWUyfvn5Wcm511QSXvoDtrBJkpedewzaE/E58wdsYZMopSQ55+z+pKK6fo9KKqpXaDkAIgxLWnomK3H1JZVQ0tyv2ICW6XAvLHHJ6QD4K6GgRsVjQ3/g3WzQLffCKGHJqfHgisOXaNy2f/oU7+TdukGIUW5xJ0vic6+oWGzsS7yTd4NoncPiF594GC7FFlSrcVub+gTv4p36btE6h1Fc9nFn7IpzKmZrY5/gXbwTxI0O8xD77rGPYtZeVtE42Jt4B+8C8WAcNu6dPwZDzVh8PYzdcqdXcDbvgMdBPDHEOG7R0Xkxqy6oKAzpDZzNO0AMmIfFvH1kABwZk1epIotv9yjOxOyj+g4xYB4W/dbvlAAdozGsJ3Gmni0mzMPGLvyN6IMo/NojNt/qEZyFmR+CWLAIW3CYaDDUR+D/TTgGdwdncJaeKRbMw8bM/9XdosjlZ5VjU0O3cAZngXTBPCzqzV/cPQAXHeuqVBgu8IVj/TXFGXqWdME8LHLez55mRSw9qUI31fuEZzFjNogNFmFvHPQUACfC8IUbUlTvlbDcSsWzeobYYB42+vWfjDwbnn3c6zCewdnnQGwyD4t47UcjAXA2JO+qCi6ss4V7eUafFZuswn4wM8ex+LgKwqV2cC/OzAXxgnlY+KvfmxkIVaPyr6tRhbWWuId79RnxgnmYY+53VlaHLj2lRm6stRSSc0ph7xoQL1mEzfnWyhPQNrKgGgE1hrjGPTAExEvmYWGvfNOVPUErz6vhiDDCNez5GMQHVmFfd2Vq6MLD6smCGkNc4x4QH5iHPfXyV125H64NX1eFkOpO+I5reo/4wDws9KUDdhSPxFdNIGLc8R3XQHxkFfalHYnB8w6qYRuqO+E7roH4yDws5MX9dtwHlYF5lQi6qYjPfKfXxEcWYbO/sKtsBP50QxFFI/D/De8qQLrBPCwYizY9M2r+of/D+Mx3ID6zDJv1uaVwGfAIBDqGJsbhZ9eQ/BuK+OwYlhzPNe7hXh9Yhe0zwqBB4IAYouCZn1wIXH5GEZ/d1sjBMzzrBfOwoBf2GWFYBMS4C03JWRA087OaoBmf3uCz5zrP8Kx9lmF7jXiE2RbBs95ghB0MIo8/pS0OeJAzvOBLmKY//BAGURBN+jmMa3qPkLdh/wKOL8SpLbnYFgAAAABJRU5ErkJggg=='
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAA/CAMAAAC7OkrPAAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAEJQTFRFAAAA8Yti8Yti8Itj8Iti74tj8Itj8YtiKwADKwADKhw5Kh07KwADKwADKwADKwAD4odn1YBlKwADKwADKwADKwAD/5y7LQAAABZ0Uk5TAP/8/f/B/PYOHjY3CCozLP3XCSkvMhA05K4AAAC4SURBVHic7dXLDoIwEIXhwSsoLSrw/q8qbSAiMy3/oivj2czmS5omnVORdapVJJFKBSEL2mrrUurbpdXa5dTH5dXi9tTsGNtX0TFG1OT+7PdY2YdEGd0FuFmUwXWm5UAZbCTKYA3SUrXZQTHLHbUy2OlsMO0ultLsajLlbEWZMEUZ+ig5E6YKM2GqMBOmGKubW1D3ps6g1nnvA5uGa5Os85E9nmF2ebYkzeKhc9wre4V+GMeh317hDfXgCWigIGJbAAAAAElFTkSuQmCC';
|
||||||
|
const defaultImage =
|
||||||
|
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAA/CAYAAACM5Lr9AAAFkklEQVR42s3VaWxUVRjG8ddiEKPRxAQTCVSWLnZaWmjpTgulpYUBExP9Agou4IKAogUKAgItlNJCgUIXINFPfsFoDCjibkQRI0QIICAQWUpZugKtpcv0+DxyYqaTe2/vTLf58Etu7znnPf+0k44opQw5i5qsjIFs2APHoBZatFq+02vZeq94yyKs0dOjsAzOTCtuVtNKWtX0UpeaXqHU07tgt4ZnvuMa93Avz/CsniE2WIQV3iEaCDnQ8F/MTgZ4h2d4ljNgmZ4pFszDpmIRIuFP57YWDMcFu7uHMziLMyEKxJBl2MbbM6DZub2NQ3sUZ3K2vkMMGIdNKbi1ADqcZe1q2i7VKzibd8BCEE8GUQ3PQ4ez3KWcGNCbeAfv0neKm85hWRvqo+Hu1LJ2HuwTvAt3tkAciKbDIDO/7iE4l7X9rpqCA30pa3uLwt3nYRAIuIfV5mcWN6msnapf8G405IGQMGry+prB0DiloqPfwng3G3SLDltXnTt5S6PK3NnRr9jAFhDJyLsZAJcz8SGcjOr+xAa0XGGTpOfeSMrYUKcyKlx+gS1oSkbY9VXpm2+rjHKXX2ALm2TS2qq96duaVHp5u19gC5skbc3V05N23FWT8NIfsIVNkra6siGttE2llbX7h9JWhaZ6mfj+lfaJZW3Kn6DJJRNWXWqbgN+Y39jRqtDUKKkrL15PxfdjammrfyhpVmiqlNQVfx9KwX/cFJT6A7awSVLeu1CeUlinxu9o8QsphbUKTWUyfvn5Wcm511QSXvoDtrBJkpedewzaE/E58wdsYZMopSQ55+z+pKK6fo9KKqpXaDkAIgxLWnomK3H1JZVQ0tyv2ICW6XAvLHHJ6QD4K6GgRsVjQ3/g3WzQLffCKGHJqfHgisOXaNy2f/oU7+TdukGIUW5xJ0vic6+oWGzsS7yTd4NoncPiF594GC7FFlSrcVub+gTv4p36btE6h1Fc9nFn7IpzKmZrY5/gXbwTxI0O8xD77rGPYtZeVtE42Jt4B+8C8WAcNu6dPwZDzVh8PYzdcqdXcDbvgMdBPDHEOG7R0Xkxqy6oKAzpDZzNO0AMmIfFvH1kABwZk1epIotv9yjOxOyj+g4xYB4W/dbvlAAdozGsJ3Gmni0mzMPGLvyN6IMo/NojNt/qEZyFmR+CWLAIW3CYaDDUR+D/TTgGdwdncJaeKRbMw8bM/9XdosjlZ5VjU0O3cAZngXTBPCzqzV/cPQAXHeuqVBgu8IVj/TXFGXqWdME8LHLez55mRSw9qUI31fuEZzFjNogNFmFvHPQUACfC8IUbUlTvlbDcSsWzeobYYB42+vWfjDwbnn3c6zCewdnnQGwyD4t47UcjAXA2JO+qCi6ss4V7eUafFZuswn4wM8ex+LgKwqV2cC/OzAXxgnlY+KvfmxkIVaPyr6tRhbWWuId79RnxgnmYY+53VlaHLj2lRm6stRSSc0ph7xoQL1mEzfnWyhPQNrKgGgE1hrjGPTAExEvmYWGvfNOVPUErz6vhiDDCNez5GMQHVmFfd2Vq6MLD6smCGkNc4x4QH5iHPfXyV125H64NX1eFkOpO+I5reo/4wDws9KUDdhSPxFdNIGLc8R3XQHxkFfalHYnB8w6qYRuqO+E7roH4yDws5MX9dtwHlYF5lQi6qYjPfKfXxEcWYbO/sKtsBP50QxFFI/D/De8qQLrBPCwYizY9M2r+of/D+Mx3ID6zDJv1uaVwGfAIBDqGJsbhZ9eQ/BuK+OwYlhzPNe7hXh9Yhe0zwqBB4IAYouCZn1wIXH5GEZ/d1sjBMzzrBfOwoBf2GWFYBMS4C03JWRA087OaoBmf3uCz5zrP8Kx9lmF7jXiE2RbBs95ghB0MIo8/pS0OeJAzvOBLmKY//BAGURBN+jmMa3qPkLdh/wKOL8SpLbnYFgAAAABJRU5ErkJggg==';
|
||||||
|
|
||||||
export const MapBlock = (props) => {
|
export const MapBlock = (props) => {
|
||||||
const { fieldNames, dataSource = [], fixedBlock, zoom, selectedRecordKeys, setSelectedRecordKeys } = useProps(props);
|
const { fieldNames, dataSource = [], fixedBlock, zoom, selectedRecordKeys, setSelectedRecordKeys } = useProps(props);
|
||||||
@ -22,7 +24,9 @@ export const MapBlock = (props) => {
|
|||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [selectingMode, setSelecting] = useState('');
|
const [selectingMode, setSelecting] = useState('');
|
||||||
const { t } = useMapTranslation();
|
const { t } = useMapTranslation();
|
||||||
const compile = useCompile()
|
const compile = useCompile();
|
||||||
|
const { isConnected, doFilter } = useFilterAPI();
|
||||||
|
const [, setPrevSelected] = useState(null);
|
||||||
const selectingModeRef = useRef(selectingMode);
|
const selectingModeRef = useRef(selectingMode);
|
||||||
selectingModeRef.current = selectingMode;
|
selectingModeRef.current = selectingMode;
|
||||||
|
|
||||||
@ -31,10 +35,12 @@ export const MapBlock = (props) => {
|
|||||||
const selected = typeof state === 'undefined' ? extData.selected : !state;
|
const selected = typeof state === 'undefined' ? extData.selected : !state;
|
||||||
extData.selected = !selected;
|
extData.selected = !selected;
|
||||||
if ('setIcon' in overlay) {
|
if ('setIcon' in overlay) {
|
||||||
overlay.setIcon(new mapRef.current.aMap.Icon({
|
overlay.setIcon(
|
||||||
imageSize: [19, 32],
|
new mapRef.current.aMap.Icon({
|
||||||
image: selected ? defaultImage : selectedImage
|
imageSize: [19, 32],
|
||||||
} as AMap.IconOpts));
|
image: selected ? defaultImage : selectedImage,
|
||||||
|
} as AMap.IconOpts),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
(overlay as AMap.Polygon).setOptions({
|
(overlay as AMap.Polygon).setOptions({
|
||||||
extData,
|
extData,
|
||||||
@ -106,6 +112,7 @@ export const MapBlock = (props) => {
|
|||||||
const overlay = mapRef.current.setOverlay(field.type, data, {
|
const overlay = mapRef.current.setOverlay(field.type, data, {
|
||||||
strokeColor: '#4e9bff',
|
strokeColor: '#4e9bff',
|
||||||
fillColor: '#4e9bff',
|
fillColor: '#4e9bff',
|
||||||
|
cursor: 'pointer',
|
||||||
label: {
|
label: {
|
||||||
direction: 'bottom',
|
direction: 'bottom',
|
||||||
offset: [0, 5],
|
offset: [0, 5],
|
||||||
@ -137,6 +144,27 @@ export const MapBlock = (props) => {
|
|||||||
const data = dataSource?.find((item) => {
|
const data = dataSource?.find((item) => {
|
||||||
return extData.id === item[getPrimaryKey()];
|
return extData.id === item[getPrimaryKey()];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 筛选区块模式
|
||||||
|
if (isConnected) {
|
||||||
|
setPrevSelected((prev) => {
|
||||||
|
prev && clearSelected(prev);
|
||||||
|
if (prev === o) {
|
||||||
|
clearSelected(o);
|
||||||
|
|
||||||
|
// 删除过滤参数
|
||||||
|
doFilter(null);
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
selectMarker(o);
|
||||||
|
doFilter(data[getPrimaryKey()], (target) => target.field || getPrimaryKey(), '$eq');
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
setVisible(true);
|
setVisible(true);
|
||||||
setRecord(data);
|
setRecord(data);
|
||||||
@ -152,7 +180,7 @@ export const MapBlock = (props) => {
|
|||||||
});
|
});
|
||||||
events.forEach((e) => e());
|
events.forEach((e) => e());
|
||||||
};
|
};
|
||||||
}, [dataSource, isMapInitialization, fieldNames, field.type]);
|
}, [dataSource, isMapInitialization, fieldNames, field.type, isConnected]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -254,3 +282,29 @@ const MapBlockDrawer = (props) => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function clearSelected(marker: AMap.Marker | AMap.Polygon | AMap.Polyline | AMap.Circle) {
|
||||||
|
if ((marker as AMap.Marker).dom) {
|
||||||
|
(marker as AMap.Marker).dom.style.filter = 'none';
|
||||||
|
|
||||||
|
// AMap.Polygon | AMap.Polyline | AMap.Circle 都有 setOptions 方法
|
||||||
|
} else if ((marker as AMap.Polygon).setOptions) {
|
||||||
|
(marker as AMap.Polygon).setOptions({
|
||||||
|
strokeColor: '#4e9bff',
|
||||||
|
fillColor: '#4e9bff',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectMarker(marker: AMap.Marker | AMap.Polygon | AMap.Polyline | AMap.Circle) {
|
||||||
|
if ((marker as AMap.Marker).dom) {
|
||||||
|
(marker as AMap.Marker).dom.style.filter = 'brightness(1.2) contrast(1.2) hue-rotate(180deg)';
|
||||||
|
|
||||||
|
// AMap.Polygon | AMap.Polyline | AMap.Circle 都有 setOptions 方法
|
||||||
|
} else if ((marker as AMap.Polygon).setOptions) {
|
||||||
|
(marker as AMap.Polygon).setOptions({
|
||||||
|
strokeColor: '#F18b62',
|
||||||
|
fillColor: '#F18b62',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
import { ISchema, useField, useFieldSchema } from '@formily/react';
|
||||||
import {
|
import {
|
||||||
useCollection,
|
FilterBlockType,
|
||||||
useCollectionFilterOptions,
|
|
||||||
useDesignable,
|
|
||||||
useSchemaTemplate,
|
|
||||||
FixedBlockDesignerItem,
|
FixedBlockDesignerItem,
|
||||||
GeneralSchemaDesigner,
|
GeneralSchemaDesigner,
|
||||||
SchemaSettings,
|
SchemaSettings,
|
||||||
mergeFilter,
|
mergeFilter,
|
||||||
|
useCollection,
|
||||||
|
useCollectionFilterOptions,
|
||||||
useCollectionManager,
|
useCollectionManager,
|
||||||
|
useDesignable,
|
||||||
|
useSchemaTemplate,
|
||||||
} from '@nocobase/client';
|
} from '@nocobase/client';
|
||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@ -145,6 +146,7 @@ export const MapBlockDesigner = () => {
|
|||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<SchemaSettings.ConnectDataBlocks type={FilterBlockType.TABLE} emptyDescription={t('No blocks to connect')} />
|
||||||
<SchemaSettings.Divider />
|
<SchemaSettings.Divider />
|
||||||
<SchemaSettings.Template componentName={'Map'} collectionName={name} resourceName={defaultResource} />
|
<SchemaSettings.Template componentName={'Map'} collectionName={name} resourceName={defaultResource} />
|
||||||
<SchemaSettings.Divider />
|
<SchemaSettings.Divider />
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
import { BlockProvider, FixedBlockWrapper, SchemaComponentOptions, useBlockRequestContext } from '@nocobase/client';
|
import { BlockProvider, FixedBlockWrapper, SchemaComponentOptions, useBlockRequestContext } from '@nocobase/client';
|
||||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useContext, useState } from 'react';
|
||||||
|
|
||||||
export const MapBlockContext = createContext<any>({});
|
export const MapBlockContext = createContext<any>({});
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@ export const createMapBlockSchema = (options) => {
|
|||||||
},
|
},
|
||||||
'x-designer': 'MapBlockDesigner',
|
'x-designer': 'MapBlockDesigner',
|
||||||
'x-component': 'CardItem',
|
'x-component': 'CardItem',
|
||||||
|
// 保存当前筛选区块所能过滤的数据区块
|
||||||
|
'x-filter-targets': [],
|
||||||
properties: {
|
properties: {
|
||||||
actions: {
|
actions: {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
@ -75,6 +77,5 @@ export const createMapBlockSchema = (options) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
console.log(JSON.stringify(schema, null, 2));
|
|
||||||
return schema;
|
return schema;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user