admin-vue3/src/views/crm/stationsite/StationSiteForm.vue

486 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="130px"
v-loading="formLoading"
>
<el-row>
<el-col :span="12">
<el-form-item label="场地名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入场地名称" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="场地状态" prop="siteStatus">
<el-select v-model="formData.siteStatus" placeholder="请选择场地状态" class="w-1/1">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_STATION_SITE_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="场地类型" prop="siteType">
<el-select v-model="formData.siteType" placeholder="请选择场地类型" class="w-1/1">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.CRM_STATION_SITE_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="10">
<el-form-item label="可建充电桩数" prop="estimatedPiles" >
<el-input-number v-model="formData.estimatedPiles" :min="0" :max="255" :step="1"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="地区" prop="areaId">
<el-cascader
v-model="formData.areaId"
:options="areaList"
:props="defaultProps"
class="w-1/1"
clearable
filterable
placeholder="请选择地区"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="详细地址" prop="detailAddress">
<el-input v-model="formData.detailAddress" placeholder="请输入详细地址" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="地图选点" prop="locationName">
<el-input v-model="formData.locationName" placeholder="请选择地图位置" readonly>
<template #append>
<el-button @click="openMapDialog">地图选点</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-dialog v-model="mapDialogVisible" title="获取经纬度" width="800px" append-to-body>
<iframe
v-if="mapDialogVisible"
:src="tencentLbsUrl"
width="100%"
height="600"
frameborder="0"
></iframe>
</el-dialog>
<el-row>
<el-col :span="12">
<el-form-item label="业主方" prop="ownerId">
<el-input v-model="formData.ownerName" placeholder="请输入业主方" :disabled="ownerInputDisabled">
<template #append>
<el-button @click="openOwnerDialog">关联</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物管方" prop="managementId">
<el-input v-model="formData.managementName" placeholder="请输入物管方" :disabled="managementInputDisabled">
<template #append>
<el-button @click="openManagementDialog">关联</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="推荐人姓名" prop="recommenderName">
<el-input v-model="formData.recommenderName" placeholder="请输入推荐人姓名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="推荐人联系方式" prop="recommenderContact">
<el-input v-model="formData.recommenderContact" placeholder="请输入推荐人联系方式" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="交通情况" prop="params.traffic">
<el-input v-model="formData.params.traffic" type="textarea" placeholder="请输入交通情况" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="电力距离" prop="params.powerDistance">
<el-input v-model="formData.params.powerDistance" placeholder="请输入电力距离" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="道闸情况" prop="params.barrierGate">
<el-input v-model="formData.params.barrierGate" placeholder="请输入道闸情况" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="周边竞品" prop="params.competitor">
<el-input v-model="formData.params.competitor" placeholder="请输入周边竞品" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="附加图片" prop="picUrls">
<UploadImgs v-model="formData.picUrls" />
</el-form-item>
<el-form-item label="附件" prop="fileUrls">
<UploadFile v-model="formData.fileUrls" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 业主方选择弹窗 -->
<el-dialog
title="选择业主方"
v-model="ownerDialogVisible"
width="400px"
>
<el-table
:data="customerList"
style="width: 100%"
@current-change="handleOwnerSelect"
highlight-current-row
ref="ownerTable"
>
<el-table-column type="index" width="55" />
<el-table-column prop="name" label="客户名称" width="300" />
</el-table>
<div style="text-align: right; margin-top: 10px;">
<el-button @click="ownerDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="confirmOwnerSelection">确 定</el-button>
</div>
</el-dialog>
<!-- 物管方选择弹窗 -->
<el-dialog
title="选择物管方"
v-model="managementDialogVisible"
width="400px"
>
<el-table
:data="customerList"
style="width: 100%"
@current-change="handleManagementSelect"
highlight-current-row
ref="managementTable"
>
<el-table-column type="index" width="55" />
<el-table-column prop="name" label="客户名称" width="300" />
</el-table>
<div style="text-align: right; margin-top: 10px;">
<el-button @click="managementDialogVisible = false">取 消</el-button>
<el-button type="primary" @click="confirmManagementSelection">确 定</el-button>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { StationSiteApi, StationSiteVO } from '@/api/crm/stationsite'
import { defaultProps } from '@/utils/tree'
import * as AreaApi from '@/api/system/area'
import { useUserStore } from '@/store/modules/user'
import * as CustomerApi from '@/api/crm/customer'
/** */
defineOptions({ name: 'StationSiteForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
name: undefined,
areaId: undefined,
detailAddress: undefined,
locationLng: 0,
locationLat: 0,
estimatedPiles: 0,
siteStatus: undefined,
siteType: undefined,
ownerUserId: 0,
ownerId: undefined,
ownerName: undefined,
managementId: undefined,
managementName: undefined,
recommenderName: undefined,
recommenderContact: undefined,
picUrls: [], //
fileUrls: [], //
parkingSpaces: 0,
rentPrice: '',
params: {
traffic: '',
powerDistance: '',
barrierGate: '',
competitor: ''
},
locationName: '', // locationName
})
const areaList = ref([]) //
const customerList = ref<{ id: string | number; name: string }[]>([])
const formRules = reactive({
name: [{ required: true, message: '场地名称不能为空', trigger: 'blur' }],
areaId: [{ required: true, message: '地区不能为空', trigger: 'blur' }],
siteType: [{ required: true, message: '场地类型不能为空', trigger: 'blur' }],
locationName: [{ required: true, message: '地图选点不能为空', trigger: 'blur' }],
estimatedPiles: [{ required: true, message: '可建充电桩数不能为空', trigger: 'blur' }],
siteStatus: [{ required: true, message: '场地状态不能为空', trigger: 'blur' }],
recommenderName: [{ required: true, message: '推荐人姓名不能为空', trigger: 'blur' }],
recommenderContact: [{ required: true, message: '推荐人联系方式不能为空', trigger: 'blur' }],
})
const formRef = ref() // 表单 Ref
const mapDialogVisible = ref(false)
const tencentLbsUrl = ref('')
const TENCENT_MAP_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY // 你的腾讯地图key
const ownerDialogVisible = ref(false)
const managementDialogVisible = ref(false)
const selectedOwner = ref()
const selectedManagement = ref()
const ownerFlag = ref(false)
const managementFlag = ref(false)
const ownerInputDisabled = computed(() => !!formData.value.ownerId)
const managementInputDisabled = computed(() => !!formData.value.managementId)
/** 打开弹窗 */
const open = async (type: string, id?: number) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
// 修改时,设置数据
if (id) {
formLoading.value = true
try {
formData.value = await StationSiteApi.getStationSite(id)
// 修复 params 多重转义问题
if (typeof formData.value.params === 'string') {
try {
formData.value.params = JSON.parse(formData.value.params)
} catch (e) {
formData.value.params = {
traffic: '',
powerDistance: '',
barrierGate: '',
competitor: ''
}
}
}
} finally {
formLoading.value = false
}
}
// 默认新建时选中自己
if (formType.value === 'create') {
formData.value.ownerUserId = useUserStore().getUser.id
}
}
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
const submitForm = async () => {
// 校验表单
await formRef.value.validate()
// 提交请求
formLoading.value = true
try {
const data = {
...formData.value,
params: JSON.stringify(formData.value.params)
} as unknown as StationSiteVO
if (formType.value === 'create') {
await StationSiteApi.createStationSite(data)
message.success(t('common.createSuccess'))
} else {
await StationSiteApi.updateStationSite(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
// 发送操作成功的事件
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
name: undefined,
areaId: undefined,
detailAddress: undefined,
locationLng: 0,
locationLat: 0,
estimatedPiles: 0,
siteStatus: undefined,
siteType: undefined,
ownerUserId: useUserStore().getUser.id,
ownerId: undefined,
ownerName: undefined,
managementId: undefined,
managementName: undefined,
recommenderName: undefined,
recommenderContact: undefined,
picUrls: [], // 修复:初始化为空数组
fileUrls: [], // 修复:初始化为空数组
parkingSpaces: 0,
rentPrice: '',
params: {
traffic: '',
powerDistance: '',
barrierGate: '',
competitor: ''
},
locationName: '',
}
formRef.value?.resetFields()
}
/** 初始化 **/
const openMapDialog = () => {
// 拼接带初始点的 url
let url = `https://apis.map.qq.com/tools/locpicker?type=1&key=${TENCENT_MAP_KEY}&referer=myapp`
if (formData.value.locationLat && formData.value.locationLng) {
url += `&coord=${formData.value.locationLat},${formData.value.locationLng}`
}
tencentLbsUrl.value = url
mapDialogVisible.value = true
}
function selectAddress(loc: any): void {
if (loc.poiname) {
formData.value.locationName = loc.poiname
} else {
formData.value.locationName = ''
}
if (loc.latlng && loc.latlng.lat) {
formData.value.locationLat = Number(loc.latlng.lat)
formData.value.locationLng = Number(loc.latlng.lng)
}
mapDialogVisible.value = false
}
const initTencentLbsMap = () => {
// @ts-ignore
window.selectAddress = selectAddress
window.addEventListener(
'message',
function (event) {
let loc = event.data
if (loc && loc.module === 'locationPicker') {
// @ts-ignore
window.selectAddress(loc)
}
},
false
)
}
onMounted(() => {
AreaApi.getAreaTree().then(res => {
areaList.value = res
})
initTencentLbsMap()
})
watch(mapDialogVisible, (val) => {
if (!val) {
tencentLbsUrl.value = '' // 关闭时重置,避免缓存
}
})
/** 打开业主方选择弹窗 */
const openOwnerDialog = async () => {
ownerDialogVisible.value = true
const list = await CustomerApi.getCustomerSimpleList()
customerList.value = [{ id: '0', name: '无' }, ...list] // 添加空数据
}
/** 打开物管方选择弹窗 */
const openManagementDialog = async () => {
managementDialogVisible.value = true
const list = await CustomerApi.getCustomerSimpleList()
customerList.value = [{ id: '0', name: '无' }, ...list] // 添加空数据
}
/** 选择业主方 */
const handleOwnerSelect = (val) => {
if (!val) return;
selectedOwner.value = val
formData.value.ownerId = val.id
formData.value.ownerName = val.name // 记录业主方名称
}
/** 选择物管方 */
const handleManagementSelect = (val) => {
if (!val) return;
selectedManagement.value = val
formData.value.managementId = val.id
formData.value.managementName = val.name // 记录物管方名称
}
/** 确认业主方选择 */
const confirmOwnerSelection = () => {
if (!selectedOwner.value) {
message.error('请先选择业主方')
return
}
if (selectedOwner.value.id === '0') {
formData.value.ownerId = undefined
formData.value.ownerName = undefined
ownerFlag.value = false
} else {
formData.value.ownerId = selectedOwner.value.id
formData.value.ownerName = selectedOwner.value.name
ownerFlag.value = true
}
ownerDialogVisible.value = false
}
/** 确认物管方选择 */
const confirmManagementSelection = () => {
if (!selectedManagement.value) {
message.error('请先选择物管方')
return
}
if (selectedManagement.value.id === '0') {
formData.value.managementId = undefined
formData.value.managementName = undefined
managementFlag.value = false
} else {
formData.value.managementId = selectedManagement.value.id
formData.value.managementName = selectedManagement.value.name
managementFlag.value = true
}
managementDialogVisible.value = false
}
</script>