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

339 lines
9.1 KiB
Vue

<template>
<div>
<el-dialog
:append-to-body="true"
:before-close="handleClose"
:close-on-click-modal="false"
:title="title"
:visible.sync="mapFormVisible"
class="bs-dialog-wrap bs-el-dialog"
width="700px"
>
<el-form
ref="mapForm"
:model="mapForm"
:rules="rules"
class="bs-el-form"
label-width="120px"
>
<el-form-item
label="上级地图"
prop="parentId"
>
<el-input
v-model="parentName"
class="bs-el-input"
disabled
/>
</el-form-item>
<el-form-item
label="地图名称"
prop="name"
>
<el-input
v-model="mapForm.name"
class="bs-el-input"
placeholder="请输入"
/>
</el-form-item>
<el-form-item
label="地图标识"
prop="mapCode"
>
<template slot="label">
<span>地图标识</span>
<el-tooltip
v-if="mapForm.parentId !== '0'"
class="item"
effect="light"
content="地图标识取自上级地图JSON数据中的properties.name值用于在地图中显示地区名称"
placement="top"
>
<i
class="el-icon-warning-outline"
style="color: #E3C98C;margin-left: 6px;font-size:14px"
/>
</el-tooltip>
</template>
<el-input
v-model="mapForm.mapCode"
class="bs-el-input"
placeholder="请输入地图标识"
/>
</el-form-item>
<el-form-item
label="地图级别"
prop="level"
>
<template slot="label">
<span>地图级别</span>
<el-tooltip
v-if="mapForm.parentId !== '0'"
class="item"
effect="light"
content="子级地图的级别根据上级地图自动递增,不可修改"
placement="top"
>
<i
class="el-icon-warning-outline"
style="color: #E3C98C;margin-left: 6px;font-size:14px"
/>
</el-tooltip>
</template>
<el-select
v-model="mapForm.level"
disabled
class="bs-el-select"
placeholder="请选择地图级别"
popper-class="bs-el-select"
>
<el-option
v-for="level in levelList"
:key="level.value"
:label="level.label"
:value="level.value"
/>
<el-option
v-if="![0,1,2,3,4].includes(mapForm.level)"
:value="mapForm.level"
:label="outRangeLabel"
/>
</el-select>
</el-form-item>
<el-form-item
label="geoJson"
>
<vue-json-viewer
v-model="mapForm.geoJson"
theme="dark"
:show-btns="false"
mode="code"
/>
<el-button
v-if="mapForm.uploadedGeoJson !== 1"
class="bs-el-button-default"
@click="upload"
>
<i class="el-icon-upload2" />
上传
</el-button>
</el-form-item>
<el-form-item
v-if="autoParseNextLevelShow"
label="自动解析下一级"
prop="autoParseNextLevel"
>
<el-switch
v-model="mapForm.autoParseNextLevel"
:active-value="1"
:inactive-value="0"
class="bs-el-switch"
/>
</el-form-item>
</el-form>
<span
slot="footer"
class="dialog-footer"
>
<el-button
class="bs-el-button-default"
@click="handleClose"
>
取消
</el-button>
<el-button
type="primary"
@click="submitForm"
>
确定
</el-button>
</span>
</el-dialog>
<input
ref="geoJsonFile"
accept=".json"
name="file"
style="display: none"
type="file"
@change="handleBatchUpload"
>
</div>
</template>
<script>
import _ from 'lodash'
import vueJsonViewer from 'vue-json-viewer'
import { mapUpdate, getMapChildFromGeoJson, nameRepeatCheck } from 'data-room-ui/js/utils/mapDataService'
export default {
name: 'EditForm',
components: {
vueJsonViewer
},
computed: {
autoParseNextLevelShow () {
// geoJson 不为空,且未上传过(说明是刚上传的)
return !this.isWhitespace(this.mapForm.geoJson) && this.mapForm.uploadedGeoJson === 0
},
outRangeLabel() {
return `级别${this.mapForm.level + 1}`;
}
},
data () {
const validateCode = (rule, value, callback) => {
if (this.mapForm.parentId === '0' || this.mapForm.parentId === 0) {
// 不需要校验
callback()
return
}
getMapChildFromGeoJson(this.mapForm.parentId).then(children => {
let repeat = false
children.forEach(child => {
if (child.exist && child.name === value && child.existId !== this.mapForm.id) {
repeat = true
}
})
if (repeat) {
callback(new Error('地图标识已存在'))
} else {
callback()
}
})
}
const validateName = (rule, value, callback) => {
if (this.mapForm.parentId !== '0') {
// 不需要校验
callback()
return
}
nameRepeatCheck({
id: this.mapForm.id,
parentId: this.mapForm.parentId,
mapName: value
}).then(res => {
if (res) {
callback(new Error('地图名称已存在'))
} else {
callback()
}
})
}
return {
mapFormVisible: false,
geoJsonVisible: false,
uploadLoading: false,
title: '编辑地图数据',
parentName: '顶级',
mapForm: {
parentId: '0',
mapCode: '',
name: '',
level: 0,
geoJson: '',
uploadedGeoJson: 0,
autoParseNextLevel: 0
},
rules: {
mapCode: [
{ required: true, message: '请输入地图标识', trigger: 'blur' },
{ validator: validateCode, trigger: 'blur' }
],
name: [
{ required: true, message: '请输入地图名称', trigger: 'blur' },
{ validator: validateName, trigger: 'blur' }
],
level: [
{ required: true, message: '请选择地图级别', trigger: 'change' }
],
geoJson: [
{ required: true, message: '请上传地图数据', trigger: 'change' }
]
},
levelList: [
{ value: 0, label: '世界' },
{ value: 1, label: '国家' },
{ value: 2, label: '省份' },
{ value: 3, label: '城市' },
{ value: 4, label: '区县' }
],
mapCodeList: []
}
},
methods: {
init (map) {
this.mapForm = _.cloneDeep(map)
if (!this.isWhitespace(this.mapForm.geoJson)) {
this.mapForm.geoJson = JSON.parse(this.mapForm.geoJson)
}
},
handleClose () {
this.mapFormVisible = false
},
submitForm () {
this.$refs.mapForm.validate(valid => {
if (!valid) {
return false
}
let geoJson
// 如果geoJson是空的包括空字符串纯空格、空对象空数组都不允许提交
if (this.isWhitespace(this.mapForm.geoJson) || this.mapForm.geoJson === '{}' || this.mapForm.geoJson === '[]') {
geoJson = ''
} else {
geoJson = JSON.stringify(this.mapForm.geoJson)
}
mapUpdate({
...this.mapForm,
geoJson: geoJson
}).then(res => {
this.mapFormVisible = false
this.$emit('refresh', {
id: this.mapForm.id,
parentId: this.mapForm.parentId
})
})
})
},
isWhitespace (str) {
// 如果是null、undefined返回true
if (str == null) {
return true
}
return /^\s*$/.test(str)
},
upload () {
this.$refs.geoJsonFile.click()
},
handleBatchUpload (source) {
this.uploadLoading = true
const file = source.target.files
const reader = new FileReader() // 新建一个FileReader
reader.readAsText(file[0], 'UTF-8') // 读取文件
reader.onload = (event) => {
const jsonStr = event.target.result
// 读取文件内容
try {
this.mapForm.geoJson = JSON.parse(jsonStr)
} catch (e) {
this.uploadLoading = false
this.$message.error('JSON文件格式错误')
return false
}
this.uploadLoading = false
// input通过onchange事件来触发js代码的由于两次文件是重复的所以这个时候onchange事件是没有触发到的所以需要手动清空input的值
source.target.value = ''
}
}
}
}
</script>
<style lang="scss" scoped>
@import '../../assets/style/bsTheme.scss';
.jv-container.dark {
color: aliceblue;
background: #161A26;
}
</style>