988 lines
22 KiB
Vue
988 lines
22 KiB
Vue
<template>
|
||
<view class="rental-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="saveRental">
|
||
<text class="save-text">保存</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 表单内容 -->
|
||
<scroll-view scroll-y class="form-content">
|
||
<!-- 步骤指示器 -->
|
||
<view class="step-indicator">
|
||
<view class="step-item" :class="{ active: currentStep >= 1 }">
|
||
<view class="step-num">1</view>
|
||
<text class="step-text">选择房源</text>
|
||
</view>
|
||
<view class="step-line" :class="{ active: currentStep >= 2 }"></view>
|
||
<view class="step-item" :class="{ active: currentStep >= 2 }">
|
||
<view class="step-num">2</view>
|
||
<text class="step-text">选择租客</text>
|
||
</view>
|
||
<view class="step-line" :class="{ active: currentStep >= 3 }"></view>
|
||
<view class="step-item" :class="{ active: currentStep >= 3 }">
|
||
<view class="step-num">3</view>
|
||
<text class="step-text">租赁信息</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 步骤1:选择房源 -->
|
||
<view v-if="currentStep === 1" class="step-content">
|
||
<view class="section-title">选择公寓</view>
|
||
<view class="select-list">
|
||
<view
|
||
v-for="item in apartments"
|
||
:key="item.id"
|
||
class="select-item"
|
||
:class="{ active: form.apartmentId === item.id }"
|
||
@click="selectApartment(item)"
|
||
>
|
||
<text class="item-name">{{item.name}}</text>
|
||
<text class="item-address">{{item.address}}</text>
|
||
<uni-icons v-if="form.apartmentId === item.id" type="checkmarkempty" size="20" color="#2563EB"></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section-title" v-if="form.apartmentId">选择房间</view>
|
||
<view class="select-list" v-if="form.apartmentId">
|
||
<view
|
||
v-for="item in rooms"
|
||
:key="item.id"
|
||
class="select-item"
|
||
:class="{ active: form.roomId === item.id, disabled: item.status === 'rented' }"
|
||
@click="selectRoom(item)"
|
||
>
|
||
<view class="item-info">
|
||
<text class="item-name">{{item.roomNumber}}</text>
|
||
<text class="item-status" :class="item.status">{{item.status === 'rented' ? '已出租' : '空置中'}}</text>
|
||
</view>
|
||
<uni-icons v-if="form.roomId === item.id" type="checkmarkempty" size="20" color="#2563EB"></uni-icons>
|
||
</view>
|
||
<view v-if="rooms.length === 0" class="empty-tip">该公寓暂无房间</view>
|
||
</view>
|
||
|
||
<button class="btn-next" :disabled="!form.roomId" @click="nextStep">下一步</button>
|
||
</view>
|
||
|
||
<!-- 步骤2:选择租客 -->
|
||
<view v-if="currentStep === 2" class="step-content">
|
||
<view class="section-title">选择租客</view>
|
||
<view class="search-bar">
|
||
<uni-icons type="search" size="18" color="#94A3B8"></uni-icons>
|
||
<input
|
||
class="search-input"
|
||
type="text"
|
||
placeholder="搜索租客姓名或电话"
|
||
v-model="renterSearchKeyword"
|
||
@input="searchRenters"
|
||
/>
|
||
</view>
|
||
|
||
<view class="select-list">
|
||
<view
|
||
v-for="item in renters"
|
||
:key="item.id"
|
||
class="select-item renter-item"
|
||
:class="{ active: form.renterId === item.id }"
|
||
@click="selectRenter(item)"
|
||
>
|
||
<view class="renter-avatar">
|
||
<text>{{item.name.charAt(0)}}</text>
|
||
</view>
|
||
<view class="renter-info">
|
||
<text class="renter-name">{{item.name}}</text>
|
||
<text class="renter-phone">{{item.phone}}</text>
|
||
</view>
|
||
<uni-icons v-if="form.renterId === item.id" type="checkmarkempty" size="20" color="#2563EB"></uni-icons>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="divider">
|
||
<text>或</text>
|
||
</view>
|
||
|
||
<button class="btn-add-renter" @click="showAddRenter = true">
|
||
<uni-icons type="plusempty" size="18" color="#2563EB"></uni-icons>
|
||
<text>添加新租客</text>
|
||
</button>
|
||
|
||
<view class="btn-group">
|
||
<button class="btn-prev" @click="prevStep">上一步</button>
|
||
<button class="btn-next" :disabled="!form.renterId && !isNewRenter" @click="nextStep">下一步</button>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 步骤3:租赁信息 -->
|
||
<view v-if="currentStep === 3" class="step-content">
|
||
<view class="section-title">租赁信息</view>
|
||
<view class="form-card">
|
||
<view class="form-item">
|
||
<text class="form-label">付租方式 <text class="required">*</text></text>
|
||
<picker mode="selector" :range="paymentTypeOptions" :value="paymentTypeIndex" @change="onPaymentTypeChange">
|
||
<view class="picker-value">
|
||
<text>{{form.paymentTypeText}}</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>
|
||
<picker mode="date" :value="form.startDate" @change="onStartDateChange">
|
||
<view class="picker-value">
|
||
<text>{{form.startDate || '请选择开始日期'}}</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>
|
||
<picker mode="date" :value="form.endDate" @change="onEndDateChange">
|
||
<view class="picker-value">
|
||
<text>{{form.endDate || '请选择结束日期'}}</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="digit"
|
||
v-model="form.rent"
|
||
placeholder="请输入月租金"
|
||
class="form-input"
|
||
/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">押金</text>
|
||
<input
|
||
type="digit"
|
||
v-model="form.deposit"
|
||
placeholder="请输入押金金额"
|
||
class="form-input"
|
||
/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">水表起始读数</text>
|
||
<input
|
||
type="digit"
|
||
v-model="form.waterMeterStart"
|
||
placeholder="请输入水表起始读数"
|
||
class="form-input"
|
||
/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">电表起始读数</text>
|
||
<input
|
||
type="digit"
|
||
v-model="form.electricityMeterStart"
|
||
placeholder="请输入电表起始读数"
|
||
class="form-input"
|
||
/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<text class="form-label">备注</text>
|
||
<textarea
|
||
v-model="form.remark"
|
||
placeholder="请输入备注(选填)"
|
||
class="form-textarea"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="btn-group">
|
||
<button class="btn-prev" @click="prevStep">上一步</button>
|
||
<button class="btn-submit" :loading="submitLoading" @click="submitForm">确认提交</button>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="safe-area-bottom" style="height: 40rpx;"></view>
|
||
</scroll-view>
|
||
|
||
<!-- 添加新租客弹窗 -->
|
||
<uni-popup ref="addRenterPopup" type="center">
|
||
<view class="popup-content">
|
||
<view class="popup-header">
|
||
<text class="popup-title">添加新租客</text>
|
||
<uni-icons type="close" size="20" color="#94A3B8" @click="closeAddRenterPopup"></uni-icons>
|
||
</view>
|
||
<view class="popup-body">
|
||
<view class="form-item">
|
||
<text class="form-label">姓名 <text class="required">*</text></text>
|
||
<input
|
||
type="text"
|
||
v-model="newRenter.name"
|
||
placeholder="请输入租客姓名"
|
||
class="form-input"
|
||
/>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">电话 <text class="required">*</text></text>
|
||
<input
|
||
type="number"
|
||
v-model="newRenter.phone"
|
||
placeholder="请输入租客电话"
|
||
class="form-input"
|
||
maxlength="11"
|
||
/>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="form-label">身份证号</text>
|
||
<input
|
||
type="idcard"
|
||
v-model="newRenter.idCard"
|
||
placeholder="请输入身份证号(选填)"
|
||
class="form-input"
|
||
maxlength="18"
|
||
/>
|
||
</view>
|
||
</view>
|
||
<view class="popup-footer">
|
||
<button class="btn-cancel" @click="closeAddRenterPopup">取消</button>
|
||
<button class="btn-confirm" @click="confirmAddRenter">确认添加</button>
|
||
</view>
|
||
</view>
|
||
</uni-popup>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import rentalApi from '@/api/rental.js'
|
||
import apartmentApi from '@/api/apartment.js'
|
||
import roomApi from '@/api/room.js'
|
||
import renterApi from '@/api/renter.js'
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
isEdit: false,
|
||
rentalId: null,
|
||
currentStep: 1,
|
||
submitLoading: false,
|
||
apartments: [],
|
||
rooms: [],
|
||
renters: [],
|
||
renterSearchKeyword: '',
|
||
isNewRenter: false,
|
||
form: {
|
||
apartmentId: '',
|
||
roomId: '',
|
||
renterId: '',
|
||
paymentType: 'monthly',
|
||
paymentTypeText: '月租',
|
||
startDate: '',
|
||
endDate: '',
|
||
rent: '',
|
||
deposit: '',
|
||
waterMeterStart: '',
|
||
electricityMeterStart: '',
|
||
remark: ''
|
||
},
|
||
newRenter: {
|
||
name: '',
|
||
phone: '',
|
||
idCard: ''
|
||
},
|
||
paymentTypeOptions: ['月租', '季租', '半年租', '年租'],
|
||
paymentTypeMap: {
|
||
'月租': 'monthly',
|
||
'季租': 'quarterly',
|
||
'半年租': 'half_year',
|
||
'年租': 'yearly'
|
||
}
|
||
}
|
||
},
|
||
computed: {
|
||
paymentTypeIndex() {
|
||
return this.paymentTypeOptions.indexOf(this.form.paymentTypeText)
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
this.loadApartments()
|
||
if (options.id) {
|
||
this.isEdit = true
|
||
this.rentalId = options.id
|
||
this.loadRentalDetail(options.id)
|
||
} else {
|
||
// 设置默认开始日期为今天
|
||
this.form.startDate = this.formatDate(new Date())
|
||
}
|
||
},
|
||
methods: {
|
||
async loadApartments() {
|
||
try {
|
||
const res = await apartmentApi.getList({ pageSize: 999 })
|
||
if (res.data) {
|
||
this.apartments = res.data
|
||
}
|
||
} catch (error) {
|
||
console.error('加载公寓列表失败:', error)
|
||
}
|
||
},
|
||
|
||
async loadRooms(apartmentId) {
|
||
try {
|
||
const res = await roomApi.getList({ apartmentId, pageSize: 999 })
|
||
if (res.data) {
|
||
this.rooms = res.data
|
||
}
|
||
} catch (error) {
|
||
console.error('加载房间列表失败:', error)
|
||
}
|
||
},
|
||
|
||
async loadRenters() {
|
||
try {
|
||
const res = await renterApi.getOptions({ keyword: this.renterSearchKeyword })
|
||
if (res.data) {
|
||
this.renters = res.data
|
||
}
|
||
} catch (error) {
|
||
console.error('加载租客列表失败:', error)
|
||
}
|
||
},
|
||
|
||
async loadRentalDetail(id) {
|
||
try {
|
||
const res = await rentalApi.getDetail(id)
|
||
if (res.data) {
|
||
const data = res.data
|
||
this.form = {
|
||
apartmentId: data.Room?.Apartment?.id,
|
||
roomId: data.roomId,
|
||
renterId: data.renterId,
|
||
paymentType: data.paymentType,
|
||
paymentTypeText: this.getPaymentTypeText(data.paymentType),
|
||
startDate: data.startDate,
|
||
endDate: data.endDate,
|
||
rent: String(data.rent),
|
||
deposit: String(data.deposit || ''),
|
||
waterMeterStart: String(data.waterMeterStart || ''),
|
||
electricityMeterStart: String(data.electricityMeterStart || ''),
|
||
remark: data.remark || ''
|
||
}
|
||
this.loadRooms(this.form.apartmentId)
|
||
}
|
||
} catch (error) {
|
||
console.error('加载租赁详情失败:', error)
|
||
}
|
||
},
|
||
|
||
selectApartment(item) {
|
||
this.form.apartmentId = item.id
|
||
this.form.roomId = ''
|
||
this.loadRooms(item.id)
|
||
},
|
||
|
||
selectRoom(item) {
|
||
if (item.status === 'rented') {
|
||
uni.showToast({ title: '该房间已出租', icon: 'none' })
|
||
return
|
||
}
|
||
this.form.roomId = item.id
|
||
},
|
||
|
||
selectRenter(item) {
|
||
this.form.renterId = item.id
|
||
this.isNewRenter = false
|
||
},
|
||
|
||
searchRenters() {
|
||
this.loadRenters()
|
||
},
|
||
|
||
nextStep() {
|
||
if (this.currentStep < 3) {
|
||
this.currentStep++
|
||
if (this.currentStep === 2) {
|
||
this.loadRenters()
|
||
}
|
||
}
|
||
},
|
||
|
||
prevStep() {
|
||
if (this.currentStep > 1) {
|
||
this.currentStep--
|
||
}
|
||
},
|
||
|
||
onPaymentTypeChange(e) {
|
||
const text = this.paymentTypeOptions[e.detail.value]
|
||
this.form.paymentTypeText = text
|
||
this.form.paymentType = this.paymentTypeMap[text]
|
||
},
|
||
|
||
onStartDateChange(e) {
|
||
this.form.startDate = e.detail.value
|
||
},
|
||
|
||
onEndDateChange(e) {
|
||
this.form.endDate = e.detail.value
|
||
},
|
||
|
||
showAddRenterPopup() {
|
||
this.$refs.addRenterPopup.open()
|
||
},
|
||
|
||
closeAddRenterPopup() {
|
||
this.$refs.addRenterPopup.close()
|
||
this.newRenter = { name: '', phone: '', idCard: '' }
|
||
},
|
||
|
||
confirmAddRenter() {
|
||
if (!this.newRenter.name.trim()) {
|
||
uni.showToast({ title: '请输入租客姓名', icon: 'none' })
|
||
return
|
||
}
|
||
if (!this.newRenter.phone.trim()) {
|
||
uni.showToast({ title: '请输入租客电话', icon: 'none' })
|
||
return
|
||
}
|
||
this.isNewRenter = true
|
||
this.form.renterId = ''
|
||
this.closeAddRenterPopup()
|
||
uni.showToast({ title: '新租客信息已保存', icon: 'success' })
|
||
},
|
||
|
||
async submitForm() {
|
||
// 表单验证
|
||
if (!this.form.roomId) {
|
||
uni.showToast({ title: '请选择房间', icon: 'none' })
|
||
return
|
||
}
|
||
if (!this.form.renterId && !this.isNewRenter) {
|
||
uni.showToast({ title: '请选择或添加租客', icon: 'none' })
|
||
return
|
||
}
|
||
if (!this.form.startDate) {
|
||
uni.showToast({ title: '请选择开始日期', icon: 'none' })
|
||
return
|
||
}
|
||
if (!this.form.endDate) {
|
||
uni.showToast({ title: '请选择结束日期', icon: 'none' })
|
||
return
|
||
}
|
||
if (!this.form.rent) {
|
||
uni.showToast({ title: '请输入月租金', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
this.submitLoading = true
|
||
try {
|
||
const data = {
|
||
roomId: this.form.roomId,
|
||
paymentType: this.form.paymentType,
|
||
startDate: this.form.startDate,
|
||
endDate: this.form.endDate,
|
||
rent: parseFloat(this.form.rent),
|
||
deposit: parseFloat(this.form.deposit) || 0,
|
||
waterMeterStart: this.form.waterMeterStart ? parseFloat(this.form.waterMeterStart) : null,
|
||
electricityMeterStart: this.form.electricityMeterStart ? parseFloat(this.form.electricityMeterStart) : null,
|
||
remark: this.form.remark
|
||
}
|
||
|
||
if (this.isNewRenter) {
|
||
// 创建租赁同时创建租客
|
||
data.renter = this.newRenter
|
||
await rentalApi.createWithRenter(data)
|
||
} else {
|
||
data.renterId = this.form.renterId
|
||
if (this.isEdit) {
|
||
await rentalApi.update(this.rentalId, data)
|
||
} else {
|
||
await rentalApi.create(data)
|
||
}
|
||
}
|
||
|
||
uni.showToast({
|
||
title: this.isEdit ? '更新成功' : '创建成功',
|
||
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()
|
||
},
|
||
|
||
getPaymentTypeText(type) {
|
||
const map = {
|
||
monthly: '月租',
|
||
quarterly: '季租',
|
||
half_year: '半年租',
|
||
yearly: '年租'
|
||
}
|
||
return map[type] || type
|
||
},
|
||
|
||
formatDate(date) {
|
||
const d = new Date(date)
|
||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.rental-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-btn:active {
|
||
background: #F1F5F9;
|
||
}
|
||
|
||
.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;
|
||
}
|
||
|
||
/* 步骤指示器 */
|
||
.step-indicator {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 40rpx;
|
||
padding: 24rpx;
|
||
background: #FFFFFF;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.step-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.step-num {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
border-radius: 50%;
|
||
background: #E2E8F0;
|
||
color: #64748B;
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.step-item.active .step-num {
|
||
background: #2563EB;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.step-text {
|
||
font-size: 22rpx;
|
||
color: #64748B;
|
||
}
|
||
|
||
.step-item.active .step-text {
|
||
color: #2563EB;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.step-line {
|
||
width: 80rpx;
|
||
height: 2rpx;
|
||
background: #E2E8F0;
|
||
margin: 0 16rpx;
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.step-line.active {
|
||
background: #2563EB;
|
||
}
|
||
|
||
/* 步骤内容 */
|
||
.step-content {
|
||
animation: fadeIn 0.3s ease;
|
||
}
|
||
|
||
@keyframes fadeIn {
|
||
from { opacity: 0; transform: translateX(20rpx); }
|
||
to { opacity: 1; transform: translateX(0); }
|
||
}
|
||
|
||
/* 标题 */
|
||
.section-title {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: #1E293B;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
/* 选择列表 */
|
||
.select-list {
|
||
background: #FFFFFF;
|
||
border-radius: 16rpx;
|
||
overflow: hidden;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.select-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx;
|
||
border-bottom: 2rpx solid #F1F5F9;
|
||
}
|
||
|
||
.select-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.select-item.active {
|
||
background: #EFF6FF;
|
||
}
|
||
|
||
.select-item.disabled {
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.item-name {
|
||
font-size: 28rpx;
|
||
color: #1E293B;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.item-address {
|
||
font-size: 24rpx;
|
||
color: #94A3B8;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.item-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.item-status {
|
||
font-size: 22rpx;
|
||
padding: 4rpx 12rpx;
|
||
border-radius: 6rpx;
|
||
}
|
||
|
||
.item-status.vacant {
|
||
background: #D1FAE5;
|
||
color: #059669;
|
||
}
|
||
|
||
.item-status.rented {
|
||
background: #FEE2E2;
|
||
color: #DC2626;
|
||
}
|
||
|
||
.empty-tip {
|
||
padding: 48rpx;
|
||
text-align: center;
|
||
font-size: 26rpx;
|
||
color: #94A3B8;
|
||
}
|
||
|
||
/* 租客项 */
|
||
.renter-item {
|
||
padding: 20rpx 24rpx;
|
||
}
|
||
|
||
.renter-avatar {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.renter-avatar text {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #FFFFFF;
|
||
}
|
||
|
||
.renter-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.renter-name {
|
||
font-size: 28rpx;
|
||
color: #1E293B;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.renter-phone {
|
||
font-size: 24rpx;
|
||
color: #64748B;
|
||
}
|
||
|
||
/* 搜索栏 */
|
||
.search-bar {
|
||
display: flex;
|
||
align-items: center;
|
||
background: #FFFFFF;
|
||
border-radius: 16rpx;
|
||
padding: 20rpx 24rpx;
|
||
margin-bottom: 24rpx;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.search-input {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
color: #1E293B;
|
||
}
|
||
|
||
/* 分隔线 */
|
||
.divider {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin: 32rpx 0;
|
||
}
|
||
|
||
.divider::before,
|
||
.divider::after {
|
||
content: '';
|
||
flex: 1;
|
||
height: 2rpx;
|
||
background: #E2E8F0;
|
||
}
|
||
|
||
.divider text {
|
||
padding: 0 24rpx;
|
||
font-size: 24rpx;
|
||
color: #94A3B8;
|
||
}
|
||
|
||
/* 添加租客按钮 */
|
||
.btn-add-renter {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
background: #FFFFFF;
|
||
border: 2rpx dashed #2563EB;
|
||
border-radius: 16rpx;
|
||
padding: 28rpx;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.btn-add-renter text {
|
||
font-size: 28rpx;
|
||
color: #2563EB;
|
||
font-weight: 500;
|
||
}
|
||
|
||
/* 表单卡片 */
|
||
.form-card {
|
||
background: #FFFFFF;
|
||
border-radius: 16rpx;
|
||
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;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
font-size: 30rpx;
|
||
color: #1E293B;
|
||
}
|
||
|
||
.form-textarea {
|
||
width: 100%;
|
||
height: 160rpx;
|
||
font-size: 30rpx;
|
||
color: #1E293B;
|
||
}
|
||
|
||
/* 按钮 */
|
||
.btn-next {
|
||
background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
|
||
color: #FFFFFF;
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
padding: 28rpx;
|
||
border-radius: 16rpx;
|
||
border: none;
|
||
}
|
||
|
||
.btn-next[disabled] {
|
||
opacity: 0.5;
|
||
}
|
||
|
||
.btn-group {
|
||
display: flex;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.btn-prev {
|
||
flex: 1;
|
||
background: #F3F4F6;
|
||
color: #64748B;
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
padding: 28rpx;
|
||
border-radius: 16rpx;
|
||
border: none;
|
||
}
|
||
|
||
.btn-submit {
|
||
flex: 2;
|
||
background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
|
||
color: #FFFFFF;
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
padding: 28rpx;
|
||
border-radius: 16rpx;
|
||
border: none;
|
||
}
|
||
|
||
/* 弹窗 */
|
||
.popup-content {
|
||
background: #FFFFFF;
|
||
border-radius: 24rpx;
|
||
width: 600rpx;
|
||
}
|
||
|
||
.popup-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 32rpx;
|
||
border-bottom: 2rpx solid #F1F5F9;
|
||
}
|
||
|
||
.popup-title {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #1E293B;
|
||
}
|
||
|
||
.popup-body {
|
||
padding: 32rpx;
|
||
}
|
||
|
||
.popup-footer {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
padding: 24rpx 32rpx;
|
||
border-top: 2rpx solid #F1F5F9;
|
||
}
|
||
|
||
.btn-cancel {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
background: #F3F4F6;
|
||
border-radius: 12rpx;
|
||
font-size: 28rpx;
|
||
color: #64748B;
|
||
border: none;
|
||
}
|
||
|
||
.btn-confirm {
|
||
flex: 1;
|
||
height: 80rpx;
|
||
background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
|
||
border-radius: 12rpx;
|
||
font-size: 28rpx;
|
||
color: #FFFFFF;
|
||
font-weight: 600;
|
||
border: none;
|
||
}
|
||
</style>
|