@nocobase/plugin-map 0.8.1-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/client.d.ts +4 -0
- package/client.js +30 -0
- package/lib/client/components/AMap.d.ts +13 -0
- package/lib/client/components/AMap.js +502 -0
- package/lib/client/components/Configuration.d.ts +2 -0
- package/lib/client/components/Configuration.js +167 -0
- package/lib/client/components/Designer.d.ts +2 -0
- package/lib/client/components/Designer.js +308 -0
- package/lib/client/components/Map.d.ts +6 -0
- package/lib/client/components/Map.js +65 -0
- package/lib/client/components/ReadPretty.d.ts +2 -0
- package/lib/client/components/ReadPretty.js +81 -0
- package/lib/client/components/Search.d.ts +6 -0
- package/lib/client/components/Search.js +155 -0
- package/lib/client/constants.d.ts +4 -0
- package/lib/client/constants.js +17 -0
- package/lib/client/fields/circle.d.ts +2 -0
- package/lib/client/fields/circle.js +37 -0
- package/lib/client/fields/index.d.ts +2 -0
- package/lib/client/fields/index.js +22 -0
- package/lib/client/fields/lineString.d.ts +2 -0
- package/lib/client/fields/lineString.js +37 -0
- package/lib/client/fields/point.d.ts +2 -0
- package/lib/client/fields/point.js +37 -0
- package/lib/client/fields/polygon.d.ts +2 -0
- package/lib/client/fields/polygon.js +37 -0
- package/lib/client/fields/schema.d.ts +99 -0
- package/lib/client/fields/schema.js +79 -0
- package/lib/client/hooks/index.d.ts +1 -0
- package/lib/client/hooks/index.js +18 -0
- package/lib/client/hooks/useMapConfiguration.d.ts +2 -0
- package/lib/client/hooks/useMapConfiguration.js +33 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.js +80 -0
- package/lib/client/initialize.d.ts +4 -0
- package/lib/client/initialize.js +67 -0
- package/lib/client/locales/en-US.d.ts +2 -0
- package/lib/client/locales/en-US.js +9 -0
- package/lib/client/locales/index.d.ts +4 -0
- package/lib/client/locales/index.js +56 -0
- package/lib/client/locales/zh-CN.d.ts +43 -0
- package/lib/client/locales/zh-CN.js +51 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +15 -0
- package/lib/server/actions/index.d.ts +3 -0
- package/lib/server/actions/index.js +66 -0
- package/lib/server/collections/mapConfiguration.d.ts +3 -0
- package/lib/server/collections/mapConfiguration.js +30 -0
- package/lib/server/constants.d.ts +1 -0
- package/lib/server/constants.js +8 -0
- package/lib/server/fields/circle.d.ts +13 -0
- package/lib/server/fields/circle.js +84 -0
- package/lib/server/fields/index.d.ts +4 -0
- package/lib/server/fields/index.js +57 -0
- package/lib/server/fields/lineString.d.ts +13 -0
- package/lib/server/fields/lineString.js +91 -0
- package/lib/server/fields/point.d.ts +13 -0
- package/lib/server/fields/point.js +95 -0
- package/lib/server/fields/polygon.d.ts +13 -0
- package/lib/server/fields/polygon.js +89 -0
- package/lib/server/helpers/index.d.ts +6 -0
- package/lib/server/helpers/index.js +44 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +15 -0
- package/lib/server/plugin.d.ts +11 -0
- package/lib/server/plugin.js +88 -0
- package/package.json +19 -0
- package/server.d.ts +4 -0
- package/server.js +30 -0
- package/src/client/components/AMap.tsx +369 -0
- package/src/client/components/Configuration.tsx +91 -0
- package/src/client/components/Designer.tsx +260 -0
- package/src/client/components/Map.tsx +29 -0
- package/src/client/components/ReadPretty.tsx +34 -0
- package/src/client/components/Search.tsx +93 -0
- package/src/client/constants.ts +6 -0
- package/src/client/fields/circle.ts +23 -0
- package/src/client/fields/index.ts +16 -0
- package/src/client/fields/lineString.ts +23 -0
- package/src/client/fields/point.ts +24 -0
- package/src/client/fields/polygon.ts +23 -0
- package/src/client/fields/schema.ts +57 -0
- package/src/client/hooks/index.ts +1 -0
- package/src/client/hooks/useMapConfiguration.ts +15 -0
- package/src/client/index.tsx +43 -0
- package/src/client/initialize.tsx +33 -0
- package/src/client/locales/en-US.ts +5 -0
- package/src/client/locales/index.ts +22 -0
- package/src/client/locales/zh-CN.ts +45 -0
- package/src/index.ts +1 -0
- package/src/server/__tests__/fields.test.ts +168 -0
- package/src/server/actions/index.ts +46 -0
- package/src/server/collections/mapConfiguration.ts +27 -0
- package/src/server/constants.ts +1 -0
- package/src/server/fields/.gitkeep +0 -0
- package/src/server/fields/circle.ts +50 -0
- package/src/server/fields/index.ts +4 -0
- package/src/server/fields/lineString.ts +56 -0
- package/src/server/fields/point.ts +59 -0
- package/src/server/fields/polygon.ts +56 -0
- package/src/server/helpers/index.ts +25 -0
- package/src/server/index.ts +1 -0
- package/src/server/plugin.ts +46 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PolygonField = void 0;
|
|
7
|
+
|
|
8
|
+
function _database() {
|
|
9
|
+
const data = require("@nocobase/database");
|
|
10
|
+
|
|
11
|
+
_database = function _database() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function _sequelize() {
|
|
19
|
+
const data = require("sequelize");
|
|
20
|
+
|
|
21
|
+
_sequelize = function _sequelize() {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return data;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var _helpers = require("../helpers");
|
|
29
|
+
|
|
30
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
31
|
+
|
|
32
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
33
|
+
|
|
34
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
35
|
+
|
|
36
|
+
class Polygon extends _sequelize().DataTypes.ABSTRACT {
|
|
37
|
+
constructor(...args) {
|
|
38
|
+
super(...args);
|
|
39
|
+
this.key = 'Polygon';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class PolygonField extends _database().Field {
|
|
45
|
+
constructor(options, context) {
|
|
46
|
+
const name = options.name;
|
|
47
|
+
super(_objectSpread({
|
|
48
|
+
get() {
|
|
49
|
+
const value = this.getDataValue(name);
|
|
50
|
+
|
|
51
|
+
if ((0, _helpers.isPg)(context)) {
|
|
52
|
+
return (0, _helpers.toValue)(value);
|
|
53
|
+
} else if ((0, _helpers.isMysql)(context)) {
|
|
54
|
+
return (value === null || value === void 0 ? void 0 : value.coordinates[0].slice(0, -1)) || null;
|
|
55
|
+
} else {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
set(value) {
|
|
61
|
+
var _value;
|
|
62
|
+
|
|
63
|
+
if (!((_value = value) === null || _value === void 0 ? void 0 : _value.length)) value = null;else if ((0, _helpers.isPg)(context)) {
|
|
64
|
+
value = (0, _helpers.joinComma)(value.map(item => (0, _helpers.joinComma)(item)));
|
|
65
|
+
} else if ((0, _helpers.isMysql)(context)) {
|
|
66
|
+
value = {
|
|
67
|
+
type: 'Polygon',
|
|
68
|
+
coordinates: [value.concat([value[0]])]
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
this.setDataValue(name, value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
}, options), context);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
get dataType() {
|
|
78
|
+
if ((0, _helpers.isPg)(this.context)) {
|
|
79
|
+
return Polygon;
|
|
80
|
+
} else if ((0, _helpers.isMysql)(this.context)) {
|
|
81
|
+
return _sequelize().DataTypes.GEOMETRY('POLYGON');
|
|
82
|
+
} else {
|
|
83
|
+
return _sequelize().DataTypes.JSON;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
exports.PolygonField = PolygonField;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const joinComma: (value: any[]) => string;
|
|
2
|
+
export declare const toValue: (value?: string) => any;
|
|
3
|
+
export declare const getDialect: (ctx: any) => any;
|
|
4
|
+
export declare const isPg: (ctx: any) => boolean;
|
|
5
|
+
export declare const isSqlite: (ctx: any) => boolean;
|
|
6
|
+
export declare const isMysql: (ctx: any) => boolean;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.toValue = exports.joinComma = exports.isSqlite = exports.isPg = exports.isMysql = exports.getDialect = void 0;
|
|
7
|
+
|
|
8
|
+
const joinComma = value => {
|
|
9
|
+
if (!value) return null;
|
|
10
|
+
return `(${value.join(',')})`;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
exports.joinComma = joinComma;
|
|
14
|
+
|
|
15
|
+
const toValue = value => {
|
|
16
|
+
if (!value) return null;
|
|
17
|
+
return JSON.parse(value.replace(/\(/g, '[').replace(/\)/g, ']'));
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
exports.toValue = toValue;
|
|
21
|
+
|
|
22
|
+
const getDialect = ctx => {
|
|
23
|
+
return (ctx.db || ctx.database).sequelize.getDialect();
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
exports.getDialect = getDialect;
|
|
27
|
+
|
|
28
|
+
const isPg = ctx => {
|
|
29
|
+
return getDialect(ctx) === 'postgres';
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
exports.isPg = isPg;
|
|
33
|
+
|
|
34
|
+
const isSqlite = ctx => {
|
|
35
|
+
return getDialect(ctx) === 'sqlite';
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
exports.isSqlite = isSqlite;
|
|
39
|
+
|
|
40
|
+
const isMysql = ctx => {
|
|
41
|
+
return getDialect(ctx) === 'mysql';
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
exports.isMysql = isMysql;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './plugin';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "default", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _plugin.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
var _plugin = _interopRequireDefault(require("./plugin"));
|
|
14
|
+
|
|
15
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { InstallOptions, Plugin } from '@nocobase/server';
|
|
2
|
+
export declare class MapPlugin extends Plugin {
|
|
3
|
+
afterAdd(): void;
|
|
4
|
+
beforeLoad(): void;
|
|
5
|
+
load(): Promise<void>;
|
|
6
|
+
install(options?: InstallOptions): Promise<void>;
|
|
7
|
+
afterEnable(): Promise<void>;
|
|
8
|
+
afterDisable(): Promise<void>;
|
|
9
|
+
remove(): Promise<void>;
|
|
10
|
+
}
|
|
11
|
+
export default MapPlugin;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.MapPlugin = void 0;
|
|
7
|
+
|
|
8
|
+
function _server() {
|
|
9
|
+
const data = require("@nocobase/server");
|
|
10
|
+
|
|
11
|
+
_server = function _server() {
|
|
12
|
+
return data;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
var _fields = require("./fields");
|
|
19
|
+
|
|
20
|
+
function _path() {
|
|
21
|
+
const data = require("path");
|
|
22
|
+
|
|
23
|
+
_path = function _path() {
|
|
24
|
+
return data;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
return data;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var _actions = require("./actions");
|
|
31
|
+
|
|
32
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
33
|
+
|
|
34
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
35
|
+
|
|
36
|
+
class MapPlugin extends _server().Plugin {
|
|
37
|
+
afterAdd() {}
|
|
38
|
+
|
|
39
|
+
beforeLoad() {
|
|
40
|
+
const fields = {
|
|
41
|
+
point: _fields.PointField,
|
|
42
|
+
polygon: _fields.PolygonField,
|
|
43
|
+
lineString: _fields.LineStringField,
|
|
44
|
+
circle: _fields.CircleField
|
|
45
|
+
};
|
|
46
|
+
this.db.registerFieldTypes(fields);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
load() {
|
|
50
|
+
var _this = this;
|
|
51
|
+
|
|
52
|
+
return _asyncToGenerator(function* () {
|
|
53
|
+
yield _this.db.import({
|
|
54
|
+
directory: (0, _path().resolve)(__dirname, 'collections')
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
_this.app.resource({
|
|
58
|
+
name: 'map-configuration',
|
|
59
|
+
actions: {
|
|
60
|
+
get: _actions.getConfiguration,
|
|
61
|
+
set: _actions.setConfiguration
|
|
62
|
+
},
|
|
63
|
+
only: ['get', 'set']
|
|
64
|
+
});
|
|
65
|
+
})();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
install(options) {
|
|
69
|
+
return _asyncToGenerator(function* () {})();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
afterEnable() {
|
|
73
|
+
return _asyncToGenerator(function* () {})();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
afterDisable() {
|
|
77
|
+
return _asyncToGenerator(function* () {})();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
remove() {
|
|
81
|
+
return _asyncToGenerator(function* () {})();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
exports.MapPlugin = MapPlugin;
|
|
87
|
+
var _default = MapPlugin;
|
|
88
|
+
exports.default = _default;
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nocobase/plugin-map",
|
|
3
|
+
"version": "0.8.1-alpha.3",
|
|
4
|
+
"main": "lib/server/index.js",
|
|
5
|
+
"devDependencies": {
|
|
6
|
+
"@nocobase/server": "0.8.1-alpha.3",
|
|
7
|
+
"@nocobase/test": "0.8.1-alpha.3"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@amap/amap-jsapi-loader": "^1.0.1",
|
|
11
|
+
"@amap/amap-jsapi-types": "^0.0.10",
|
|
12
|
+
"@emotion/css": "^11.7.1",
|
|
13
|
+
"@formily/react": "2.0.20",
|
|
14
|
+
"ahooks": "^3.7.2",
|
|
15
|
+
"antd": "~4.19.5",
|
|
16
|
+
"sequelize": "^6.26.0"
|
|
17
|
+
},
|
|
18
|
+
"gitHead": "e03df3df5962b99d9fbf5b6e33fbe2b23f14f3d3"
|
|
19
|
+
}
|
package/server.d.ts
ADDED
package/server.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
4
|
+
|
|
5
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
6
|
+
|
|
7
|
+
var _index = _interopRequireWildcard(require("./lib/server"));
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, "__esModule", {
|
|
10
|
+
value: true
|
|
11
|
+
});
|
|
12
|
+
var _exportNames = {};
|
|
13
|
+
Object.defineProperty(exports, "default", {
|
|
14
|
+
enumerable: true,
|
|
15
|
+
get: function get() {
|
|
16
|
+
return _index.default;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
Object.keys(_index).forEach(function (key) {
|
|
21
|
+
if (key === "default" || key === "__esModule") return;
|
|
22
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
23
|
+
if (key in exports && exports[key] === _index[key]) return;
|
|
24
|
+
Object.defineProperty(exports, key, {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _index[key];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import AMapLoader from '@amap/amap-jsapi-loader';
|
|
4
|
+
import '@amap/amap-jsapi-types';
|
|
5
|
+
import { useFieldSchema } from '@formily/react';
|
|
6
|
+
import { useCollection } from '@nocobase/client';
|
|
7
|
+
import { css } from '@emotion/css';
|
|
8
|
+
import { Alert, Button, Modal } from 'antd';
|
|
9
|
+
import { useMapTranslation } from '../locales';
|
|
10
|
+
import Search from './Search';
|
|
11
|
+
import { useMemoizedFn } from 'ahooks';
|
|
12
|
+
import { useMapConfiguration } from '../hooks';
|
|
13
|
+
import { useHistory } from 'react-router';
|
|
14
|
+
import { SyncOutlined } from '@ant-design/icons';
|
|
15
|
+
|
|
16
|
+
interface AMapComponentProps {
|
|
17
|
+
accessKey: string;
|
|
18
|
+
securityJsCode: string;
|
|
19
|
+
value: any;
|
|
20
|
+
onChange: (value: number[]) => void;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
mapType: string;
|
|
23
|
+
zoom: number;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const methodMapping = {
|
|
27
|
+
point: {
|
|
28
|
+
mouseTool: 'marker',
|
|
29
|
+
propertyKey: 'position',
|
|
30
|
+
overlay: 'Marker',
|
|
31
|
+
},
|
|
32
|
+
polygon: {
|
|
33
|
+
mouseTool: 'polygon',
|
|
34
|
+
editor: 'PolygonEditor',
|
|
35
|
+
propertyKey: 'path',
|
|
36
|
+
overlay: 'Polygon',
|
|
37
|
+
},
|
|
38
|
+
lineString: {
|
|
39
|
+
mouseTool: 'polyline',
|
|
40
|
+
editor: 'PolylineEditor',
|
|
41
|
+
propertyKey: 'path',
|
|
42
|
+
overlay: 'Polyline',
|
|
43
|
+
},
|
|
44
|
+
circle: {
|
|
45
|
+
mouseTool: 'circle',
|
|
46
|
+
editor: 'CircleEditor',
|
|
47
|
+
transformOptions(value) {
|
|
48
|
+
return {
|
|
49
|
+
center: value.slice(0, 2),
|
|
50
|
+
radius: value[2],
|
|
51
|
+
};
|
|
52
|
+
},
|
|
53
|
+
overlay: 'Circle',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const AMapComponent: React.FC<AMapComponentProps> = (props) => {
|
|
58
|
+
const { accessKey, securityJsCode } = useMapConfiguration(props.mapType) || {};
|
|
59
|
+
const { value, onChange, disabled, zoom = 13 } = props;
|
|
60
|
+
const { t } = useMapTranslation();
|
|
61
|
+
const fieldSchema = useFieldSchema();
|
|
62
|
+
const aMap = useRef<any>();
|
|
63
|
+
const map = useRef<AMap.Map>();
|
|
64
|
+
const mouseTool = useRef<any>();
|
|
65
|
+
const [needUpdateFlag, forceUpdate] = useState([]);
|
|
66
|
+
const [errMessage, setErrMessage] = useState('');
|
|
67
|
+
const { getField } = useCollection();
|
|
68
|
+
const collectionField = getField(fieldSchema.name);
|
|
69
|
+
const type = collectionField?.interface;
|
|
70
|
+
const overlay = useRef<any>();
|
|
71
|
+
const editor = useRef(null);
|
|
72
|
+
const history = useHistory();
|
|
73
|
+
const id = useRef(`nocobase-map-${type}-${Date.now().toString(32)}`);
|
|
74
|
+
|
|
75
|
+
const [commonOptions] = useState<AMap.PolylineOptions & AMap.PolygonOptions>({
|
|
76
|
+
strokeWeight: 5,
|
|
77
|
+
strokeColor: '#4e9bff',
|
|
78
|
+
fillColor: '#4e9bff',
|
|
79
|
+
strokeOpacity: 1,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const toRemoveOverlay = useMemoizedFn(() => {
|
|
83
|
+
if (overlay.current) {
|
|
84
|
+
map.current?.remove(overlay.current);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const setTarget = useMemoizedFn(() => {
|
|
89
|
+
if (!disabled && type !== 'point' && editor.current) {
|
|
90
|
+
editor.current.setTarget(overlay.current);
|
|
91
|
+
editor.current.open();
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const onMapChange = useMemoizedFn((target, onlyChange = false) => {
|
|
96
|
+
let nextValue = null;
|
|
97
|
+
|
|
98
|
+
if (type === 'point') {
|
|
99
|
+
const { lat, lng } = (target as AMap.Marker).getPosition();
|
|
100
|
+
nextValue = [lng, lat];
|
|
101
|
+
} else if (type === 'polygon' || type === 'lineString') {
|
|
102
|
+
nextValue = (target as AMap.Polygon).getPath().map((item) => [item.lng, item.lat]);
|
|
103
|
+
if (nextValue.length < 2) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
} else if (type === 'circle') {
|
|
107
|
+
const center = target.getCenter();
|
|
108
|
+
const radius = target.getRadius();
|
|
109
|
+
nextValue = [center.lng, center.lat, radius];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!onlyChange) {
|
|
113
|
+
toRemoveOverlay();
|
|
114
|
+
overlay.current = target;
|
|
115
|
+
setTarget();
|
|
116
|
+
}
|
|
117
|
+
onChange(nextValue);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const createEditor = useMemoizedFn(() => {
|
|
121
|
+
const mapping = methodMapping[type as keyof typeof methodMapping];
|
|
122
|
+
if (mapping && 'editor' in mapping && !editor.current) {
|
|
123
|
+
editor.current = new aMap.current[mapping.editor](map.current);
|
|
124
|
+
editor.current.on('adjust', function ({ target }) {
|
|
125
|
+
onMapChange(target, true);
|
|
126
|
+
});
|
|
127
|
+
editor.current.on('move', function ({ target }) {
|
|
128
|
+
onMapChange(target, true);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const executeMouseTool = useMemoizedFn(() => {
|
|
134
|
+
if (!mouseTool.current || editor.current?.getTarget()) return;
|
|
135
|
+
const mapping = methodMapping[type as keyof typeof methodMapping];
|
|
136
|
+
if (!mapping) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
mouseTool.current[mapping.mouseTool]({
|
|
140
|
+
...commonOptions,
|
|
141
|
+
} as AMap.PolylineOptions);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const createMouseTool = useMemoizedFn(() => {
|
|
145
|
+
if (mouseTool.current) return;
|
|
146
|
+
|
|
147
|
+
mouseTool.current = new aMap.current.MouseTool(map.current);
|
|
148
|
+
mouseTool.current.on('draw', function ({ obj }) {
|
|
149
|
+
onMapChange(obj);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
executeMouseTool();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const toCenter = (position, imm?: boolean) => {
|
|
156
|
+
if (map.current) {
|
|
157
|
+
map.current.setZoomAndCenter(18, position, imm);
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const onReset = () => {
|
|
162
|
+
const ok = () => {
|
|
163
|
+
toRemoveOverlay();
|
|
164
|
+
if (editor.current) {
|
|
165
|
+
editor.current.setTarget();
|
|
166
|
+
editor.current.close();
|
|
167
|
+
}
|
|
168
|
+
onChange(null);
|
|
169
|
+
};
|
|
170
|
+
Modal.confirm({
|
|
171
|
+
title: t('Clear the canvas'),
|
|
172
|
+
content: t('Are you sure to clear the canvas?'),
|
|
173
|
+
okText: t('Confirm'),
|
|
174
|
+
cancelText: t('Cancel'),
|
|
175
|
+
onOk() {
|
|
176
|
+
ok();
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const onFocusOverlay = () => {
|
|
182
|
+
if (overlay.current) {
|
|
183
|
+
map.current.setFitView([overlay.current]);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
// 编辑时
|
|
188
|
+
useEffect(() => {
|
|
189
|
+
if (!aMap.current) return;
|
|
190
|
+
if (!value || overlay.current) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const mapping = methodMapping[type as keyof typeof methodMapping];
|
|
194
|
+
if (!mapping) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const options = { ...commonOptions };
|
|
198
|
+
if ('transformOptions' in mapping) {
|
|
199
|
+
Object.assign(options, mapping.transformOptions(value));
|
|
200
|
+
} else if ('propertyKey' in mapping) {
|
|
201
|
+
options[mapping.propertyKey] = value;
|
|
202
|
+
}
|
|
203
|
+
const nextOverlay = new aMap.current[mapping.overlay](options);
|
|
204
|
+
|
|
205
|
+
// 聚焦在编辑的位置
|
|
206
|
+
map.current.setFitView([nextOverlay]);
|
|
207
|
+
|
|
208
|
+
nextOverlay.setMap(map.current);
|
|
209
|
+
overlay.current = nextOverlay;
|
|
210
|
+
|
|
211
|
+
createEditor();
|
|
212
|
+
setTarget();
|
|
213
|
+
}, [value, needUpdateFlag, type, commonOptions]);
|
|
214
|
+
|
|
215
|
+
// 当在编辑时,关闭 mouseTool
|
|
216
|
+
useEffect(() => {
|
|
217
|
+
if (!mouseTool.current) return;
|
|
218
|
+
|
|
219
|
+
if (disabled) {
|
|
220
|
+
mouseTool.current?.close();
|
|
221
|
+
editor.current?.close();
|
|
222
|
+
} else {
|
|
223
|
+
executeMouseTool();
|
|
224
|
+
editor.current?.open();
|
|
225
|
+
}
|
|
226
|
+
}, [disabled]);
|
|
227
|
+
|
|
228
|
+
// AMap.MouseTool & AMap.XXXEditor
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
if (!aMap.current || !type || disabled) return;
|
|
231
|
+
createMouseTool();
|
|
232
|
+
createEditor();
|
|
233
|
+
}, [disabled, needUpdateFlag, type]);
|
|
234
|
+
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
if (!mouseTool.current || !editor.current) return;
|
|
237
|
+
const target = editor.current.getTarget();
|
|
238
|
+
if (target) {
|
|
239
|
+
mouseTool.current.close?.();
|
|
240
|
+
} else {
|
|
241
|
+
executeMouseTool();
|
|
242
|
+
}
|
|
243
|
+
}, [type, value]);
|
|
244
|
+
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
if (!accessKey || map.current) return;
|
|
247
|
+
|
|
248
|
+
if (securityJsCode) {
|
|
249
|
+
(window as any)._AMapSecurityConfig = {
|
|
250
|
+
[securityJsCode.endsWith('_AMapService') ? 'serviceHOST' : 'securityJsCode']: securityJsCode,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
AMapLoader.load({
|
|
255
|
+
key: accessKey,
|
|
256
|
+
version: '2.0',
|
|
257
|
+
plugins: ['AMap.MouseTool', 'AMap.PolygonEditor', 'AMap.PolylineEditor', 'AMap.CircleEditor'],
|
|
258
|
+
})
|
|
259
|
+
.then((amap) => {
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
map.current = new amap.Map(id.current, {
|
|
262
|
+
resizeEnable: true,
|
|
263
|
+
zoom,
|
|
264
|
+
} as AMap.MapOptions);
|
|
265
|
+
aMap.current = amap;
|
|
266
|
+
setErrMessage('');
|
|
267
|
+
forceUpdate([]);
|
|
268
|
+
}, Math.random() * 300);
|
|
269
|
+
})
|
|
270
|
+
.catch((err) => {
|
|
271
|
+
if (err.includes('多个不一致的 key')) {
|
|
272
|
+
setErrMessage(t('The AccessKey is incorrect, please check it'));
|
|
273
|
+
} else {
|
|
274
|
+
setErrMessage(err);
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
return () => {
|
|
279
|
+
map.current?.destroy();
|
|
280
|
+
aMap.current = null;
|
|
281
|
+
map.current = null;
|
|
282
|
+
mouseTool.current = null;
|
|
283
|
+
editor.current = null;
|
|
284
|
+
};
|
|
285
|
+
}, [accessKey, type, securityJsCode]);
|
|
286
|
+
|
|
287
|
+
if (!accessKey || errMessage) {
|
|
288
|
+
return (
|
|
289
|
+
<Alert
|
|
290
|
+
action={
|
|
291
|
+
<Button type="primary" onClick={() => history.push('/admin/settings/map-configuration/configuration')}>
|
|
292
|
+
{t('Go to the configuration page')}
|
|
293
|
+
</Button>
|
|
294
|
+
}
|
|
295
|
+
message={errMessage || t('Please configure the AccessKey and SecurityJsCode first')}
|
|
296
|
+
type="error"
|
|
297
|
+
/>
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<div
|
|
303
|
+
className={css`
|
|
304
|
+
position: relative;
|
|
305
|
+
`}
|
|
306
|
+
id={id.current}
|
|
307
|
+
style={{
|
|
308
|
+
height: '500px',
|
|
309
|
+
}}
|
|
310
|
+
>
|
|
311
|
+
{/* bottom: 20px; right: 50%; transform: translateX(50%); z-index: 2; */}
|
|
312
|
+
<div
|
|
313
|
+
className={css`
|
|
314
|
+
position: absolute;
|
|
315
|
+
bottom: 80px;
|
|
316
|
+
right: 20px;
|
|
317
|
+
z-index: 10;
|
|
318
|
+
`}
|
|
319
|
+
>
|
|
320
|
+
<Button
|
|
321
|
+
onClick={onFocusOverlay}
|
|
322
|
+
disabled={!overlay.current}
|
|
323
|
+
type="primary"
|
|
324
|
+
shape="round"
|
|
325
|
+
size="large"
|
|
326
|
+
icon={<SyncOutlined />}
|
|
327
|
+
></Button>
|
|
328
|
+
</div>
|
|
329
|
+
{!disabled ? (
|
|
330
|
+
<>
|
|
331
|
+
<Search toCenter={toCenter} aMap={aMap.current} />
|
|
332
|
+
<div
|
|
333
|
+
className={css`
|
|
334
|
+
position: absolute;
|
|
335
|
+
bottom: 20px;
|
|
336
|
+
left: 10px;
|
|
337
|
+
z-index: 2;
|
|
338
|
+
pointer-events: none;
|
|
339
|
+
`}
|
|
340
|
+
>
|
|
341
|
+
<Alert message={t('Click to select the starting point and double-click to end the drawing')} type="info" />
|
|
342
|
+
</div>
|
|
343
|
+
<div
|
|
344
|
+
className={css`
|
|
345
|
+
position: absolute;
|
|
346
|
+
bottom: 20px;
|
|
347
|
+
right: 20px;
|
|
348
|
+
z-index: 2;
|
|
349
|
+
`}
|
|
350
|
+
>
|
|
351
|
+
<Button
|
|
352
|
+
disabled={!value}
|
|
353
|
+
style={{
|
|
354
|
+
height: '40px',
|
|
355
|
+
}}
|
|
356
|
+
onClick={onReset}
|
|
357
|
+
type="primary"
|
|
358
|
+
danger
|
|
359
|
+
>
|
|
360
|
+
{t('Clear')}
|
|
361
|
+
</Button>
|
|
362
|
+
</div>
|
|
363
|
+
</>
|
|
364
|
+
) : null}
|
|
365
|
+
</div>
|
|
366
|
+
);
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export default AMapComponent;
|