feat: 添加HTTP客户端、API接口、地图组件及复用函数
This commit is contained in:
parent
c3004d0780
commit
c5c713c908
|
@ -0,0 +1,32 @@
|
|||
const base = "/api/v1/feature";
|
||||
|
||||
export interface FeatureListParams {
|
||||
name?: string;
|
||||
status?: string;
|
||||
page: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface FeatureCreateParams {}
|
||||
|
||||
export interface FeatureUpdateParams {}
|
||||
|
||||
export const list = async <T>(params: FeatureListParams) => {
|
||||
return useHttp<T>(base + "s", { method: "GET", params });
|
||||
};
|
||||
|
||||
// export const detail = async (id: string) => {
|
||||
// return useHttp.get(base + "/" + id);
|
||||
// };
|
||||
|
||||
// export const create = async (params: FeatureCreateParams) => {
|
||||
// return useHttp.post(base, params);
|
||||
// };
|
||||
|
||||
// export const update = async (params: FeatureUpdateParams) => {
|
||||
// return useHttp.put(base, params);
|
||||
// };
|
||||
|
||||
// export const remove = async (id: string) => {
|
||||
// return useHttp.delete(base + "/" + id);
|
||||
// };
|
|
@ -0,0 +1,5 @@
|
|||
import * as feature from "./feature";
|
||||
|
||||
export default {
|
||||
feature,
|
||||
};
|
|
@ -0,0 +1,90 @@
|
|||
<script setup lang="ts">
|
||||
import maplibregl from "maplibre-gl";
|
||||
import "maplibre-gl/dist/maplibre-gl.css";
|
||||
import * as turf from "@turf/turf";
|
||||
import MapboxDraw from "@mapbox/mapbox-gl-draw";
|
||||
import "@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css";
|
||||
|
||||
const mapContainer = useTemplateRef("mapContainer");
|
||||
|
||||
const map = ref<maplibregl.Map>();
|
||||
|
||||
const {feature} = useApi();
|
||||
|
||||
MapboxDraw.constants.classes.CANVAS = 'maplibregl-canvas';
|
||||
MapboxDraw.constants.classes.CONTROL_BASE = 'maplibregl-ctrl';
|
||||
MapboxDraw.constants.classes.CONTROL_PREFIX = 'maplibregl-ctrl-';
|
||||
MapboxDraw.constants.classes.CONTROL_GROUP = 'maplibregl-ctrl-group';
|
||||
MapboxDraw.constants.classes.ATTRIBUTION = 'maplibregl-ctrl-attrib';
|
||||
|
||||
MapboxDraw.lib.theme.find((x: any) => x.id === 'gl-draw-lines').paint['line-dasharray'] = [0.2, 2]
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
if (!mapContainer.value) return;
|
||||
map.value = new maplibregl.Map({
|
||||
container: mapContainer.value, // container id
|
||||
style: "https://demotiles.maplibre.org/style.json", // style URL
|
||||
center: [0, 0], // starting position [lng, lat]
|
||||
zoom: 12, // starting zoom
|
||||
});
|
||||
// map.value.removeControl(map.value._controls[0]);
|
||||
const draw = new MapboxDraw({
|
||||
displayControlsDefault: false,
|
||||
controls: {
|
||||
polygon: true,
|
||||
trash: true
|
||||
}
|
||||
})
|
||||
|
||||
const updateArea = (e: any) => {
|
||||
const data = draw.getAll();
|
||||
console.log(data)
|
||||
}
|
||||
|
||||
map.value.addControl(draw, "top-right");
|
||||
map.value.on('draw.create', updateArea);
|
||||
map.value.on('draw.delete', updateArea);
|
||||
map.value.on('draw.update', updateArea);
|
||||
map.value.on('draw.selectionchange', (e: any) => {
|
||||
console.log(e)
|
||||
});
|
||||
|
||||
const {data, status} = await feature.list<any>({page: 1, size: 10});
|
||||
if (status.value !== 'success') return;
|
||||
let jsonData = turf.featureCollection(data.value.data.map((x: any) => turf.feature(x.geometry, {
|
||||
id: x.id,
|
||||
name: x.name
|
||||
})));
|
||||
console.log(jsonData);
|
||||
|
||||
map.value.addSource("data", {type: "geojson", data: jsonData});
|
||||
map.value.addLayer({
|
||||
id: "data-symbol",
|
||||
type: "symbol",
|
||||
source: "data",
|
||||
paint: {
|
||||
"text-color": "#000",
|
||||
},
|
||||
layout: {
|
||||
"text-field": ["get", "name"],
|
||||
"text-font": ["Open Sans Regular", "Arial Unicode MS Regular"],
|
||||
"text-size": 12,
|
||||
},
|
||||
});
|
||||
map.value.addLayer({
|
||||
id: "data-fill",
|
||||
type: "fill",
|
||||
source: "data",
|
||||
paint: {
|
||||
"fill-color": "#000",
|
||||
"fill-opacity": 0.5,
|
||||
"fill-outline-color": "#FF0000", // 添加边界线颜色
|
||||
},
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="mapContainer" class="w-full h-full"/>
|
||||
</template>
|
|
@ -0,0 +1,3 @@
|
|||
import apis from "~/apis";
|
||||
|
||||
export const useApi = () => apis
|
|
@ -0,0 +1,8 @@
|
|||
import type { UseFetchOptions } from "nuxt/app";
|
||||
|
||||
export const useHttp = <T>(
|
||||
url: string | (() => string),
|
||||
options: UseFetchOptions<T> = {}
|
||||
) => {
|
||||
return useFetch(url, { ...options, $fetch: useNuxtApp().$http });
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
import type { FetchResponse, SearchParameters } from "ofetch";
|
||||
|
||||
export interface ResponseOptions<T> {
|
||||
data: T;
|
||||
code: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin((nuxtApp) => {
|
||||
const err = (text: string) => {
|
||||
console.log(text);
|
||||
};
|
||||
|
||||
const handleStatus: { [key: number]: () => void } = {
|
||||
404: () => err("服务器资源不存在"),
|
||||
500: () => err("服务器内部错误"),
|
||||
403: () => err("没有权限访问该资源"),
|
||||
401: () => err("登录状态已过期,需要重新登录"),
|
||||
};
|
||||
|
||||
const handleError = <T>(
|
||||
response: FetchResponse<ResponseOptions<T>> & FetchResponse<ResponseType>
|
||||
) => {
|
||||
if (!response._data) {
|
||||
err("请求超时,服务器无响应!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (handleStatus[response.status]) {
|
||||
handleStatus[response.status]();
|
||||
} else {
|
||||
err("未知错误!");
|
||||
}
|
||||
};
|
||||
|
||||
const paramsSerializer = (params?: SearchParameters) => {
|
||||
if (!params) return;
|
||||
const query = useCloned(params, { deep: true }) as any;
|
||||
Object.entries(query).forEach(([key, value]) => {
|
||||
if (typeof value === "object" && Array.isArray(value) && value !== null) {
|
||||
query[`${key}[]`] = toRaw(value).map((val: any) => JSON.stringify(val));
|
||||
delete query[key];
|
||||
}
|
||||
});
|
||||
return query;
|
||||
};
|
||||
|
||||
const http = $fetch.create({
|
||||
onRequest({ options }) {
|
||||
options.params = paramsSerializer(options.params);
|
||||
//TODO 添加token
|
||||
},
|
||||
|
||||
onResponse({ response }) {
|
||||
if (
|
||||
response.headers.get("content-disposition") &&
|
||||
response.status === 200
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
if (response._data.code !== 200) {
|
||||
handleError(response);
|
||||
return Promise.reject(response._data);
|
||||
}
|
||||
|
||||
response._data = response._data.data
|
||||
return
|
||||
},
|
||||
onResponseError({ response }) {
|
||||
handleError(response);
|
||||
return Promise.reject(response?._data ?? null);
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
provide: {
|
||||
http: http,
|
||||
},
|
||||
};
|
||||
});
|
Loading…
Reference in New Issue