rentease-app/pages/room-add/room-add.vue

306 lines
8.6 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>
<view class="room-add-page">
<view class="custom-nav safe-area-top">
<view class="nav-content">
<view class="nav-btn" @click="goBack">
<uni-icons type="left" size="22" color="#1E293B"></uni-icons>
</view>
<text class="nav-title">{{isEdit ? '编辑房间' : '添加房间'}}</text>
<view class="nav-btn" @click="saveRoom">
<text class="save-text">保存</text>
</view>
</view>
</view>
<scroll-view scroll-y class="form-content">
<view class="form-card">
<view class="form-item">
<text class="form-label">所属公寓 <text class="required">*</text></text>
<picker mode="selector" :range="apartmentOptions" :value="selectedApartmentIndex" @change="onApartmentChange">
<view class="picker-value" :class="{ placeholder: !form.apartmentId }">
<text>{{selectedApartmentLabel}}</text>
<uni-icons type="arrowright" size="16" color="#94A3B8"></uni-icons>
</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">房间号 <text class="required">*</text></text>
<input
type="text"
v-model="form.roomNumber"
placeholder="请输入房间号101"
class="form-input"
maxlength="20"
/>
</view>
<view class="form-item">
<text class="form-label">房间面积 (m²)</text>
<input
type="digit"
v-model="form.area"
placeholder="请输入房间面积"
class="form-input"
/>
</view>
<view class="form-item">
<text class="form-label">房间朝向</text>
<picker mode="selector" :range="orientationOptions" :value="orientationIndex" @change="onOrientationChange">
<view class="picker-value" :class="{ placeholder: !form.orientation }">
<text>{{form.orientation || '请选择朝向'}}</text>
<uni-icons type="arrowright" size="16" color="#94A3B8"></uni-icons>
</view>
</picker>
</view>
<view class="form-item">
<text class="form-label">月租金 (元)</text>
<input
type="digit"
v-model="form.rent"
placeholder="请输入月租金"
class="form-input"
/>
</view>
<view class="form-item">
<text class="form-label">房间描述</text>
<textarea
v-model="form.description"
placeholder="请输入房间描述(选填)"
class="form-textarea"
maxlength="200"
/>
</view>
</view>
<button class="btn-submit" :loading="submitLoading" @click="saveRoom">{{isEdit ? '保存修改' : '确认添加'}}</button>
<view class="safe-area-bottom" style="height: 40rpx;"></view>
</scroll-view>
</view>
</template>
<script>
import roomApi from '@/api/room.js'
import apartmentApi from '@/api/apartment.js'
export default {
data() {
return {
isEdit: false,
roomId: null,
submitLoading: false,
apartments: [],
orientationOptions: ['东', '南', '西', '北', '东南', '东北', '西南', '西北'],
form: {
apartmentId: '',
roomNumber: '',
area: '',
orientation: '',
rent: '',
description: ''
}
}
},
computed: {
apartmentOptions() {
return this.apartments.map(a => a.name)
},
selectedApartmentIndex() {
const index = this.apartments.findIndex(a => a.id === this.form.apartmentId)
return index >= 0 ? index : -1
},
selectedApartmentLabel() {
const apartment = this.apartments.find(a => a.id === this.form.apartmentId)
return apartment ? apartment.name : '请选择公寓'
},
orientationIndex() {
return this.orientationOptions.indexOf(this.form.orientation)
}
},
onLoad(options) {
this.loadApartments()
if (options.id) {
this.isEdit = true
this.roomId = options.id
this.loadRoomDetail(options.id)
} else if (options.apartmentId) {
this.form.apartmentId = parseInt(options.apartmentId)
}
},
methods: {
async loadApartments() {
try {
const res = await apartmentApi.getList({ pageSize: 999 })
if (res.data) {
this.apartments = res.data
}
} catch (error) {
console.error('加载公寓列表失败:', error)
}
},
async loadRoomDetail(id) {
try {
const res = await roomApi.getDetail(id)
if (res.data) {
const data = res.data
this.form = {
apartmentId: data.apartmentId,
roomNumber: data.roomNumber,
area: data.area ? String(data.area) : '',
orientation: data.orientation || '',
rent: data.rent ? String(data.rent) : '',
description: data.description || ''
}
}
} catch (error) {
console.error('加载房间详情失败:', error)
uni.showToast({ title: '加载失败', icon: 'none' })
}
},
onApartmentChange(e) {
this.form.apartmentId = this.apartments[e.detail.value].id
},
onOrientationChange(e) {
this.form.orientation = this.orientationOptions[e.detail.value]
},
async saveRoom() {
if (!this.form.apartmentId) {
uni.showToast({ title: '请选择所属公寓', icon: 'none' })
return
}
if (!this.form.roomNumber.trim()) {
uni.showToast({ title: '请输入房间号', icon: 'none' })
return
}
this.submitLoading = true
try {
const data = {
apartmentId: this.form.apartmentId,
roomNumber: this.form.roomNumber.trim(),
area: this.form.area ? parseFloat(this.form.area) : null,
orientation: this.form.orientation || null,
rent: this.form.rent ? parseFloat(this.form.rent) : null,
description: this.form.description.trim() || null
}
if (this.isEdit) {
await roomApi.update(this.roomId, data)
uni.showToast({ title: '修改成功', icon: 'success' })
} else {
await roomApi.create(data)
uni.showToast({ title: '添加成功', icon: 'success' })
}
setTimeout(() => uni.navigateBack(), 1500)
} catch (error) {
console.error('保存失败:', error)
uni.showToast({ title: this.isEdit ? '修改失败' : '添加失败', icon: 'none' })
} finally {
this.submitLoading = false
}
},
goBack() {
uni.navigateBack()
}
}
}
</script>
<style scoped>
.room-add-page {
min-height: 100vh;
background: #F8FAFC;
display: flex;
flex-direction: column;
}
.custom-nav {
background: #FFFFFF;
border-bottom: 2rpx solid #F1F5F9;
}
.nav-content {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 32rpx;
}
.nav-btn {
width: 72rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.nav-title {
font-size: 34rpx;
font-weight: 600;
color: #1E293B;
}
.save-text {
font-size: 28rpx;
color: #2563EB;
font-weight: 600;
}
.form-content {
flex: 1;
padding: 24rpx 32rpx;
}
.form-card {
background: #FFFFFF;
border-radius: 20rpx;
padding: 0 24rpx;
margin-bottom: 40rpx;
}
.form-item {
padding: 24rpx 0;
border-bottom: 2rpx solid #F1F5F9;
}
.form-item:last-child {
border-bottom: none;
}
.form-label {
display: block;
font-size: 26rpx;
color: #64748B;
margin-bottom: 16rpx;
}
.required {
color: #EF4444;
}
.picker-value {
display: flex;
align-items: center;
justify-content: space-between;
font-size: 30rpx;
color: #1E293B;
}
.picker-value.placeholder {
color: #94A3B8;
}
.form-input {
width: 100%;
height: 60rpx;
font-size: 30rpx;
color: #1E293B;
}
.form-textarea {
width: 100%;
height: 160rpx;
font-size: 30rpx;
color: #1E293B;
}
.btn-submit {
background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
color: #FFFFFF;
font-size: 30rpx;
font-weight: 600;
padding: 28rpx;
border-radius: 16rpx;
border: none;
}
</style>