2025-04-17 09:53:08 +08:00

664 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>房源列表</span>
<el-button-group style="float: right;">
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">新增房源</el-button>
<el-button type="primary" icon="el-icon-upload2" size="mini" @click="handleImport">批量导入</el-button>
<el-button type="primary" icon="el-icon-download" size="mini" @click="handleExport">批量导出</el-button>
</el-button-group>
</div>
<!-- 标签页切换 -->
<el-tabs v-model="activeTab" @tab-click="handleTabClick">
<el-tab-pane label="全部房源" name="all"></el-tab-pane>
<el-tab-pane label="招商房源" name="commercial"></el-tab-pane>
</el-tabs>
<!-- 搜索条件 -->
<el-form :model="queryParams" ref="queryForm" :inline="true" label-width="70px">
<el-form-item label="项目" prop="projectId">
<el-select v-model="queryParams.projectId" placeholder="请选择项目" clearable
@change="handleProjectChange" style="width: 240px;">
<el-option v-for="item in projectOptions" :key="item.id" :label="item.projectName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="楼宇" prop="buildingId">
<el-select v-model="queryParams.buildingId" placeholder="请选择楼宇" clearable
@change="handleBuildingChange" style="width: 240px;">
<el-option v-for="item in buildingOptions" :key="item.id" :label="item.buildingName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="楼层" prop="floorId">
<el-select v-model="queryParams.floorId" placeholder="请选择楼层" clearable style="width: 240px;">
<el-option v-for="item in floorOptions" :key="item.id" :label="item.floorName" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="房号" prop="roomNumber">
<el-input v-model="queryParams.roomNumber" placeholder="请输入房号" clearable style="width: 240px;" />
</el-form-item>
<el-form-item label="标签" prop="tags">
<el-select v-model="queryParams.tags" placeholder="请选择房源标签" clearable multiple style="width: 240px;">
<el-option v-for="tag in tagOptions" :key="tag.id" :label="tag.tagName" :value="tag.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
<el-button @click="toggleAdvanced" type="text">
{{ advanced ? '收起' : '展开' }}
<i :class="advanced ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
</el-button>
</el-form-item>
</el-form>
<!-- 高级搜索条件展开时显示 -->
<el-form v-show="advanced" :model="queryParams" ref="advancedQueryForm" :inline="true" label-width="100px">
<el-form-item label="租赁状态" prop="rentalStatus">
<el-select v-model="queryParams.rentalStatus" placeholder="请选择租赁状态" clearable style="width: 240px;">
<el-option label="待租" value="1" />
<el-option label="已租" value="2" />
</el-select>
</el-form-item>
<el-form-item v-if="activeTab === 'all'" label="招商状态" prop="businessStatus">
<el-select v-model="queryParams.businessStatus" placeholder="请选择招商状态" clearable style="width: 240px;">
<el-option label="招商" value="1" />
<el-option label="不招商" value="2" />
</el-select>
</el-form-item>
<el-form-item label="装修情况" prop="decorationStatus">
<el-select v-model="queryParams.decorationStatus" placeholder="请选择装修情况" clearable style="width: 240px;">
<el-option label="精装" value="1" />
<el-option label="简装" value="2" />
<el-option label="毛坯" value="3" />
<el-option label="标准交付" value="4" />
<el-option label="豪装" value="5" />
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
style="width: 240px;"
/>
</el-form-item>
</el-form>
<!-- 列表展示区域 -->
<el-table v-loading="loading" :data="roomList" border style="width: 100%; margin-top: 15px;"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="项目名称" prop="projectName" min-width="140" show-overflow-tooltip />
<el-table-column label="楼宇名称" prop="buildingName" min-width="120" show-overflow-tooltip />
<el-table-column label="楼层" prop="floorName" min-width="80" />
<el-table-column label="房号" prop="roomNumber" min-width="100" />
<el-table-column label="计租面积(㎡)" prop="rentalArea" min-width="110" />
<el-table-column label="报价" align="center" prop="price" width="150">
</el-table-column>
<el-table-column label="租赁状态" min-width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.rentalStatus === '1' ? 'success' : scope.row.rentalStatus === '2' ? 'danger' : 'warning'">
{{ scope.row.rentalStatus === '1' ? '待租' : scope.row.rentalStatus === '2' ? '已租' : '暂无' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="装修情况" min-width="100">
<template slot-scope="scope">
{{ scope.row.decorationStatus === '1' ? '精装' :
scope.row.decorationStatus === '2' ? '简装' :
scope.row.decorationStatus === '3' ? '毛坯' :
scope.row.decorationStatus === '4' ? '标准交付' :
scope.row.decorationStatus === '5' ? '豪装' : '-' }}
</template>
</el-table-column>
<el-table-column label="交付时间" prop="deliveryTime" min-width="110" />
<el-table-column label="可租日期" prop="availableDate" min-width="110" />
<el-table-column label="房源标签" min-width="120">
<template slot-scope="scope">
<el-tag v-for="tag in scope.row.tagList" :key="tag.id" type="info" size="mini" style="margin-right: 4px">
{{ tag.tagName }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="虚拟房源" min-width="90">
<template slot-scope="scope">
{{ scope.row.isVirtual === '1' ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column label="招商状态" min-width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.businessStatus === '1' ? 'primary' : 'info'">
{{ scope.row.businessStatus === '1' ? '招商' : '不招商' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" prop="createTime" min-width="150" />
<el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="handleDetail(scope.row)">详情</el-button>
<el-button type="text" size="mini" @click="handleUpdate(scope.row)">编辑</el-button>
<el-button type="text" size="mini" @click="handleDelete(scope.row)" style="color: #F56C6C;">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="queryParams.pageNum"
:page-sizes="[10, 20, 50, 100]"
:page-size="queryParams.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
class="pagination">
</el-pagination>
</el-card>
<!-- 导入对话框 -->
<el-dialog :title="importTitle" :visible.sync="importOpen" width="400px" append-to-body>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">
<el-button type="text" @click="downloadImportTemplate">下载模板</el-button>
<div>只允许导入xlsxlsx格式文件</div>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="importOpen = false"> </el-button>
</div>
</el-dialog>
<!-- 查看详情对话框 -->
<el-dialog :title="viewTitle" :visible.sync="viewOpen" width="900px" append-to-body>
<detail-view v-if="viewOpen" :roomId="currentRoomId" />
</el-dialog>
<!-- 添加/修改房源对话框 -->
<el-dialog :title="title" :visible.sync="open" width="1100px" append-to-body>
<room-form
v-if="open"
ref="roomForm"
:roomId="currentRoomId"
:isEdit="isEdit"
@refreshList="getList"
@close="open = false" />
</el-dialog>
</div>
</template>
<script>
import { listRoom, exportRoom, downloadTemplate, importRoom, listRoomTags, listProjects, listBuildings, listFloors, delRoom } from '@/api/room'
import { getProjectList,getTagByType } from '@/api/project'
import { getBuildingList,getFloorList,getFloorListByBuilding } from '@/api/building'
import DetailView from './components/DetailView'
import RoomForm from './components/RoomForm'
export default {
name: 'ProjectRoom',
components: {
DetailView,
RoomForm
},
data() {
return {
// 遮罩层
loading: false,
// 选中数组
ids: [],
// 非单个禁用
single: true,
// 非多个禁用
multiple: true,
// 显示搜索条件
advanced: false,
// 总条数
total: 0,
// 房源表格数据
roomList: [],
// 弹出层标题
title: '',
// 是否显示弹出层
open: false,
// 是否显示详情弹出层
viewOpen: false,
// 是否显示导入弹出层
importOpen: false,
// 导入标题
importTitle: '导入房源数据',
// 详情标题
viewTitle: '房源详情',
// 日期范围
dateRange: [],
// 当前处理的房源ID
currentRoomId: null,
// 是否编辑模式
isEdit: false,
// 当前激活的Tab页
activeTab: 'all',
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
projectId: undefined,
buildingId: undefined,
floorId: undefined,
roomNumber: undefined,
tags: [],
rentalStatus: undefined,
businessStatus: undefined,
decorationStatus: undefined
},
// 项目选项
projectOptions: [],
// 楼宇选项
buildingOptions: [],
// 楼层选项
floorOptions: [],
// 标签选项
tagOptions: [],
// 上传参数
upload: {
// 是否禁用上传
isUploading: false,
// 设置上传的请求头部
headers: { },
// 上传的URL
url: process.env.VUE_APP_BASE_API + '/room/template/import'
}
}
},
created() {
this.getList()
this.getProjectOptions()
this.getTagOptions()
},
methods: {
/** 处理Tab切换 */
handleTabClick() {
// 重置页码
this.queryParams.pageNum = 1
if (this.activeTab === 'all') {
// 全部房源清除businessStatus的查询条件
this.queryParams.businessStatus = undefined
} else if (this.activeTab === 'commercial') {
// 招商房源设置businessStatus为1
this.queryParams.businessStatus = '1'
}
// 重新加载列表
this.getList()
},
/** 获取房源列表 */
getList() {
this.loading = true
// 添加日期范围参数
const params = {...this.queryParams}
if (this.dateRange && this.dateRange.length > 0) {
params.beginTime = this.dateRange[0]
params.endTime = this.dateRange[1]
}
listRoom(params).then(response => {
if (response.code === '000000') {
this.roomList = response.data.list || []
this.total = response.data.total
} else {
this.$message.error(response.msg || '获取房源列表失败')
this.roomList = []
this.total = 0
}
this.loading = false
}).catch(() => {
this.loading = false
})
},
/** 获取项目选项 */
getProjectOptions() {
// 调用项目列表接口获取项目选项
getProjectList({ pageSize: 100 }).then(res => {
if (res.code === '000000') {
this.projectOptions = res.data.list.map(item => {
return { id: item.id, projectName: item.projectName }
})
}
})
},
/** 获取楼宇选项 */
getBuildingOptions(projectId) {
if (!projectId) {
this.buildingOptions = []
this.queryParams.buildingId = undefined
this.floorOptions = []
this.queryParams.floorId = undefined
return
}
const params = {
projectId: projectId,
pageNum: 1,
pageSize: 100,
}
getBuildingList(params).then(response => {
if (response.code === '000000') {
this.buildingOptions = response.data.list || []
} else {
this.$message.error(response.msg || '获取楼宇列表失败')
}
})
},
/** 获取楼层选项 */
getFloorOptions(buildingId) {
if (!buildingId) {
this.floorOptions = []
this.queryParams.floorId = undefined
return
}
listFloors(buildingId).then(response => {
if (response.code === '000000') {
this.floorOptions = response.data || []
} else {
this.$message.error(response.msg || '获取楼层列表失败')
}
})
},
/** 获取房源标签选项 */
getTagOptions() {
getTagByType({ tagType: "房源标签", tagName: "房源标签" }).then(res => {
this.tagOptions = res.data
}).catch(() => {
this.tagOptions = [
{ id: '1', tagName: '标签1' },
{ id: '2', tagName: '标签2' }
]
})
},
/** 项目选择改变事件 */
handleProjectChange(projectId) {
// 清空楼宇和楼层的选择
this.queryParams.buildingId = undefined
this.queryParams.floorId = undefined
this.buildingOptions = []
this.floorOptions = []
if (projectId) {
this.getBuildingOptions(projectId)
}
},
/** 楼宇选择改变事件 */
handleBuildingChange(buildingId) {
// 清空楼层的选择
this.queryParams.floorId = undefined
this.floorOptions = []
if (buildingId) {
getFloorListByBuilding(buildingId).then(response => {
if (response.code === '000000') {
this.floorOptions = response.data || []
} else {
this.$message.error(response.msg || '获取楼层列表失败')
}
})
}
},
/** 查询房源列表 */
handleQuery() {
this.queryParams.pageNum = 1
this.getList()
},
/** 重置查询条件 */
resetQuery() {
this.dateRange = []
this.resetForm('queryForm')
this.resetForm('advancedQueryForm')
// 保持当前Tab的状态
const tabBusinessStatus = this.activeTab === 'commercial' ? '1' : undefined
this.queryParams = {
pageNum: 1,
pageSize: 10,
projectId: undefined,
buildingId: undefined,
floorId: undefined,
roomNumber: undefined,
tags: [],
rentalStatus: undefined,
businessStatus: tabBusinessStatus,
decorationStatus: undefined
}
this.buildingOptions = []
this.floorOptions = []
this.handleQuery()
},
/** 切换高级搜索 */
toggleAdvanced() {
this.advanced = !this.advanced
},
/** 多选框选中数据 */
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length !== 1
this.multiple = !selection.length
},
/** 导出房源数据 */
handleExport() {
const params = this.ids
if(this.ids.length === 0){
this.$message.warning('请至少选择一条数据')
return
}
this.$confirm('是否确认导出所选房源数据?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.loading = true
exportRoom(params).then(response => {
this.download(response, '房源信息.xlsx')
this.loading = false
}).catch(() => {
this.loading = false
})
})
},
/** 下载导入模板 */
downloadImportTemplate() {
downloadTemplate().then(response => {
this.download(response, 'room_import.xlsx')
})
},
/** 导入按钮操作 */
handleImport() {
this.importOpen = true
},
/** 文件上传中处理 */
handleFileUploadProgress() {
this.upload.isUploading = true
},
/** 文件上传成功处理 */
handleFileSuccess(response) {
this.upload.isUploading = false
this.$refs.upload.clearFiles()
this.importOpen = false
if (response.code === '000000') {
this.$alert(`response.data.message `, { type: 'success' })
this.getList()
} else {
this.$alert(response.msg || '导入失败,正在下载错误文件', '导入结果', { type: 'error' })
}
},
/** 提交上传文件 */
submitFileForm() {
this.$refs.upload.submit()
},
/** 新增按钮操作 */
handleAdd() {
this.currentRoomId = null
this.isEdit = false
this.title = '新增房源'
this.open = true
},
/** 修改按钮操作 */
handleUpdate(row) {
this.currentRoomId = row.id
this.isEdit = true
this.title = '修改房源'
this.open = true
},
/** 查看详情按钮操作 */
handleDetail(row) {
this.currentRoomId = row.id
this.viewTitle = '房源详情'
this.viewOpen = true
},
/** 删除按钮操作 */
handleDelete(row) {
const roomId = row.id
this.$confirm('是否确认删除该房源?删除后所有相关信息将被清除', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delRoom(roomId).then(response => {
if (response.code === '000000') {
this.$message.success('删除成功')
this.getList()
} else {
this.$message.error(response.msg || '删除失败')
}
})
}).catch(() => {})
},
/** 分页大小改变 */
handleSizeChange(val) {
this.queryParams.pageSize = val
this.getList()
},
/** 分页页码改变 */
handleCurrentChange(val) {
this.queryParams.pageNum = val
this.getList()
},
/** 获取价格单位文本 */
getPriceUnitText(unitType) {
if (!unitType) return '';
const unitMap = {
'1': '元/㎡/天',
'2': '元/㎡/月',
'3': '元/月',
'4': '元/天',
'5': '元/年'
};
return unitMap[unitType] || '';
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
.el-card {
margin-bottom: 20px;
}
.el-table {
margin-top: 15px;
}
.el-tag + .el-tag {
margin-left: 3px;
}
.pagination {
margin-top: 15px;
text-align: right;
}
.el-form {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
}
::v-deep .el-upload-dragger {
width: 100%;
}
::v-deep .el-upload {
width: 100%;
}
.el-select {
display: block;
}
::v-deep .el-input__inner {
height: 32px;
line-height: 32px;
}
::v-deep .el-input--suffix .el-input__inner {
padding-right: 30px;
}
/* 确保表格内容垂直居中 */
::v-deep .el-table td, ::v-deep .el-table th {
padding: 8px 0;
}
}
::v-deep .el-range-separator {
width: 30px !important; /* 增加分隔符宽度 */
padding: 0 5px !important;
line-height: 25px !important;
}
::v-deep .el-date-editor .el-range__icon {
line-height: 25px !important;
}
</style>