This commit is contained in:
wangxiaoxian 2026-03-07 19:46:38 +08:00
parent 0da0b3fab3
commit 06a49a3ad9
7 changed files with 92 additions and 4 deletions

View File

@ -51,6 +51,17 @@
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :xs="12" :sm="12" :md="8">
<el-card class="stat-card">
<div class="stat-item">
<i class="el-icon-sold-out stat-icon"></i>
<div class="stat-info">
<div class="stat-value">{{ reservedRoomCount }}</div>
<div class="stat-label">预订数量</div>
</div>
</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="12" :md="8"> <el-col :xs="12" :sm="12" :md="8">
<el-card class="stat-card"> <el-card class="stat-card">
<div class="stat-item"> <div class="stat-item">
@ -125,6 +136,7 @@
<el-table-column prop="region" label="区域" min-width="100"></el-table-column> <el-table-column prop="region" label="区域" min-width="100"></el-table-column>
<el-table-column prop="apartment" label="公寓" min-width="100"></el-table-column> <el-table-column prop="apartment" label="公寓" min-width="100"></el-table-column>
<el-table-column prop="empty" label="空房" width="70"></el-table-column> <el-table-column prop="empty" label="空房" width="70"></el-table-column>
<el-table-column prop="reserved" label="预订" width="70"></el-table-column>
<el-table-column prop="rented" label="在租" width="70"></el-table-column> <el-table-column prop="rented" label="在租" width="70"></el-table-column>
<el-table-column prop="soon_expire" label="即将到期" width="90"></el-table-column> <el-table-column prop="soon_expire" label="即将到期" width="90"></el-table-column>
<el-table-column prop="expired" label="已到期" width="70"></el-table-column> <el-table-column prop="expired" label="已到期" width="70"></el-table-column>
@ -148,6 +160,7 @@ export default {
apartmentCount: 0, apartmentCount: 0,
roomCount: 0, roomCount: 0,
emptyRoomCount: 0, emptyRoomCount: 0,
reservedRoomCount: 0,
rentedRoomCount: 0, rentedRoomCount: 0,
soonExpireRoomCount: 0, soonExpireRoomCount: 0,
expiredRoomCount: 0, expiredRoomCount: 0,
@ -176,6 +189,7 @@ export default {
this.apartmentCount = dashboardStats.apartmentCount this.apartmentCount = dashboardStats.apartmentCount
this.roomCount = dashboardStats.roomCount this.roomCount = dashboardStats.roomCount
this.emptyRoomCount = dashboardStats.emptyRoomCount this.emptyRoomCount = dashboardStats.emptyRoomCount
this.reservedRoomCount = dashboardStats.reservedRoomCount
this.rentedRoomCount = dashboardStats.rentedRoomCount this.rentedRoomCount = dashboardStats.rentedRoomCount
this.soonExpireRoomCount = dashboardStats.soonExpireRoomCount this.soonExpireRoomCount = dashboardStats.soonExpireRoomCount
this.expiredRoomCount = dashboardStats.expiredRoomCount this.expiredRoomCount = dashboardStats.expiredRoomCount
@ -210,6 +224,10 @@ export default {
const value = Number(curr) || 0; const value = Number(curr) || 0;
return prev + value; return prev + value;
}, 0); }, 0);
} else if (column.property === 'total') {
sums[index] = data.reduce((sum, item) => {
return sum + (Number(item.empty) || 0) + (Number(item.reserved) || 0) + (Number(item.rented) || 0);
}, 0);
} else { } else {
sums[index] = ''; sums[index] = '';
} }

View File

@ -5,7 +5,9 @@
<div class="card-header"> <div class="card-header">
<span>房屋详情</span> <span>房屋详情</span>
<div class="action-buttons"> <div class="action-buttons">
<el-button v-if="room.status === 'empty'" type="primary" size="small" @click="handleRent">租房</el-button> <el-button v-if="room.status === 'empty' || room.status === 'reserved'" type="primary" size="small" @click="handleRent">租房</el-button>
<el-button v-if="room.status === 'empty'" type="info" size="small" @click="handleReserve">预订</el-button>
<el-button v-if="room.status === 'reserved'" type="warning" size="small" @click="handleCancelReserve">取消预订</el-button>
<el-button v-if="room.status === 'rented'" type="warning" size="small" @click="handleCheckout">退房</el-button> <el-button v-if="room.status === 'rented'" type="warning" size="small" @click="handleCheckout">退房</el-button>
<el-button v-if="!room.otherStatus || room.otherStatus === ''" type="info" size="small" @click="handleCleaning">打扫</el-button> <el-button v-if="!room.otherStatus || room.otherStatus === ''" type="info" size="small" @click="handleCleaning">打扫</el-button>
<el-button v-if="!room.otherStatus || room.otherStatus === ''" type="danger" size="small" @click="handleMaintenance">维修</el-button> <el-button v-if="!room.otherStatus || room.otherStatus === ''" type="danger" size="small" @click="handleMaintenance">维修</el-button>
@ -387,6 +389,7 @@ export default {
getStatusType(status) { getStatusType(status) {
switch (status) { switch (status) {
case 'empty': return '' case 'empty': return ''
case 'reserved': return 'warning'
case 'rented': return 'success' case 'rented': return 'success'
case 'soon_expire': return 'warning' case 'soon_expire': return 'warning'
case 'expired': return 'danger' case 'expired': return 'danger'
@ -398,6 +401,7 @@ export default {
getStatusText(status) { getStatusText(status) {
switch (status) { switch (status) {
case 'empty': return '空房' case 'empty': return '空房'
case 'reserved': return '预订'
case 'rented': return '在租' case 'rented': return '在租'
case 'soon_expire': return '即将到期' case 'soon_expire': return '即将到期'
case 'expired': return '到期' case 'expired': return '到期'
@ -445,6 +449,50 @@ export default {
} }
}) })
}, },
async handleReserve() {
if (!this.room.id) {
this.$message.error('房间信息加载失败,无法进行预订操作')
return
}
this.$confirm('确定要预订这个房间吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'info'
}).then(async () => {
try {
const roomId = this.$route.params.id
await roomApi.update(roomId, { status: 'reserved' })
this.$message.success('预订成功')
this.loadData()
} catch (error) {
console.error('预订失败:', error)
this.$message.error('预订失败:' + (error.message || '未知错误'))
}
}).catch(() => {})
},
async handleCancelReserve() {
if (!this.room.id) {
this.$message.error('房间信息加载失败,无法进行取消预订操作')
return
}
this.$confirm('确定要取消预订吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
try {
const roomId = this.$route.params.id
await roomApi.update(roomId, { status: 'empty' })
this.$message.success('取消预订成功')
this.loadData()
} catch (error) {
console.error('取消预订失败:', error)
this.$message.error('取消预订失败:' + (error.message || '未知错误'))
}
}).catch(() => {})
},
async handleCheckout() { async handleCheckout() {
if (!this.room.id) { if (!this.room.id) {
this.$message.error('房间信息加载失败,无法进行退房操作') this.$message.error('房间信息加载失败,无法进行退房操作')

View File

@ -19,6 +19,7 @@
<el-select v-model="searchForm.status" placeholder="请选择主状态" style="width: 100%"> <el-select v-model="searchForm.status" placeholder="请选择主状态" style="width: 100%">
<el-option label="全部" value=""></el-option> <el-option label="全部" value=""></el-option>
<el-option label="空房" value="empty"></el-option> <el-option label="空房" value="empty"></el-option>
<el-option label="预订" value="reserved"></el-option>
<el-option label="在租" value="rented"></el-option> <el-option label="在租" value="rented"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -61,7 +62,7 @@
<h3>{{ getApartmentName(room.apartmentId) }}</h3> <h3>{{ getApartmentName(room.apartmentId) }}</h3>
<div class="room-card-tags"> <div class="room-card-tags">
<el-tag v-if="room.status === 'rented'" :type="getSubStatusType(room.subStatus)" size="small">{{ getSubStatusText(room.subStatus) }}</el-tag> <el-tag v-if="room.status === 'rented'" :type="getSubStatusType(room.subStatus)" size="small">{{ getSubStatusText(room.subStatus) }}</el-tag>
<el-tag v-else size="small">空房</el-tag> <el-tag v-else :type="getStatusType(room.status)" size="small">{{ getStatusText(room.status) }}</el-tag>
<el-tag v-if="room.otherStatus" :type="getOtherStatusType(room.otherStatus)" size="small">{{ getOtherStatusText(room.otherStatus) }}</el-tag> <el-tag v-if="room.otherStatus" :type="getOtherStatusType(room.otherStatus)" size="small">{{ getOtherStatusText(room.otherStatus) }}</el-tag>
</div> </div>
</div> </div>
@ -190,6 +191,22 @@ export default {
const apartment = this.apartments.find(a => a.id == apartmentId) const apartment = this.apartments.find(a => a.id == apartmentId)
return apartment ? apartment.name : '' return apartment ? apartment.name : ''
}, },
getStatusType(status) {
switch (status) {
case 'empty': return 'info'
case 'reserved': return 'warning'
case 'rented': return 'success'
default: return ''
}
},
getStatusText(status) {
switch (status) {
case 'empty': return '空房'
case 'reserved': return '预订'
case 'rented': return '在租'
default: return status
}
},
getSubStatusType(status) { getSubStatusType(status) {
switch (status) { switch (status) {
case 'normal': return 'success' case 'normal': return 'success'

View File

@ -27,6 +27,7 @@
<el-form-item label="主状态" prop="status"> <el-form-item label="主状态" prop="status">
<el-select v-model="roomForm.status" placeholder="请选择主状态" style="width: 100%"> <el-select v-model="roomForm.status" placeholder="请选择主状态" style="width: 100%">
<el-option label="空房" value="empty"></el-option> <el-option label="空房" value="empty"></el-option>
<el-option label="预订" value="reserved"></el-option>
<el-option label="在租" value="rented"></el-option> <el-option label="在租" value="rented"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>

View File

@ -27,6 +27,7 @@
<el-form-item label="主状态" prop="status"> <el-form-item label="主状态" prop="status">
<el-select v-model="roomForm.status" placeholder="请选择主状态" style="width: 100%"> <el-select v-model="roomForm.status" placeholder="请选择主状态" style="width: 100%">
<el-option label="空房" value="empty"></el-option> <el-option label="空房" value="empty"></el-option>
<el-option label="预订" value="reserved"></el-option>
<el-option label="在租" value="rented"></el-option> <el-option label="在租" value="rented"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>

View File

@ -20,6 +20,7 @@
<el-select v-model="searchForm.status" placeholder="请选择主状态" style="width: 100%"> <el-select v-model="searchForm.status" placeholder="请选择主状态" style="width: 100%">
<el-option label="全部" value=""></el-option> <el-option label="全部" value=""></el-option>
<el-option label="空房" value="empty"></el-option> <el-option label="空房" value="empty"></el-option>
<el-option label="预订" value="reserved"></el-option>
<el-option label="在租" value="rented"></el-option> <el-option label="在租" value="rented"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -246,6 +247,7 @@ export default {
getStatusType(status) { getStatusType(status) {
switch (status) { switch (status) {
case 'empty': return 'info' case 'empty': return 'info'
case 'reserved': return 'warning'
case 'rented': return 'success' case 'rented': return 'success'
default: return '' default: return ''
} }
@ -253,6 +255,7 @@ export default {
getStatusText(status) { getStatusText(status) {
switch (status) { switch (status) {
case 'empty': return '空房' case 'empty': return '空房'
case 'reserved': return '预订'
case 'rented': return '在租' case 'rented': return '在租'
default: return status default: return status
} }

View File

@ -44,7 +44,7 @@ export default {
computed: { computed: {
totalCount() { totalCount() {
return this.roomStatusData return this.roomStatusData
.filter(item => item.status === '在租' || item.status === '空房') .filter(item => item.status === '在租' || item.status === '空房' || item.status === '预订')
.reduce((sum, item) => sum + item.count, 0) .reduce((sum, item) => sum + item.count, 0)
} }
}, },
@ -57,7 +57,7 @@ export default {
const response = await statisticsApi.getRoomStatus() const response = await statisticsApi.getRoomStatus()
const data = response const data = response
const total = data const total = data
.filter(item => item.status === '在租' || item.status === '空房') .filter(item => item.status === '在租' || item.status === '空房' || item.status === '预订')
.reduce((sum, item) => sum + item.count, 0) .reduce((sum, item) => sum + item.count, 0)
this.roomStatusData = data.map(item => ({ this.roomStatusData = data.map(item => ({
...item, ...item,