:feat:运营区域功能
This commit is contained in:
parent
eba5b80fa8
commit
b1d513fe56
8
.env
8
.env
@ -8,4 +8,10 @@ VITE_GLOB_APP_TITLE = 卓景出行
|
||||
VITE_IMG_BASE_URL = ''
|
||||
|
||||
# 本地mock数据 true开启 false关闭
|
||||
VITE_APP_OPEN_MOCK = false
|
||||
VITE_APP_OPEN_MOCK = false
|
||||
|
||||
#高德securityJsCode
|
||||
VITE_GLOB_AMAP_SECURITY_JS_CODE = 'b85d17b7e0fa98864d495a9a52f162e4'
|
||||
|
||||
# 高德密钥
|
||||
VITE_GLOB_AMAP_KEY = '0e6910fae6848722b0e57f0c01597499'
|
||||
@ -9,4 +9,4 @@ VITE_ROUTER_MODE = hash
|
||||
VITE_PUBLIC_PATH = './'
|
||||
|
||||
# 请求路径 管理系统/开发环境
|
||||
VITE_APP_BASE_URL = 'http://192.168.2.200:10010'
|
||||
VITE_APP_BASE_URL = 'http://192.168.101.20:10010'
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
"preinstall": "npx only-allow pnpm"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amap/amap-jsapi-loader": "^1.0.1",
|
||||
"@arco-design/color": "^0.4.0",
|
||||
"@codemirror/lang-javascript": "^6.2.2",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
|
||||
9
pnpm-lock.yaml
generated
9
pnpm-lock.yaml
generated
@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@amap/amap-jsapi-loader':
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
'@arco-design/color':
|
||||
specifier: ^0.4.0
|
||||
version: 0.4.0
|
||||
@ -237,6 +240,9 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@amap/amap-jsapi-loader@1.0.1':
|
||||
resolution: {integrity: sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==}
|
||||
|
||||
'@antfu/utils@0.7.10':
|
||||
resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==}
|
||||
|
||||
@ -4941,6 +4947,8 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@amap/amap-jsapi-loader@1.0.1': {}
|
||||
|
||||
'@antfu/utils@0.7.10': {}
|
||||
|
||||
'@arco-design/color@0.4.0':
|
||||
@ -9270,6 +9278,7 @@ snapshots:
|
||||
print-js: 1.6.0
|
||||
qrcode: 1.5.4
|
||||
recorder-core: 1.3.25011100
|
||||
sm-crypto: 0.3.13
|
||||
sortablejs: 1.15.6
|
||||
uuid: 11.1.0
|
||||
vue: 3.5.15(typescript@5.8.3)
|
||||
|
||||
56
src/api/modules/region/index.ts
Normal file
56
src/api/modules/region/index.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import axios from "@/api";
|
||||
import { RegionPageParams, AddRegion } from "./types";
|
||||
|
||||
// 分页查询运营区域表
|
||||
export const getRegionByPageAPI = (params: RegionPageParams) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeRegion/page",
|
||||
method: "get",
|
||||
params
|
||||
});
|
||||
};
|
||||
|
||||
// 添加运营区域
|
||||
export const addRegionAPI = (data: AddRegion) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeRegion/save",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 删除运营区域表
|
||||
export const deleteRegionAPI = (regionId: string) => {
|
||||
return axios({
|
||||
url: `/operations/ebikeRegion/remove`,
|
||||
method: "get",
|
||||
params: { regionId }
|
||||
});
|
||||
};
|
||||
|
||||
// 更新运营区域表
|
||||
export const updateRegionAPI = (data: AddRegion) => {
|
||||
return axios({
|
||||
url: "/operations/ebikeRegion/update",
|
||||
method: "post",
|
||||
data
|
||||
});
|
||||
};
|
||||
|
||||
// 开始运营
|
||||
export const startRegionAPI = (regionId: string) => {
|
||||
return axios({
|
||||
url: `/operations/ebikeRegion/commenceOperation`,
|
||||
method: "get",
|
||||
params: { regionId }
|
||||
});
|
||||
};
|
||||
|
||||
// 停止运营
|
||||
export const stopRegionAPI = (regionId: string) => {
|
||||
return axios({
|
||||
url: `/operations/ebikeRegion/stopOperation`,
|
||||
method: "get",
|
||||
params: { regionId }
|
||||
});
|
||||
};
|
||||
25
src/api/modules/region/types.ts
Normal file
25
src/api/modules/region/types.ts
Normal file
@ -0,0 +1,25 @@
|
||||
interface ListType {
|
||||
pageNum: number;
|
||||
pageSize: number;
|
||||
}
|
||||
|
||||
// 分页查询运营区域表参数
|
||||
export interface RegionPageParams extends ListType {
|
||||
regionName?: string; // 运营区名称
|
||||
regionSimpleName?: string; //运营区简称
|
||||
}
|
||||
|
||||
// 添加运营区域
|
||||
type Coordinate = [number, number];
|
||||
interface RegionPolygon {
|
||||
type: "polygon" | "point";
|
||||
coordinates: Coordinate[];
|
||||
}
|
||||
export interface AddRegion {
|
||||
regionId?: string;
|
||||
regionName: string;
|
||||
regionPolygon: RegionPolygon;
|
||||
regionSimpleName?: string | null;
|
||||
status?: number;
|
||||
operatorId: string;
|
||||
}
|
||||
2
src/auto-import.d.ts
vendored
2
src/auto-import.d.ts
vendored
@ -5,6 +5,8 @@
|
||||
// Generated by unplugin-auto-import
|
||||
export {}
|
||||
declare global {
|
||||
const AMap: typeof import('@arco-design/web-vue')['Map']
|
||||
const AMaps: typeof import('@arco-design/web-vue')['Maps']
|
||||
const EffectScope: typeof import('vue')['EffectScope']
|
||||
const Message: (typeof import("./globals/index"))["Message"]
|
||||
const arcoMessage: typeof import('./globals/index')['arcoMessage']
|
||||
|
||||
@ -25,6 +25,8 @@ import Layout from "@/layout/index.vue";
|
||||
* @description 前端控制路由 直接改 mock/_data/system_menu 中的路由,后端控制则不需要
|
||||
* @returns 返回路由菜单数据
|
||||
*/
|
||||
|
||||
// @/views/login/login.vue
|
||||
export const staticRoutes = [
|
||||
{
|
||||
path: "/",
|
||||
|
||||
42
src/utils/map-tools.ts
Normal file
42
src/utils/map-tools.ts
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* 表示一个二维地理坐标点
|
||||
*/
|
||||
type Point = [number, number];
|
||||
|
||||
/**
|
||||
* 点位数据处理工具
|
||||
*/
|
||||
export const PointDataHandler = {
|
||||
/**
|
||||
* 准备上传:在点位数组末尾添加第一个点位,用于闭合路径(如多边形)。
|
||||
* @param points - 点位数组,每个点为 [经度, 纬度] 格式。
|
||||
* @returns 处理后的点位数组。
|
||||
*/
|
||||
prepareForUpload(points: Point[]): Point[] {
|
||||
if (!Array.isArray(points) || points.length < 2) {
|
||||
return points;
|
||||
}
|
||||
return [...points, points[0]];
|
||||
},
|
||||
|
||||
/**
|
||||
* 恢复显示:移除为闭合路径而添加的最后一个点位(仅当其与第一个点相同时)。
|
||||
* @param points - 从服务端返回的点位数组。
|
||||
* @returns 去除重复闭合点后的点位数组。
|
||||
*/
|
||||
restoreForDisplay(points: Point[]): Point[] {
|
||||
if (!Array.isArray(points) || points.length <= 1) {
|
||||
return points;
|
||||
}
|
||||
|
||||
const first = points[0];
|
||||
const last = points[points.length - 1];
|
||||
|
||||
// 仅当最后一个点与第一个点完全相同时才移除
|
||||
if (first[0] === last[0] && first[1] === last[1]) {
|
||||
return points.slice(0, -1);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
};
|
||||
219
src/views/component/RegionalMap/RegionalMap.vue
Normal file
219
src/views/component/RegionalMap/RegionalMap.vue
Normal file
@ -0,0 +1,219 @@
|
||||
<script lang="ts" setup>
|
||||
declare global {
|
||||
interface Window {
|
||||
_AMapSecurityConfig: any;
|
||||
}
|
||||
}
|
||||
import AMapLoader from "@amap/amap-jsapi-loader";
|
||||
const { VITE_GLOB_AMAP_KEY, VITE_GLOB_AMAP_SECURITY_JS_CODE } = import.meta.env; // 获取环境变量中的高德密钥
|
||||
|
||||
const emits = defineEmits(["ok"]);
|
||||
const open = ref<boolean>(false);
|
||||
|
||||
// 地图实例
|
||||
const map = shallowRef<any>(null);
|
||||
const mouseTool = shallowRef<any>(null);
|
||||
const polyEditor = shallowRef<any>(null);
|
||||
const path = ref<any>([]);
|
||||
const mapAmap = shallowRef<any>(null);
|
||||
const type = ref<string>("add");
|
||||
const polygons = ref<any>([]);
|
||||
const options__polygon = {
|
||||
strokeColor: "#007bff",
|
||||
strokeWeight: 3,
|
||||
strokeOpacity: 1,
|
||||
fillColor: "rgba(0, 123, 255, 0.1)",
|
||||
fillOpacity: 0.8,
|
||||
strokeStyle: "solid"
|
||||
};
|
||||
|
||||
const openMap = async (parmas: any) => {
|
||||
console.log("parmas", parmas);
|
||||
|
||||
try {
|
||||
open.value = true;
|
||||
await initMap();
|
||||
if (parmas) {
|
||||
const { points } = parmas;
|
||||
path.value = points;
|
||||
console.log("points", points);
|
||||
type.value = "edit";
|
||||
editMap();
|
||||
return;
|
||||
}
|
||||
addPolygons();
|
||||
} catch (err) {
|
||||
console.error("err", err);
|
||||
}
|
||||
};
|
||||
// 地图容器初始化
|
||||
const initMap = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
window._AMapSecurityConfig = {
|
||||
securityJsCode: VITE_GLOB_AMAP_SECURITY_JS_CODE // 高德地图安全密钥,
|
||||
};
|
||||
|
||||
AMapLoader.load({
|
||||
key: VITE_GLOB_AMAP_KEY,
|
||||
version: "2.0",
|
||||
plugins: [
|
||||
"AMap.Marker",
|
||||
"AMap.Pixel",
|
||||
"AMap.Polyline",
|
||||
"AMap.Geolocation",
|
||||
"AMap.MouseTool",
|
||||
"AMap.Polygon",
|
||||
"AMap.PolygonEditor"
|
||||
]
|
||||
})
|
||||
.then((mapRes: any) => {
|
||||
mapAmap.value = mapRes;
|
||||
map.value = new mapRes.Map("container", {
|
||||
zoom: 12,
|
||||
center: [104.066541, 30.572269]
|
||||
});
|
||||
|
||||
// 鼠标工具
|
||||
if (map.value) {
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
.catch((e: any) => {
|
||||
console.error(e);
|
||||
reject(false);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 添加区域
|
||||
function addPolygons() {
|
||||
if (mapAmap.value) {
|
||||
mouseTool.value = new mapAmap.value.MouseTool(map.value);
|
||||
|
||||
if (mouseTool.value) {
|
||||
mouseTool.value.polygon({
|
||||
...options__polygon
|
||||
});
|
||||
|
||||
mouseTool.value.on("draw", onDraw);
|
||||
}
|
||||
}
|
||||
}
|
||||
function onDraw(e: any) {
|
||||
const { obj } = e;
|
||||
const mapPathList = obj.getPath();
|
||||
|
||||
path.value = [];
|
||||
mapPathList.map((item: any) => {
|
||||
path.value.push([item.lng, item.lat]);
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑地图
|
||||
function editMap() {
|
||||
if (map.value) {
|
||||
map.value.clearMap();
|
||||
if (polyEditor.value) {
|
||||
polyEditor.value.close();
|
||||
}
|
||||
const polygon = new mapAmap.value.Polygon(getPolygonOption());
|
||||
map.value.add([polygon]);
|
||||
|
||||
polyEditor.value = new mapAmap.value.PolygonEditor(map.value, polygon);
|
||||
polyEditor.value.open();
|
||||
}
|
||||
}
|
||||
|
||||
function getPolygonOption() {
|
||||
return { ...options__polygon, path: path.value };
|
||||
}
|
||||
|
||||
// 清除
|
||||
function clearMap() {
|
||||
map.value.clearMap();
|
||||
path.value = [];
|
||||
}
|
||||
|
||||
// 确认
|
||||
function handleOk() {
|
||||
const points = getPolygons();
|
||||
if (points.length > 2) {
|
||||
emits("ok", points);
|
||||
afterClose();
|
||||
return true;
|
||||
}
|
||||
arcoMessage("error", "请绘制一个有效的区域");
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPolygons() {
|
||||
switch (type.value) {
|
||||
case "add":
|
||||
return path.value;
|
||||
case "edit":
|
||||
const polygon = polyEditor.value.getTarget();
|
||||
const paths = polygon.getPath();
|
||||
return paths.map((item: any) => [item.lng, item.lat]);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭
|
||||
function afterClose() {
|
||||
clearMap();
|
||||
map.value = null;
|
||||
mouseTool.value = null;
|
||||
polyEditor.value = null;
|
||||
mapAmap.value = null;
|
||||
polygons.value = [];
|
||||
type.value = "add";
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
openMap
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-modal v-model:visible="open" fullscreen :body-style="{ height: '100%' }" @before-ok="handleOk" @cancel="afterClose">
|
||||
<template #title>
|
||||
<div class="title_bar">
|
||||
<div style="font-weight: bold">区域电子围栏编辑</div>
|
||||
<div style="color: red; font-weight: bold">在地图上请点击鼠标【左键】进行绘制多边形,完成绘制后请点击鼠标【右键】。</div>
|
||||
</div>
|
||||
</template>
|
||||
<div class="map_bar">
|
||||
<div id="container" style="height: 100%; width: 100%"></div>
|
||||
</div>
|
||||
<!-- 按钮区域 -->
|
||||
<div class="button_bar">
|
||||
<a-button type="primary" style="width: 100%" @click="clearMap" v-if="type == 'add'">清除</a-button>
|
||||
<a-button type="primary" style="width: 100%" @click="editMap" v-if="type == 'edit'">复原</a-button>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.title_bar {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.map_bar {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.button_bar {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
width: 200px;
|
||||
background-color: #fffc;
|
||||
padding: 15px;
|
||||
right: 50px;
|
||||
bottom: 60px;
|
||||
}
|
||||
</style>
|
||||
116
src/views/urban/operateRegion/component/addForm.vue
Normal file
116
src/views/urban/operateRegion/component/addForm.vue
Normal file
@ -0,0 +1,116 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref } from "vue";
|
||||
import RegionalMap from "@/views/component/RegionalMap/RegionalMap.vue";
|
||||
import { deepClone } from "@/utils";
|
||||
|
||||
const props = defineProps({
|
||||
operatorList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const addFormRef = ref<any>();
|
||||
const operatorAllList = ref<any>([]);
|
||||
const addForm = reactive<any>({
|
||||
regionId: "",
|
||||
operatorId: "",
|
||||
regionName: "",
|
||||
regionSimpleName: "",
|
||||
coordinates: []
|
||||
});
|
||||
const rules = {
|
||||
operatorId: [{ required: true, message: "请选择运营商", trigger: "change" }],
|
||||
regionName: [{ required: true, message: "请输入运营区名称", trigger: "blur" }],
|
||||
coordinates: [
|
||||
{
|
||||
required: true,
|
||||
validator: (value: any, cb: any) => {
|
||||
console.log(value);
|
||||
if (value.length === 0) {
|
||||
cb("请编辑区域电子围栏");
|
||||
} else {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
const RegionalMapRef = ref();
|
||||
const handleOpenMap = () => {
|
||||
const path = addForm.coordinates.length === 0 ? null : { points: deepClone(addForm.coordinates) };
|
||||
RegionalMapRef.value?.openMap(path);
|
||||
};
|
||||
|
||||
const updateForm = (data: any) => {
|
||||
addForm.regionId = data.regionId;
|
||||
addForm.operatorId = data.operatorId;
|
||||
addForm.regionName = data.regionName;
|
||||
addForm.regionSimpleName = data.regionSimpleName;
|
||||
addForm.coordinates = data.coordinates || [];
|
||||
};
|
||||
|
||||
//获取地图点位
|
||||
const getPoint = (paths: any[]) => {
|
||||
addForm.coordinates = paths;
|
||||
};
|
||||
|
||||
// 提交表单
|
||||
const submit = () => {
|
||||
return new Promise(async resolve => {
|
||||
let status = await addFormRef.value.validate();
|
||||
return resolve({
|
||||
status,
|
||||
data: deepClone(addForm)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const resetForm = () => {
|
||||
addForm.regionId = "";
|
||||
addForm.operatorId = "";
|
||||
addForm.regionName = "";
|
||||
addForm.regionSimpleName = "";
|
||||
addForm.coordinates = [];
|
||||
if (addFormRef.value) {
|
||||
addFormRef.value.resetFields();
|
||||
}
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.operatorList,
|
||||
val => {
|
||||
operatorAllList.value = val;
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
submit,
|
||||
resetForm,
|
||||
updateForm
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a-form ref="addFormRef" :model="addForm" :rules="rules">
|
||||
<a-form-item field="operatorId" label="运营商" validate-trigger="blur">
|
||||
<a-select v-model="addForm.operatorId" placeholder="请选择运营商" validate-trigger="change">
|
||||
<a-option v-for="it in operatorAllList" :key="it.operatorId" :value="it.operatorId">{{ it.operatorName }}</a-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
<a-form-item label="运营区名称" field="regionName" validate-trigger="blur">
|
||||
<a-input placeholder="请输入运营区名称" allow-clear v-model="addForm.regionName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="简称" field="regionSimpleName">
|
||||
<a-input placeholder="请输入简称" allow-clear v-model="addForm.regionSimpleName" />
|
||||
</a-form-item>
|
||||
<a-form-item label="区域电子围栏" field="coordinates" validate-trigger="blur">
|
||||
<a-tag bordered color="orange" v-if="addForm.coordinates.length === 0">未绘制</a-tag>
|
||||
<a-tag bordered color="green" v-else>已绘制</a-tag>
|
||||
<a-link @click="handleOpenMap" style="margin-left: 15px">编辑地图</a-link>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<RegionalMap ref="RegionalMapRef" @ok="getPoint" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
377
src/views/urban/operateRegion/operateRegion.vue
Normal file
377
src/views/urban/operateRegion/operateRegion.vue
Normal file
@ -0,0 +1,377 @@
|
||||
<script lang="ts" setup>
|
||||
import AddForm from "./component/addForm.vue";
|
||||
import {
|
||||
getRegionByPageAPI,
|
||||
addRegionAPI,
|
||||
deleteRegionAPI,
|
||||
updateRegionAPI,
|
||||
startRegionAPI,
|
||||
stopRegionAPI
|
||||
} from "@/api/modules/region";
|
||||
import { deepClone, dictTranslate } from "@/utils";
|
||||
import { useSystemStore } from "@/store/modules/system";
|
||||
import { PointDataHandler } from "@/utils/map-tools";
|
||||
import { getOperatorAllListAPI } from "@/api/modules/system";
|
||||
import { Modal } from "@arco-design/web-vue";
|
||||
|
||||
// 列表
|
||||
const form = ref<any>({
|
||||
regionSimpleName: "",
|
||||
regionName: ""
|
||||
});
|
||||
|
||||
const system = useSystemStore();
|
||||
const moduleList = ref<any>([]);
|
||||
const regionStatusList = ref<any>([]);
|
||||
const loading = ref<boolean>(false);
|
||||
const tableRef = ref();
|
||||
const AddFormRef = ref<any>(null);
|
||||
const operatorAllList = ref<any>([]);
|
||||
const title = ref<string>("");
|
||||
const pagination = ref({
|
||||
pageNum: 1,
|
||||
total: 0,
|
||||
pageSize: 10,
|
||||
showPageSize: true,
|
||||
showTotal: true
|
||||
});
|
||||
|
||||
const handlePageSizeChange = (pageSize: number) => {
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.pageNum = 1;
|
||||
getRegionByPage();
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
pagination.value.pageNum = page;
|
||||
getRegionByPage();
|
||||
};
|
||||
|
||||
const search = () => {
|
||||
pagination.value.pageNum = 1;
|
||||
getRegionByPage();
|
||||
};
|
||||
const reset = () => {
|
||||
form.value = {
|
||||
regionSimpleName: "",
|
||||
regionName: ""
|
||||
};
|
||||
search();
|
||||
};
|
||||
const onAdd = () => {
|
||||
open.value = true;
|
||||
title.value = "新增运营区";
|
||||
};
|
||||
|
||||
const getRegionByPage = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const res: any = await getRegionByPageAPI({
|
||||
regionName: form.value.regionName,
|
||||
regionSimpleName: form.value.regionSimpleName,
|
||||
pageNum: pagination.value.pageNum,
|
||||
pageSize: pagination.value.pageSize
|
||||
});
|
||||
loading.value = false;
|
||||
if (res.code !== 200) {
|
||||
return;
|
||||
}
|
||||
const { records, pageNumber, pageSize } = res.data;
|
||||
pagination.value.pageNum = pageNumber;
|
||||
pagination.value.pageSize = pageSize;
|
||||
pagination.value.total = res.data.totalRow;
|
||||
moduleList.value = records;
|
||||
} catch (error) {
|
||||
console.error("获取列表失败:", error);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// tag颜色
|
||||
const tagColor = (record: any) => {
|
||||
const { status } = record;
|
||||
|
||||
switch (status) {
|
||||
case 0:
|
||||
return "gray";
|
||||
case 1:
|
||||
return "green";
|
||||
case 2:
|
||||
return "red";
|
||||
default:
|
||||
return "gray";
|
||||
}
|
||||
};
|
||||
|
||||
//翻译字典值
|
||||
const dictFormat = (list: any[], key: string, value: string | number, valueKey: string = "dicValueName") => {
|
||||
return dictTranslate(list, key, value, valueKey);
|
||||
};
|
||||
|
||||
// 获取所有运营商列表
|
||||
const getAllOperatorList = async () => {
|
||||
return new Promise<void>(async resolve => {
|
||||
try {
|
||||
const res: any = await getOperatorAllListAPI();
|
||||
if (res.code === 200) {
|
||||
operatorAllList.value = res.data;
|
||||
resolve();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("获取运营商列表失败:", error);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 删除运营区
|
||||
const handleDelete = async (record: any) => {
|
||||
const { regionId } = record;
|
||||
try {
|
||||
const res: any = await deleteRegionAPI(regionId);
|
||||
if (res.code === 200) {
|
||||
arcoMessage("success", "删除成功");
|
||||
getRegionByPage();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("删除失败:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelect = (val: any, record: any) => {
|
||||
switch (val) {
|
||||
case "start":
|
||||
handleStart(record);
|
||||
break;
|
||||
case "stop":
|
||||
handleStop(record);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
// 开始运营
|
||||
const handleStart = (record: any) => {
|
||||
const { regionId } = record;
|
||||
Modal.info({
|
||||
title: "开始运营",
|
||||
content: "请确认是否启动运营区开始运营?",
|
||||
hideCancel: false,
|
||||
closable: true,
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
await startRegionAPI(regionId);
|
||||
arcoMessage("success", "启动成功");
|
||||
reset();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("启动运营区失败:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 停止运营
|
||||
const handleStop = (record: any) => {
|
||||
const { regionId } = record;
|
||||
Modal.error({
|
||||
title: "停止运营",
|
||||
content: "请确认是否停止运营区运营?",
|
||||
hideCancel: false,
|
||||
closable: true,
|
||||
onBeforeOk: async () => {
|
||||
try {
|
||||
await stopRegionAPI(regionId);
|
||||
arcoMessage("success", "停止成功");
|
||||
reset();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("停止运营区失败:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*新增模态框
|
||||
* **/
|
||||
const open = ref<boolean>(false);
|
||||
const afterClose = () => {
|
||||
resetForm();
|
||||
};
|
||||
|
||||
// 修改运营区
|
||||
const handleUpdate = (record: any) => {
|
||||
open.value = true;
|
||||
title.value = "修改运营区";
|
||||
const data = deepClone(record);
|
||||
data.coordinates = PointDataHandler.restoreForDisplay(data.regionPolygon.coordinates);
|
||||
AddFormRef.value.updateForm(data);
|
||||
};
|
||||
|
||||
// 格式化上传数据
|
||||
const formatData = (data: any, type: string = "add") => {
|
||||
if (type === "add") {
|
||||
const regionPolygon: any = {
|
||||
type: "Polygon",
|
||||
coordinates: []
|
||||
};
|
||||
regionPolygon.coordinates = PointDataHandler.prepareForUpload(data.coordinates);
|
||||
|
||||
return {
|
||||
operatorId: data.operatorId,
|
||||
regionName: data.regionName,
|
||||
regionId: data.regionId ? data.regionId : "",
|
||||
regionSimpleName: data.regionSimpleName,
|
||||
regionPolygon
|
||||
};
|
||||
}
|
||||
|
||||
if (type === "edit") {
|
||||
}
|
||||
};
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
open.value = false;
|
||||
AddFormRef.value?.resetForm();
|
||||
};
|
||||
|
||||
// 新增提交
|
||||
const handleOk = async () => {
|
||||
const { status, data } = await AddFormRef.value?.submit();
|
||||
if (status) return false;
|
||||
|
||||
try {
|
||||
const parmas = formatData(data, "add");
|
||||
|
||||
if (!parmas) {
|
||||
arcoMessage("error", "数据格式有误");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data.regionId) {
|
||||
await updateRegionAPI(parmas);
|
||||
} else {
|
||||
await addRegionAPI(parmas);
|
||||
}
|
||||
|
||||
arcoMessage("success", data.regionId ? "修改成功" : "新增成功");
|
||||
resetForm();
|
||||
getRegionByPage();
|
||||
|
||||
return false;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getRegionByPage();
|
||||
});
|
||||
onBeforeMount(async () => {
|
||||
regionStatusList.value = deepClone(system.getDictByCode("regionStatus"));
|
||||
await getAllOperatorList();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="snow-page">
|
||||
<div class="snow-inner">
|
||||
<s-layout-tools>
|
||||
<template #left>
|
||||
<a-space wrap>
|
||||
<a-input v-model="form.regionName" placeholder="运营区名称" allow-clear />
|
||||
<a-input v-model="form.regionSimpleName" placeholder="运营区简称" allow-clear />
|
||||
<a-button type="primary" @click="search">
|
||||
<template #icon><icon-search /></template>
|
||||
<span>查询</span>
|
||||
</a-button>
|
||||
<a-button @click="reset">
|
||||
<template #icon><icon-refresh /></template>
|
||||
<span>重置</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #right>
|
||||
<a-space wrap>
|
||||
<a-button type="primary" @click="onAdd">
|
||||
<template #icon><icon-plus /></template>
|
||||
<span>新增</span>
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</s-layout-tools>
|
||||
<a-table
|
||||
ref="tableRef"
|
||||
row-key="batteryId"
|
||||
:data="moduleList"
|
||||
:bordered="{ cell: true }"
|
||||
:loading="loading"
|
||||
:scroll="{ x: '100%', y: '100%', minWidth: 1000 }"
|
||||
:pagination="pagination"
|
||||
@page-change="handlePageChange"
|
||||
@page-size-change="handlePageSizeChange"
|
||||
>
|
||||
<template #columns>
|
||||
<a-table-column title="序号" :width="60" align="center">
|
||||
<template #cell="cell">
|
||||
<span>{{ (pagination.pageNum - 1) * pagination.pageSize + cell.rowIndex + 1 }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="运营区名称" data-index="regionName" align="center"></a-table-column>
|
||||
<a-table-column title="运营区简称" data-index="regionSimpleName" align="center"></a-table-column>
|
||||
<a-table-column title="运营商" data-index="operatorId" align="center">
|
||||
<template #cell="{ record }">
|
||||
<span>{{ dictFormat(operatorAllList, "operatorId", record.operatorId, "operatorName") }}</span>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="状态" data-index="status" align="center">
|
||||
<template #cell="{ record }">
|
||||
<a-tag :color="tagColor(record)" bordered>{{ dictFormat(regionStatusList, "dicValue", record.status) }}</a-tag>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="创建时间" data-index="createdAt" align="center"></a-table-column>
|
||||
<a-table-column title="操作" align="center" :fixed="'right'">
|
||||
<template #cell="{ record }">
|
||||
<a-space>
|
||||
<a-button type="primary" size="mini" @click="handleUpdate(record)" :disabled="record.status === 1">
|
||||
<template #icon><icon-link /></template>
|
||||
<span>修改</span>
|
||||
</a-button>
|
||||
<a-popconfirm type="warning" content="确定删除该运营区?" @ok="handleDelete(record)">
|
||||
<a-button type="primary" status="danger" size="mini">
|
||||
<template #icon><icon-delete /></template>
|
||||
<span>删除</span>
|
||||
</a-button>
|
||||
</a-popconfirm>
|
||||
<a-dropdown @select="(v: any) => handleSelect(v, record)">
|
||||
<a-button size="mini" type="primary">
|
||||
更多
|
||||
<template #icon><icon-down /></template>
|
||||
</a-button>
|
||||
<template #content>
|
||||
<a-doption value="start" :disabled="record.status === 1">开始运营</a-doption>
|
||||
<a-doption value="stop" :disabled="record.status !== 1">停止运营</a-doption>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table-column>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
<!-- 新增 -->
|
||||
<a-modal v-model:visible="open" @close="afterClose" @before-ok="handleOk" @cancel="afterClose" :width="700">
|
||||
<template #title> {{ title }} </template>
|
||||
<AddForm ref="AddFormRef" :operatorList="operatorAllList" />
|
||||
</a-modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
Loading…
x
Reference in New Issue
Block a user