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 { | |||
| // baseUrl : 'http://127.0.0.1:8000', | |||
| // 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:'https://houserent-admin.hhlm1688.com' | |||
| // 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: {} | |||
| } | |||