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.
crmeb/admin/src/views/pm/complaint/suggestion/pmcomplaintsuggestion-add-a...

559 lines
22 KiB

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>
<!-- 基于 Element UI 新增和修改弹窗 -->
<el-dialog
:title="!dataForm.id ? '添加' : '修改'"
:close-on-click-modal="false"
:visible.sync="visible"
width="80%">
<!-- 新增和修改表单 -->
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" @keyup.enter.native="dataSubmit()" label-width="100px">
<!-- 第一行业主类型业主/租户名称房屋名称 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="业主类型" prop="ownerType">
<el-select v-model="dataForm.ownerType" placeholder="请选择业主类型" clearable style="width: 100%"
@change="handleOwnerTypeChange" filterable>
<el-option
v-for="dict in dict.type.owner_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="dataForm.ownerType === '1' ? '业主/租户' : '业主/租户'" prop="ownerId">
<el-select v-if="dataForm.ownerType === '1'" v-model="dataForm.ownerId" placeholder="请选择业主" clearable
style="width: 100%" @change="handleOwnerChange" filterable>
<el-option
v-for="item in ownerList"
:key="item.id"
:label="item.ownerName"
:value="item.id"
/>
</el-select>
<el-select v-else-if="dataForm.ownerType === '2'" v-model="dataForm.ownerId" placeholder="请选择租户" clearable
style="width: 100%" @change="handleOwnerChange" filterable>
<el-option
v-for="item in tenantList"
:key="item.id"
:label="item.tenantName"
:value="item.id"
/>
</el-select>
<el-select v-else v-model="dataForm.ownerId" placeholder="请先选择业主类型" clearable disabled style="width: 100%"></el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="房屋名称" prop="houseId">
<el-select v-model="dataForm.houseId" placeholder="选择房屋" clearable style="width: 100%"
@change="handleHouseChange" filterable>
<el-option
v-for="item in ownerHouseList"
:key="item.id"
:label="`${item.unitNo}单元 ${item.floorNo}层 ${item.houseNo}室`"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<!-- 第二行:被投诉房屋、类型、业主所属部门 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="被投诉房屋" prop="complainedHouseId">
<el-select v-model="dataForm.complainedHouseId" placeholder="选择被投诉房屋" clearable style="width: 100%" filterable>
<el-option
v-for="item in houseList"
:key="item.id"
:label="`${item.unitNo}单元 ${item.floorNo}层 ${item.houseNo}室`"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="类型" prop="csType">
<el-select v-model="dataForm.csType" placeholder="请选择类型" clearable style="width: 100%" filterable>
<el-option
v-for="dict in dict.type.cs_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="业主所属部门" prop="ownerCompany">
<el-input v-model="dataForm.ownerCompanyName" placeholder="业主所属部门" readonly></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 第三行:状态、提交渠道、联系方式 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="状态" prop="status">
<el-select v-model="dataForm.status" placeholder="请选择状态" clearable style="width: 100%" filterable disabled>
<el-option
v-for="dict in dict.type.suggestion_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="提交渠道" prop="submitChannel">
<el-select v-model="dataForm.submitChannel" placeholder="请选择提交渠道" clearable style="width: 100%" filterable>
<el-option
v-for="dict in dict.type.submit_channel"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="联系方式" prop="phone">
<el-input v-model="dataForm.phone" placeholder="联系方式"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 第四行:提交时间、处理人、处理时间 -->
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="提交时间" prop="submitTime">
<el-date-picker v-model="dataForm.submitTime" type="datetime" placeholder="选择提交时间" style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="处理人" prop="handlerId">
<el-select v-model="dataForm.handlerId" placeholder="请选择处理人" clearable style="width: 100%" filterable>
<el-option
v-for="item in adminList"
:key="item.id"
:label="item.realName"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="处理时间" prop="handlerDate">
<el-date-picker v-model="dataForm.handlerDate" type="datetime" placeholder="选择处理时间" style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
</el-row>
<!-- 第七行:内容 -->
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="内容" prop="csContent">
<el-input v-model="dataForm.csContent" placeholder="内容" type="textarea" :rows="3"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 第八行:处理结果 -->
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="处理结果" prop="handlerReslut">
<el-input v-model="dataForm.handlerReslut" placeholder="处理结果" type="textarea" :rows="3"></el-input>
</el-form-item>
</el-col>
</el-row>
<!-- 隐藏的房屋业主id字段 -->
<el-form-item label="房屋业主id" prop="houseOwnerId" v-show="false">
<el-input v-model="dataForm.houseOwnerId" placeholder="房屋业主id" readonly></el-input>
</el-form-item>
<!-- 附件 -->
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="附件" prop="files">
<FileUploadVO
:value="complaintFiles"
@input="updateComplaintFiles"
></FileUploadVO>
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="dataSubmit()"></el-button>
</span>
</el-dialog>
</template>
<script>
import * as api from '@/api/pmcomplaintsuggestion.js'
import * as ownerApi from '@/api/pmowner.js'
import * as tenantApi from '@/api/pmtenant.js'
import * as tenantHouseApi from '@/api/pmtenanthouse.js'
import * as houseApi from '@/api/pmhouse.js'
import * as ownerHouseRelApi from '@/api/pmownerhouserel.js'
import * as tenantHouseRelApi from '@/api/pmtenanthouserel.js'
import * as adminApi from '@/api/systemadmin.js'
import FileUploadVO from '@/components/FileUploadVO/index.vue'
export default {
components: {
FileUploadVO
},
dicts: ['owner_type', 'cs_type', 'submit_channel', 'suggestion_status'],
data () {
return {
visible: false,
ownerList: [],
tenantList: [],
houseList: [],
adminList: [], // 管理员列表
ownerHouseList: [], // 所选业主/租户的房屋列表
complaintFiles: [], // 附件文件列表
dataForm: {
id: 0,
csType: '' ,
status: '0' ,
csContent: '' ,
submitChannel: '' ,
submitTime: '' ,
handlerReslut: '' ,
handlerId: '' ,
handlerDate: '' ,
phone: '' ,
ownerType: '' ,
ownerId: '' ,
houseId: '' ,
houseOwnerId: '',
complainedHouseId: '',
ownerCompany: '',
ownerCompanyName: '',
files: []
},
dataRule: {
csType: [
{ required: true, message: '类型 为必填项', trigger: 'blur' }
],
// status: [
// { required: true, message: '状态 为必填项', trigger: 'blur' }
// ],
ownerType: [
{ required: true, message: '业主类型 为必填项', trigger: 'blur' }
],
ownerId: [
{ required: true, message: '业主 为必填项', trigger: 'blur' }
],
houseId: [
{ required: true, message: '房屋 为必填项', trigger: 'blur' }
],
}
}
},
mounted() {
this.handleGetOwnerList()
this.handleGetTenantList()
this.handleGetHouseList()
this.loadAdminList()
},
methods: {
// 加载管理员列表数据
loadAdminList(deptId = null) {
const params = { page: 1, limit: 999 }
// 如果提供了部门ID添加到参数中
if (deptId && typeof deptId !== 'object') {
params.deptId = deptId
}
adminApi.adminList(params).then((res) => {
this.adminList = res.list || []
}).catch(() => {
this.adminList = []
})
},
// 获取业主列表
handleGetOwnerList() {
ownerApi.pmownerListApi({page: 1, limit: 9999}).then(res => {
this.ownerList = res.list || []
})
},
// 获取租户列表
handleGetTenantList() {
tenantApi.pmtenantListApi({page: 1, limit: 9999}).then(res => {
this.tenantList = res.list || []
})
},
// 获取房屋列表
handleGetHouseList() {
houseApi.pmhouseListApi({page: 1, limit: 9999}).then(res => {
this.houseList = res.list || []
})
},
// 处理业主类型变化
handleOwnerTypeChange(ownerType) {
// 清空业主/租户ID和房屋ID
this.dataForm.ownerId = ''
this.dataForm.houseId = ''
this.dataForm.houseOwnerId = ''
this.ownerHouseList = []
},
// 处理业主选择变化
handleOwnerChange(ownerId, callback) {
// 获取关联房屋
if (ownerId) {
if (this.dataForm.ownerType === '1') {
// 业主类型,查询业主的房屋
ownerHouseRelApi.pmownerhouserelListApi({ ownerId: ownerId, page: 1, limit: 9999 }).then(res => {
const relList = res.list || []
// 获取房屋ID列表
const houseIds = relList.map(item => item.houseId)
// 从房屋列表中筛选出关联的房屋
this.ownerHouseList = this.houseList.filter(house => houseIds.includes(house.id))
// 清空房屋选择,让用户手动选择
this.dataForm.houseId = ''
this.dataForm.houseOwnerId = ''
// 设置业主所属部门
const owner = this.ownerList.find(item => item.id === ownerId)
if (owner && owner.deptId) {
this.dataForm.ownerCompany = owner.deptId
this.dataForm.ownerCompanyName = owner.deptName || ''
}
// 调用回调
if (callback) {
callback()
}
})
} else if (this.dataForm.ownerType === '2') {
// 租户类型先查询PmTenantHousetenantId对应的是Long rentId可能对应多个记录
tenantHouseApi.pmtenanthouseListApi({ rentId: ownerId, page: 1, limit: 9999 }).then(res => {
const tenantHouses = res.list || []
if (tenantHouses.length > 0) {
// 收集所有房屋ID
const allHouseIds = []
// 遍历所有的PmTenantHouse记录收集所有房屋ID
const promises = tenantHouses.map(tenantHouse => {
// 用pm_tenant_house中的id查询PmTenantHouseRel
return tenantHouseRelApi.pmtenanthouserelListApi({ tenantHouseId: tenantHouse.id, page: 1, limit: 9999 }).then(relRes => {
const relList = relRes.list || []
if (relList.length > 0) {
const houseIds = relList.map(item => item.houseId)
return houseIds
}
return []
})
})
Promise.all(promises).then(results => {
// 合并所有房屋ID
results.forEach(houseIds => {
allHouseIds.push(...houseIds)
})
// 从房屋列表中筛选出关联的房屋
this.ownerHouseList = this.houseList.filter(house => allHouseIds.includes(house.id))
// 清空房屋选择,让用户手动选择
this.dataForm.houseId = ''
this.dataForm.houseOwnerId = ''
// 设置租户所属部门
const tenant = this.tenantList.find(item => item.id === ownerId)
if (tenant && tenant.deptId) {
this.dataForm.ownerCompany = tenant.deptId
this.dataForm.ownerCompanyName = tenant.deptName || ''
}
// 调用回调
if (callback) {
callback()
}
})
} else {
// 没有找到租户房屋记录
this.ownerHouseList = []
this.dataForm.houseId = ''
this.dataForm.houseOwnerId = ''
// 设置租户所属部门
const tenant = this.tenantList.find(item => item.id === ownerId)
if (tenant && tenant.deptId) {
this.dataForm.ownerCompany = tenant.deptId
this.dataForm.ownerCompanyName = tenant.deptName || ''
}
// 调用回调
if (callback) {
callback()
}
}
})
}
} else {
this.ownerHouseList = []
this.dataForm.houseId = ''
this.dataForm.houseOwnerId = ''
// 清空部门信息
this.dataForm.ownerCompany = ''
this.dataForm.ownerCompanyName = ''
// 调用回调
if (callback) {
callback()
}
}
},
// 处理房屋选择变化
handleHouseChange(houseId) {
if (houseId) {
// 设置房屋业主ID为当前选择的业主ID
this.dataForm.houseOwnerId = this.dataForm.ownerId
} else {
// 清空房屋业主ID
this.dataForm.houseOwnerId = ''
}
},
// 更新附件文件列表
updateComplaintFiles(files) {
this.complaintFiles = files
// 将文件保存到dataForm.files中
if (files && files.length > 0) {
// 将FileUploadVO返回的文件格式转换为后端SystemAttachment需要的格式
this.dataForm.files = files.map(file => {
// 处理文件路径,确保符合后端要求的格式
let attDir = file.attDir || file.attachFileUrl || ''
// 如果路径以/file/public/开头,去掉这个前缀,因为后端存储格式不需要
if (attDir.startsWith('/file/public/')) {
attDir = attDir.replace('/file/public/', '')
} else if (attDir.startsWith('/file/')) {
attDir = attDir.replace('/file/', '')
}
return {
// 严格按照SystemAttachment的字段要求设置
attId: file.id || file.attId || '', // 确保转换为字符串
name: file.name || file.oldName || '', // 附件名称
attDir: attDir, // 附件路径
attSize: file.attSize || '', // 附件大小
attType: file.attType || '', // 附件类型
// 保留原有字段以保持兼容性
fileName: file.name || file.oldName || '',
filePath: attDir,
url: attDir,
createTime: null,
createdBy: null,
createTimeStr: null,
delFlag: '0',
updateBy: null,
updateTime: null,
i18nCode: '',
i18nLanguage: '',
originalFileName: file.name || file.oldName || '',
position: 0,
remark: file.remark || '',
sort: 0,
status: ''
}
})
} else {
this.dataForm.files = []
}
},
init (id) { // 初始化表单验证规则
this.dataForm.id = id || 0
this.visible = true
this.complaintFiles = [] // 清空文件列表
this.$nextTick(function() {
this.$refs['dataForm'].resetFields()
if (this.dataForm.id) {
api.pmcomplaintsuggestionDetailApi(id).then(function(res) {
// 处理日期字段,转换为 Date 对象
const data = res;
if (data.submitTime) {
data.submitTime = new Date(data.submitTime)
}
if (data.handlerDate) {
data.handlerDate = new Date(data.handlerDate)
}
this.dataForm = data;
// 设置文件列表
if (data.files && data.files.length > 0) {
this.complaintFiles = data.files.map(file => {
return {
id: file.attId,
attId: file.attId,
name: file.name || file.fileName || file.originalFileName,
oldName: file.name || file.fileName || file.originalFileName,
attDir: file.attDir || file.filePath || file.url,
attachFileUrl: file.attDir || file.filePath || file.url,
attSize: file.attSize,
attType: file.attType
}
})
} else {
this.complaintFiles = []
}
// 保存房屋ID
const houseId = data.houseId;
// 触发业主选择变化,加载房屋列表
this.handleOwnerChange(data.ownerId, () => {
// 重新设置房屋ID
this.$nextTick(() => {
this.dataForm.houseId = houseId;
// 触发房屋选择变化设置房屋业主ID
this.handleHouseChange(houseId);
});
});
}.bind(this))
}
}.bind(this))
},
// 表单数据提交
dataSubmit () {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
// 格式化日期时间
const submitData = { ...this.dataForm }
if (submitData.submitTime) {
submitData.submitTime = this.formatDate(submitData.submitTime)
}
if (submitData.handlerDate) {
submitData.handlerDate = this.formatDate(submitData.handlerDate)
}
if (this.dataForm.id) {
api.pmcomplaintsuggestionUpdateApi(submitData).then(function(res) {
this.$message.success('保存成功')
this.visible = false
this.$emit('refreshDataList')
}.bind(this));
} else {
api.pmcomplaintsuggestionCreateApi(submitData).then(function(res) {
this.$message.success('新增成功')
this.visible = false
this.$emit('refreshDataList')
}.bind(this));
}
}
})
},
// 格式化日期时间为 YYYY-MM-DD HH:mm:ss
formatDate(date) {
if (!date) return ''
const d = new Date(date)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
const hours = String(d.getHours()).padStart(2, '0')
const minutes = String(d.getMinutes()).padStart(2, '0')
const seconds = String(d.getSeconds()).padStart(2, '0')
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
}
}
</script>