refactor: 重构房源发布表单输入类型和验证规则 feat(house): 新增经营性建设用地和其他农村资源录入页面 style: 优化首页位置显示和搜索框布局 refactor(user): 重构用户信息展示和会员状态显示 feat(detail): 优化房源详情页字段显示逻辑 refactor(store): 合并data和user模块到主store fix(config): 修复uvUI初始化顺序和HTTP实例检查 docs: 更新README和注释说明 chore: 更新依赖和配置文件master
| @ -0,0 +1,5 @@ | |||||
| --- | |||||
| description: | |||||
| globs: | |||||
| alwaysApply: true | |||||
| --- | |||||
| @ -1,7 +1,8 @@ | |||||
| export default { | export default { | ||||
| // baseUrl : 'http://127.0.0.1:8000', | // baseUrl : 'http://127.0.0.1:8000', | ||||
| // baseUrl: 'https://api.book118.com', | // baseUrl: 'https://api.book118.com', | ||||
| baseUrl:'https://houserent-admin.hhlm1688.com' | |||||
| baseUrl:'https://houserent-admin.hhlm1688.com', | |||||
| // baseUrl:'http://augcl.natapp1.cc', | |||||
| // baseUrl:'http://h5.xzaiyp.top' | // baseUrl:'http://h5.xzaiyp.top' | ||||
| // baseUrl:'https://houserent-admin.hhlm1688.com' | // baseUrl:'https://houserent-admin.hhlm1688.com' | ||||
| // baseUrl:'http://h5.xzaiyp.top' | // baseUrl:'http://h5.xzaiyp.top' | ||||
| @ -0,0 +1,450 @@ | |||||
| <template> | |||||
| <view class="container"> | |||||
| <view class="header"> | |||||
| <view class="title">经营性建设用地录入</view> | |||||
| </view> | |||||
| <view class="form-container"> | |||||
| <uv-form labelPosition="left" :model="form" :rules="rules" ref="form" labelWidth="80" labelStyle="font-size:28rpx;"> | |||||
| <!-- 必填项 --> | |||||
| <view class="section-title">基本信息(必填)</view> | |||||
| <!-- 1. 出租/出让 --> | |||||
| <uv-form-item label="类型" prop="type" required> | |||||
| <uv-radio-group v-model="form.type" placement="row"> | |||||
| <uv-radio name="rent" label="出租"></uv-radio> | |||||
| <uv-radio name="transfer" customStyle="margin-left:30rpx;" label="出让"></uv-radio> | |||||
| </uv-radio-group> | |||||
| </uv-form-item> | |||||
| <!-- 2. 地址 --> | |||||
| <uv-form-item label="地址" prop="address" required @click="handleAddressSelect()"> | |||||
| <uv-input v-model="form.address" @click="handleAddressSelect()" disabled disabledColor="#ffffff" placeholder="请选择地块位置" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 3. 联系人和电话 --> | |||||
| <uv-form-item label="联系人" prop="contactName" required> | |||||
| <uv-input v-model="form.contactName" type="text" placeholder="请输入联系人姓名" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <uv-form-item label="联系电话" prop="contactPhone" required> | |||||
| <uv-input v-model="form.contactPhone" type="number" placeholder="请输入联系电话" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <!-- 4. 产权证照片 --> | |||||
| <uv-form-item label="产权证照片" labelWidth="250" prop="propertyImages" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传房产证、土地证或不动产权证照片</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" :fileList="form.propertyImages" @afterRead="afterPropertyRead" @delete="deletePropertyPic" name="1" | |||||
| multiple :maxCount="5"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 5. 土地面积 --> | |||||
| <uv-form-item label="土地面积" prop="landArea" required> | |||||
| <view class="input-with-unit"> | |||||
| <uv-input v-model="form.landArea" type="digit" placeholder="请输入土地面积" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| <text class="unit">亩</text> | |||||
| </view> | |||||
| <view class="input-tip">请录入土地使用证或不动产权证面积,仅输入数字</view> | |||||
| </uv-form-item> | |||||
| <!-- 6. 地块视频 --> | |||||
| <uv-form-item label="地块视频" labelWidth="250" prop="videos" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传地块视频(1分钟内)</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" accept="video" :fileList="form.videos" @afterRead="afterVideoRead" @delete="deleteVideoPic" name="1" | |||||
| multiple :maxCount="2"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 7. 价格 --> | |||||
| <uv-form-item label="价格" prop="price" required> | |||||
| <view class="price-container"> | |||||
| <uv-input v-model="form.price" type="digit" placeholder="请输入价格" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;flex:1;"></uv-input> | |||||
| <text class="price-unit" v-if="form.type === 'rent'">元/亩/年</text> | |||||
| <text class="price-unit" v-else-if="form.type === 'transfer'">万元/亩</text> | |||||
| <text class="price-unit" v-else>元</text> | |||||
| </view> | |||||
| <view class="input-tip">请输入数字,支持小数点后两位</view> | |||||
| </uv-form-item> | |||||
| <!-- 分类标识 --> | |||||
| <uv-form-item label="分类标识" prop="classId" @click="handleClass()"> | |||||
| <uv-input v-model="form.className" @click="handleClass()" disabled disabledColor="#ffffff" placeholder="选择分类标识" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 选填项 --> | |||||
| <view class="section-title">详细信息(选填)</view> | |||||
| <!-- 8. 地块介绍 --> | |||||
| <uv-form-item label="地块介绍" prop="description" labelPosition="top"> | |||||
| <uv-input | |||||
| v-model="form.description" | |||||
| type="textarea" | |||||
| placeholder="请详细介绍地块情况、用途规划、周边环境等" | |||||
| customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:10px;" | |||||
| :autoHeight="true" | |||||
| :maxlength="500" | |||||
| ></uv-input> | |||||
| </uv-form-item> | |||||
| <uv-form-item> | |||||
| <uv-button type="primary" text="提交信息" customStyle="margin-top: 30px;background-color: #1EC77A;border-radius: 30px;" @click="submit"></uv-button> | |||||
| </uv-form-item> | |||||
| </uv-form> | |||||
| </view> | |||||
| <!-- 分类选择器 --> | |||||
| <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { saveOrUpdateHouse, houseType } from "@/common/api.js" | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| commonClass: '', // 所属分类ID | |||||
| form: { | |||||
| type: '', // 出租/出让 | |||||
| address: '', // 地址 | |||||
| contactName: '', // 联系人 | |||||
| contactPhone: '', // 联系电话 | |||||
| propertyImages: [], // 产权证照片 | |||||
| landArea: '', // 土地面积 | |||||
| videos: [], // 地块视频 | |||||
| price: '', // 价格 | |||||
| description: '', // 地块介绍 | |||||
| longitude: '', // 经度 | |||||
| latitude: '', // 纬度 | |||||
| classId: '', // 分类标识 | |||||
| className: '' // 分类名称 | |||||
| }, | |||||
| columns: [], // 分类选择器数据 | |||||
| houseTypeList: [], // 分类列表 | |||||
| rules: { | |||||
| type: [ | |||||
| { required: true, message: '请选择出租或出让', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| address: [ | |||||
| { required: true, message: '请选择地块地址', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactName: [ | |||||
| { required: true, message: '请输入联系人姓名', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactPhone: [ | |||||
| { required: true, message: '请输入联系电话', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| landArea: [ | |||||
| { required: true, message: '请输入土地面积', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的数字格式', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| price: [ | |||||
| { required: true, message: '请输入价格', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的价格格式', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| classId: [ | |||||
| { required: true, message: '请选择分类标识', trigger: ['blur', 'change'] } | |||||
| ] | |||||
| } | |||||
| } | |||||
| }, | |||||
| onReady() { | |||||
| this.$refs.form.setRules(this.rules) | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 设置页面标题 | |||||
| uni.setNavigationBarTitle({ | |||||
| title: '经营性建设用地录入' | |||||
| }) | |||||
| // 接收传递的commonClass参数 | |||||
| if(options.commonClass) { | |||||
| this.commonClass = options.commonClass | |||||
| } | |||||
| // 如果是编辑模式,设置classId用于回显 | |||||
| if(options.classId) { | |||||
| this.form.classId = options.classId | |||||
| } | |||||
| // 初始化分类数据 | |||||
| this.onHouseType() | |||||
| }, | |||||
| methods: { | |||||
| // 获取分类数据 | |||||
| onHouseType(){ | |||||
| let that = this | |||||
| houseType({}).then(response=>{ | |||||
| let arr=[] | |||||
| that.houseTypeList = response.result | |||||
| response.result.forEach(items=>{ | |||||
| arr.push(items.title) | |||||
| // 数据回显:如果当前classId匹配,设置className | |||||
| if(items.id == that.form.classId){ | |||||
| that.form.className = items.title | |||||
| } | |||||
| }) | |||||
| that.columns[0]=arr | |||||
| }).catch(error=>{ | |||||
| }) | |||||
| }, | |||||
| // 地址选择 | |||||
| handleAddressSelect() { | |||||
| const that = this; | |||||
| wx.chooseLocation({ | |||||
| success: function (res) { | |||||
| console.log('选择的位置:', res); | |||||
| that.form.longitude = res.longitude | |||||
| that.form.latitude = res.latitude | |||||
| that.form.address = res.address | |||||
| } | |||||
| }) | |||||
| }, | |||||
| // 分类选择 | |||||
| handleClass() { | |||||
| this.$refs.picker.open(); | |||||
| }, | |||||
| confirm(e) { | |||||
| let that = this | |||||
| let {indexs,value,values} = e | |||||
| that.form.classId = that.houseTypeList[indexs[0]].id; | |||||
| that.form.className = that.houseTypeList[indexs[0]].title; | |||||
| }, | |||||
| // 产权证照片上传 | |||||
| async afterPropertyRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.propertyImages.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deletePropertyPic(event) { | |||||
| this.form.propertyImages.splice(event.index, 1) | |||||
| }, | |||||
| // 视频上传 | |||||
| async afterVideoRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.videos.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deleteVideoPic(event) { | |||||
| this.form.videos.splice(event.index, 1) | |||||
| }, | |||||
| // 提交表单 | |||||
| submit() { | |||||
| this.$refs.form.validate().then(res => { | |||||
| // 验证必填的图片和视频 | |||||
| if (this.form.propertyImages.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传产权证照片', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (this.form.videos.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传地块视频', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 构建与index.vue兼容的提交参数 | |||||
| const params = { | |||||
| userId: uni.getStorageSync('userInfo')?.id || "", | |||||
| id: "", // 新增数据,无ID | |||||
| classId: this.form.classId, // 使用固定分类标识 | |||||
| commonClass: this.commonClass, // 所属分类 | |||||
| address: this.form.address, // 地址 | |||||
| homeAge: "", // 户主年龄 - 经营性用地无此字段 | |||||
| homeAz: "", // 是否经过安置 - 默认否 | |||||
| homeBian: "", // 房屋周边 - 经营性用地无此字段 | |||||
| homeBjsx: "", // 报建手续 - 经营性用地无此字段 | |||||
| homeCai: "", // 菜地 - 经营性用地无此字段 | |||||
| homeCat: "", // 停车 - 经营性用地无此字段 | |||||
| homeGz: "", // 房屋主体是否改造 - 默认否 | |||||
| homeHb: "", // 房屋朝向及海拔 - 经营性用地无此字段 | |||||
| homeBz: this.form.description, // 备注 - 使用地块介绍 | |||||
| homeJg: "经营性建设用地", // 房屋结构 - 使用固定值 | |||||
| homeJl: "", // 距离场镇距离 - 经营性用地无此字段 | |||||
| homeJt: "", // 交通 - 经营性用地无此字段 | |||||
| homeJtzy: "", // 户主家庭职业 - 经营性用地无此字段 | |||||
| homeMi: this.form.landArea, // 面积 - 使用土地面积 | |||||
| homeMj: this.form.landArea, // 房屋面积 - 使用土地面积 | |||||
| homeMoney: "", // 佣金 - 经营性用地无此字段 | |||||
| homeNo: "", // 房屋编号 - 经营性用地无此字段 | |||||
| homeNum: "", // 房间数量 - 经营性用地无此字段 | |||||
| homePay: "", // 付款方式及押金 - 经营性用地无此字段 | |||||
| homePj: "", // 邻居对房东评价 - 经营性用地无此字段 | |||||
| homeSd: "", // 水电气网 - 经营性用地无此字段 | |||||
| homeShjl: "", // 距离成都西三环 - 经营性用地无此字段 | |||||
| homeSw: "", // 非正常死亡 - 默认无 | |||||
| homeTf: "", // 府市民云房屋信息档案查询 - 经营性用地无此字段 | |||||
| homeTime: "", // 租期 - 经营性用地无此字段 | |||||
| homeType: this.form.type === 'rent' ? '出租' : '出让', // 户型 - 使用类型 | |||||
| homeYs: "", // 钥匙 - 默认无 | |||||
| homeYzmj: this.form.landArea, // 院子总面积 - 使用土地面积 | |||||
| homeZy: "", // 坟包及电塔 工厂噪音 - 经营性用地无此字段 | |||||
| iconName: "经营性建设用地", // 热点名称 | |||||
| iconTitle: "经营性用地", // 标签 | |||||
| num: "0", // 浏览量 - 默认0 | |||||
| price: this.form.price, // 价格 | |||||
| timeGo: "", // 年限 - 经营性用地无此字段 | |||||
| title: `${this.form.type === 'rent' ? '出租' : '出让'}-经营性建设用地-${this.form.address.split('市')[1] || this.form.address}`, // 标题 - 自动生成 | |||||
| unit: this.form.type === 'rent' ? '元/亩/年' : '万元/亩', // 单位 | |||||
| image: "", // 图片 - 经营性用地无房屋照片 | |||||
| iconImage: "", // 左上角图标 | |||||
| homeImage: this.form.propertyImages.map(item => item.url).join(','), // 产权证照片 | |||||
| homeMp4: this.form.videos.map(item => item.url).join(','), // 视频 | |||||
| latitude: this.form.latitude, | |||||
| longitude: this.form.longitude, | |||||
| // 新增字段用于标识经营性用地 | |||||
| category: 'commercial', | |||||
| contactName: this.form.contactName, | |||||
| contactPhone: this.form.contactPhone | |||||
| }; | |||||
| console.log('经营性用地提交参数:', params); | |||||
| uni.showLoading({ | |||||
| title: '提交中...' | |||||
| }); | |||||
| // 调用统一API | |||||
| saveOrUpdateHouse(params).then(response => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: response.message || '提交成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| setTimeout(() => { | |||||
| uni.redirectTo({ | |||||
| url: "/pages_subpack/successful-apply/index" | |||||
| }); | |||||
| }, 2000); | |||||
| }).catch(error => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: error.message || '提交失败', | |||||
| icon: 'none' | |||||
| }); | |||||
| console.error('经营性用地提交失败:', error); | |||||
| }); | |||||
| }).catch(errors => { | |||||
| console.log('表单验证失败:', errors); | |||||
| uni.showToast({ | |||||
| title: '请补全必填项', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .container { | |||||
| min-height: 100vh; | |||||
| background-color: #f5f5f5; | |||||
| } | |||||
| .header { | |||||
| background: linear-gradient(135deg, #1EC77A 0%, #4CAF50 100%); | |||||
| padding: 40rpx 40rpx 60rpx; | |||||
| color: white; | |||||
| } | |||||
| .title { | |||||
| font-size: 36rpx; | |||||
| font-weight: bold; | |||||
| text-align: center; | |||||
| } | |||||
| .form-container { | |||||
| background: white; | |||||
| margin: -30rpx 20rpx 20rpx; | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx; | |||||
| box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1); | |||||
| } | |||||
| .section-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin: 40rpx 0 30rpx; | |||||
| padding-left: 20rpx; | |||||
| border-left: 6rpx solid #1EC77A; | |||||
| } | |||||
| .section-title:first-child { | |||||
| margin-top: 0; | |||||
| } | |||||
| .input-with-unit { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| } | |||||
| .unit { | |||||
| font-size: 26rpx; | |||||
| color: #666; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| .input-tip { | |||||
| font-size: 22rpx; | |||||
| color: #999; | |||||
| margin-top: 10rpx; | |||||
| line-height: 1.4; | |||||
| } | |||||
| .upload-tip { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| margin-bottom: 10rpx; | |||||
| line-height: 1.5; | |||||
| } | |||||
| .price-container { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| } | |||||
| .price-unit { | |||||
| font-size: 26rpx; | |||||
| color: #FF6B35; | |||||
| font-weight: bold; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,623 @@ | |||||
| <template> | |||||
| <view class="container"> | |||||
| <view class="header"> | |||||
| <view class="title">闲置农房信息录入</view> | |||||
| </view> | |||||
| <view class="form-container"> | |||||
| <uv-form labelPosition="left" :model="form" :rules="rules" ref="form" labelWidth="80" labelStyle="font-size:28rpx;"> | |||||
| <!-- 必填项 --> | |||||
| <view class="section-title">基本信息(必填)</view> | |||||
| <!-- 1. 出租/流转 --> | |||||
| <uv-form-item label="类型" prop="type" required> | |||||
| <uv-radio-group v-model="form.type" placement="row"> | |||||
| <uv-radio name="rent" label="出租"></uv-radio> | |||||
| <uv-radio name="transfer" customStyle="margin-left:30rpx;" label="流转"></uv-radio> | |||||
| </uv-radio-group> | |||||
| </uv-form-item> | |||||
| <!-- 2. 地址 --> | |||||
| <uv-form-item label="地址" prop="address" required @click="handleAddressSelect()"> | |||||
| <uv-input v-model="form.address" @click="handleAddressSelect()" disabled disabledColor="#ffffff" placeholder="请选择房屋位置" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 3. 联系人和电话 --> | |||||
| <uv-form-item label="联系人" prop="contactName" required> | |||||
| <uv-input v-model="form.contactName" type="text" placeholder="请输入联系人姓名" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <uv-form-item label="联系电话" prop="contactPhone" required> | |||||
| <uv-input v-model="form.contactPhone" type="number" placeholder="请输入联系电话" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <!-- 4. 房屋状况 --> | |||||
| <uv-form-item label="房屋状况" prop="houseCondition" required @click="handleHouseConditionSelect()"> | |||||
| <uv-input v-model="form.houseConditionName" @click="handleHouseConditionSelect()" disabled disabledColor="#ffffff" placeholder="请选择房屋状况" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 5. 产权证照片 --> | |||||
| <uv-form-item label="产权证照片" labelWidth="250" prop="propertyImages" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传房产证、土地证或不动产权证照片</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" :fileList="form.propertyImages" @afterRead="afterPropertyRead" @delete="deletePropertyPic" name="1" | |||||
| multiple :maxCount="5"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 6. 产权面积 --> | |||||
| <uv-form-item label="房屋面积" prop="houseArea" required> | |||||
| <view class="input-with-unit"> | |||||
| <uv-input v-model="form.houseArea" type="digit" placeholder="请输入房屋面积" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| <text class="unit">平米</text> | |||||
| </view> | |||||
| <view class="input-tip">请录入房屋证或不动产权证登记面积</view> | |||||
| </uv-form-item> | |||||
| <uv-form-item label="土地面积" prop="landArea" required> | |||||
| <view class="input-with-unit"> | |||||
| <uv-input v-model="form.landArea" type="digit" placeholder="请输入土地面积" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| <text class="unit">平米</text> | |||||
| </view> | |||||
| <view class="input-tip">请录入土地使用证或不动产权证面积</view> | |||||
| </uv-form-item> | |||||
| <!-- 7. 房屋正面照片 --> | |||||
| <uv-form-item label="房屋正面照片" labelWidth="250" prop="frontImages" labelPosition="top" required> | |||||
| <view class="upload-tip">作为封面展示,建议拍摄房屋正面全貌</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" :fileList="form.frontImages" @afterRead="afterFrontRead" @delete="deleteFrontPic" name="1" | |||||
| multiple :maxCount="3"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 8. 房屋视频 --> | |||||
| <uv-form-item label="房屋视频" labelWidth="250" prop="videos" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传房屋内部和外部视频(1分钟内)</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" accept="video" :fileList="form.videos" @afterRead="afterVideoRead" @delete="deleteVideoPic" name="1" | |||||
| multiple :maxCount="2"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 9. 价格 --> | |||||
| <uv-form-item label="价格" prop="price" required> | |||||
| <view class="price-container"> | |||||
| <uv-input v-model="form.price" type="digit" placeholder="请输入价格" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;flex:1;"></uv-input> | |||||
| <text class="price-unit" v-if="form.type === 'rent'">元/年</text> | |||||
| <text class="price-unit" v-else-if="form.type === 'transfer'">万元</text> | |||||
| <text class="price-unit" v-else>元</text> | |||||
| </view> | |||||
| <view class="input-tip">请输入数字,支持小数点后两位</view> | |||||
| </uv-form-item> | |||||
| <!-- 分类标识 --> | |||||
| <uv-form-item label="分类标识" prop="classId" @click="handleClass()"> | |||||
| <uv-input v-model="form.className" @click="handleClass()" disabled disabledColor="#ffffff" placeholder="选择分类标识" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 选填项 --> | |||||
| <view class="section-title">详细信息(选填)</view> | |||||
| <!-- 10. 可用菜地 --> | |||||
| <uv-form-item label="可用菜地" prop="vegetableGarden"> | |||||
| <view class="input-with-unit"> | |||||
| <uv-input v-model="form.vegetableGarden" type="digit" placeholder="请输入菜地面积" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| <text class="unit">平米</text> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| <!-- 11. 房屋亮点 --> | |||||
| <uv-form-item label="房屋亮点" prop="highlights" labelPosition="top"> | |||||
| <view class="tags-container"> | |||||
| <view | |||||
| class="tag-item" | |||||
| :class="{ 'tag-selected': form.highlights.includes(item) }" | |||||
| v-for="item in highlightOptions" | |||||
| :key="item" | |||||
| @click="toggleHighlight(item)" | |||||
| > | |||||
| {{item}} | |||||
| </view> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| <!-- 12. 不利因素 --> | |||||
| <uv-form-item label="不利因素" prop="disadvantages" labelPosition="top"> | |||||
| <view class="tags-container"> | |||||
| <view | |||||
| class="tag-item disadvantage-tag" | |||||
| :class="{ 'tag-selected': form.disadvantages.includes(item) }" | |||||
| v-for="item in disadvantageOptions" | |||||
| :key="item" | |||||
| @click="toggleDisadvantage(item)" | |||||
| > | |||||
| {{item}} | |||||
| </view> | |||||
| </view> | |||||
| </uv-form-item> | |||||
| <!-- 13. 房屋介绍 --> | |||||
| <uv-form-item label="房屋介绍" prop="description" labelPosition="top"> | |||||
| <uv-input | |||||
| v-model="form.description" | |||||
| type="textarea" | |||||
| placeholder="请详细介绍房屋情况、周边环境等" | |||||
| customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:10px;" | |||||
| :autoHeight="true" | |||||
| :maxlength="500" | |||||
| ></uv-input> | |||||
| </uv-form-item> | |||||
| <uv-form-item> | |||||
| <uv-button type="primary" text="提交信息" customStyle="margin-top: 30px;background-color: #1EC77A;border-radius: 30px;" @click="submit"></uv-button> | |||||
| </uv-form-item> | |||||
| </uv-form> | |||||
| </view> | |||||
| <!-- 房屋状况选择器 --> | |||||
| <uv-picker ref="houseConditionPicker" :columns="houseConditionColumns" @confirm="confirmHouseCondition"></uv-picker> | |||||
| <!-- 分类选择器 --> | |||||
| <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { saveOrUpdateHouse, houseType } from "@/common/api.js" | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| commonClass: '', // 所属分类ID | |||||
| form: { | |||||
| type: '', // 出租/流转 | |||||
| address: '', // 地址 | |||||
| contactName: '', // 联系人 | |||||
| contactPhone: '', // 联系电话 | |||||
| houseCondition: '', // 房屋状况ID | |||||
| houseConditionName: '', // 房屋状况名称 | |||||
| propertyImages: [], // 产权证照片 | |||||
| houseArea: '', // 房屋面积 | |||||
| landArea: '', // 土地面积 | |||||
| frontImages: [], // 房屋正面照片 | |||||
| videos: [], // 房屋视频 | |||||
| price: '', // 价格 | |||||
| longitude: '', // 经度 | |||||
| latitude: '', // 纬度 | |||||
| vegetableGarden: '', // 可用菜地 | |||||
| highlights: [], // 房屋亮点 | |||||
| disadvantages: [], // 不利因素 | |||||
| description: '', // 房屋介绍 | |||||
| classId: '', // 分类标识 | |||||
| className: '' // 分类名称 | |||||
| }, | |||||
| houseConditionColumns: [ | |||||
| ['老旧房屋', '装修较好可拎包入住', '新房'] | |||||
| ], | |||||
| highlightOptions: [ | |||||
| '靠河', '靠山', '通自来水', '通天然气', '近场镇或城市', | |||||
| '双车道到家', '精装修', '四合院', '周边无坟墓', '周边无电线塔' | |||||
| ], | |||||
| disadvantageOptions: [ | |||||
| '可见坟墓', '周边有电塔', '非正常死亡' | |||||
| ], | |||||
| columns: [], // 分类选择器数据 | |||||
| houseTypeList: [], // 分类列表 | |||||
| rules: { | |||||
| type: [ | |||||
| { required: true, message: '请选择出租或流转', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| address: [ | |||||
| { required: true, message: '请选择房屋地址', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactName: [ | |||||
| { required: true, message: '请输入联系人姓名', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactPhone: [ | |||||
| { required: true, message: '请输入联系电话', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| houseCondition: [ | |||||
| { required: true, message: '请选择房屋状况', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| houseArea: [ | |||||
| { required: true, message: '请输入房屋面积', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的数字格式', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| landArea: [ | |||||
| { required: true, message: '请输入土地面积', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的数字格式', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| price: [ | |||||
| { required: true, message: '请输入价格', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的价格格式', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| classId: [ | |||||
| { required: true, message: '请选择分类标识', trigger: ['blur', 'change'] } | |||||
| ] | |||||
| } | |||||
| } | |||||
| }, | |||||
| onReady() { | |||||
| this.$refs.form.setRules(this.rules) | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 设置页面标题 | |||||
| uni.setNavigationBarTitle({ | |||||
| title: '闲置农房录入' | |||||
| }) | |||||
| // 接收传递的commonClass参数 | |||||
| if(options.commonClass) { | |||||
| this.commonClass = options.commonClass | |||||
| } | |||||
| // 如果是编辑模式,设置classId用于回显 | |||||
| if(options.classId) { | |||||
| this.form.classId = options.classId | |||||
| } | |||||
| // 初始化分类数据 | |||||
| this.onHouseType() | |||||
| }, | |||||
| methods: { | |||||
| // 获取分类数据 | |||||
| onHouseType(){ | |||||
| let that = this | |||||
| houseType({}).then(response=>{ | |||||
| let arr=[] | |||||
| that.houseTypeList = response.result | |||||
| response.result.forEach(items=>{ | |||||
| arr.push(items.title) | |||||
| // 数据回显:如果当前classId匹配,设置className | |||||
| if(items.id == that.form.classId){ | |||||
| that.form.className = items.title | |||||
| } | |||||
| }) | |||||
| that.columns[0]=arr | |||||
| }).catch(error=>{ | |||||
| }) | |||||
| }, | |||||
| // 地址选择 | |||||
| handleAddressSelect() { | |||||
| const that = this; | |||||
| wx.chooseLocation({ | |||||
| success: function (res) { | |||||
| console.log('选择的位置:', res); | |||||
| that.form.longitude = res.longitude | |||||
| that.form.latitude = res.latitude | |||||
| that.form.address = res.address | |||||
| } | |||||
| }) | |||||
| }, | |||||
| // 房屋状况选择 | |||||
| handleHouseConditionSelect() { | |||||
| this.$refs.houseConditionPicker.open(); | |||||
| }, | |||||
| confirmHouseCondition(e) { | |||||
| const { indexs, value } = e; | |||||
| this.form.houseCondition = value[0]; // 修改:直接使用选择的值而不是索引 | |||||
| this.form.houseConditionName = value[0]; | |||||
| }, | |||||
| // 分类标识选择 | |||||
| handleClass() { | |||||
| this.$refs.picker.open(); | |||||
| }, | |||||
| confirm(e) { | |||||
| let that = this | |||||
| let {indexs,value,values} = e | |||||
| that.form.classId = that.houseTypeList[indexs[0]].id; | |||||
| that.form.className = that.houseTypeList[indexs[0]].title; | |||||
| }, | |||||
| // 产权证照片上传 | |||||
| async afterPropertyRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.propertyImages.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deletePropertyPic(event) { | |||||
| this.form.propertyImages.splice(event.index, 1) | |||||
| }, | |||||
| // 房屋正面照片上传 | |||||
| async afterFrontRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.frontImages.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deleteFrontPic(event) { | |||||
| this.form.frontImages.splice(event.index, 1) | |||||
| }, | |||||
| // 视频上传 | |||||
| async afterVideoRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.videos.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deleteVideoPic(event) { | |||||
| this.form.videos.splice(event.index, 1) | |||||
| }, | |||||
| // 切换房屋亮点 | |||||
| toggleHighlight(item) { | |||||
| const index = this.form.highlights.indexOf(item); | |||||
| if (index > -1) { | |||||
| this.form.highlights.splice(index, 1); | |||||
| } else { | |||||
| this.form.highlights.push(item); | |||||
| } | |||||
| }, | |||||
| // 切换不利因素 | |||||
| toggleDisadvantage(item) { | |||||
| const index = this.form.disadvantages.indexOf(item); | |||||
| if (index > -1) { | |||||
| this.form.disadvantages.splice(index, 1); | |||||
| } else { | |||||
| this.form.disadvantages.push(item); | |||||
| } | |||||
| }, | |||||
| // 提交表单 | |||||
| submit() { | |||||
| this.$refs.form.validate().then(res => { | |||||
| // 验证必填的图片和视频 | |||||
| if (this.form.propertyImages.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传产权证照片', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (this.form.frontImages.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传房屋正面照片', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (this.form.videos.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传房屋视频', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 构建与index.vue兼容的提交参数 | |||||
| const params = { | |||||
| userId: uni.getStorageSync('userInfo')?.id || "", | |||||
| id: "", // 新增数据,无ID | |||||
| classId: this.form.classId, // 使用分类标识 | |||||
| commonClass: this.commonClass, // 所属分类 | |||||
| address: this.form.address, // 地址 | |||||
| homeAge: "", // 户主年龄 - 农房录入无此字段 | |||||
| homeAz: "", // 是否经过安置 - 默认否 | |||||
| homeBian: this.form.highlights.join(','), // 房屋周边 - 使用亮点代替 | |||||
| homeBjsx: "", // 报建手续 - 农房录入无此字段 | |||||
| homeCai: this.form.vegetableGarden || "", // 菜地面积 | |||||
| homeCat: "", // 停车 - 农房录入无此字段 | |||||
| homeGz: "", // 房屋主体是否改造 - 农房录入无此字段 | |||||
| homeHb: "", // 房屋朝向及海拔 - 农房录入无此字段 | |||||
| homeBz: this.form.description, // 备注 - 使用房屋介绍 | |||||
| homeJg: this.form.houseCondition, // 房屋结构 - 使用房屋状况 | |||||
| homeJl: "", // 距离场镇距离 - 农房录入无此字段 | |||||
| homeJt: "", // 交通 - 农房录入无此字段 | |||||
| homeJtzy: "", // 户主家庭职业 - 农房录入无此字段 | |||||
| homeMi: "", // 面积 - 使用房屋面积 | |||||
| homeMj: this.form.houseArea, // 房屋面积 | |||||
| homeMoney: "", // 佣金 - 农房录入无此字段 | |||||
| homeNo: "", // 房屋编号 - 农房录入无此字段 | |||||
| homeNum: "1", // 房间数量 - 农房录入无此字段 | |||||
| homePay: "", // 付款方式及押金 - 农房录入无此字段 | |||||
| homePj: "", // 邻居对房东评价 - 农房录入无此字段 | |||||
| homeSd: "", // 水电气网 - 农房录入无此字段 | |||||
| homeShjl: "", // 距离成都西三环 - 农房录入无此字段 | |||||
| homeSw: this.form.disadvantages.join(','), // 非正常死亡 - 显示不利因素信息 | |||||
| homeTf: "", // 府市民云房屋信息档案查询 - 农房录入无此字段 | |||||
| homeTime: "", // 租期 - 农房录入无此字段 | |||||
| homeType: this.form.type === 'rent' ? '出租' : '流转', // 户型 - 使用类型 | |||||
| homeYs: "", // 钥匙 - 默认无 | |||||
| homeYzmj: this.form.landArea, // 院子总面积 - 使用土地面积 | |||||
| homeZy: this.form.disadvantages.join(','), // 坟包及电塔 工厂噪音 - 使用不利因素 | |||||
| iconName: "闲置农房", // 热点名称 | |||||
| iconTitle: this.form.highlights.join(','), // 标签 - 使用亮点 | |||||
| num: "0", // 浏览量 - 默认0 | |||||
| price: this.form.price, // 价格 | |||||
| timeGo: "", // 年限 - 农房录入无此字段 | |||||
| title: `${this.form.type === 'rent' ? '出租' : '流转'}-${this.form.address.split('市')[1] || this.form.address}`, // 标题 - 自动生成 | |||||
| unit: this.form.type === 'rent' ? '元/年' : '万元', // 单位 | |||||
| image: this.form.frontImages.map(item => item.url).join(','), // 图片 - 使用正面照片 | |||||
| iconImage: "", // 左上角图标 | |||||
| homeImage: this.form.propertyImages.map(item => item.url).join(','), // 产权证照片 | |||||
| homeMp4: this.form.videos.map(item => item.url).join(','), // 视频 | |||||
| latitude: this.form.latitude, | |||||
| longitude: this.form.longitude, | |||||
| // 新增字段用于标识农房 | |||||
| category: 'farmhouse', | |||||
| contactName: this.form.contactName, | |||||
| contactPhone: this.form.contactPhone | |||||
| }; | |||||
| console.log('农房提交参数:', params); | |||||
| uni.showLoading({ | |||||
| title: '提交中...' | |||||
| }); | |||||
| // 调用统一API | |||||
| saveOrUpdateHouse(params).then(response => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: response.message || '提交成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| setTimeout(() => { | |||||
| uni.redirectTo({ | |||||
| url: "/pages_subpack/successful-apply/index" | |||||
| }); | |||||
| }, 2000); | |||||
| }).catch(error => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: error.message || '提交失败', | |||||
| icon: 'none' | |||||
| }); | |||||
| console.error('农房提交失败:', error); | |||||
| }); | |||||
| }).catch(errors => { | |||||
| console.log('表单验证失败:', errors); | |||||
| uni.showToast({ | |||||
| title: '请补全必填项', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .container { | |||||
| min-height: 100vh; | |||||
| background-color: #f5f5f5; | |||||
| } | |||||
| .header { | |||||
| background: linear-gradient(135deg, #1EC77A 0%, #4CAF50 100%); | |||||
| padding: 40rpx 40rpx 60rpx; | |||||
| color: white; | |||||
| } | |||||
| .title { | |||||
| font-size: 36rpx; | |||||
| font-weight: bold; | |||||
| text-align: center; | |||||
| } | |||||
| .form-container { | |||||
| background: white; | |||||
| margin: -30rpx 20rpx 20rpx; | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx; | |||||
| box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1); | |||||
| } | |||||
| .section-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin: 40rpx 0 30rpx; | |||||
| padding-left: 20rpx; | |||||
| border-left: 6rpx solid #1EC77A; | |||||
| } | |||||
| .section-title:first-child { | |||||
| margin-top: 0; | |||||
| } | |||||
| .input-with-unit { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| } | |||||
| .unit { | |||||
| font-size: 26rpx; | |||||
| color: #666; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| .input-tip { | |||||
| font-size: 22rpx; | |||||
| color: #999; | |||||
| margin-top: 10rpx; | |||||
| line-height: 1.4; | |||||
| } | |||||
| .upload-tip { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| margin-bottom: 10rpx; | |||||
| line-height: 1.5; | |||||
| } | |||||
| .price-container { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| } | |||||
| .price-unit { | |||||
| font-size: 26rpx; | |||||
| color: #1EC77A; | |||||
| font-weight: bold; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| .tags-container { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| gap: 15rpx; | |||||
| margin-top: 20rpx; | |||||
| } | |||||
| .tag-item { | |||||
| padding: 15rpx 25rpx; | |||||
| border: 2rpx solid #e0e0e0; | |||||
| border-radius: 25rpx; | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| background: #f9f9f9; | |||||
| transition: all 0.3s ease; | |||||
| } | |||||
| .tag-item.tag-selected { | |||||
| border-color: #1EC77A; | |||||
| background: #1EC77A; | |||||
| color: white; | |||||
| } | |||||
| .disadvantage-tag.tag-selected { | |||||
| border-color: #ff4757; | |||||
| background: #ff4757; | |||||
| color: white; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,479 @@ | |||||
| <template> | |||||
| <view class="container"> | |||||
| <view class="header"> | |||||
| <view class="title">其他农村资源录入</view> | |||||
| </view> | |||||
| <view class="form-container"> | |||||
| <uv-form labelPosition="left" :model="form" :rules="rules" ref="form" labelWidth="80" labelStyle="font-size:28rpx;"> | |||||
| <!-- 必填项 --> | |||||
| <view class="section-title">基本信息(必填)</view> | |||||
| <!-- 1. 出租/流转 --> | |||||
| <uv-form-item label="类型" prop="type" required> | |||||
| <uv-radio-group v-model="form.type" placement="row"> | |||||
| <uv-radio name="rent" label="出租"></uv-radio> | |||||
| <uv-radio name="transfer" customStyle="margin-left:30rpx;" label="流转"></uv-radio> | |||||
| </uv-radio-group> | |||||
| </uv-form-item> | |||||
| <!-- 2. 地址 --> | |||||
| <uv-form-item label="地址" prop="address" required @click="handleAddressSelect()"> | |||||
| <uv-input v-model="form.address" @click="handleAddressSelect()" disabled disabledColor="#ffffff" placeholder="请选择资源位置" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 3. 联系人和电话 --> | |||||
| <uv-form-item label="联系人" prop="contactName" required> | |||||
| <uv-input v-model="form.contactName" type="text" placeholder="请输入联系人姓名" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <uv-form-item label="联系电话" prop="contactPhone" required> | |||||
| <uv-input v-model="form.contactPhone" type="number" placeholder="请输入联系电话" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input> | |||||
| </uv-form-item> | |||||
| <!-- 4. 照片和视频 --> | |||||
| <uv-form-item label="资源照片" labelWidth="250" prop="images" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传资源相关照片</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" :fileList="form.images" @afterRead="afterImageRead" @delete="deleteImagePic" name="1" | |||||
| multiple :maxCount="10"></uv-upload> | |||||
| </uv-form-item> | |||||
| <uv-form-item label="资源视频" labelWidth="250" prop="videos" labelPosition="top" required> | |||||
| <view class="upload-tip">请上传资源视频(1分钟内)</view> | |||||
| <uv-upload customStyle="margin-top:20rpx;" accept="video" :fileList="form.videos" @afterRead="afterVideoRead" @delete="deleteVideoPic" name="1" | |||||
| multiple :maxCount="3"></uv-upload> | |||||
| </uv-form-item> | |||||
| <!-- 5. 价格 --> | |||||
| <uv-form-item label="价格" prop="price" required> | |||||
| <view class="price-container"> | |||||
| <uv-input v-model="form.price" type="text" placeholder="请描述价格,如:面议、1000元/年等" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;flex:1;"></uv-input> | |||||
| </view> | |||||
| <view class="input-tip">开放式填写,可填写具体价格或"面议"等</view> | |||||
| </uv-form-item> | |||||
| <!-- 6. 资源介绍 --> | |||||
| <uv-form-item label="资源介绍" prop="description" labelPosition="top" required> | |||||
| <uv-input | |||||
| v-model="form.description" | |||||
| type="textarea" | |||||
| placeholder="请详细介绍资源类型、用途、特色、优势等信息" | |||||
| customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:10px;" | |||||
| :autoHeight="true" | |||||
| :maxlength="1000" | |||||
| ></uv-input> | |||||
| <view class="char-count">{{form.description.length}}/1000</view> | |||||
| <view class="input-tip">请详细描述资源的类型、用途、特色、规模、优势等</view> | |||||
| </uv-form-item> | |||||
| <!-- 分类标识 --> | |||||
| <uv-form-item label="分类标识" prop="classId" @click="handleClass()"> | |||||
| <uv-input v-model="form.className" @click="handleClass()" disabled disabledColor="#ffffff" placeholder="选择分类标识" border="none"> | |||||
| </uv-input> | |||||
| <template v-slot:right> | |||||
| <uv-icon name="arrow-right"></uv-icon> | |||||
| </template> | |||||
| </uv-form-item> | |||||
| <!-- 代理协议 --> | |||||
| <view class="section-title">代理协议</view> | |||||
| <view class="agreement-container"> | |||||
| <view class="agreement-content"> | |||||
| <text class="agreement-title">代理协议</text> | |||||
| <text class="agreement-text"> | |||||
| 本人同意授权我平台发布信息、代理销售等。本人承诺所提供的信息真实有效,并同意平台进行相关推广和销售代理。 | |||||
| </text> | |||||
| </view> | |||||
| <uv-checkbox v-model="form.agreeProtocol" shape="circle" activeColor="#1EC77A"> | |||||
| <text class="agreement-label">我已阅读并同意代理协议</text> | |||||
| </uv-checkbox> | |||||
| </view> | |||||
| <uv-form-item> | |||||
| <uv-button type="primary" text="提交信息" customStyle="margin-top: 30px;background-color: #1EC77A;border-radius: 30px;" @click="submit"></uv-button> | |||||
| </uv-form-item> | |||||
| </uv-form> | |||||
| </view> | |||||
| <!-- 分类选择器 --> | |||||
| <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { saveOrUpdateHouse, houseType } from "@/common/api.js" | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| commonClass: '', // 所属分类ID | |||||
| form: { | |||||
| type: '', // 出租/流转 | |||||
| address: '', // 地址 | |||||
| contactName: '', // 联系人 | |||||
| contactPhone: '', // 联系电话 | |||||
| images: [], // 资源照片 | |||||
| videos: [], // 资源视频 | |||||
| price: '', // 价格(开放式) | |||||
| description: '', // 资源介绍 | |||||
| agreeProtocol: false, // 同意代理协议 | |||||
| longitude: '', // 经度 | |||||
| latitude: '', // 纬度 | |||||
| classId: '', // 分类标识 | |||||
| className: '' // 分类名称 | |||||
| }, | |||||
| columns: [], // 分类选择器数据 | |||||
| houseTypeList: [], // 分类列表 | |||||
| rules: { | |||||
| type: [ | |||||
| { required: true, message: '请选择出租或流转', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| address: [ | |||||
| { required: true, message: '请选择资源地址', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactName: [ | |||||
| { required: true, message: '请输入联系人姓名', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| contactPhone: [ | |||||
| { required: true, message: '请输入联系电话', trigger: ['blur', 'change'] }, | |||||
| { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| price: [ | |||||
| { required: true, message: '请输入价格信息', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| description: [ | |||||
| { required: true, message: '请输入资源介绍', trigger: ['blur', 'change'] }, | |||||
| { min: 10, message: '资源介绍至少需要10个字符', trigger: ['blur', 'change'] } | |||||
| ], | |||||
| classId: [ | |||||
| { required: true, message: '请选择分类标识', trigger: ['blur', 'change'] } | |||||
| ] | |||||
| } | |||||
| } | |||||
| }, | |||||
| onReady() { | |||||
| this.$refs.form.setRules(this.rules) | |||||
| }, | |||||
| onLoad(options) { | |||||
| // 设置页面标题 | |||||
| uni.setNavigationBarTitle({ | |||||
| title: '其他农村资源录入' | |||||
| }) | |||||
| // 接收传递的commonClass参数 | |||||
| if(options.commonClass) { | |||||
| this.commonClass = options.commonClass | |||||
| } | |||||
| // 如果是编辑模式,设置classId用于回显 | |||||
| if(options.classId) { | |||||
| this.form.classId = options.classId | |||||
| } | |||||
| // 初始化分类数据 | |||||
| this.onHouseType() | |||||
| }, | |||||
| methods: { | |||||
| // 获取分类数据 | |||||
| onHouseType(){ | |||||
| let that = this | |||||
| houseType({}).then(response=>{ | |||||
| let arr=[] | |||||
| that.houseTypeList = response.result | |||||
| response.result.forEach(items=>{ | |||||
| arr.push(items.title) | |||||
| // 数据回显:如果当前classId匹配,设置className | |||||
| if(items.id == that.form.classId){ | |||||
| that.form.className = items.title | |||||
| } | |||||
| }) | |||||
| that.columns[0]=arr | |||||
| }).catch(error=>{ | |||||
| }) | |||||
| }, | |||||
| // 地址选择 | |||||
| handleAddressSelect() { | |||||
| const that = this; | |||||
| wx.chooseLocation({ | |||||
| success: function (res) { | |||||
| console.log('选择的位置:', res); | |||||
| that.form.longitude = res.longitude | |||||
| that.form.latitude = res.latitude | |||||
| that.form.address = res.address | |||||
| } | |||||
| }) | |||||
| }, | |||||
| // 资源照片上传 | |||||
| async afterImageRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.images.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deleteImagePic(event) { | |||||
| this.form.images.splice(event.index, 1) | |||||
| }, | |||||
| // 视频上传 | |||||
| async afterVideoRead(e) { | |||||
| let self = this | |||||
| e.file.forEach(file => { | |||||
| self.$Oss.ossUpload(file.url).then(url => { | |||||
| self.form.videos.push({ | |||||
| url | |||||
| }) | |||||
| }) | |||||
| }) | |||||
| }, | |||||
| deleteVideoPic(event) { | |||||
| this.form.videos.splice(event.index, 1) | |||||
| }, | |||||
| // 分类选择 | |||||
| handleClass() { | |||||
| this.$refs.picker.open(); | |||||
| }, | |||||
| confirm(e) { | |||||
| let that = this | |||||
| let {indexs,value,values} = e | |||||
| that.form.classId = that.houseTypeList[indexs[0]].id; | |||||
| that.form.className = that.houseTypeList[indexs[0]].title; | |||||
| }, | |||||
| // 提交表单 | |||||
| submit() { | |||||
| // 检查是否同意代理协议 | |||||
| if (!this.form.agreeProtocol) { | |||||
| uni.showToast({ | |||||
| title: '请先同意代理协议', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| this.$refs.form.validate().then(res => { | |||||
| // 验证必填的图片和视频 | |||||
| if (this.form.images.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传资源照片', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| if (this.form.videos.length === 0) { | |||||
| uni.showToast({ | |||||
| title: '请上传资源视频', | |||||
| icon: 'none' | |||||
| }); | |||||
| return; | |||||
| } | |||||
| // 构建与index.vue兼容的提交参数 | |||||
| const params = { | |||||
| userId: uni.getStorageSync('userInfo')?.id || "", | |||||
| id: "", // 新增数据,无ID | |||||
| classId: this.form.classId, // 使用分类标识 | |||||
| commonClass: this.commonClass, // 所属分类 | |||||
| address: this.form.address, // 地址 | |||||
| homeAge: "", // 户主年龄 - 其他资源无此字段 | |||||
| homeAz: "", // 是否经过安置 - 默认否 | |||||
| homeBian: "", // 房屋周边 - 其他资源无此字段 | |||||
| homeBjsx: "", // 报建手续 - 其他资源无此字段 | |||||
| homeCai: "", // 菜地 - 其他资源无此字段 | |||||
| homeCat: "", // 停车 - 其他资源无此字段 | |||||
| homeGz: "", // 房屋主体是否改造 - 默认否 | |||||
| homeHb: "", // 房屋朝向及海拔 - 其他资源无此字段 | |||||
| homeBz: this.form.description, // 备注 - 使用资源介绍 | |||||
| homeJg: "其他农村资源", // 房屋结构 - 使用固定值 | |||||
| homeJl: "", // 距离场镇距离 - 其他资源无此字段 | |||||
| homeJt: "", // 交通 - 其他资源无此字段 | |||||
| homeJtzy: "", // 户主家庭职业 - 其他资源无此字段 | |||||
| homeMi: "", // 面积 - 其他资源无此字段 | |||||
| homeMj: "", // 房屋面积 - 其他资源无此字段 | |||||
| homeMoney: "", // 佣金 - 其他资源无此字段 | |||||
| homeNo: "", // 房屋编号 - 其他资源无此字段 | |||||
| homeNum: "", // 房间数量 - 其他资源无此字段 | |||||
| homePay: this.form.price, // 付款方式及押金 - 使用价格信息 | |||||
| homePj: "", // 邻居对房东评价 - 其他资源无此字段 | |||||
| homeSd: "", // 水电气网 - 其他资源无此字段 | |||||
| homeShjl: "", // 距离成都西三环 - 其他资源无此字段 | |||||
| homeSw: "", // 非正常死亡 - 默认无 | |||||
| homeTf: "", // 府市民云房屋信息档案查询 - 其他资源无此字段 | |||||
| homeTime: "", // 租期 - 其他资源无此字段 | |||||
| homeType: this.form.type === 'rent' ? '出租' : '流转', // 户型 - 使用类型 | |||||
| homeYs: "", // 钥匙 - 默认无 | |||||
| homeYzmj: "", // 院子总面积 - 其他资源无此字段 | |||||
| homeZy: "", // 坟包及电塔 工厂噪音 - 其他资源无此字段 | |||||
| iconName: "其他农村资源", // 热点名称 | |||||
| iconTitle: "其他资源", // 标签 | |||||
| num: "0", // 浏览量 - 默认0 | |||||
| price: this.form.price, // 价格 | |||||
| timeGo: "", // 年限 - 其他资源无此字段 | |||||
| title: `${this.form.type === 'rent' ? '出租' : '流转'}-其他农村资源-${this.form.address.split('市')[1] || this.form.address}`, // 标题 - 自动生成 | |||||
| unit: "", // 单位 - 其他资源价格单位灵活 | |||||
| image: this.form.images.map(item => item.url).join(','), // 图片 - 使用资源照片 | |||||
| iconImage: "", // 左上角图标 | |||||
| homeImage: "", // 产权证照片 - 其他资源可能无产权证 | |||||
| homeMp4: this.form.videos.map(item => item.url).join(','), // 视频 | |||||
| latitude: this.form.latitude, | |||||
| longitude: this.form.longitude, | |||||
| // 新增字段用于标识其他资源 | |||||
| category: 'other', | |||||
| contactName: this.form.contactName, | |||||
| contactPhone: this.form.contactPhone | |||||
| }; | |||||
| console.log('其他资源提交参数:', params); | |||||
| uni.showLoading({ | |||||
| title: '提交中...' | |||||
| }); | |||||
| // 调用统一API | |||||
| saveOrUpdateHouse(params).then(response => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: response.message || '提交成功', | |||||
| icon: 'success' | |||||
| }); | |||||
| setTimeout(() => { | |||||
| uni.redirectTo({ | |||||
| url: "/pages_subpack/successful-apply/index" | |||||
| }); | |||||
| }, 2000); | |||||
| }).catch(error => { | |||||
| uni.hideLoading(); | |||||
| uni.showToast({ | |||||
| title: error.message || '提交失败', | |||||
| icon: 'none' | |||||
| }); | |||||
| console.error('其他资源提交失败:', error); | |||||
| }); | |||||
| }).catch(errors => { | |||||
| console.log('表单验证失败:', errors); | |||||
| uni.showToast({ | |||||
| title: '请补全必填项', | |||||
| icon: 'none' | |||||
| }); | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .container { | |||||
| min-height: 100vh; | |||||
| background-color: #f5f5f5; | |||||
| } | |||||
| .header { | |||||
| background: linear-gradient(135deg, #1EC77A 0%, #4CAF50 100%); | |||||
| padding: 40rpx 40rpx 60rpx; | |||||
| color: white; | |||||
| } | |||||
| .title { | |||||
| font-size: 36rpx; | |||||
| font-weight: bold; | |||||
| text-align: center; | |||||
| } | |||||
| .form-container { | |||||
| background: white; | |||||
| margin: -30rpx 20rpx 20rpx; | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx; | |||||
| box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1); | |||||
| } | |||||
| .section-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin: 40rpx 0 30rpx; | |||||
| padding-left: 20rpx; | |||||
| border-left: 6rpx solid #1EC77A; | |||||
| } | |||||
| .section-title:first-child { | |||||
| margin-top: 0; | |||||
| } | |||||
| .input-tip { | |||||
| font-size: 22rpx; | |||||
| color: #999; | |||||
| margin-top: 10rpx; | |||||
| line-height: 1.4; | |||||
| } | |||||
| .upload-tip { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| margin-bottom: 10rpx; | |||||
| line-height: 1.5; | |||||
| } | |||||
| .price-container { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| gap: 10rpx; | |||||
| } | |||||
| .char-count { | |||||
| font-size: 22rpx; | |||||
| color: #999; | |||||
| text-align: right; | |||||
| margin-top: 10rpx; | |||||
| } | |||||
| .agreement-container { | |||||
| margin: 30rpx 0; | |||||
| padding: 30rpx; | |||||
| background: #f8f9fa; | |||||
| border-radius: 15rpx; | |||||
| border: 2rpx solid #e9ecef; | |||||
| } | |||||
| .agreement-content { | |||||
| margin-bottom: 30rpx; | |||||
| } | |||||
| .agreement-title { | |||||
| display: block; | |||||
| font-size: 28rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 20rpx; | |||||
| } | |||||
| .agreement-text { | |||||
| display: block; | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| line-height: 1.6; | |||||
| } | |||||
| .agreement-label { | |||||
| font-size: 26rpx; | |||||
| color: #333; | |||||
| margin-left: 10rpx; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,254 @@ | |||||
| <template> | |||||
| <view class="container"> | |||||
| <view class="header"> | |||||
| <view class="title">选择发布类型</view> | |||||
| <view class="subtitle">请选择您要发布的房源类型</view> | |||||
| </view> | |||||
| <view class="options-container"> | |||||
| <view | |||||
| class="option-item" | |||||
| v-for="(item, index) in optionList" | |||||
| :key="index" | |||||
| @click="onSelectOption(item)" | |||||
| > | |||||
| <view class="option-icon"> | |||||
| <image :src="item.image" v-if="item.image" mode="aspectFill"></image> | |||||
| <text class="icon-emoji" v-if="item.icon">{{item.icon}}</text> | |||||
| </view> | |||||
| <view class="option-content"> | |||||
| <view class="option-title">{{item.title}}</view> | |||||
| <view class="option-desc">{{item.shortTitle}}</view> | |||||
| </view> | |||||
| <view class="option-arrow"> | |||||
| <uv-icon name="arrow-right" color="#999" size="20"></uv-icon> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <view class="tips"> | |||||
| <view class="tips-title">温馨提示</view> | |||||
| <!-- <view class="tips-content"> | |||||
| • 请根据您的实际情况选择对应的发布类型<br/> | |||||
| • 不同类型的房源信息录入内容会有所差异<br/> | |||||
| • 提交后将进入相应的信息录入页面 | |||||
| </view> --> | |||||
| <view class="tips-content" | |||||
| v-html="info"> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| import { commonIndexIndexIcon } from "@/common/api.js" | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| optionList: [ | |||||
| // { | |||||
| // code: 'idle_farmhouse', | |||||
| // title: '闲置农房/宅基地', | |||||
| // shortTitle: '农村闲置房屋、宅基地等资源', | |||||
| // icon: '🏡', | |||||
| // type: 1 | |||||
| // }, | |||||
| // { | |||||
| // code: 'commercial_land', | |||||
| // title: '经营性建设用地', | |||||
| // shortTitle: '可用于商业经营的建设用地', | |||||
| // icon: '🏢', | |||||
| // type: 2 | |||||
| // }, | |||||
| // { | |||||
| // code: 'other_resources', | |||||
| // title: '其他农村资源', | |||||
| // shortTitle: '其他类型的农村可利用资源', | |||||
| // icon: '🌾', | |||||
| // type: 3 | |||||
| // }, | |||||
| ], | |||||
| info : '', | |||||
| } | |||||
| }, | |||||
| onLoad() { | |||||
| this.getRlease_home_info() | |||||
| this.onCommonIndexIndexIcon() | |||||
| }, | |||||
| methods: { | |||||
| onCommonIndexIndexIcon(){ | |||||
| let that = this | |||||
| commonIndexIndexIcon({}).then(response=>{ | |||||
| console.info('onCommonIndexIndexIcon',response) | |||||
| that.optionList = response.result | |||||
| }) | |||||
| }, | |||||
| getRlease_home_info(){ | |||||
| console.log(this.$utils.getkeyContent('release_home_info')); | |||||
| let a = this.$utils.getkeyContent('release_home_info') || {} | |||||
| this.info = (a.keyContent || '').replaceAll('\n', '<br>') | |||||
| }, | |||||
| onSelectOption(item) { | |||||
| console.log('选择了:', item); | |||||
| // 根据不同类型跳转到不同的录入页面 | |||||
| let targetUrl = ''; | |||||
| if (item.code === 'idle_farmhouse') { | |||||
| // 闲置农房跳转到专门的录入页面 | |||||
| targetUrl = `/pages_subpack/house/farmhouse?commonClass=${item.id}`; | |||||
| } else if (item.code === 'commercial_land') { | |||||
| // 经营性建设用地跳转到专门的录入页面 | |||||
| targetUrl = `/pages_subpack/house/commercial?commonClass=${item.id}`; | |||||
| } else if (item.code === 'other_resources') { | |||||
| // 其他农村资源跳转到专门的录入页面 | |||||
| targetUrl = `/pages_subpack/house/other?commonClass=${item.id}`; | |||||
| } else { | |||||
| // 其他类型跳转到通用录入页面 | |||||
| targetUrl = `/pages_subpack/house/index?id=${item.id}&title=${item.title}`; | |||||
| } | |||||
| uni.navigateTo({ | |||||
| url: targetUrl | |||||
| }); | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped lang="scss"> | |||||
| .container { | |||||
| min-height: 100vh; | |||||
| background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); | |||||
| padding: 40rpx; | |||||
| } | |||||
| .header { | |||||
| text-align: center; | |||||
| margin-bottom: 80rpx; | |||||
| padding-top: 60rpx; | |||||
| } | |||||
| .title { | |||||
| font-size: 48rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 20rpx; | |||||
| } | |||||
| .subtitle { | |||||
| font-size: 28rpx; | |||||
| color: #666; | |||||
| line-height: 1.6; | |||||
| } | |||||
| .options-container { | |||||
| margin-bottom: 60rpx; | |||||
| } | |||||
| .option-item { | |||||
| background: #fff; | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx 30rpx; | |||||
| margin-bottom: 30rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| box-shadow: 0 8rpx 25rpx rgba(0,0,0,0.08); | |||||
| transition: all 0.3s ease; | |||||
| position: relative; | |||||
| overflow: hidden; | |||||
| } | |||||
| .option-item::before { | |||||
| content: ''; | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 0; | |||||
| right: 0; | |||||
| height: 6rpx; | |||||
| background: linear-gradient(90deg, #1EC77A 0%, #4CAF50 100%); | |||||
| transform: scaleX(0); | |||||
| transition: transform 0.3s ease; | |||||
| } | |||||
| .option-item:active { | |||||
| transform: translateY(2rpx); | |||||
| box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.12); | |||||
| } | |||||
| .option-item:active::before { | |||||
| transform: scaleX(1); | |||||
| } | |||||
| .option-icon { | |||||
| width: 120rpx; | |||||
| height: 120rpx; | |||||
| margin-right: 30rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| justify-content: center; | |||||
| background: #f8f9fa; | |||||
| border-radius: 50%; | |||||
| image{ | |||||
| width: 100rpx; | |||||
| height: 100rpx; | |||||
| border-radius: 50%; | |||||
| } | |||||
| } | |||||
| .icon-emoji { | |||||
| font-size: 60rpx; | |||||
| line-height: 1; | |||||
| } | |||||
| .option-content { | |||||
| flex: 1; | |||||
| } | |||||
| .option-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 10rpx; | |||||
| } | |||||
| .option-desc { | |||||
| font-size: 26rpx; | |||||
| color: #666; | |||||
| line-height: 1.5; | |||||
| } | |||||
| .option-arrow { | |||||
| margin-left: 20rpx; | |||||
| } | |||||
| .tips { | |||||
| background: #fff; | |||||
| border-radius: 20rpx; | |||||
| padding: 30rpx; | |||||
| box-shadow: 0 4rpx 15rpx rgba(0,0,0,0.06); | |||||
| } | |||||
| .tips-title { | |||||
| font-size: 28rpx; | |||||
| font-weight: bold; | |||||
| color: #1EC77A; | |||||
| margin-bottom: 20rpx; | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .tips-title::before { | |||||
| content: ''; | |||||
| width: 8rpx; | |||||
| height: 32rpx; | |||||
| background: #1EC77A; | |||||
| border-radius: 4rpx; | |||||
| margin-right: 15rpx; | |||||
| } | |||||
| .tips-content { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| line-height: 1.8; | |||||
| } | |||||
| </style> | |||||
| @ -0,0 +1,311 @@ | |||||
| <template> | |||||
| <view class="u-page"> | |||||
| <!-- 头部会员卡片 --> | |||||
| <view class="member-header"> | |||||
| <view class="member-card"> | |||||
| <view class="card-bg"> | |||||
| <view class="member-title"> | |||||
| <uv-icon name="level" size="60rpx" color="#FFD700"></uv-icon> | |||||
| <text class="title-text">会员中心</text> | |||||
| </view> | |||||
| <view class="member-desc">开通永久会员,享受更多专属权益</view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 会员权益 --> | |||||
| <view class="rights-section"> | |||||
| <view class="section-title"> | |||||
| <text>会员专享权益</text> | |||||
| </view> | |||||
| <view class="rights-list"> | |||||
| <view class="right-item"> | |||||
| <view class="right-icon"> | |||||
| <uv-icon name="map-fill" size="40rpx" color="#FF6B6B"></uv-icon> | |||||
| </view> | |||||
| <view class="right-content"> | |||||
| <text class="right-title">查看详细地址</text> | |||||
| <text class="right-desc">查看具体定位和村址,普通用户只能看到乡镇</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="right-item"> | |||||
| <view class="right-icon"> | |||||
| <uv-icon name="phone-fill" size="40rpx" color="#4ECDC4"></uv-icon> | |||||
| </view> | |||||
| <view class="right-content"> | |||||
| <text class="right-title">查看联系方式</text> | |||||
| <text class="right-desc">查看房主手机号,方便直接联系</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="right-item"> | |||||
| <view class="right-icon"> | |||||
| <uv-icon name="star-fill" size="40rpx" color="#FFD700"></uv-icon> | |||||
| </view> | |||||
| <view class="right-content"> | |||||
| <text class="right-title">优先查看房源</text> | |||||
| <text class="right-desc">抢先查看最新房源信息</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="right-item"> | |||||
| <view class="right-icon"> | |||||
| <uv-icon name="heart-fill" size="40rpx" color="#9B59B6"></uv-icon> | |||||
| </view> | |||||
| <view class="right-content"> | |||||
| <text class="right-title">专属客服</text> | |||||
| <text class="right-desc">享受一对一专属客服服务</text> | |||||
| </view> | |||||
| </view> | |||||
| <view class="right-item"> | |||||
| <view class="right-icon"> | |||||
| <uv-icon name="gift-fill" size="40rpx" color="#E74C3C"></uv-icon> | |||||
| </view> | |||||
| <view class="right-content"> | |||||
| <text class="right-title">永久会员标识</text> | |||||
| <text class="right-desc">尊贵的永久会员身份标识</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 永久会员价格 --> | |||||
| <view class="package-section"> | |||||
| <view class="price-card"> | |||||
| <view class="price-header"> | |||||
| <view class="price-tag"> | |||||
| <text class="currency">¥</text> | |||||
| <text class="price">99</text> | |||||
| </view> | |||||
| <text class="price-desc">永久会员</text> | |||||
| </view> | |||||
| <view class="price-benefits"> | |||||
| <text class="benefit-text">• 一次购买,终身享受所有会员权益</text> | |||||
| <text class="benefit-text">• 无需续费,永久有效</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| <!-- 开通按钮 --> | |||||
| <view class="action-section"> | |||||
| <uv-button type="primary" @click="openMember" | |||||
| style="background: linear-gradient(135deg, #1EC77A 0%, #16A085 100%); border: none; border-radius: 50rpx; height: 100rpx; font-size: 32rpx; font-weight: bold;"> | |||||
| 立即开通永久会员 - ¥99 | |||||
| </uv-button> | |||||
| <view class="agreement"> | |||||
| <text>开通即表示同意</text> | |||||
| <text class="link" @click="showAgreement">《永久会员服务协议》</text> | |||||
| </view> | |||||
| </view> | |||||
| </view> | |||||
| </template> | |||||
| <script> | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| memberPrice: 99 // 永久会员价格 | |||||
| } | |||||
| }, | |||||
| methods: { | |||||
| openMember() { | |||||
| uni.showModal({ | |||||
| title: '确认开通', | |||||
| content: `确定开通永久会员吗?\n价格:¥${this.memberPrice}\n终身享受会员权益`, | |||||
| confirmText: '确认开通', | |||||
| cancelText: '取消', | |||||
| success: (res) => { | |||||
| if (res.confirm) { | |||||
| this.processPay() | |||||
| } | |||||
| } | |||||
| }) | |||||
| }, | |||||
| processPay() { | |||||
| // 这里应该调用支付接口 | |||||
| uni.showLoading({ | |||||
| title: '处理中...' | |||||
| }) | |||||
| // 模拟支付处理 | |||||
| setTimeout(() => { | |||||
| uni.hideLoading() | |||||
| uni.showToast({ | |||||
| title: '永久会员开通成功', | |||||
| icon: 'success', | |||||
| duration: 2000 | |||||
| }) | |||||
| // 返回上一页并刷新用户信息 | |||||
| setTimeout(() => { | |||||
| uni.navigateBack() | |||||
| }, 2000) | |||||
| }, 2000) | |||||
| }, | |||||
| showAgreement() { | |||||
| uni.showModal({ | |||||
| title: '永久会员服务协议', | |||||
| content: '1. 永久会员享有查看详细地址和联系方式的权限\n2. 会员权益包括但不限于:查看具体定位、村址信息、房主手机号等\n3. 永久会员权益终身有效,无需续费\n4. 其他会员服务条款...', | |||||
| showCancel: false, | |||||
| confirmText: '我知道了' | |||||
| }) | |||||
| } | |||||
| } | |||||
| } | |||||
| </script> | |||||
| <style scoped> | |||||
| .u-page { | |||||
| background: linear-gradient(180deg, #1EC77A 0%, #f5f5f5 30%); | |||||
| min-height: 100vh; | |||||
| } | |||||
| .member-header { | |||||
| padding: 40rpx 30rpx; | |||||
| } | |||||
| .member-card { | |||||
| background: rgba(255, 255, 255, 0.15); | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx; | |||||
| backdrop-filter: blur(10rpx); | |||||
| } | |||||
| .member-title { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| margin-bottom: 20rpx; | |||||
| } | |||||
| .title-text { | |||||
| font-size: 40rpx; | |||||
| font-weight: bold; | |||||
| color: white; | |||||
| margin-left: 20rpx; | |||||
| } | |||||
| .member-desc { | |||||
| font-size: 28rpx; | |||||
| color: rgba(255, 255, 255, 0.8); | |||||
| } | |||||
| .rights-section, .package-section { | |||||
| margin: 30rpx; | |||||
| background: white; | |||||
| border-radius: 20rpx; | |||||
| padding: 40rpx 30rpx; | |||||
| } | |||||
| .section-title { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 30rpx; | |||||
| } | |||||
| .rights-list { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| gap: 30rpx; | |||||
| } | |||||
| .right-item { | |||||
| display: flex; | |||||
| align-items: center; | |||||
| } | |||||
| .right-icon { | |||||
| margin-right: 20rpx; | |||||
| } | |||||
| .right-content { | |||||
| flex: 1; | |||||
| } | |||||
| .right-title { | |||||
| display: block; | |||||
| font-size: 28rpx; | |||||
| font-weight: bold; | |||||
| color: #333; | |||||
| margin-bottom: 8rpx; | |||||
| } | |||||
| .right-desc { | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| } | |||||
| .price-card { | |||||
| text-align: center; | |||||
| background: linear-gradient(135deg, #1EC77A 0%, #16A085 100%); | |||||
| border-radius: 20rpx; | |||||
| padding: 50rpx 30rpx; | |||||
| color: white; | |||||
| position: relative; | |||||
| overflow: hidden; | |||||
| } | |||||
| .price-card::before { | |||||
| content: ''; | |||||
| position: absolute; | |||||
| top: -50rpx; | |||||
| right: -50rpx; | |||||
| width: 200rpx; | |||||
| height: 200rpx; | |||||
| background: rgba(255, 255, 255, 0.1); | |||||
| border-radius: 50%; | |||||
| } | |||||
| .price-header { | |||||
| margin-bottom: 30rpx; | |||||
| } | |||||
| .price-tag { | |||||
| display: flex; | |||||
| align-items: baseline; | |||||
| justify-content: center; | |||||
| margin-bottom: 10rpx; | |||||
| } | |||||
| .currency { | |||||
| font-size: 40rpx; | |||||
| font-weight: bold; | |||||
| } | |||||
| .price { | |||||
| font-size: 120rpx; | |||||
| font-weight: bold; | |||||
| line-height: 1; | |||||
| } | |||||
| .price-desc { | |||||
| font-size: 32rpx; | |||||
| font-weight: bold; | |||||
| opacity: 0.9; | |||||
| } | |||||
| .price-benefits { | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| gap: 15rpx; | |||||
| } | |||||
| .benefit-text { | |||||
| font-size: 26rpx; | |||||
| opacity: 0.9; | |||||
| text-align: left; | |||||
| } | |||||
| .action-section { | |||||
| padding: 30rpx; | |||||
| } | |||||
| .agreement { | |||||
| text-align: center; | |||||
| margin-top: 20rpx; | |||||
| font-size: 24rpx; | |||||
| color: #666; | |||||
| } | |||||
| .link { | |||||
| color: #1EC77A; | |||||
| } | |||||
| </style> | |||||
| @ -1,21 +0,0 @@ | |||||
| import { getConfig } from "@/common/api.js" | |||||
| export default { | |||||
| state: { | |||||
| }, | |||||
| getters: { | |||||
| }, | |||||
| mutations: { | |||||
| // 初始化配置 | |||||
| initConfig(state){ | |||||
| getConfig({}).then(response=>{ | |||||
| uni.setStorageSync('configList', response.result) | |||||
| }).catch(error=>{ | |||||
| }) | |||||
| }, | |||||
| }, | |||||
| actions: {} | |||||
| } | |||||
| @ -1,53 +0,0 @@ | |||||
| import { getInfo } from "@/common/api.js" | |||||
| export default { | |||||
| state: { | |||||
| token:"", | |||||
| userInfo : {}, //用户信息 | |||||
| }, | |||||
| mutations: { | |||||
| onAuth(state){ | |||||
| }, | |||||
| setUserInfo(state,obj){ | |||||
| state.userInfo = obj.userInfo | |||||
| state.token = obj.token | |||||
| }, | |||||
| getUserInfo(state){ | |||||
| if(!uni.getStorageSync('token')){ | |||||
| return | |||||
| } | |||||
| getInfo({}).then(result=>{ | |||||
| if(result.result.nickName){ | |||||
| state.userInfo = result.result | |||||
| }else{ | |||||
| uni.navigateTo({ | |||||
| url:"/pages/login/index" | |||||
| }) | |||||
| } | |||||
| }) | |||||
| }, | |||||
| logout(state){ | |||||
| uni.showModal({ | |||||
| title: '确认退出登录吗', | |||||
| success(r) { | |||||
| if(r.confirm){ | |||||
| state.userInfo = {} | |||||
| state.token = "" | |||||
| uni.removeStorageSync('token') | |||||
| uni.redirectTo({ | |||||
| url: '/pages/index/index' | |||||
| }) | |||||
| } | |||||
| } | |||||
| }) | |||||
| }, | |||||
| }, | |||||
| actions: {} | |||||
| } | |||||