6.3 KiB
6.3 KiB
网格管理页面设计文档
1. 页面概述
网格管理页面允许系统管理员创建、查看、编辑和删除地理网格。每个网格代表一个责任区域,可以关联到特定的主管或网格员。此功能是任务分配和地理数据可视化的基础。
2. 页面布局
2.1 布局结构
页面由两部分组成:
- 左侧: 网格列表,以表格形式展示所有已定义的网格及其基本信息(名称、负责人等)。
- 右侧: 交互式地图,用于可视化展示所选网格的地理边界。当创建或编辑网格时,地图将进入绘图模式。
3. 组件结构
<template>
<div class="grid-management-page">
<el-page-header title="网格管理" content="定义地理责任区" />
<el-row :gutter="20" class="page-container">
<!-- 左侧网格列表与操作 -->
<el-col :span="10" :xs="24">
<el-card>
<template #header>
<div class="table-toolbar">
<span>网格列表</span>
<el-button type="primary" icon="Plus" @click="handleCreate">新建网格</el-button>
</div>
</template>
<el-table :data="grids" v-loading="loading" @row-click="handleRowClick" highlight-current-row>
<el-table-column prop="name" label="网格名称" />
<el-table-column prop="manager" label="负责人" />
<el-table-column label="操作" width="120">
<template #default="{ row }">
<el-button link type="primary" @click.stop="handleEdit(row)">编辑</el-button>
<el-popconfirm title="确定删除此网格?" @confirm="handleDelete(row)">
<template #reference>
<el-button link type="danger" @click.stop>删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<!-- 右侧地图显示 -->
<el-col :span="14" :xs="24">
<el-card>
<template #header>地图预览</template>
<div ref="mapContainer" class="map-container"></div>
</el-card>
</el-col>
</el-row>
<!-- 网格编辑/创建对话框 -->
<GridFormDialog v-model="dialogVisible" :grid-id="selectedGridId" @success="onFormSuccess" />
</div>
</template>
4. 数据结构
// 网格列表项
interface GridListItem {
id: number;
name: string;
manager?: string;
// GeoJSON 字符串
geometry: string;
}
// 网格表单数据 (用于对话框)
interface GridFormData {
id?: number;
name: string;
managerId?: number;
// GeoJSON 字符串
geometry: string;
}
5. 状态管理
// 地图实例
let mapInstance = null;
let currentGridLayer = null;
// 组件内状态
const mapContainer = ref<HTMLElement>();
const dialogVisible = ref(false);
const selectedGridId = ref<number | null>(null);
// 全局状态 (Pinia Store)
const gridStore = useGridStore();
const { grids, loading } = storeToRefs(gridStore);
6. 交互逻辑
6.1 地图与列表交互
onMounted(() => {
gridStore.fetchGrids();
initializeMap();
});
const initializeMap = () => {
// ... 地图初始化逻辑
};
// 点击表格行,在地图上高亮显示对应网格
const handleRowClick = (row: GridListItem) => {
if (currentGridLayer) {
mapInstance.removeLayer(currentGridLayer);
}
if (row.geometry) {
const geoJson = JSON.parse(row.geometry);
currentGridLayer = L.geoJSON(geoJson).addTo(mapInstance);
mapInstance.fitBounds(currentGridLayer.getBounds());
}
};
6.2 CRUD 操作
const handleCreate = () => {
selectedGridId.value = null;
dialogVisible.value = true;
};
const handleEdit = (grid: GridListItem) => {
selectedGridId.value = grid.id;
dialogVisible.value = true;
};
const handleDelete = async (grid: GridListItem) => {
await gridStore.deleteGrid(grid.id);
ElMessage.success('网格删除成功');
gridStore.fetchGrids();
};
const onFormSuccess = () => {
dialogVisible.value = false;
gridStore.fetchGrids();
};
7. API 调用
// api/grid.ts
export const gridApi = {
getGrids: () => apiClient.get('/grid'),
getGridById: (id: number) => apiClient.get(`/grid/${id}`),
createGrid: (data: GridFormData) => apiClient.post('/grid', data),
updateGrid: (id: number, data: GridFormData) => apiClient.put(`/grid/${id}`, data),
deleteGrid: (id: number) => apiClient.delete(`/grid/${id}`),
};
// stores/grid.ts
export const useGridStore = defineStore('grid', {
state: () => ({
grids: [] as GridListItem[],
loading: false,
}),
actions: {
async fetchGrids() {
this.loading = true;
try {
const { data } = await gridApi.getGrids();
this.grids = data;
} finally {
this.loading = false;
}
},
// ... create, update, delete actions
}
});
8. 样式设计
.grid-management-page {
padding: 24px;
.page-container {
margin-top: 24px;
}
.table-toolbar {
display: flex;
justify-content: space-between;
align-items: center;
}
.map-container {
height: 600px;
}
}
9. 关联组件
GridFormDialog.vue
这是本页面的核心复杂组件,用于创建和编辑网格。
- Props:
modelValue,gridId - 内部组件:
- 一个表单,包含网格名称、负责人(下拉选择)等字段。
- 一个内嵌的 Leaflet 地图,用于绘制和编辑网格边界。
- 功能:
- 地图绘制: 提供多边形(Polygon)绘制工具。用户可以在地图上绘制闭合区域来定义网格边界。
- 数据加载: 在编辑模式下,根据
gridId加载网格数据,并在表单和内嵌地图上显示。 - 数据保存: 用户完成绘制和表单填写后,点击保存。组件将绘制的多边形转换为 GeoJSON 字符串,连同表单数据一起,调用 store 的 action 进行保存。
10. 测试用例
- 集成测试:
- 测试能否成功创建一个新网格,包括在地图上绘制边界和填写信息。
- 测试点击列表中的网格,地图上是否正确显示其边界。
- 测试编辑功能,包括修改网格信息和在地图上重新编辑边界。
- 测试删除网格功能。
