fix: 修改demo

This commit is contained in:
lzxue 2021-11-23 17:56:44 +08:00
parent 9de2360085
commit 86c5f97534
48 changed files with 1 additions and 2707 deletions

View File

@ -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',

View File

@ -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 }} />;
}

View File

@ -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>
);
}

View File

@ -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>
);
}

View File

@ -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}}/>;
}

View File

@ -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}}/>;
}

View File

@ -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: [],
};

View File

@ -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: [],
},
],
},
];

View File

@ -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>
);
}

View File

@ -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>
);
};

View File

@ -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 <></>;
}

View File

@ -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>
);
}

View File

@ -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>
);
}

View File

@ -1,13 +0,0 @@
.meahname {
padding: 20px;
}
.closeicon {
padding: 0 8px;
}
.edit {
display: flex;
align-items: center;
}
.edit span:hover {
color: #1890ff;
}

View File

@ -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>
)}
</>
);
}

View File

@ -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;
}

View File

@ -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>
);
}

View File

@ -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)
}

View File

@ -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 }} />;
}

View File

@ -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 }} />;
}

View File

@ -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 }} />;
}

View File

@ -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 }} />;
}

View File

@ -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: [],
};

View File

@ -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: [],
},
],
},
];

View File

@ -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>
}

View File

@ -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>
)
}

View File

@ -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;
}

View File

@ -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>
)
}

View File

@ -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 <></>;
}

View File

@ -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);
}

View File

@ -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>
)
}

View File

@ -1,13 +0,0 @@
.meahname {
padding: 20px;
}
.closeicon {
padding: 0 8px;
}
.edit {
display: flex;
align-items: center;
}
.edit span:hover {
color: #1890ff;
}

View File

@ -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}
</>
);
}

View File

@ -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>
);
}

View File

@ -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;
}

View File

@ -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>
)
}

View File

@ -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>
);
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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>
)
}

View File

@ -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)
}

View File

@ -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';

View File

@ -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;

View File

@ -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;

View File

@ -1,2 +0,0 @@
import Index from './task.en';
export default Index;

View File

@ -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,
}
}

View File

@ -1,2 +0,0 @@
import Index from './view.zh';
export default Index;

View File

@ -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;