mirror of https://gitee.com/antv-l7/antv-l7
fix: 修改demo
This commit is contained in:
parent
9de2360085
commit
86c5f97534
|
@ -63,42 +63,12 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
name: {
|
||||
zh: '地理可视分开发框架',
|
||||
zh: 'Dipper 地理可视分开发框架',
|
||||
en: 'Dipper',
|
||||
},
|
||||
url: 'http://antv.vision/Dipper',
|
||||
},
|
||||
],
|
||||
Dipper: [
|
||||
{
|
||||
name: {
|
||||
zh: 'L7 React组件',
|
||||
en: 'L7React L7 For React',
|
||||
},
|
||||
url: 'http://antv.vision/L7-react/',
|
||||
},
|
||||
{
|
||||
name: {
|
||||
zh: 'L7Draw 地理围栏绘制组件库',
|
||||
en: 'L7Draw',
|
||||
},
|
||||
url: 'http://antv.vision/L7-draw/',
|
||||
},
|
||||
{
|
||||
name: {
|
||||
zh: 'L7Plot',
|
||||
en: 'L7Plot',
|
||||
},
|
||||
url: 'http://antv.vision/L7-draw/',
|
||||
},
|
||||
{
|
||||
name: {
|
||||
zh: 'L7Boundary 行政区划可视化库',
|
||||
en: 'L7Boundary',
|
||||
},
|
||||
url: 'http://antv.vision/L7-boundary/',
|
||||
},
|
||||
],
|
||||
docs: [
|
||||
{
|
||||
slug: 'api/l7',
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Bar } from '@antv/g2plot';
|
||||
|
||||
export interface ChatData {
|
||||
data: object[];
|
||||
legend?: boolean;
|
||||
loading?: boolean;
|
||||
}
|
||||
|
||||
export function BarCahrt({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [barplot, setBarplot] = useState<Bar>();
|
||||
useEffect(() => {
|
||||
if (!barplot && id.current) {
|
||||
const bar = new Bar(id.current, {
|
||||
// @ts-ignore
|
||||
data: data.sort((a, b) => b.xField - a.xField),
|
||||
autoFit: true,
|
||||
xField: 'yField',
|
||||
yField: 'xField',
|
||||
xAxis: false,
|
||||
label: {
|
||||
position: 'left',
|
||||
style: {
|
||||
fill: '#fff',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
|
||||
bar.render();
|
||||
setBarplot(bar);
|
||||
} else {
|
||||
barplot.update({
|
||||
data,
|
||||
});
|
||||
}
|
||||
}, [id.current, data]);
|
||||
|
||||
return <div ref={id} style={{ height: 300 }} />;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Line } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
export function LineCahrt({ data, loading }: ChatData) {
|
||||
const id = useRef();
|
||||
const [lineplot, setLinePlot] = useState<Line>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!lineplot && id.current && data) {
|
||||
const lineplot = new Line(id.current, {
|
||||
data,
|
||||
autoFit: true,
|
||||
xField: 'xField',
|
||||
yField: 'yField',
|
||||
seriesField: 'series',
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
lineplot.render();
|
||||
setLinePlot(lineplot);
|
||||
} else {
|
||||
lineplot.update({
|
||||
data,
|
||||
});
|
||||
}
|
||||
}, [id.current, data]);
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<div ref={id} style={{ height: 300 }} />
|
||||
</Spin>
|
||||
);
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Pie } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
import { Spin } from 'antd';
|
||||
|
||||
export function PieChart({ data, legend, loading }: ChatData) {
|
||||
const id = useRef();
|
||||
const [pieplot, setPiePlot] = useState<Pie>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!pieplot && id.current && data) {
|
||||
const pie = new Pie(id.current, {
|
||||
data,
|
||||
autoFit: true,
|
||||
angleField: 'xField',
|
||||
colorField: 'yField',
|
||||
radius: 0.7,
|
||||
label: {
|
||||
type: 'spider',
|
||||
labelHeight: 28,
|
||||
content: '{name}\n{percentage}',
|
||||
},
|
||||
legend: legend
|
||||
? {
|
||||
position: 'top-left',
|
||||
}
|
||||
: false,
|
||||
});
|
||||
|
||||
pie.render();
|
||||
setPiePlot(pie);
|
||||
} else {
|
||||
pieplot.update({
|
||||
data,
|
||||
});
|
||||
}
|
||||
}, [id.current, data]);
|
||||
|
||||
return (
|
||||
<Spin spinning={loading}>
|
||||
<div ref={id} style={{ height: 300 }} />
|
||||
</Spin>
|
||||
);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Line } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
|
||||
export function SingleLineCahrt({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [lineplot, setLinePlot] = useState<Line>();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!lineplot && id.current && data) {
|
||||
const area = new Line(id.current, {
|
||||
data,
|
||||
autoFit: true,
|
||||
xField: 'xField',
|
||||
yField: 'yField',
|
||||
});
|
||||
area.render();
|
||||
setLinePlot(area);
|
||||
}else{
|
||||
lineplot.update({
|
||||
data
|
||||
})
|
||||
}
|
||||
}, [id.current,data]);
|
||||
|
||||
return <div ref={id} style={{height:300}}/>;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Area } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
|
||||
export function StackAreaCahrt({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [pieplot, setAreaPlot] = useState<Area>();
|
||||
const [list,setData] = useState([])
|
||||
|
||||
useEffect(()=>{
|
||||
fetch('https://gw.alipayobjects.com/os/bmw-prod/b21e7336-0b3e-486c-9070-612ede49284e.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setData(data);
|
||||
});
|
||||
},[])
|
||||
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!pieplot && id.current && list) {
|
||||
const area = new Area(id.current, {
|
||||
data:list,
|
||||
autoFit: true,
|
||||
xField: 'date',
|
||||
yField: 'value',
|
||||
seriesField: 'country',
|
||||
legend:{
|
||||
position:'top-left'
|
||||
}
|
||||
});
|
||||
area.render();
|
||||
setAreaPlot(area);
|
||||
}else{
|
||||
pieplot.update({
|
||||
data:list
|
||||
})
|
||||
}
|
||||
}, [id.current,data]);
|
||||
|
||||
return <div ref={id} style={{height:300}}/>;
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
import { IConfig, SingleSequentialColorScale } from '@antv/dipper';
|
||||
import { CityList } from './mock';
|
||||
export const config: Partial<IConfig> = {
|
||||
viewData: {
|
||||
global: {
|
||||
filterData: [],
|
||||
areaCode: '330100',
|
||||
view: 'task',
|
||||
},
|
||||
widgets: {
|
||||
citySelect: {
|
||||
options: CityList,
|
||||
value: ['330000', '330100'],
|
||||
},
|
||||
},
|
||||
},
|
||||
headerbar: {
|
||||
display: true,
|
||||
title: {
|
||||
value: '数据分析',
|
||||
display: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '选择城市',
|
||||
type: 'citySelect',
|
||||
event: {
|
||||
actionType: 'map',
|
||||
action: 'queryArea',
|
||||
},
|
||||
},
|
||||
{
|
||||
display: false,
|
||||
position: 'right',
|
||||
type: 'publishbar',
|
||||
event: {
|
||||
actionType: 'map',
|
||||
action: 'publish',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
panel: {
|
||||
display: true,
|
||||
options: {
|
||||
enableToggle: true,
|
||||
defaultTitle: '所有网格',
|
||||
opened: true,
|
||||
width: 426,
|
||||
},
|
||||
position: 'right',
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
type: 'meshName',
|
||||
title: '网格名称',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
type: 'meshchart',
|
||||
title: '所有网格数据',
|
||||
},
|
||||
{
|
||||
display: false,
|
||||
type: 'panelTabContent',
|
||||
title: '所有网格',
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
type: 'mesh_indicator',
|
||||
title: '业务数据',
|
||||
},
|
||||
{
|
||||
type: 'total_data_panel',
|
||||
title: '人员数据',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
toolbar: {
|
||||
display: false,
|
||||
children: [],
|
||||
},
|
||||
map: {
|
||||
zoom: 10,
|
||||
center: [120.153576, 30.287459],
|
||||
pitch: 0,
|
||||
style: 'normal',
|
||||
},
|
||||
controls: [
|
||||
{
|
||||
display: true,
|
||||
position: 'topleft',
|
||||
type: 'filter',
|
||||
title: '筛选',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'bottomright',
|
||||
type: 'location',
|
||||
title: '定位',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'bottomright',
|
||||
type: 'mapStyle',
|
||||
title: '地图样式',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'topleft',
|
||||
type: 'searchPlaces',
|
||||
title: '地区搜索',
|
||||
},
|
||||
],
|
||||
defaultcontrols: [
|
||||
{
|
||||
type: 'zoom',
|
||||
position: 'bottomright',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
type: 'scale',
|
||||
position: 'bottomleft',
|
||||
display: true,
|
||||
},
|
||||
],
|
||||
popup: {
|
||||
enable: false,
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
type: 'gridLayer',
|
||||
options: {
|
||||
label: {
|
||||
field: 'name',
|
||||
size: 12,
|
||||
color: '#000',
|
||||
},
|
||||
fill: {
|
||||
field: 'unit_price',
|
||||
color: ['#A9D3FF', '#82B1FF', '#6294FF', '#457BFF', '#2962FF'],
|
||||
bandNum: 5,
|
||||
scale: 'quantile',
|
||||
unknownName: '无类型',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
legends: [],
|
||||
};
|
|
@ -1,267 +0,0 @@
|
|||
import Mock from 'mockjs';
|
||||
|
||||
// 单折线图
|
||||
export const singleLineChart = () => {
|
||||
const data = Mock.mock({
|
||||
'list|9': [
|
||||
{
|
||||
// 生成长度在 100~1000 之间的小写字母
|
||||
yField: '@integer(0,5000)',
|
||||
},
|
||||
],
|
||||
});
|
||||
return data.list
|
||||
.sort((a, b) => a.yField - b.yField)
|
||||
.map((item, index) => {
|
||||
return {
|
||||
xField: `${index + 1}月`,
|
||||
...item,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 条形图
|
||||
export const barChart = () => {
|
||||
let xField = ['餐饮', '影院', '百货购物中心', '国内旅游', '医疗'];
|
||||
const data = Mock.mock({
|
||||
'list|5': [
|
||||
{
|
||||
// 生成长度在 100~1000 之间的小写字母
|
||||
yField: '@integer(0,5000)',
|
||||
},
|
||||
],
|
||||
});
|
||||
return data.list
|
||||
.sort((a, b) => b.yField - a.yField)
|
||||
.map((item, index) => {
|
||||
return {
|
||||
xField: xField[index],
|
||||
...item,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 多维折线图
|
||||
export const multidimensionalChart = () => {
|
||||
const series = ['铺设失败', '铺设中', '铺设成功', '虚假铺设'];
|
||||
const xField = new Array(12).fill('').map((item, index) => {
|
||||
return `${2 * index + 2}:00`;
|
||||
});
|
||||
|
||||
return series
|
||||
.map((a, k) => {
|
||||
return xField.map((b, index) => {
|
||||
return {
|
||||
xField: b,
|
||||
series: a,
|
||||
yField: Number(
|
||||
((index + 1) * 10 + 20 * Math.random() + k * 20).toFixed(),
|
||||
),
|
||||
};
|
||||
});
|
||||
})
|
||||
.flat();
|
||||
};
|
||||
|
||||
// 作业单数
|
||||
export const operation = () => {
|
||||
const data = Mock.mock({
|
||||
'list|15': [
|
||||
{
|
||||
name: '@cname',
|
||||
order_count: '@integer(0,100)',
|
||||
staff_no: '@integer(100000,1000000)',
|
||||
},
|
||||
],
|
||||
});
|
||||
return data.list;
|
||||
};
|
||||
|
||||
// 行业市场份额
|
||||
export const marketShare = () => {
|
||||
const data = Mock.mock({
|
||||
'list|3': [
|
||||
{
|
||||
// 生成长度在 100~1000 之间的小写字母
|
||||
xField: '@integer(0,100)',
|
||||
},
|
||||
],
|
||||
});
|
||||
const yField = ['街电', '怪兽', '小电'];
|
||||
return data.list
|
||||
.sort((a, b) => a.yField - b.yField)
|
||||
.map((item, index) => {
|
||||
return {
|
||||
yField: yField[index],
|
||||
...item,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
// 各品牌营收
|
||||
export const brandRevenue = () => {
|
||||
const series = ['街电', '来电', '怪兽', '美团', '小电'];
|
||||
const xField = new Array(11).fill('').map((item, index) => {
|
||||
return `${2009 + index}`;
|
||||
});
|
||||
|
||||
return series
|
||||
.map((a, k) => {
|
||||
return xField.map((b, index) => {
|
||||
return {
|
||||
xField: b,
|
||||
series: a,
|
||||
yField: Number(
|
||||
((index + 1) * 10 + 30 * Math.random() + k * 20).toFixed(),
|
||||
),
|
||||
};
|
||||
});
|
||||
})
|
||||
.flat();
|
||||
};
|
||||
|
||||
export function randomData<T>(data: T): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve(data);
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
// 生成范围内的随机数
|
||||
export const randomNumBoth = (min: number, max: number) => {
|
||||
const Range = max - min;
|
||||
const Rand = Math.random();
|
||||
const num = min + Math.round(Rand * Range);
|
||||
return num;
|
||||
}
|
||||
|
||||
export const brandOption = [
|
||||
{ label: '全部类型', value: '1' },
|
||||
{ label: '街电', value: '2' },
|
||||
{ label: '怪兽', value: '3' },
|
||||
{ label: '小电', value: '4' },
|
||||
];
|
||||
|
||||
export const CityList = [
|
||||
{
|
||||
value: '330000',
|
||||
areaLevel: 'province',
|
||||
label: '浙江省',
|
||||
children: [
|
||||
{
|
||||
value: '330100',
|
||||
areaLevel: 'city',
|
||||
label: '杭州市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '110000',
|
||||
areaLevel: 'province',
|
||||
label: '北京市',
|
||||
children: [
|
||||
{
|
||||
value: '110000',
|
||||
areaLevel: 'city',
|
||||
label: '北京市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '120000',
|
||||
areaLevel: 'province',
|
||||
label: '天津市',
|
||||
children: [
|
||||
{
|
||||
value: '120000',
|
||||
areaLevel: 'city',
|
||||
label: '天津市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '310000',
|
||||
areaLevel: 'province',
|
||||
label: '上海市',
|
||||
children: [
|
||||
{
|
||||
value: '310000',
|
||||
areaLevel: 'province',
|
||||
label: '上海市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '440000',
|
||||
areaLevel: 'province',
|
||||
label: '广东省',
|
||||
children: [
|
||||
{
|
||||
value: '440100',
|
||||
areaLevel: 'city',
|
||||
label: '广州市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440300',
|
||||
areaLevel: 'city',
|
||||
label: '深圳市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440400',
|
||||
areaLevel: 'city',
|
||||
label: '珠海市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440600',
|
||||
areaLevel: 'city',
|
||||
label: '佛山市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '441300',
|
||||
areaLevel: 'city',
|
||||
label: '惠州市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '441900',
|
||||
areaLevel: 'city',
|
||||
label: '东莞市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '442000',
|
||||
areaLevel: 'city',
|
||||
label: '中山市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '130000',
|
||||
areaLevel: 'province',
|
||||
label: '河北省',
|
||||
children: [
|
||||
{
|
||||
value: '130100',
|
||||
areaLevel: 'city',
|
||||
label: '石家庄市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '131000',
|
||||
areaLevel: 'city',
|
||||
label: '廊坊市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
|
@ -1,27 +0,0 @@
|
|||
import { initWidgets } from './widgets';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { config } from './configs/config';
|
||||
import { DipperContainer, IConfig } from '@antv/dipper';
|
||||
import 'antd/dist/antd.css'
|
||||
interface IInitData {
|
||||
areaVOList: any[];
|
||||
sceneCode: string;
|
||||
areaCode: string;
|
||||
filterData: any[];
|
||||
}
|
||||
|
||||
export default function RumbMap() {
|
||||
const [mapConfig, setMapConfig] = useState<IConfig<IInitData>>();
|
||||
// 初始化相关数据
|
||||
|
||||
useEffect(() => {
|
||||
initWidgets();
|
||||
setMapConfig(config);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%',width:'100%',position:'absolute' }}>
|
||||
<DipperContainer<IInitData> cfg={mapConfig!} />
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import { Select } from 'antd';
|
||||
import React from 'react';
|
||||
import { useConfigService } from '@antv/dipper';
|
||||
import { brandOption } from '../configs/mock';
|
||||
|
||||
const { Option } = Select;
|
||||
|
||||
export const Filter = () => {
|
||||
const { setWidgetsValue } = useConfigService();
|
||||
|
||||
const onBrandChange = (e: any) => {
|
||||
setWidgetsValue('brand', e);
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ background: '#fff', borderRadius: 3 }}>
|
||||
<Select
|
||||
defaultValue="全部地区"
|
||||
style={{ width: 100, color: 'rgba(0,0,0,0.65)' }}
|
||||
bordered={false}
|
||||
>
|
||||
<Option value="全部地区">全部地区</Option>
|
||||
<Option value="示例地区1">示例地区1</Option>
|
||||
<Option value="示例地区2">示例地区2</Option>
|
||||
</Select>
|
||||
<Select
|
||||
defaultValue="1"
|
||||
style={{ width: 100, color: 'rgba(0,0,0,0.65)' }}
|
||||
bordered={false}
|
||||
onChange={(e) => onBrandChange(e)}
|
||||
>
|
||||
{brandOption.map((item) => {
|
||||
return (
|
||||
<Option key={item.label} value={item.value}>
|
||||
{item.label}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,140 +0,0 @@
|
|||
import {
|
||||
useSceneService,
|
||||
useConfigService,
|
||||
LayerGroupEventEnum,
|
||||
useLayerService,
|
||||
} from '@antv/dipper';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { GridLayerGroup } from '@antv/dipper';
|
||||
import { randomNumBoth } from '../configs/mock';
|
||||
const formatLegend = (data: any[]) => {
|
||||
return data.map((item) => {
|
||||
if (Array.isArray(item.value)) {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.map((v) => v.toFixed(2)),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.toFixed(2),
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
export function GridLayer() {
|
||||
const { layerService } = useLayerService();
|
||||
const { sceneService } = useSceneService();
|
||||
const { globalConfig, updateLegend, getWidgetsValue } = useConfigService();
|
||||
const { layers } = globalConfig;
|
||||
const [gridLayer, setGridLayer] = useState<GridLayerGroup>();
|
||||
const cityValue = getWidgetsValue('citySelect');
|
||||
const brandValue = getWidgetsValue('brand');
|
||||
const [geoData, setGeoData] = useState();
|
||||
|
||||
const layerProps = useMemo(() => {
|
||||
return layers.find((item: any) => item.type === 'gridLayer');
|
||||
}, [layers]);
|
||||
|
||||
const updateLayerLegend = (items: any[]) => {
|
||||
updateLegend('gridLayerLegend', {
|
||||
type: 'classifyColor',
|
||||
display: true,
|
||||
position: 'bottomleft',
|
||||
options: {
|
||||
title: '充电宝投放数量',
|
||||
unkownName: layerProps.options.unkownName,
|
||||
items: items.map((item) => {
|
||||
return {
|
||||
color: item.color,
|
||||
value: item.value.map((v) => {
|
||||
return (v / 10000).toFixed(2);
|
||||
}),
|
||||
};
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 根据筛选器条件请求数据
|
||||
useEffect(() => {
|
||||
// 可以根据业务需求配置接口
|
||||
fetch(
|
||||
`https://gw.alipayobjects.com/os/antvdemo/assets/dipper-city/${cityValue[1]}.json`,
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const geoDataList =
|
||||
data &&
|
||||
data.features?.map((item) => {
|
||||
return {
|
||||
...item,
|
||||
properties: {
|
||||
...item.properties,
|
||||
brand_type: randomNumBoth(1, 4).toString(), // 充电宝品牌
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
// 品牌 过滤
|
||||
if (brandValue && geoDataList) {
|
||||
// @ts-ignore
|
||||
const data =
|
||||
brandValue === '1'
|
||||
? geoDataList
|
||||
: geoDataList.filter(
|
||||
(item) => item.properties.brand_type === brandValue,
|
||||
);
|
||||
if (data.length) {
|
||||
// @ts-ignore
|
||||
setGeoData({ type: 'FeatureCollection', features: data });
|
||||
}
|
||||
} else {
|
||||
// @ts-ignore
|
||||
setGeoData({ type: 'FeatureCollection', features: geoDataList });
|
||||
}
|
||||
});
|
||||
// 切换城市 高德地图方法
|
||||
sceneService.getScene().map?.setCity(cityValue[1]);
|
||||
}, [JSON.stringify(cityValue), brandValue]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!geoData) {
|
||||
return;
|
||||
}
|
||||
if (gridLayer) {
|
||||
gridLayer.setData(geoData);
|
||||
return;
|
||||
}
|
||||
const layer = new GridLayerGroup({
|
||||
name: 'grid',
|
||||
data: geoData,
|
||||
options: layerProps.options,
|
||||
});
|
||||
layerService.addLayer(layer);
|
||||
|
||||
layer.on(LayerGroupEventEnum.DATAUPDATE, () => {
|
||||
layer.getLegendItem().map((item) => {
|
||||
if (Array.isArray(item.value)) {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.map((v) => v.toFixed(2)),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.toFixed(2),
|
||||
};
|
||||
}
|
||||
});
|
||||
updateLayerLegend(formatLegend(layer.getLegendItem()));
|
||||
});
|
||||
|
||||
// 更新图例
|
||||
updateLayerLegend(formatLegend(layer.getLegendItem()));
|
||||
|
||||
setGridLayer(layer);
|
||||
}, [geoData]);
|
||||
|
||||
return <></>;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { useLayerGroup } from '@antv/dipper';
|
||||
import { brandRevenue, marketShare } from '../../configs/mock';
|
||||
import { PieChart } from '../../components/Pie';
|
||||
import { LineCahrt } from '../../components/Line';
|
||||
|
||||
export function MeshChart() {
|
||||
const { selectFeatures } = useLayerGroup('grid');
|
||||
const [pieData, setPieData] = useState([]);
|
||||
const [lineData, setLineData] = useState([]);
|
||||
const [loding, setLoding] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setLoding(true);
|
||||
setTimeout(() => {
|
||||
setLoding(false);
|
||||
setPieData(marketShare());
|
||||
setLineData(brandRevenue());
|
||||
}, 300);
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
return (
|
||||
<div style={{ padding: '0 15px' }}>
|
||||
<div>
|
||||
<h4>行业市场份额</h4>
|
||||
<PieChart data={pieData || []} legend={false} loading={loding} />
|
||||
</div>
|
||||
<div>
|
||||
<h4>各品牌营收</h4>
|
||||
<LineCahrt data={lineData} loading={loding} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useLayerGroup } from '@antv/dipper';
|
||||
import { SingleLineCahrt } from '../components/SingleLine';
|
||||
import { singleLineChart, barChart } from '../configs/mock';
|
||||
import { BarCahrt } from '../components/Bar';
|
||||
|
||||
export function MeshIndicator() {
|
||||
const { selectFeatures } = useLayerGroup('grid');
|
||||
|
||||
// lineChart
|
||||
const [lineData, setLineData] = useState([]);
|
||||
|
||||
const [barData, setBarData] = useState([]);
|
||||
|
||||
// lineChart
|
||||
useEffect(() => {
|
||||
setLineData(singleLineChart());
|
||||
setBarData(barChart());
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
return (
|
||||
<div style={{ overflow: 'auto', height:'630px'}}>
|
||||
<div>
|
||||
<div style={{ margin: '10px 0' }}>交易笔数</div>
|
||||
<SingleLineCahrt data={lineData} />
|
||||
</div>
|
||||
<div>
|
||||
<div style={{ margin: '20px 0' }}>各场景覆盖数</div>
|
||||
<BarCahrt data={barData} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
.meahname {
|
||||
padding: 20px;
|
||||
}
|
||||
.closeicon {
|
||||
padding: 0 8px;
|
||||
}
|
||||
.edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.edit span:hover {
|
||||
color: #1890ff;
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
import React, {
|
||||
useRef,
|
||||
useState,
|
||||
useMemo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
} from 'react';
|
||||
import { CheckOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons';
|
||||
import styles from './index.module.css'
|
||||
import { Input } from 'antd';
|
||||
import { useLayerGroup, useConfigService } from '@antv/dipper';
|
||||
import _ from 'loadsh';
|
||||
|
||||
export function MeshName() {
|
||||
const { selectFeatures, updateProperties } = useLayerGroup('grid');
|
||||
const [edit, setEdit] = useState(false);
|
||||
const ref = useRef();
|
||||
const { setConfig } = useConfigService();
|
||||
|
||||
/**
|
||||
* get meshname
|
||||
* type []string
|
||||
*/
|
||||
const meshName = useMemo(() => {
|
||||
if (!selectFeatures.length) return [];
|
||||
return selectFeatures.map((item) => {
|
||||
// @ts-ignore
|
||||
return item.feature.properties.name;
|
||||
});
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
// 修改 网格名称
|
||||
const editMeshName = useCallback(() => {
|
||||
// @ts-ignore
|
||||
const value = ref.current.state.value;
|
||||
selectFeatures.forEach((item) => {
|
||||
const properties = {
|
||||
...item.feature.properties,
|
||||
name: value,
|
||||
};
|
||||
updateProperties(item.feature, properties);
|
||||
});
|
||||
setEdit(false);
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
// select more meshname 编辑 网格名称
|
||||
const EditMeshName = () => {
|
||||
return (
|
||||
<>
|
||||
{!edit ? (
|
||||
<div onClick={() => setEdit(!edit)}>
|
||||
<span>{meshName}</span>
|
||||
<EditOutlined style={{ paddingLeft: 12 }} />
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.edit}>
|
||||
<Input defaultValue={meshName} ref={ref} />
|
||||
<CheckOutlined
|
||||
onClick={editMeshName}
|
||||
className={styles.closeicon}
|
||||
/>
|
||||
<CloseOutlined onClick={() => setEdit(false)} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// show 多个网格名称
|
||||
const ShowMeshNames = () => {
|
||||
return (
|
||||
<div style={{ padding: 15 }}>
|
||||
{meshName.length >= 2 &&
|
||||
meshName.map((s) => {
|
||||
return <span key={s}>
|
||||
{s}、
|
||||
</span>;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (selectFeatures.length) {
|
||||
// TODO 报错
|
||||
setConfig(`panel.children.1.display`, false);
|
||||
setConfig(`panel.children.2.display`, true);
|
||||
// setConfig(`panel.children.${findIdMeshchart}.display`, false)
|
||||
} else {
|
||||
setConfig(`panel.children.1.display`, true);
|
||||
setConfig(`panel.children.2.display`, false);
|
||||
}
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{meshName && meshName.length ? (
|
||||
<div className={styles.meahname}>
|
||||
{meshName.length === 1 ? <EditMeshName /> : <ShowMeshNames />}
|
||||
</div>
|
||||
) : (
|
||||
<h4 style={{ padding: 15 }}>所有网格数据概览</h4>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
.teamcontainer {
|
||||
margin: 10px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.orderlist {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 48px;
|
||||
width: 378px;
|
||||
background: #fafafa;
|
||||
border-radius: 2px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
.orderlist .leftpart {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.orderlist .leftpart > div {
|
||||
padding-right: 15px;
|
||||
}
|
||||
.orderlist .leftpart .ordericon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.sort:hover {
|
||||
color: #1e73f8;
|
||||
}
|
||||
.orderCon :global .ant-list-split .ant-list-item {
|
||||
border: none !important;
|
||||
}
|
||||
.orderCon :global .ant-list-item {
|
||||
padding: 5px 0 !important;
|
||||
}
|
|
@ -1,116 +0,0 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useLayerGroup } from '@antv/dipper'
|
||||
import { Button, List } from 'antd';
|
||||
import { multidimensionalChart, operation } from '../../configs/mock';
|
||||
import styles from './index.module.css'
|
||||
import { LineCahrt } from '../../components/Line';
|
||||
|
||||
enum Sort {
|
||||
Up,
|
||||
Dowm,
|
||||
}
|
||||
|
||||
const No1 =
|
||||
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*grCBQ4izMjcAAAAAAAAAAAAAARQnAQ';
|
||||
const No2 =
|
||||
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*r0DyQIluJ8QAAAAAAAAAAAAAARQnAQ';
|
||||
const No3 =
|
||||
'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*5R92QrzHW7YAAAAAAAAAAAAAARQnAQ';
|
||||
|
||||
export function TotalPanel() {
|
||||
const { selectFeatures = [] } = useLayerGroup('grid');
|
||||
|
||||
const [lineData, setLineData] = useState([]);
|
||||
const [orderData, setOrderData] = useState([]);
|
||||
const [ordersort, setOrderSort] = useState<Sort>(1);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// lineChart
|
||||
useEffect(() => {
|
||||
setLoading(true)
|
||||
setTimeout(()=>{
|
||||
setLoading(false)
|
||||
setLineData(multidimensionalChart());
|
||||
},300)
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (ordersort === undefined) {
|
||||
return setOrderData(operation());
|
||||
}
|
||||
const sortData = operation();
|
||||
if (ordersort === 0) {
|
||||
return setOrderData(
|
||||
sortData.sort((a, b) => a.order_count - b.order_count),
|
||||
);
|
||||
}
|
||||
if (ordersort === 1) {
|
||||
return setOrderData(
|
||||
sortData.sort((a, b) => b.order_count - a.order_count),
|
||||
);
|
||||
}
|
||||
}, [selectFeatures, ordersort]);
|
||||
|
||||
// 排序
|
||||
const sorts = (type: Sort) => {
|
||||
setOrderSort(type);
|
||||
};
|
||||
|
||||
// orderData index 与 icon 映射
|
||||
const iconOrder = { 1: No1, 2: No2, 3: No3 };
|
||||
|
||||
return (
|
||||
<div style={{ overflow: 'auto', height:'560px'}}>
|
||||
<div>
|
||||
<h4>铺设进程</h4>
|
||||
<LineCahrt data={lineData} loading={loading}/>
|
||||
</div>
|
||||
<div className={styles.orderCon}>
|
||||
<div className={styles.teamcontainer}>
|
||||
<div>团队榜单</div>
|
||||
<div>
|
||||
<Button
|
||||
type={ordersort === 1 ? 'link' : 'text'}
|
||||
className={styles.sort}
|
||||
onClick={() => sorts(1)}
|
||||
>
|
||||
正序
|
||||
</Button>
|
||||
<Button
|
||||
type={ordersort === 0 ? 'link' : 'text'}
|
||||
className={styles.sort}
|
||||
onClick={() => sorts(0)}
|
||||
>
|
||||
倒叙
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
{orderData && (
|
||||
<List
|
||||
dataSource={orderData}
|
||||
renderItem={(item, index) => (
|
||||
<List.Item>
|
||||
<div className={styles.orderlist}>
|
||||
<div className={styles.leftpart}>
|
||||
{index <= 2 ? (
|
||||
<img
|
||||
src={iconOrder[index + 1]}
|
||||
className={styles.ordericon}
|
||||
/>
|
||||
) : (
|
||||
<div>{index + 1}</div>
|
||||
)}
|
||||
<span>
|
||||
{item.name}({item.staff_no})
|
||||
</span>
|
||||
</div>
|
||||
<div>作业成功{item.order_count}单</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import { registerWidget } from '@antv/dipper-core';
|
||||
import {
|
||||
CitySelect,
|
||||
NavBar,
|
||||
ClassifyColor,
|
||||
DiscreteColor,
|
||||
Draw,
|
||||
MapStyle,
|
||||
SearchPlace,
|
||||
Location,
|
||||
} from '@antv/dipper-widgets';
|
||||
import { GridLayer } from './GridLayer';
|
||||
import { MeshIndicator } from './MeshIndicator';
|
||||
import { MeshName } from './MeshName';
|
||||
import { Filter } from './Filter';
|
||||
import { TotalPanel } from './TotalPanel/index';
|
||||
import { MeshChart } from './MeshChart';
|
||||
|
||||
export function initWidgets() {
|
||||
registerWidget('citySelect', CitySelect);
|
||||
registerWidget('navibar', NavBar);
|
||||
registerWidget('gridLayer', GridLayer);
|
||||
registerWidget('classifyColor', ClassifyColor);
|
||||
registerWidget('discreteColor', DiscreteColor);
|
||||
registerWidget('mapStyle', MapStyle);
|
||||
registerWidget('searchPlaces', SearchPlace);
|
||||
registerWidget('location', Location);
|
||||
registerWidget('filter', Filter);
|
||||
registerWidget('mesh_indicator', MeshIndicator);
|
||||
registerWidget('total_data_panel', TotalPanel);
|
||||
registerWidget('meshchart', MeshChart);
|
||||
registerWidget('draw', Draw);
|
||||
registerWidget('meshName',MeshName)
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Bar } from '@antv/g2plot';
|
||||
|
||||
export interface ChatData {
|
||||
data: object[];
|
||||
}
|
||||
|
||||
export function BarChart({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [barplot, setBarplot] = useState<Bar>();
|
||||
useEffect(() => {
|
||||
if (!barplot && id.current) {
|
||||
const bar = new Bar(id.current, {
|
||||
// @ts-ignore
|
||||
data: data.sort((a, b) => b.xField - a.xField),
|
||||
autoFit: true,
|
||||
xField: 'xField',
|
||||
yField: 'yField',
|
||||
xAxis: false,
|
||||
label: {
|
||||
position: 'left',
|
||||
style: {
|
||||
fill: '#fff',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
|
||||
bar.render();
|
||||
setBarplot(bar);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return <div ref={id} style={{ height: 300 }} />;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Line } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
|
||||
export function LineChart({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [lineplot, setLinePlot] = useState<Line>();
|
||||
const [list, setData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/b21e7336-0b3e-486c-9070-612ede49284e.json',
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setData(data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!lineplot && id.current && list) {
|
||||
const area = new Line(id.current, {
|
||||
data: list,
|
||||
autoFit: true,
|
||||
xField: 'date',
|
||||
yField: 'value',
|
||||
seriesField: 'country',
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
area.render();
|
||||
setLinePlot(area);
|
||||
} else {
|
||||
lineplot.update({
|
||||
data: list,
|
||||
});
|
||||
}
|
||||
}, [id.current, list]);
|
||||
|
||||
return <div ref={id} style={{ height: 300 }} />;
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Pie } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
|
||||
export function PieChart({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [pieplot, setPiePlot] = useState<Pie>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!pieplot && id.current && data) {
|
||||
const bar = new Pie(id.current, {
|
||||
data,
|
||||
autoFit: true,
|
||||
angleField: 'xField',
|
||||
colorField: 'yField',
|
||||
radius: 0.7,
|
||||
label: {
|
||||
type: 'spider',
|
||||
labelHeight: 28,
|
||||
content: '{name}\n{percentage}',
|
||||
},
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
|
||||
bar.render();
|
||||
setPiePlot(bar);
|
||||
}
|
||||
}, [id.current, data]);
|
||||
|
||||
return <div ref={id} style={{ height: 300 }} />;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Area } from '@antv/g2plot';
|
||||
import { ChatData } from '../Bar';
|
||||
|
||||
export function StackAreaChart({ data }: ChatData) {
|
||||
const id = useRef();
|
||||
const [pieplot, setAreaPlot] = useState<Area>();
|
||||
const [list, setData] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetch(
|
||||
'https://gw.alipayobjects.com/os/bmw-prod/b21e7336-0b3e-486c-9070-612ede49284e.json',
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setData(data);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!pieplot && id.current && list) {
|
||||
const area = new Area(id.current, {
|
||||
data: list,
|
||||
autoFit: true,
|
||||
xField: 'date',
|
||||
yField: 'value',
|
||||
seriesField: 'country',
|
||||
legend: {
|
||||
position: 'top-left',
|
||||
},
|
||||
});
|
||||
area.render();
|
||||
setAreaPlot(area);
|
||||
} else {
|
||||
pieplot.update({
|
||||
data: list,
|
||||
});
|
||||
}
|
||||
}, [id.current, data]);
|
||||
|
||||
return <div ref={id} style={{ height: 300 }} />;
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
import { IConfig, SingleSequentialColorScale } from '@antv/dipper';
|
||||
import { CityList } from './mock';
|
||||
export const config: Partial<IConfig> = {
|
||||
viewData: {
|
||||
global: {
|
||||
filterData: [],
|
||||
areaCode: '110000',
|
||||
view: 'task',
|
||||
},
|
||||
widgets: {
|
||||
citySelect: {
|
||||
options: CityList,
|
||||
value: ['110000', '110000'],
|
||||
},
|
||||
},
|
||||
},
|
||||
headerbar: {
|
||||
display: true,
|
||||
title: {
|
||||
value: 'XX 管理地图地图',
|
||||
display: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '选择城市',
|
||||
type: 'citySelect',
|
||||
event: {
|
||||
actionType: 'map',
|
||||
action: 'queryArea',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
panel: {
|
||||
display: true,
|
||||
|
||||
position: 'right',
|
||||
options: {
|
||||
enableToggle: true,
|
||||
defaultTitle: '所有网格',
|
||||
opened: true,
|
||||
width: 426,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
type: 'meshName',
|
||||
title: '网格名称',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
type: 'activityTask',
|
||||
title: '活动任务',
|
||||
},
|
||||
],
|
||||
},
|
||||
toolbar: {
|
||||
display: true,
|
||||
children: [
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '全部活动',
|
||||
type: 'activity',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '全部状态',
|
||||
type: 'status',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '地图展示',
|
||||
type: 'mapExhibit',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'left',
|
||||
title: '人员搜索',
|
||||
type: 'searchPerson',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'right',
|
||||
title: '保存',
|
||||
type: 'save',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'right',
|
||||
type: 'publishbar',
|
||||
title: '发布',
|
||||
event: {
|
||||
actionType: 'map',
|
||||
action: 'publish',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
map: {
|
||||
zoom: 10,
|
||||
center: [120.153576, 30.287459],
|
||||
pitch: 0,
|
||||
style: 'normal',
|
||||
},
|
||||
controls: [
|
||||
{
|
||||
display: true,
|
||||
position: 'bottomright',
|
||||
type: 'mapStyle',
|
||||
title: '地图样式',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'rightcenter',
|
||||
type: 'meshTools',
|
||||
title: '网格工具',
|
||||
},
|
||||
{
|
||||
display: true,
|
||||
position: 'bottomright',
|
||||
type: 'location',
|
||||
title: '定位',
|
||||
},
|
||||
],
|
||||
defaultcontrols: [
|
||||
{
|
||||
type: 'zoom',
|
||||
position: 'bottomright',
|
||||
display: true,
|
||||
},
|
||||
{
|
||||
type: 'scale',
|
||||
position: 'bottomleft',
|
||||
display: true,
|
||||
},
|
||||
],
|
||||
popup: {
|
||||
enable: false,
|
||||
},
|
||||
layers: [
|
||||
{
|
||||
type: 'gridLayer',
|
||||
options: {
|
||||
label: {
|
||||
field: 'name',
|
||||
size: 12,
|
||||
color: '#000',
|
||||
},
|
||||
|
||||
fill: {
|
||||
field: 'unit_price',
|
||||
color: ['#CFE1B9', '#B0C298', '#90A276', '#718355'],
|
||||
unknownName: '无类型',
|
||||
scale: {
|
||||
type: 'cat',
|
||||
domain: ['C', 'B', 'A'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
legends: [],
|
||||
};
|
|
@ -1,199 +0,0 @@
|
|||
import Mock from 'mockjs';
|
||||
|
||||
export const chartList = Mock.mock({
|
||||
// 生成长度在 0~32 之间的小写字母
|
||||
success: '@string("lower", 0, 32)',
|
||||
// 生成长度在 0~32 之间的小写字母
|
||||
errorMessage: '@string("lower", 0, 32)',
|
||||
data: {
|
||||
'list|4-7': [
|
||||
{
|
||||
// 生成长度在 100~1000 之间的小写字母
|
||||
xField: '@integer(100,1000)',
|
||||
// 生成长度在 3~5 之间的中文
|
||||
yField: '@ctitle(3, 5)',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
export const personOption = () => {
|
||||
const data = Mock.mock({
|
||||
'list|10': [
|
||||
{
|
||||
label: '@cname',
|
||||
staffNo: '@integer(100000,1000000)',
|
||||
value: '@integer(100000,1000000)'
|
||||
},
|
||||
],
|
||||
})
|
||||
return data.list
|
||||
}
|
||||
|
||||
export const selectActivityItem = [
|
||||
{
|
||||
label: '双十一赢金币',
|
||||
value: '双十一赢金币',
|
||||
icon: 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*JYNuSaNAga8AAAAAAAAAAAAAARQnAQ'
|
||||
},
|
||||
{
|
||||
label: '充电桩铺设',
|
||||
value: '充电桩铺设',
|
||||
icon: 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*eay2Q7nXeG4AAAAAAAAAAAAAARQnAQ'
|
||||
},
|
||||
{
|
||||
label: '1块钱升级月卡',
|
||||
value: '1块钱升级月卡',
|
||||
icon: 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*nA0vQbl_hGMAAAAAAAAAAAAAARQnAQ'
|
||||
},
|
||||
{
|
||||
label: '免费充电1小时',
|
||||
value: '免费充电1小时',
|
||||
icon: 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*snkKRYonMgEAAAAAAAAAAAAAARQnAQ'
|
||||
},
|
||||
]
|
||||
|
||||
export function randomData<T>(data: T): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
resolve(data);
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
|
||||
export const ActivityOption = [
|
||||
{ label: '全部活动', value: '全部活动' },
|
||||
{ label: '双十一赢金币', value: '双十一赢金币' },
|
||||
{ label: '充电桩铺设', value: '充电桩铺设' },
|
||||
{ label: '1块钱升级月卡', value: '1块钱升级月卡' },
|
||||
{ label: '免费充电1小时', value: '免费充电1小时' }
|
||||
]
|
||||
|
||||
export const StatusOption = [
|
||||
{ label: '全部状态', value: '全部状态' },
|
||||
{ label: '未拓展', value: '未拓展' },
|
||||
{ label: '已拓展', value: '已拓展' },
|
||||
]
|
||||
|
||||
export const CityList = [
|
||||
{
|
||||
value: '330000',
|
||||
areaLevel: 'province',
|
||||
label: '浙江省',
|
||||
children: [
|
||||
{
|
||||
value: '330100',
|
||||
areaLevel: 'city',
|
||||
label: '杭州市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '110000',
|
||||
areaLevel: 'province',
|
||||
label: '北京市',
|
||||
children: [
|
||||
{
|
||||
value: '110000',
|
||||
areaLevel: 'city',
|
||||
label: '北京市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '120000',
|
||||
areaLevel: 'province',
|
||||
label: '天津市',
|
||||
children: [
|
||||
{
|
||||
value: '120000',
|
||||
areaLevel: 'city',
|
||||
label: '天津市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '310000',
|
||||
areaLevel: 'province',
|
||||
label: '上海市',
|
||||
children: [
|
||||
{
|
||||
value: '310000',
|
||||
areaLevel: 'province',
|
||||
label: '上海市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '440000',
|
||||
areaLevel: 'province',
|
||||
label: '广东省',
|
||||
children: [
|
||||
{
|
||||
value: '440100',
|
||||
areaLevel: 'city',
|
||||
label: '广州市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440300',
|
||||
areaLevel: 'city',
|
||||
label: '深圳市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440400',
|
||||
areaLevel: 'city',
|
||||
label: '珠海市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '440600',
|
||||
areaLevel: 'city',
|
||||
label: '佛山市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '441300',
|
||||
areaLevel: 'city',
|
||||
label: '惠州市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '441900',
|
||||
areaLevel: 'city',
|
||||
label: '东莞市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '442000',
|
||||
areaLevel: 'city',
|
||||
label: '中山市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: '130000',
|
||||
areaLevel: 'province',
|
||||
label: '河北省',
|
||||
children: [
|
||||
{
|
||||
value: '130100',
|
||||
areaLevel: 'city',
|
||||
label: '石家庄市',
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
value: '131000',
|
||||
areaLevel: 'city',
|
||||
label: '廊坊市',
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
|
@ -1,30 +0,0 @@
|
|||
import { initWidgets } from './widgets';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { config } from './configs/config';
|
||||
import { DipperContainer, IConfig } from '@antv/dipper';
|
||||
import 'antd/dist/antd.css'
|
||||
|
||||
interface IInitData {
|
||||
areaVOList: any[];
|
||||
sceneCode: string;
|
||||
areaCode: string;
|
||||
filterData: any[];
|
||||
}
|
||||
|
||||
export default function RumbMap() {
|
||||
|
||||
const [mapConfig, setMapConfig] = useState<IConfig<IInitData>>();
|
||||
// 初始化相关数据
|
||||
useEffect(() => {
|
||||
|
||||
initWidgets();
|
||||
setMapConfig(config);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%',width:'100%',position:'absolute'}}>
|
||||
<DipperContainer<IInitData> cfg={mapConfig!} />
|
||||
</div>
|
||||
);
|
||||
// return <h1>测试</h1>
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { Select } from 'antd';
|
||||
import React, { useState,useEffect } from 'react';
|
||||
import { ActivityOption } from '../configs/mock';
|
||||
|
||||
const { Option } = Select
|
||||
|
||||
export function Activity() {
|
||||
|
||||
const [active,setActive] = useState<string>()
|
||||
|
||||
useEffect(()=>{
|
||||
setActive(ActivityOption[0].value)
|
||||
},[])
|
||||
|
||||
return(
|
||||
<Select value={active} bordered={false}
|
||||
onChange={(e)=> setActive(e)}>
|
||||
{ ActivityOption.map((item)=>{
|
||||
return(
|
||||
<Option value={item.value} key={item.label}>{item.label}</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
)
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
.selectactivity {
|
||||
padding: 0 0 20px 20px ;
|
||||
}
|
||||
.selectactivity .select {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.selectactivity .select .selectitem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 183px;
|
||||
height: 64px;
|
||||
margin: 0 15px 15px 0;
|
||||
position: relative;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.selectactivity .select .selectitem .icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.selectactivity .select .selectitem .selecticon {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
top: 6px;
|
||||
}
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: calc(674px - 80px);
|
||||
justify-content: center;
|
||||
}
|
||||
.empty img {
|
||||
width: 216px;
|
||||
height: 132px;
|
||||
margin-left: 100px;
|
||||
}
|
||||
.empty span {
|
||||
color: rgba(0, 0, 0, 0.55);
|
||||
margin-top: 20px;
|
||||
}
|
||||
.submit {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
.task {
|
||||
height: calc(674px - 130px);
|
||||
position: relative;
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
import React, { useState, useMemo } from 'react'
|
||||
import { useLayerGroup } from '@antv/dipper'
|
||||
import { Alert, Button, Select } from 'antd'
|
||||
import { personOption, selectActivityItem } from '../../configs/mock'
|
||||
import style from './index.module.css'
|
||||
|
||||
const { Option } = Select
|
||||
|
||||
export function ActivityTask() {
|
||||
const selecticon = 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*kyI9T7Lrej4AAAAAAAAAAAAAARQnAQ'
|
||||
const emptyicon = 'https://gw.alipayobjects.com/mdn/rms_58ab56/afts/img/A*H9dxSp69pi0AAAAAAAAAAAAAARQnAQ'
|
||||
const { selectFeatures = [] } = useLayerGroup('grid')
|
||||
const [current, setCurrent] = useState(selectActivityItem[0]?.value)
|
||||
|
||||
const selectItem = (item) => {
|
||||
setCurrent(item)
|
||||
}
|
||||
|
||||
const alertMsg = useMemo(() => {
|
||||
if (selectFeatures.length === 2) {
|
||||
return '勾选多个网格中,批量分配后将一起更新数据'
|
||||
}
|
||||
if (selectFeatures.length >= 3) {
|
||||
return '你当前多选网格中包含已分配网格,无法批量分配,建议选择单个网格、或选择多个未分配网格的批量操作'
|
||||
}
|
||||
return '';
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
const HasSelectFeature = () => {
|
||||
return (
|
||||
<div>
|
||||
<div style={{ margin: '0 20px 20px' }}>
|
||||
{selectFeatures.length >= 2 && <Alert
|
||||
style={{ display:'flex', alignItems:'baseline' }}
|
||||
message={alertMsg}
|
||||
type="warning" showIcon
|
||||
/>}
|
||||
</div>
|
||||
<div className={style.selectactivity}>
|
||||
<h4>选择活动</h4>
|
||||
<div className={style.select}>
|
||||
{selectActivityItem && selectActivityItem.map((item) => {
|
||||
return (
|
||||
<div key={item.label}
|
||||
onClick={() => selectItem(item.value)}
|
||||
style={{
|
||||
border: current === item.value ? '1px solid #1E73F8' : '1px solid rgba(0,0,0,0.15)',
|
||||
}}
|
||||
className={style.selectitem}>
|
||||
<img className={style.icon} src={item.icon} />
|
||||
<span>{item.label}</span>
|
||||
{current === item.value && <img className={style.selecticon} src={selecticon} />}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ margin: '0 20px' }}>
|
||||
<h4>分配人员</h4>
|
||||
<Select mode="multiple" style={{ width: '100%' }}
|
||||
showArrow defaultValue={['吴家豪', '周星星']}>
|
||||
{personOption().map((item) => {
|
||||
return (
|
||||
<Option key={item.label} value={item.value}>{item.label}</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
<div className={style.submit}>
|
||||
<Button style={{ marginRight: 8 }}>取消</Button>
|
||||
<Button type='primary'>确定</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Empty = () => {
|
||||
return (
|
||||
<div className={style.empty}>
|
||||
<img src={emptyicon} />
|
||||
<span>暂无数据</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={style.task}>
|
||||
{!selectFeatures.length ? <Empty /> : <HasSelectFeature />}
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
import {
|
||||
useSceneService,
|
||||
useConfigService,
|
||||
LayerGroupEventEnum,
|
||||
useLayerService,
|
||||
} from '@antv/dipper';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { GridLayerGroup } from '@antv/dipper';
|
||||
const formatLegend = (data: any[]) => {
|
||||
return data.map((item) => {
|
||||
if (Array.isArray(item.value)) {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.map((v) => v.toFixed(2)),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.toFixed(2),
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
export function GridLayer() {
|
||||
const { layerService } = useLayerService();
|
||||
const { sceneService } = useSceneService();
|
||||
const { globalConfig, updateLegend, getWidgetsValue } = useConfigService();
|
||||
const { layers } = globalConfig;
|
||||
const [gridLayer, setGridLayer] = useState<GridLayerGroup>();
|
||||
const cityValue = getWidgetsValue('citySelect');
|
||||
const [geoData, setGeoData] = useState();
|
||||
|
||||
const layerProps = useMemo(() => {
|
||||
return layers.find((item: any) => item.type === 'gridLayer');
|
||||
}, [layers]);
|
||||
|
||||
const testData = {
|
||||
title: '图例',
|
||||
items: [
|
||||
{
|
||||
colors: ['#fef0d9', '#fdcc8a', '#fc8d59', '#e34a33', '#b30000'],
|
||||
title: '已分配',
|
||||
},
|
||||
{
|
||||
colors: ['#f1eef6', '#bdc9e1', '#74a9cf', '#2b8cbe', '#045a8d'],
|
||||
title: '未分配',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const updateLayerLegend = (items: any[]) => {
|
||||
updateLegend('gridLayerLegend', {
|
||||
type: 'multiClassifyColor',
|
||||
display: true,
|
||||
position: 'bottomleft',
|
||||
options: {
|
||||
title: '网格',
|
||||
unkownName: layerProps.options.unkownName,
|
||||
items: [
|
||||
{
|
||||
colors: ['#BEC3BD', '#A1A6A0', '#828681', '#646763'],
|
||||
title: '已分配',
|
||||
},
|
||||
{
|
||||
colors: ['#CFE1B9', '#B0C298', '#90A276', '#718355'],
|
||||
title: '未分配',
|
||||
},
|
||||
],
|
||||
values: items.map((item) => {
|
||||
return item.value.map((v) => {
|
||||
return (v / 10000).toFixed(2);
|
||||
});
|
||||
}),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 根据筛选器条件请求数据
|
||||
useEffect(() => {
|
||||
// 可以根据业务需求配置接口
|
||||
fetch(
|
||||
`https://gw.alipayobjects.com/os/antvdemo/assets/dipper-city/${cityValue[1]}.json`,
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
setGeoData(data);
|
||||
});
|
||||
// 切换城市 高德地图方法
|
||||
sceneService.getScene().map?.setCity(cityValue[1]);
|
||||
}, [JSON.stringify(cityValue)]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!geoData) {
|
||||
return;
|
||||
}
|
||||
if (gridLayer) {
|
||||
gridLayer.setData(geoData);
|
||||
return;
|
||||
}
|
||||
|
||||
const color = ['#CFE1B9','#B0C298','#90A276','#718355']
|
||||
|
||||
const layer = new GridLayerGroup({
|
||||
name: 'grid',
|
||||
data: geoData,
|
||||
options: {
|
||||
...layerProps.options,
|
||||
fill:{
|
||||
...layerProps.options.fill,
|
||||
color
|
||||
}
|
||||
},
|
||||
});
|
||||
layerService.addLayer(layer);
|
||||
|
||||
layer.on(LayerGroupEventEnum.DATAUPDATE, () => {
|
||||
layer.getLegendItem().map((item) => {
|
||||
if (Array.isArray(item.value)) {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.map((v) => v.toFixed(2)),
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...item,
|
||||
value: item.value.toFixed(2),
|
||||
};
|
||||
}
|
||||
});
|
||||
updateLayerLegend(formatLegend(layer.getLegendItem()));
|
||||
});
|
||||
|
||||
// 更新图例
|
||||
updateLayerLegend(formatLegend(layer.getLegendItem()));
|
||||
|
||||
setGridLayer(layer);
|
||||
}, [geoData]);
|
||||
|
||||
return <></>;
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
.exhibititem {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.exhibititem :global .ant-switch-checked {
|
||||
background-color: #1E73F8;
|
||||
}
|
||||
.dropdown {
|
||||
border-left: 1px solid #f3f3f3;
|
||||
border-right: 1px solid #f3f3f3;
|
||||
padding: 0 10px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
}
|
||||
.dropicon {
|
||||
padding-left: 8px;
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
import { DownOutlined } from "@ant-design/icons";
|
||||
import { Dropdown, Menu, Switch } from "antd";
|
||||
import React from "react";
|
||||
import style from './index.module.css'
|
||||
|
||||
export function MapExhibit() {
|
||||
const onChange = (e) => {
|
||||
// TODO 根据业务实现
|
||||
console.log(e)
|
||||
}
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="1">
|
||||
<div className={style.exhibititem}>
|
||||
<div style={{ marginRight: 50 }}>地图放大展示分配人员</div>
|
||||
<Switch defaultChecked size='small' onChange={onChange} />
|
||||
</div>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu}>
|
||||
<div className={style.dropdown} >
|
||||
地图展示<DownOutlined className={style.dropicon} />
|
||||
</div>
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
.meahname {
|
||||
padding: 20px;
|
||||
}
|
||||
.closeicon {
|
||||
padding: 0 8px;
|
||||
}
|
||||
.edit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.edit span:hover {
|
||||
color: #1890ff;
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
import React, { useRef, useState, useMemo, useCallback } from 'react';
|
||||
import { CheckOutlined, CloseOutlined, EditOutlined } from '@ant-design/icons';
|
||||
import styles from './index.module.css'
|
||||
import { Input } from 'antd';
|
||||
import { useLayerGroup } from '@antv/dipper';
|
||||
|
||||
export function MeshName() {
|
||||
const { selectFeatures, updateProperties } = useLayerGroup('grid');
|
||||
const [edit, setEdit] = useState(false);
|
||||
const ref = useRef();
|
||||
|
||||
/**
|
||||
* get meshname
|
||||
* type []string
|
||||
*/
|
||||
const meshName = useMemo(() => {
|
||||
if (!selectFeatures.length) return [];
|
||||
return selectFeatures.map((item) => {
|
||||
// @ts-ignore
|
||||
return item.feature.properties.name;
|
||||
});
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
// 修改 网格名称
|
||||
const editMeshName = useCallback(() => {
|
||||
// @ts-ignore
|
||||
const value = ref.current.state.value;
|
||||
selectFeatures.forEach((item) => {
|
||||
const properties = {
|
||||
...item.feature.properties,
|
||||
name: value,
|
||||
};
|
||||
updateProperties(item.feature, properties);
|
||||
});
|
||||
setEdit(false);
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
// select more meshname 编辑 网格名称
|
||||
const EditMeshName = () => {
|
||||
return (
|
||||
<>
|
||||
{!edit ? (
|
||||
<div onClick={() => setEdit(!edit)}>
|
||||
<span>{meshName}</span>
|
||||
<EditOutlined style={{ paddingLeft: 12 }}/>
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.edit}>
|
||||
<Input defaultValue={meshName} ref={ref} />
|
||||
<CheckOutlined
|
||||
onClick={editMeshName}
|
||||
className={styles.closeicon}
|
||||
/>
|
||||
<CloseOutlined onClick={() => setEdit(false)} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
// show 多个网格名称
|
||||
const ShowMeshNames = () => {
|
||||
return (
|
||||
<div>
|
||||
{meshName.length >= 2 && meshName.map((s) => {
|
||||
return (
|
||||
<span key={s}>{s},</span>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{meshName && meshName.length ? (
|
||||
<div className={styles.meahname}>
|
||||
{meshName.length === 1 ? <EditMeshName /> : <ShowMeshNames />}
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
import React from 'react';
|
||||
export function MeshSplitSvg() {
|
||||
return (
|
||||
<div style={{ marginLeft: 4 }}>
|
||||
<svg
|
||||
width="16px"
|
||||
height="20px"
|
||||
viewBox="0 0 16 16"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M7.74074074,2.02 C8.01688312,2.02 8.24074074,2.24385763 8.24074074,2.52 L8.24,7.797 L13.5185185,7.79777778 C13.7946609,7.79777778 14.0185185,8.0216354 14.0185185,8.29777778 L14.0185185,14.0385185 C14.0185185,14.3146609 13.7946609,14.5385185 13.5185185,14.5385185 L2,14.5385185 C1.72385763,14.5385185 1.5,14.3146609 1.5,14.0385185 L1.5,2.52 C1.5,2.24385763 1.72385763,2.02 2,2.02 L7.74074074,2.02 Z M7.26727273,3.06 L2.54,3.06 L2.54,13.46 L12.94,13.46 L12.94,8.73272727 L7.267,8.732 L7.26727273,3.06 Z M14,1.5 C14.2761424,1.5 14.5,1.72385763 14.5,2 L14.5,6.2962963 C14.5,6.57243867 14.2761424,6.7962963 14,6.7962963 L9.7037037,6.7962963 C9.42756133,6.7962963 9.2037037,6.57243867 9.2037037,6.2962963 L9.2037037,2 C9.2037037,1.72385763 9.42756133,1.5 9.7037037,1.5 L14,1.5 Z M13.617284,2.38271605 L10.0864198,2.38271605 L10.0864198,5.91358025 L13.617284,5.91358025 L13.617284,2.38271605 Z"
|
||||
id="形状结合"
|
||||
fill="#333333"
|
||||
></path>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MeshMergeSvg() {
|
||||
return (
|
||||
<div style={{ marginLeft: 4 }}>
|
||||
<svg
|
||||
width="14px"
|
||||
height="14px"
|
||||
viewBox="0 0 14 14"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>自动合并</title>
|
||||
<g
|
||||
id="设计方案"
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
>
|
||||
<g
|
||||
id="兼容性播报中心"
|
||||
transform="translate(-968.000000, -207.000000)"
|
||||
>
|
||||
<g id="自动合并" transform="translate(967.000000, 206.000000)">
|
||||
<rect id="矩形" x="0" y="0" width="16" height="16"></rect>
|
||||
<path
|
||||
d="M10.3121824,7.30025029 L10.3121824,13.8 C10.3121824,13.9104569 10.2226393,14 10.1121824,14 L2.2,14 C2.08954305,14 2,13.9104569 2,13.8 L2,5.64440342 C2,5.53394647 2.08954305,5.44440342 2.2,5.44440342 L8.27622473,5.44440342 L8.27622473,5.44440342 L8.27622473,2.2 C8.27622473,2.08954305 8.36576778,2 8.47622473,2 L13.8,2 C13.9104569,2 14,2.08954305 14,2.2 L14,7.10025029 C14,7.21070724 13.9104569,7.30025029 13.8,7.30025029 L10.3121824,7.30025029 L10.3121824,7.30025029 Z"
|
||||
id="路径-3"
|
||||
stroke="#333333"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
.meshTools{
|
||||
width: 32px;
|
||||
height: 160px;
|
||||
background: #fff;
|
||||
border-radius: 2px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding:15px 5px;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
import React, { useMemo, useState, useRef } from 'react';
|
||||
import styles from './index.module.css'
|
||||
import { MeshSplitSvg, MeshMergeSvg } from './SvgElement';
|
||||
import { useLayerGroup } from '@antv/dipper'
|
||||
import { Input, message, Modal, Popconfirm, Tooltip } from 'antd';
|
||||
|
||||
|
||||
export function MeshTools() {
|
||||
const { selectFeatures = [] } = useLayerGroup('grid')
|
||||
const [visible, setVisible] = useState(false)
|
||||
const refs = useRef()
|
||||
|
||||
const disable = { cursor: 'pointer', opacity: 1 }
|
||||
const noDisable = { cursor: 'not-allowed', opacity: 0.25 }
|
||||
|
||||
const cssPropsSplit = useMemo(() => {
|
||||
if (selectFeatures.length === 1) return disable;
|
||||
return noDisable;
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
const cssPropsMerge = useMemo(() => {
|
||||
if (selectFeatures.length >= 2) {
|
||||
return disable
|
||||
}
|
||||
return noDisable;
|
||||
}, [JSON.stringify(selectFeatures)]);
|
||||
|
||||
const splitMesh = () => {
|
||||
// TODO 根据业务实现
|
||||
}
|
||||
|
||||
const mergrMesh = () => {
|
||||
// @ts-ignore
|
||||
const value = refs.current.state.value
|
||||
if (!value) {
|
||||
return message.error('请输入要合并后的名称')
|
||||
}
|
||||
// TODO 根据业务实现
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.meshTools}>
|
||||
<Tooltip placement="left"
|
||||
title={selectFeatures.length === 1 ? '选择单个网格,可以拆分' : null}>
|
||||
<Popconfirm
|
||||
disabled={selectFeatures.length !== 1}
|
||||
placement='left'
|
||||
title='该网格将被拆分成xx个基础网格,你确定要拆分吗?'
|
||||
onConfirm={splitMesh}
|
||||
okText='确定'
|
||||
trigger='click'
|
||||
cancelText='取消'
|
||||
>
|
||||
<div style={{ ...cssPropsSplit }}>
|
||||
<MeshSplitSvg />
|
||||
<div style={{ width: 32 }}>网格拆分</div>
|
||||
</div>
|
||||
</Popconfirm>
|
||||
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip placement='left'
|
||||
title={selectFeatures.length >= 2 ? '选择多个网格,可以合并' : null}>
|
||||
<div style={{ ...cssPropsMerge }} onClick={() => setVisible(true)}>
|
||||
<MeshMergeSvg />
|
||||
<div style={{ width: 32 }}>网格合并</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<Modal title='网格合并'
|
||||
okText='确认' cancelText='取消'
|
||||
visible={visible} onOk={mergrMesh}
|
||||
onCancel={() => setVisible(false)}
|
||||
>
|
||||
<h4>合并后的新网格名称</h4>
|
||||
<Input ref={refs} placeholder='请输入名称' />
|
||||
</Modal>
|
||||
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
import { SaveOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
export function Save() {
|
||||
return (
|
||||
<Button type="text" icon={<SaveOutlined />}>
|
||||
保存
|
||||
</Button>
|
||||
);
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { Dropdown, Input, Menu, Select } from 'antd';
|
||||
import { SearchOutlined } from "@ant-design/icons";
|
||||
import { personOption } from "../configs/mock";
|
||||
|
||||
const { Search } = Input
|
||||
const { Option } = Select
|
||||
|
||||
// 此功能 仅做展示,以实际业务为准
|
||||
export function SearchPerson() {
|
||||
|
||||
const [persons, setPersons] = useState([])
|
||||
const [visible, setVisible] = useState(false)
|
||||
|
||||
const onSearch = (e) => {
|
||||
const value = e.target.value
|
||||
setTimeout(() => {
|
||||
if (value) {
|
||||
setPersons(personOption())
|
||||
setVisible(true)
|
||||
} else {
|
||||
setPersons([])
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
}, 300)
|
||||
}
|
||||
|
||||
// 人员搜索
|
||||
const onSelect = (value) =>{
|
||||
// TODO 根据业务实现
|
||||
}
|
||||
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item key="1">
|
||||
{persons && persons.map((item) => {
|
||||
return (
|
||||
<div key={item.label}
|
||||
onClick={()=>onSelect(item.value)}
|
||||
style={{ paddingBottom: '5px' }}
|
||||
>{item.label}</div>
|
||||
)
|
||||
})}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{ background:'#fff'}}>
|
||||
<Dropdown overlay={menu} visible={visible}>
|
||||
<Input bordered={false}
|
||||
placeholder="搜索网格名称/人员名称"
|
||||
prefix={<SearchOutlined />}
|
||||
onChange={onSearch}
|
||||
/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
import { SendOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
|
||||
export function Send() {
|
||||
return(
|
||||
<Button type='primary' icon={<SendOutlined rotate={-60} style={{color:'#fff'}}/>}>发布</Button>
|
||||
)
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
import { Select } from 'antd';
|
||||
import React,{ useState,useEffect } from 'react';
|
||||
import { StatusOption } from '../configs/mock';
|
||||
|
||||
const { Option } = Select
|
||||
|
||||
export function Status() {
|
||||
|
||||
const [status,setStatus] = useState<string>()
|
||||
|
||||
useEffect(()=>{
|
||||
setStatus(StatusOption[0].value)
|
||||
},[])
|
||||
|
||||
return(
|
||||
<Select value={status} bordered={false}
|
||||
onChange={(e)=> setStatus(e)}>
|
||||
{ StatusOption.map((item)=>{
|
||||
return(
|
||||
<Option value={item.value} key={item.label}>{item.label}</Option>
|
||||
)
|
||||
})}
|
||||
</Select>
|
||||
)
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
import { registerWidget } from '@antv/dipper-core';
|
||||
import {
|
||||
CitySelect,
|
||||
ClassifyColor,
|
||||
DiscreteColor,
|
||||
} from '@antv/dipper-widgets';
|
||||
import { Activity } from './Activity';
|
||||
import { ActivityTask } from './ActivityTask';
|
||||
import { GridLayer } from './GridLayer';
|
||||
import { MeshName } from './MeshName/index';
|
||||
import { Save } from './Save';
|
||||
import { SearchPerson } from './SearchPerson';
|
||||
import { Send } from './Send';
|
||||
import { Status } from './Status';
|
||||
import { MeshTools } from './MeshTools';
|
||||
import { MapExhibit } from './MapExhibit/index';
|
||||
|
||||
export function initWidgets() {
|
||||
registerWidget('citySelect', CitySelect);
|
||||
registerWidget('gridLayer', GridLayer);
|
||||
registerWidget('classifyColor', ClassifyColor);
|
||||
registerWidget('discreteColor', DiscreteColor);
|
||||
registerWidget('meshName', MeshName);
|
||||
registerWidget('meshTools',MeshTools)
|
||||
|
||||
registerWidget('save', Save);
|
||||
registerWidget('publishbar', Send);
|
||||
registerWidget('activity', Activity);
|
||||
registerWidget('status',Status);
|
||||
registerWidget('mapExhibit', MapExhibit);
|
||||
registerWidget('searchPerson',SearchPerson)
|
||||
registerWidget('activityTask',ActivityTask)
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
import Banner from '@antv/gatsby-theme-antv/site/components/Banner';
|
||||
import BannerSVG from '@antv/gatsby-theme-antv/site/components/BannerSVG';
|
||||
import Cases from '@antv/gatsby-theme-antv/site/components/Cases';
|
||||
import Companies from '@antv/gatsby-theme-antv/site/components/Companies';
|
||||
import Features from '@antv/gatsby-theme-antv/site/components/Features';
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
import React from 'react';
|
||||
import Loadable from "@loadable/component"
|
||||
const Map = Loadable(() => import("../components/analysis"))
|
||||
const Page: React.FC & { noLayout: boolean } = () => <Map/>;
|
||||
|
||||
Page.noLayout = true;
|
||||
|
||||
export default Page;
|
|
@ -1,8 +0,0 @@
|
|||
import React from 'react';
|
||||
import Loadable from "@loadable/component"
|
||||
const Map = Loadable(() => import("../components/task"))
|
||||
const Page: React.FC & { noLayout: boolean } = () => <Map/>;
|
||||
|
||||
Page.noLayout = true;
|
||||
|
||||
export default Page;
|
|
@ -1,2 +0,0 @@
|
|||
import Index from './task.en';
|
||||
export default Index;
|
|
@ -1,159 +0,0 @@
|
|||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useConfig = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
// 通知
|
||||
const notifications = useMemo(() => {
|
||||
return [{
|
||||
type: t('推荐'),
|
||||
title: t('如何制作不一样的疫情世界地图-酷炫、动感的地理可视化'),
|
||||
date: '2020.03.12',
|
||||
link: 'https://www.yuque.com/antv/blog/wigku2',
|
||||
},
|
||||
{
|
||||
type: t('新版发布'),
|
||||
title: t('L7 2.1 正式版'),
|
||||
date: '2020.03.12',
|
||||
link: ' https://www.yuque.com/antv/blog/ows55v',
|
||||
},
|
||||
];
|
||||
}, []);
|
||||
|
||||
// L7 特性
|
||||
const L7Features = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
icon:
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/ca2168d1-ae50-4929-8738-c6df62231de3.svg',
|
||||
title: t('架构灵活且自由'),
|
||||
description: t('支持地图底图,渲染引擎,图层自由定制、扩展,组合'),
|
||||
},
|
||||
{
|
||||
icon:
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/0ccf4dcb-1bac-4f4e-8d8d-f1031c77c9c8.svg',
|
||||
title: t('业务专业且通用'),
|
||||
description: t(
|
||||
'以图形符号学地理设计体系理论基础,易用、易理解、专业、专注',
|
||||
),
|
||||
},
|
||||
{
|
||||
icon:
|
||||
'https://gw.alipayobjects.com/zos/basement_prod/fd232581-14b3-45ec-a85c-fb349c51b376.svg',
|
||||
title: t('视觉酷炫且动感'),
|
||||
description: t('支持海量数据,2D、3D,动态,可交互,高性能渲染'),
|
||||
},
|
||||
];
|
||||
|
||||
}, [])
|
||||
|
||||
|
||||
const L7Case = useMemo(() => {
|
||||
return [
|
||||
{
|
||||
logo:
|
||||
'https://antv-2018.alipay.com/assets/image/icon/l7.svg',
|
||||
title: t('指挥分配场景'),
|
||||
description: t(
|
||||
'区域化网格化数据管理指挥分配场景',
|
||||
),
|
||||
link: `/${i18n.language}/task`,
|
||||
image:
|
||||
'https://gw.alipayobjects.com/mdn/rms_08cc33/afts/img/A*CLJESKDO1g4AAAAAAAAAAAAAARQnAQ',
|
||||
},
|
||||
{
|
||||
logo:
|
||||
'https://antv-2018.alipay.com/assets/image/icon/l7.svg',
|
||||
title: t('地图数据分析'),
|
||||
description: t(
|
||||
'区域化网格化数据分析场景',
|
||||
),
|
||||
link: `/${i18n.language}/view`,
|
||||
image:
|
||||
'https://gw.alipayobjects.com/mdn/rms_08cc33/afts/img/A*jb4tS7BiNo4AAAAAAAAAAAAAARQnAQ',
|
||||
},
|
||||
{
|
||||
logo:
|
||||
'https://gw.alipayobjects.com/zos/bmw-prod/222865fc-15e9-44b9-b726-444e1512d937.ico',
|
||||
title: t('地理分析工具'),
|
||||
description: t(
|
||||
'地图可视化配置分析类场景',
|
||||
),
|
||||
link: `/${i18n.language}/examples/gallery/basic`,
|
||||
image:
|
||||
'https://gw.alipayobjects.com/mdn/rms_e7e1c6/afts/img/A*MPWKQqh54vwAAAAAAAAAAAAAARQnAQ',
|
||||
},
|
||||
]
|
||||
|
||||
}, [])
|
||||
const companies = useMemo(() => [{
|
||||
name: '阿里云',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*V_xMRIvw2iwAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '支付宝',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*lYDrRZvcvD4AAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '天猫',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*BQrxRK6oemMAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '淘宝网',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*1l8-TqUr7UcAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '网商银行',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*ZAKFQJ5Bz4MAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '盒马',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ePJMQZCb8vkAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: 'yunos',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*_js7SaNosUwAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '菜鸟',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*TgV-RZDODJIAAAAAAAAAAABkARQnAQ',
|
||||
}
|
||||
], []);
|
||||
|
||||
const ecosystems = useMemo(() => [{
|
||||
name: '阿里云',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*V_xMRIvw2iwAAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '支付宝',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*lYDrRZvcvD4AAAAAAAAAAABkARQnAQ',
|
||||
},
|
||||
{
|
||||
name: '天猫',
|
||||
img:
|
||||
'https://gw.alipayobjects.com/mdn/rms_2274c3/afts/img/A*BQrxRK6oemMAAAAAAAAAAABkARQnAQ',
|
||||
}
|
||||
], []);
|
||||
|
||||
return {
|
||||
ecosystems,
|
||||
L7Features,
|
||||
notifications,
|
||||
companies,
|
||||
L7Case,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
import Index from './view.zh';
|
||||
export default Index;
|
|
@ -1,8 +0,0 @@
|
|||
import React from 'react';
|
||||
import Loadable from "@loadable/component"
|
||||
const Map = Loadable(() => import("../components/analysis"))
|
||||
const Page: React.FC & { noLayout: boolean } = () => <Map/>;
|
||||
|
||||
Page.noLayout = true;
|
||||
|
||||
export default Page;
|
Loading…
Reference in New Issue