You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

467 lines
12 KiB

<template>
<el-dialog
:title="title"
v-model="visible"
width="35%"
class="x-dialog"
:destroy-on-close="true"
append-to-body
@closed="handlerClose()"
>
<el-form
class="dialog-data"
:model="form"
:rules="rules"
ref="formRef"
label-width="88px"
>
<el-form-item label="工单地址:" prop="address">
<div class="map">
<MarsMap
:url="configUrl"
:options="getMapOptions"
map-key="workOrder"
@onload="marsOnload"
/>
</div>
<el-input
v-model="form.address"
placeholder="请输入"
clearable
@keyup.enter="handleSearch"
>
<template #prepend>
<el-button icon="MapLocation" />
</template>
3 weeks ago
<template #append>
<span class="location-search" @click="handleSearch"></span>
</template>
</el-input>
<div class="serch-list" v-show="gaodePOIList.length > 0">
<div
clss="list-item"
:class="currentId === item.id ? 'activeitem' : ''"
v-for="item in gaodePOIList"
:key="item.id"
@click="handleCograph(item)"
>
{{ item.name }}
</div>
</div>
</el-form-item>
<el-form-item label="工单类型:" prop="gdType">
<el-radio-group v-model="form.gdType" @change="changeType()">
<el-radio :value="parseInt(dict.value)" v-for="dict in dict.gdlx">{{
dict.label
}}</el-radio>
</el-radio-group>
</el-form-item>
<section v-if="id">
<el-form-item prop="xdsqm" v-if="form.gdType === 0">
<el-radio-group v-model="form.xdsqm">
<el-radio
:value="parseInt(dict.value)"
v-for="dict in dict.xdsqm"
>{{ dict.label }}</el-radio
>
</el-radio-group>
</el-form-item>
<el-form-item label="影响类型:" prop="yxlx">
<el-checkbox-group v-model="form.yxlx">
<el-checkbox
3 weeks ago
v-for="dict in dict.yxlx"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-checkbox-group>
</el-form-item>
3 weeks ago
<el-form-item label="工单照片:" prop="gdtp">
<ImageUpload v-model="form.gdtp" :limit="3"></ImageUpload>
</el-form-item>
</section>
<section v-else>
<el-form-item label="选派班组:" prop="zzjg">
<el-cascader
v-model="form.zzjg"
:options="dict.deptList"
:props="cascaderProps"
@change="handleChange"
/>
</el-form-item>
</section>
<el-form-item label="工单描述:">
<el-input
v-model="form.gdms"
:rows="2"
type="textarea"
placeholder="请填写"
/>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<section v-if="id">
<el-button @click="handlerRetreat()">退</el-button>
<el-button type="primary" @click="confirm()"></el-button>
<el-button type="primary" @click="handleFeedBack()"
>处理反馈</el-button
>
</section>
<section v-else>
<el-button @click="handlerClose()"></el-button>
<el-button type="primary" @click="confirm()"></el-button>
</section>
</div>
</template>
<!-- 退单 -->
<chargeBack v-model="retreat" :id="id" @confirm="handlerClose"></chargeBack>
<!-- 处理反馈 -->
<feedBack v-model="feedBackView" :id="id" @confirm="handlerClose" />
</el-dialog>
</template>
<script setup>
3 weeks ago
import { addyj, updateyj, intruderyj, getyjById } from "@/api/emergency";
import { chargeBack, feedBack } from "../index";
import MarsMap from "@/components/mars-work/mars-map.vue";
import mapOptions from "@/components/mars-work/mapOptions";
import markerIcon from "@/assets/images/map-marker.png";
import { gaodeAddress, gaodePOI } from "@/utils/common.js";
const { proxy } = getCurrentInstance();
const gaodePOIList = ref([]);
const currentId = ref(0);
const cascaderProps = {
value: "deptId",
label: "deptName",
};
const props = defineProps({
title: {
type: String,
default: "",
},
3 weeks ago
dict: {
type: Object,
default: {
gdlx: [],
gdlevel: [],
clfa: [],
gdms: [],
deptList: [],
3 weeks ago
},
},
3 weeks ago
id: {
type: Number,
},
modelValue: {
type: Boolean,
default: false,
},
});
const emit = defineEmits(["update:modelValue", "confirm"]);
//地图配置
const configUrl = "lib/config/config.json";
let mapData = null;
let mapLayer = {};
let entity = null;
const data = reactive({
form: {
id: null,
address: undefined, //地址
clbz: undefined, //处理班组
clfa: undefined, //处理方案
clhtp: undefined, //处理后图片
clms: undefined, //处理描述
createBy: undefined, //创建人
createId: undefined, //创建者id
createTime: undefined, //创建时间
deptId: undefined, //部门id
gdLevel: undefined, //工单等级
gdType: undefined, //工单类型
gdms: undefined, //工单描述
gdtp: undefined, //工单图片
lat: undefined, //纬度
lon: undefined, //经度
pqcl: undefined, //派遣车辆
pqrs: undefined, //派遣人数
reason: undefined, //退单原因
status: undefined, //状态 0:待勘察1:待派发,2:已退单.3:待处理,4:已完成
zzjg: undefined,
xdsqm: undefined, //行道树/乔木
yxlx: undefined, //影响类型
},
rules: {
address: [{ required: true, message: "请填写工单地址", trigger: "blur" }],
3 weeks ago
gdType: [{ required: true, message: "请选择工单类型", trigger: "blur" }],
xdsqm: [{ required: true, message: "请选择", trigger: "blur" }],
zzjg: [{ required: true, message: "请选择选派班组", trigger: "blur" }],
3 weeks ago
gdtp: [{ required: true, message: "请上传工单照片", trigger: "blur" }],
yxlx: [{ required: true, message: "请选择影响类型", trigger: "blur" }],
},
});
3 weeks ago
const { form, rules } = toRefs(data);
const visible = ref(props.modelValue);
const retreat = ref(false);
const feedBackView = ref(false);
// 监听外部 modelValue 变化
watch(
() => props.modelValue,
(val) => {
visible.value = val;
}
);
watch(visible, (val) => {
emit("update:modelValue", val);
});
const changeType = () => {
if (props.id) form.value.xdsqm = undefined;
};
/**
* 处理反馈
*
*/
2 weeks ago
const handleFeedBack = () => {
confirm(false);
};
/**
* 退单
*
*/
2 weeks ago
const handlerRetreat = () => {
retreat.value = true;
};
/**
* 提交
*/
2 weeks ago
const confirm = (isConfirm = true) => {
proxy.$refs["formRef"].validate(async (valid) => {
if (valid) {
3 weeks ago
if (!form.value.lat || !form.value.lon) {
proxy.$modal.msgWarning("请先落点至地图上!");
return;
}
if (form.value.id) {
form.value.yxlx = filterArray(form.value.yxlx, "join");
await intruderyj(form.value);
proxy.$modal.msgSuccess(`${props.title}成功`);
} else {
form.value.zzjg = filterArray(form.value.zzjg, "join");
await addyj(form.value);
proxy.$modal.msgSuccess("新增成功");
}
2 weeks ago
if (isConfirm) {
handlerClose(isConfirm);
} else {
feedBackView.value = true;
form.value.yxlx = filterArray(form.value.yxlx);
}
}
});
};
/**
* 获取详情
*/
const getInfo = async (val) => {
if (!props.id || !visible.value) return;
const res = await getyjById(props.id);
if (props.id) {
res.data.yxlx = filterArray(res.data.yxlx);
} else {
res.data.zzjg = res.data.zzjg.split(",").map((item) => parseInt(item));
}
form.value = res.data;
if (form.value.lat && form.value.lon && mapData) {
nextTick(() => {
handleMapClick(form.value.lat, form.value.lon);
mapData.flyToGraphic(mapLayer.marker, { radius: 300 });
});
}
};
const filterArray = (data, type) => {
3 weeks ago
if (!type) {
if (data) {
return data.split(",");
} else {
return [];
}
} else {
3 weeks ago
if (data) {
return data.join();
} else {
return "";
}
}
};
/**
*
*/
const handlerClose = (isConfirm) => {
if (isConfirm) {
emit("confirm");
}
visible.value = false;
3 weeks ago
proxy.resetForm("formRef");
gaodePOIList.value = [];
if (mapData) {
mapData.destroy();
mapData = null;
mapLayer.marker?.clear();
entity = null;
}
};
/**
* 地址搜索
*/
const handleSearch = async () => {
if (!form.value.address) {
proxy.$modal.msgWarning("请输入关键字");
return;
}
const res = await gaodePOI(form.value.address);
gaodePOIList.value = res;
};
/**
* 结果上图
* @param item
*/
const handleCograph = (item) => {
if (currentId.value != item.id) {
const point = item.location.split(",");
handleMapClick(parseFloat(point[0]), parseFloat(point[1]));
mapData.flyToGraphic(mapLayer.marker, { radius: 300 });
currentId.value = item.id;
form.value.address = item.name;
}
};
/**
* 级联取人员deptID
*/
const handleChange = (value) => {
form.value.deptId = value[value.length - 1];
};
/**
* 获取地图配置
*/
const getMapOptions = computed(() => {
mapOptions.scene.sceneMode = 2;
mapOptions.basemaps[0] = {
pid: 10,
name: "高德电子",
type: "gaode",
icon: "//data.mars3d.cn/img/thumbnail/basemap/gaode_vec.png",
layer: "vec",
show: true,
};
return mapOptions;
});
/**
* 地图初始化成功
* @param map
*/
const marsOnload = (map) => {
mapData = map;
mapLayer.marker = new mars3d.layer.GraphicLayer({
allowDrillPick: true,
});
mapData.addLayer(mapLayer.marker);
map.on(mars3d.EventType.click, async ({ cartesian }) => {
const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const res = await gaodeAddress(`${longitude},${latitude}`);
form.value.address = res.formatted_address;
handleMapClick(longitude, latitude);
});
getInfo();
};
/**
* @description: 处理地图点击
* @private
* @param {number} longitude 经度
* @param {number} latitude 纬度
* @returns
*/
const handleMapClick = (longitude, latitude) => {
if (!isPositiveDecimal(longitude)) longitude = parseFloat(longitude);
if (!isPositiveDecimal(latitude)) latitude = parseFloat(latitude);
if (entity) {
entity.position = [longitude, latitude];
} else {
entity = new mars3d.graphic.BillboardEntity({
position: [longitude, latitude],
style: {
image: markerIcon,
width: 35,
height: 36,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
});
mapLayer.marker?.addGraphic(entity);
}
form.value.lat = longitude; //纬度
form.value.lon = latitude; //经度
};
const isPositiveDecimal = (num) => {
return typeof num === "number" && num >= 0 && !Number.isInteger(num);
};
</script>
<style lang="scss" scoped>
.map {
height: 400px;
width: 100%;
border: 1px solid #ccc;
margin-bottom: 15px;
}
.map-gps {
height: 25px;
width: 25px;
}
.serch-list {
width: 100%;
min-height: 50px;
max-height: 250px;
overflow-y: auto;
border: 1px solid #ccc;
& > div {
cursor: pointer;
padding: 3px 10px;
font-size: 14px;
}
& > div:hover,
.activeitem {
background-color: #4776eb;
color: white;
font-weight: bold;
}
}
3 weeks ago
.location-search {
font-size: 14px;
cursor: pointer;
}
</style>