495 lines
10 KiB
Vue
495 lines
10 KiB
Vue
|
<template>
|
|||
|
<view class="page">
|
|||
|
<u-navbar :title="getTitle" :border-bottom="false" :background="bgc" title-color='#000' title-size='36'
|
|||
|
height='45'>
|
|||
|
</u-navbar>
|
|||
|
|
|||
|
<view class="content">
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">区域名称</text>
|
|||
|
<u-input v-model="formData.parkingName" placeholder="请输入区域名称" />
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">区域类型</text>
|
|||
|
<picker :range="typeList" range-key="text" @change="handleTypeChange">
|
|||
|
<view class="type-selector">
|
|||
|
<text>{{ getTypeName(formData.type) }}</text>
|
|||
|
<u-icon name="arrow-right"></u-icon>
|
|||
|
</view>
|
|||
|
</picker>
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">误差范围(米)</text>
|
|||
|
<u-input v-model="formData.error" type="number" placeholder="请输入误差范围" />
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">区域图片</text>
|
|||
|
<view class="image-upload">
|
|||
|
<image v-if="formData.picture" :src="formData.picture" mode="aspectFill" class="preview-image"
|
|||
|
@tap="previewImage" />
|
|||
|
<view v-else class="upload-btn" @tap="chooseImage">
|
|||
|
<u-icon name="plus" size="40"></u-icon>
|
|||
|
</view>
|
|||
|
<view v-if="formData.picture" class="delete-btn" @tap="deletePic">
|
|||
|
<u-icon name="close" color="#fff" size="20"></u-icon>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">区域坐标</text>
|
|||
|
<view class="map-container">
|
|||
|
<map id="map" :latitude="mapCenter.latitude" :longitude="mapCenter.longitude" :polygon="polygons"
|
|||
|
scale="19"></map>
|
|||
|
</view>
|
|||
|
<!-- <view class="map-tips">点击地图添加坐标点,至少需要3个点形成区域</view> -->
|
|||
|
<view class="clear-btn" @tap="toSetmap">
|
|||
|
修改区域
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="form-item">
|
|||
|
<text class="label">备注</text>
|
|||
|
<u-input v-model="formData.remark" type="textarea" placeholder="请输入备注信息" />
|
|||
|
</view>
|
|||
|
|
|||
|
<view class="btn-group">
|
|||
|
<u-button type="primary" @click="handleSubmit">保存</u-button>
|
|||
|
<u-button @click="goBack">取消</u-button>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
export default {
|
|||
|
data() {
|
|||
|
return {
|
|||
|
bgc: {
|
|||
|
backgroundColor: "#fff",
|
|||
|
},
|
|||
|
areaId: '',
|
|||
|
parkingId: '',
|
|||
|
typeList: [
|
|||
|
{ text: '停车区', value: '1' },
|
|||
|
{ text: '禁停区', value: '2' },
|
|||
|
{ text: '禁行区', value: '3' }
|
|||
|
],
|
|||
|
formData: {
|
|||
|
parkingName: '',
|
|||
|
type: '',
|
|||
|
error: '',
|
|||
|
picture: '',
|
|||
|
remark: '',
|
|||
|
boundary: '',
|
|||
|
boundaryStr: '',
|
|||
|
longitude: '',
|
|||
|
latitude: '',
|
|||
|
},
|
|||
|
mapCenter: {
|
|||
|
latitude: 27.105722,
|
|||
|
longitude: 120.25721
|
|||
|
},
|
|||
|
areaInfo: {},
|
|||
|
polygons: [],
|
|||
|
coordinates: [],
|
|||
|
token: '', // 添加七牛云token
|
|||
|
upurl: '', // 添加上传域名
|
|||
|
}
|
|||
|
},
|
|||
|
computed: {
|
|||
|
getTitle() {
|
|||
|
const action = this.parkingId ? '修改' : '新增'
|
|||
|
return `${action}${this.getTypeName(this.formData.type)}`
|
|||
|
}
|
|||
|
},
|
|||
|
onLoad(e) {
|
|||
|
this.parkingId = e.parkingId
|
|||
|
this.formData.type = e.type
|
|||
|
|
|||
|
|
|||
|
// 获取七牛云上传token
|
|||
|
this.getQiniuToken()
|
|||
|
this.areaId = uni.getStorageSync('adminAreaid')
|
|||
|
this.getArea()
|
|||
|
if (this.parkingId) {
|
|||
|
this.getParkingDetail()
|
|||
|
}
|
|||
|
},
|
|||
|
methods: {
|
|||
|
getArea() {
|
|||
|
|
|||
|
let id = this.areaId
|
|||
|
this.$u.get("/app/area/" + id).then((res) => {
|
|||
|
|
|||
|
if (res.code == 200) {
|
|||
|
this.areaInfo = res.data
|
|||
|
} else {
|
|||
|
uni.showToast({
|
|||
|
title: res.msg,
|
|||
|
icon: 'none',
|
|||
|
duration: 2000
|
|||
|
});
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
// 获取类型名称
|
|||
|
getTypeName(type) {
|
|||
|
const typeMap = {
|
|||
|
'1': '停车区',
|
|||
|
'2': '禁停区',
|
|||
|
'3': '禁行区'
|
|||
|
}
|
|||
|
return typeMap[type] || '请选择区域类型'
|
|||
|
},
|
|||
|
|
|||
|
// 处理类型选择
|
|||
|
handleTypeChange(e) {
|
|||
|
const index = e.detail.value
|
|||
|
this.formData.type = this.typeList[index].value
|
|||
|
},
|
|||
|
|
|||
|
// 获取详情
|
|||
|
getParkingDetail() {
|
|||
|
this.$u.get(`/app/parking/${this.parkingId}`).then(res => {
|
|||
|
if (res.code === 200) {
|
|||
|
const data = res.data
|
|||
|
this.formData = {
|
|||
|
parkingName: data.parkingName,
|
|||
|
type: data.type,
|
|||
|
error: data.error,
|
|||
|
picture: data.picture,
|
|||
|
remark: data.remark,
|
|||
|
boundary: data.boundary,
|
|||
|
boundaryStr: data.boundaryStr,
|
|||
|
longitude: data.longitude,
|
|||
|
latitude: data.latitude
|
|||
|
}
|
|||
|
|
|||
|
// 设置地图数据
|
|||
|
if (data.boundaryStr) {
|
|||
|
this.coordinates = JSON.parse(data.boundaryStr)
|
|||
|
this.updatePolygons()
|
|||
|
}
|
|||
|
|
|||
|
// 设置地图中心点
|
|||
|
if (data.latitude && data.longitude) {
|
|||
|
this.mapCenter = {
|
|||
|
latitude: Number(data.latitude),
|
|||
|
longitude: Number(data.longitude)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
// 选择图片
|
|||
|
chooseImage() {
|
|||
|
uni.chooseImage({
|
|||
|
count: 1,
|
|||
|
sizeType: ['compressed'],
|
|||
|
sourceType: ['album', 'camera'],
|
|||
|
success: (res) => {
|
|||
|
this.uploadImage(res.tempFilePaths[0])
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
// 获取七牛云token
|
|||
|
getQiniuToken() {
|
|||
|
this.$u.get("/common/qiniu/uploadInfo").then((res) => {
|
|||
|
if (res.code == 200) {
|
|||
|
this.token = res.token
|
|||
|
this.upurl = res.domain
|
|||
|
}
|
|||
|
});
|
|||
|
},
|
|||
|
|
|||
|
// 上传图片
|
|||
|
uploadImage(filePath) {
|
|||
|
uni.showLoading({
|
|||
|
title: '上传中...'
|
|||
|
})
|
|||
|
|
|||
|
const math = 'static/' + this.$u.guid(20)
|
|||
|
|
|||
|
uni.uploadFile({
|
|||
|
url: 'https://up-z2.qiniup.com',
|
|||
|
filePath: filePath,
|
|||
|
name: 'file',
|
|||
|
formData: {
|
|||
|
token: this.token,
|
|||
|
key: 'bike/img/' + math
|
|||
|
},
|
|||
|
success: (res) => {
|
|||
|
const response = JSON.parse(res.data)
|
|||
|
if (response.key) {
|
|||
|
this.formData.picture = this.upurl + '/' + response.key
|
|||
|
uni.showToast({
|
|||
|
title: '上传成功',
|
|||
|
icon: 'success'
|
|||
|
})
|
|||
|
} else {
|
|||
|
uni.showToast({
|
|||
|
title: '上传失败',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
fail: () => {
|
|||
|
uni.showToast({
|
|||
|
title: '上传失败',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
},
|
|||
|
complete: () => {
|
|||
|
uni.hideLoading()
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
// 预览图片
|
|||
|
previewImage() {
|
|||
|
if (this.formData.picture) {
|
|||
|
uni.previewImage({
|
|||
|
urls: [this.formData.picture]
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 删除图片
|
|||
|
deletePic() {
|
|||
|
this.formData.picture = ''
|
|||
|
},
|
|||
|
|
|||
|
toSetmap() {
|
|||
|
if (this.formData.longitude && this.formData.latitude) {
|
|||
|
uni.navigateTo({
|
|||
|
url: `/pages_adminSet/park_map?type=${this.formData.type}&boundaryStr=${encodeURIComponent(this.formData.boundaryStr || '')}&longitude=${this.formData.longitude}&latitude=${this.formData.latitude}`
|
|||
|
})
|
|||
|
} else {
|
|||
|
uni.navigateTo({
|
|||
|
url: `/pages_adminSet/park_map?type=${this.formData.type}&boundaryStr=${encodeURIComponent(this.formData.boundaryStr || '')}&longitude=${this.areaInfo.longitude}&latitude=${this.areaInfo.latitude}`
|
|||
|
})
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 处理地图返回的数据
|
|||
|
handleMapDataReturn(boundaryStr) {
|
|||
|
this.formData.boundaryStr = boundaryStr
|
|||
|
const coordinates = JSON.parse(boundaryStr)
|
|||
|
|
|||
|
// 更新 boundary
|
|||
|
// this.formData.boundary = `POLYGON((${coordinates.map(coord => coord.join(' ')).join(',')}))`
|
|||
|
|
|||
|
// 计算并更新中心点
|
|||
|
// const center = this.calculateCenter(coordinates)
|
|||
|
// this.formData.latitude = String(center.latitude)
|
|||
|
// this.formData.longitude = String(center.longitude)
|
|||
|
|
|||
|
// 更新地图显示
|
|||
|
this.coordinates = coordinates
|
|||
|
this.updatePolygons()
|
|||
|
},
|
|||
|
|
|||
|
// 更新多边形
|
|||
|
updatePolygons() {
|
|||
|
if (this.coordinates.length >= 3) {
|
|||
|
this.polygons = [{
|
|||
|
points: this.coordinates.map(coord => ({
|
|||
|
latitude: coord[1],
|
|||
|
longitude: coord[0]
|
|||
|
})),
|
|||
|
strokeWidth: 2,
|
|||
|
strokeColor: '#007AFF90',
|
|||
|
fillColor: '#007AFF60'
|
|||
|
}]
|
|||
|
|
|||
|
// 更新表单数据
|
|||
|
this.formData.boundaryStr = JSON.stringify(this.coordinates)
|
|||
|
this.formData.boundary = `POLYGON((${this.coordinates.map(coord => coord.join(' ')).join(',')}))`
|
|||
|
|
|||
|
// 计算中心点
|
|||
|
const center = this.calculateCenter()
|
|||
|
this.formData.latitude = String(center.latitude)
|
|||
|
this.formData.longitude = String(center.longitude)
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 计算中心点
|
|||
|
calculateCenter() {
|
|||
|
const lats = this.coordinates.map(coord => coord[1])
|
|||
|
const lngs = this.coordinates.map(coord => coord[0])
|
|||
|
return {
|
|||
|
latitude: (Math.max(...lats) + Math.min(...lats)) / 2,
|
|||
|
longitude: (Math.max(...lngs) + Math.min(...lngs)) / 2
|
|||
|
}
|
|||
|
},
|
|||
|
|
|||
|
// 提交表单
|
|||
|
handleSubmit() {
|
|||
|
if (!this.formData.parkingName) {
|
|||
|
return uni.showToast({
|
|||
|
title: '请输入区域名称',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if (!this.formData.type) {
|
|||
|
return uni.showToast({
|
|||
|
title: '请选择区域类型',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
if (!this.formData.boundary) {
|
|||
|
return uni.showToast({
|
|||
|
title: '请在地图上绘制区域',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
}
|
|||
|
|
|||
|
const data = {
|
|||
|
...this.formData,
|
|||
|
areaId: this.areaId
|
|||
|
}
|
|||
|
|
|||
|
const request = this.parkingId ?
|
|||
|
this.$u.put('/appVerify/parking', { ...data, parkingId: this.parkingId }) :
|
|||
|
this.$u.post('/appVerify/parking', data)
|
|||
|
|
|||
|
request.then(res => {
|
|||
|
if (res.code === 200) {
|
|||
|
uni.showToast({
|
|||
|
title: '保存成功',
|
|||
|
icon: 'success'
|
|||
|
})
|
|||
|
setTimeout(() => {
|
|||
|
this.goBack()
|
|||
|
}, 1500)
|
|||
|
} else {
|
|||
|
uni.showToast({
|
|||
|
title: res.msg || '保存失败',
|
|||
|
icon: 'none'
|
|||
|
})
|
|||
|
}
|
|||
|
})
|
|||
|
},
|
|||
|
|
|||
|
// 返回上一页
|
|||
|
goBack() {
|
|||
|
uni.navigateBack()
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss">
|
|||
|
page {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
background-color: #f5f5f5;
|
|||
|
}
|
|||
|
|
|||
|
.page {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
.content {
|
|||
|
padding: 20rpx;
|
|||
|
}
|
|||
|
|
|||
|
.form-item {
|
|||
|
background-color: #fff;
|
|||
|
padding: 20rpx;
|
|||
|
margin-bottom: 20rpx;
|
|||
|
border-radius: 8rpx;
|
|||
|
|
|||
|
.label {
|
|||
|
font-size: 28rpx;
|
|||
|
color: #333;
|
|||
|
margin-bottom: 10rpx;
|
|||
|
display: block;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.type-selector {
|
|||
|
display: flex;
|
|||
|
justify-content: space-between;
|
|||
|
align-items: center;
|
|||
|
padding: 20rpx;
|
|||
|
background-color: #f8f8f8;
|
|||
|
border-radius: 8rpx;
|
|||
|
}
|
|||
|
|
|||
|
.image-upload {
|
|||
|
position: relative;
|
|||
|
display: inline-block;
|
|||
|
|
|||
|
.preview-image {
|
|||
|
width: 200rpx;
|
|||
|
height: 200rpx;
|
|||
|
border-radius: 8rpx;
|
|||
|
}
|
|||
|
|
|||
|
.upload-btn {
|
|||
|
width: 200rpx;
|
|||
|
height: 200rpx;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
background-color: #f8f8f8;
|
|||
|
border-radius: 8rpx;
|
|||
|
}
|
|||
|
|
|||
|
.delete-btn {
|
|||
|
position: absolute;
|
|||
|
top: -20rpx;
|
|||
|
right: -20rpx;
|
|||
|
width: 40rpx;
|
|||
|
height: 40rpx;
|
|||
|
background-color: rgba(0, 0, 0, 0.5);
|
|||
|
border-radius: 50%;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.map-container {
|
|||
|
width: 100%;
|
|||
|
height: 500rpx;
|
|||
|
|
|||
|
map {
|
|||
|
width: 100%;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
.map-tips {
|
|||
|
font-size: 24rpx;
|
|||
|
color: #999;
|
|||
|
margin-top: 10rpx;
|
|||
|
}
|
|||
|
|
|||
|
.clear-btn {
|
|||
|
margin-top: 20rpx;
|
|||
|
text-align: center;
|
|||
|
color: #007AFF;
|
|||
|
font-size: 28rpx;
|
|||
|
}
|
|||
|
|
|||
|
.btn-group {
|
|||
|
margin-top: 40rpx;
|
|||
|
display: flex;
|
|||
|
gap: 20rpx;
|
|||
|
|
|||
|
.u-button {
|
|||
|
flex: 1;
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|