租房小程序前端代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

449 lines
15 KiB

  1. <template>
  2. <view class="container">
  3. <view class="header">
  4. <view class="title">经营性建设用地录入</view>
  5. </view>
  6. <view class="form-container">
  7. <uv-form labelPosition="left" :model="form" :rules="rules" ref="form" labelWidth="80" labelStyle="font-size:28rpx;">
  8. <!-- 必填项 -->
  9. <view class="section-title">基本信息必填</view>
  10. <!-- 1. 出租/出让 -->
  11. <uv-form-item label="类型" prop="type" required>
  12. <uv-radio-group v-model="form.type" placement="row">
  13. <uv-radio name="rent" label="出租"></uv-radio>
  14. <uv-radio name="transfer" customStyle="margin-left:30rpx;" label="出让"></uv-radio>
  15. </uv-radio-group>
  16. </uv-form-item>
  17. <!-- 2. 地址 -->
  18. <uv-form-item label="地址" prop="address" required @click="handleAddressSelect()">
  19. <uv-input v-model="form.address" @click="handleAddressSelect()" disabled disabledColor="#ffffff" placeholder="请选择地块位置" border="none">
  20. </uv-input>
  21. <template v-slot:right>
  22. <uv-icon name="arrow-right"></uv-icon>
  23. </template>
  24. </uv-form-item>
  25. <!-- 3. 联系人和电话 -->
  26. <uv-form-item label="联系人" prop="contactName" required>
  27. <uv-input v-model="form.contactName" type="text" placeholder="请输入联系人姓名" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input>
  28. </uv-form-item>
  29. <uv-form-item label="联系电话" prop="contactPhone" required>
  30. <uv-input v-model="form.contactPhone" type="number" placeholder="请输入联系电话" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input>
  31. </uv-form-item>
  32. <!-- 4. 产权证照片 -->
  33. <uv-form-item label="产权证照片" labelWidth="250" prop="propertyImages" labelPosition="top" required>
  34. <view class="upload-tip">请上传房产证土地证或不动产权证照片</view>
  35. <uv-upload customStyle="margin-top:20rpx;" :fileList="form.propertyImages" @afterRead="afterPropertyRead" @delete="deletePropertyPic" name="1"
  36. multiple :maxCount="5"></uv-upload>
  37. </uv-form-item>
  38. <!-- 5. 土地面积 -->
  39. <uv-form-item label="土地面积" prop="landArea" required>
  40. <view class="input-with-unit">
  41. <uv-input v-model="form.landArea" type="digit" placeholder="请输入土地面积" customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:5px 10px;"></uv-input>
  42. <text class="unit"></text>
  43. </view>
  44. <view class="input-tip">请录入土地使用证或不动产权证面积仅输入数字</view>
  45. </uv-form-item>
  46. <!-- 6. 地块视频 -->
  47. <uv-form-item label="地块视频" labelWidth="250" prop="videos" labelPosition="top" required>
  48. <view class="upload-tip">请上传地块视频1分钟内</view>
  49. <uv-upload customStyle="margin-top:20rpx;" accept="video" :fileList="form.videos" @afterRead="afterVideoRead" @delete="deleteVideoPic" name="1"
  50. multiple :maxCount="2"></uv-upload>
  51. </uv-form-item>
  52. <!-- 7. 价格 -->
  53. <uv-form-item label="价格" prop="price" required>
  54. <view class="price-container">
  55. <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>
  56. <text class="price-unit" v-if="form.type === 'rent'">//</text>
  57. <text class="price-unit" v-else-if="form.type === 'transfer'">万元/</text>
  58. <text class="price-unit" v-else></text>
  59. </view>
  60. <view class="input-tip">请输入数字支持小数点后两位</view>
  61. </uv-form-item>
  62. <!-- 分类标识 -->
  63. <uv-form-item label="分类标识" prop="classId" @click="handleClass()">
  64. <uv-input v-model="form.className" @click="handleClass()" disabled disabledColor="#ffffff" placeholder="选择分类标识" border="none">
  65. </uv-input>
  66. <template v-slot:right>
  67. <uv-icon name="arrow-right"></uv-icon>
  68. </template>
  69. </uv-form-item>
  70. <!-- 选填项 -->
  71. <view class="section-title">详细信息选填</view>
  72. <!-- 8. 地块介绍 -->
  73. <uv-form-item label="地块介绍" prop="description" labelPosition="top">
  74. <uv-input
  75. v-model="form.description"
  76. type="textarea"
  77. placeholder="请详细介绍地块情况、用途规划、周边环境等"
  78. customStyle="border-radius: 5px;margin-top:5px;background-color: #f5f5f5;padding:10px;"
  79. :autoHeight="true"
  80. :maxlength="500"
  81. ></uv-input>
  82. </uv-form-item>
  83. <uv-form-item>
  84. <uv-button type="primary" text="提交信息" customStyle="margin-top: 30px;background-color: #1EC77A;border-radius: 30px;" @click="submit"></uv-button>
  85. </uv-form-item>
  86. </uv-form>
  87. </view>
  88. <!-- 分类选择器 -->
  89. <uv-picker ref="picker" :columns="columns" @confirm="confirm"></uv-picker>
  90. </view>
  91. </template>
  92. <script>
  93. import { saveOrUpdateHouse, houseType } from "@/common/api.js"
  94. export default {
  95. data() {
  96. return {
  97. commonClass: '', // 所属分类ID
  98. form: {
  99. type: '', // 出租/出让
  100. address: '', // 地址
  101. contactName: '', // 联系人
  102. contactPhone: '', // 联系电话
  103. propertyImages: [], // 产权证照片
  104. landArea: '', // 土地面积
  105. videos: [], // 地块视频
  106. price: '', // 价格
  107. description: '', // 地块介绍
  108. longitude: '', // 经度
  109. latitude: '', // 纬度
  110. classId: '', // 分类标识
  111. className: '' // 分类名称
  112. },
  113. columns: [], // 分类选择器数据
  114. houseTypeList: [], // 分类列表
  115. rules: {
  116. type: [
  117. { required: true, message: '请选择出租或出让', trigger: ['blur', 'change'] }
  118. ],
  119. address: [
  120. { required: true, message: '请选择地块地址', trigger: ['blur', 'change'] }
  121. ],
  122. contactName: [
  123. { required: true, message: '请输入联系人姓名', trigger: ['blur', 'change'] }
  124. ],
  125. contactPhone: [
  126. { required: true, message: '请输入联系电话', trigger: ['blur', 'change'] },
  127. { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: ['blur', 'change'] }
  128. ],
  129. landArea: [
  130. { required: true, message: '请输入土地面积', trigger: ['blur', 'change'] },
  131. { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的数字格式', trigger: ['blur', 'change'] }
  132. ],
  133. price: [
  134. { required: true, message: '请输入价格', trigger: ['blur', 'change'] },
  135. { pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的价格格式', trigger: ['blur', 'change'] }
  136. ],
  137. classId: [
  138. { required: true, message: '请选择分类标识', trigger: ['blur', 'change'] }
  139. ]
  140. }
  141. }
  142. },
  143. onReady() {
  144. this.$refs.form.setRules(this.rules)
  145. },
  146. onLoad(options) {
  147. // 设置页面标题
  148. uni.setNavigationBarTitle({
  149. title: '经营性建设用地录入'
  150. })
  151. // 接收传递的commonClass参数
  152. if(options.commonClass) {
  153. this.commonClass = options.commonClass
  154. }
  155. // 如果是编辑模式,设置classId用于回显
  156. if(options.classId) {
  157. this.form.classId = options.classId
  158. }
  159. // 初始化分类数据
  160. this.onHouseType()
  161. },
  162. methods: {
  163. // 获取分类数据
  164. onHouseType(){
  165. let that = this
  166. houseType({}).then(response=>{
  167. let arr=[]
  168. that.houseTypeList = response.result
  169. response.result.forEach(items=>{
  170. arr.push(items.title)
  171. // 数据回显:如果当前classId匹配,设置className
  172. if(items.id == that.form.classId){
  173. that.form.className = items.title
  174. }
  175. })
  176. that.columns[0]=arr
  177. }).catch(error=>{
  178. })
  179. },
  180. // 地址选择
  181. handleAddressSelect() {
  182. const that = this;
  183. wx.chooseLocation({
  184. success: function (res) {
  185. console.log('选择的位置:', res);
  186. that.form.longitude = res.longitude
  187. that.form.latitude = res.latitude
  188. that.form.address = res.address
  189. }
  190. })
  191. },
  192. // 分类选择
  193. handleClass() {
  194. this.$refs.picker.open();
  195. },
  196. confirm(e) {
  197. let that = this
  198. let {indexs,value,values} = e
  199. that.form.classId = that.houseTypeList[indexs[0]].id;
  200. that.form.className = that.houseTypeList[indexs[0]].title;
  201. },
  202. // 产权证照片上传
  203. async afterPropertyRead(e) {
  204. let self = this
  205. e.file.forEach(file => {
  206. self.$Oss.ossUpload(file.url).then(url => {
  207. self.form.propertyImages.push({
  208. url
  209. })
  210. })
  211. })
  212. },
  213. deletePropertyPic(event) {
  214. this.form.propertyImages.splice(event.index, 1)
  215. },
  216. // 视频上传
  217. async afterVideoRead(e) {
  218. let self = this
  219. e.file.forEach(file => {
  220. self.$Oss.ossUpload(file.url).then(url => {
  221. self.form.videos.push({
  222. url
  223. })
  224. })
  225. })
  226. },
  227. deleteVideoPic(event) {
  228. this.form.videos.splice(event.index, 1)
  229. },
  230. // 提交表单
  231. submit() {
  232. this.$refs.form.validate().then(res => {
  233. // 验证必填的图片和视频
  234. if (this.form.propertyImages.length === 0) {
  235. uni.showToast({
  236. title: '请上传产权证照片',
  237. icon: 'none'
  238. });
  239. return;
  240. }
  241. if (this.form.videos.length === 0) {
  242. uni.showToast({
  243. title: '请上传地块视频',
  244. icon: 'none'
  245. });
  246. return;
  247. }
  248. // 构建与index.vue兼容的提交参数
  249. const params = {
  250. userId: uni.getStorageSync('userInfo')?.id || "",
  251. id: "", // 新增数据,无ID
  252. classId: this.form.classId, // 使用固定分类标识
  253. commonClass: this.commonClass, // 所属分类
  254. address: this.form.address, // 地址
  255. homeAge: "", // 户主年龄 - 经营性用地无此字段
  256. homeAz: "", // 是否经过安置 - 默认否
  257. homeBian: "", // 房屋周边 - 经营性用地无此字段
  258. homeBjsx: "", // 报建手续 - 经营性用地无此字段
  259. homeCai: "", // 菜地 - 经营性用地无此字段
  260. homeCat: "", // 停车 - 经营性用地无此字段
  261. homeGz: "", // 房屋主体是否改造 - 默认否
  262. homeHb: "", // 房屋朝向及海拔 - 经营性用地无此字段
  263. homeBz: this.form.description, // 备注 - 使用地块介绍
  264. homeJg: "经营性建设用地", // 房屋结构 - 使用固定值
  265. homeJl: "", // 距离场镇距离 - 经营性用地无此字段
  266. homeJt: "", // 交通 - 经营性用地无此字段
  267. homeJtzy: "", // 户主家庭职业 - 经营性用地无此字段
  268. homeMi: this.form.landArea, // 面积 - 使用土地面积
  269. homeMj: this.form.landArea, // 房屋面积 - 使用土地面积
  270. homeMoney: "", // 佣金 - 经营性用地无此字段
  271. homeNo: "", // 房屋编号 - 经营性用地无此字段
  272. homeNum: "", // 房间数量 - 经营性用地无此字段
  273. homePay: "", // 付款方式及押金 - 经营性用地无此字段
  274. homePj: "", // 邻居对房东评价 - 经营性用地无此字段
  275. homeSd: "", // 水电气网 - 经营性用地无此字段
  276. homeShjl: "", // 距离成都西三环 - 经营性用地无此字段
  277. homeSw: "", // 非正常死亡 - 默认无
  278. homeTf: "", // 府市民云房屋信息档案查询 - 经营性用地无此字段
  279. homeTime: "", // 租期 - 经营性用地无此字段
  280. homeType: this.form.type === 'rent' ? '出租' : '出让', // 户型 - 使用类型
  281. homeYs: "", // 钥匙 - 默认无
  282. homeYzmj: this.form.landArea, // 院子总面积 - 使用土地面积
  283. homeZy: "", // 坟包及电塔 工厂噪音 - 经营性用地无此字段
  284. iconName: "经营性建设用地", // 热点名称
  285. iconTitle: "经营性用地", // 标签
  286. num: "0", // 浏览量 - 默认0
  287. price: this.form.price, // 价格
  288. timeGo: "", // 年限 - 经营性用地无此字段
  289. title: `${this.form.type === 'rent' ? '出租' : '出让'}-经营性建设用地-${this.form.address.split('市')[1] || this.form.address}`, // 标题 - 自动生成
  290. unit: this.form.type === 'rent' ? '元/亩/年' : '万元/亩', // 单位
  291. image: "", // 图片 - 经营性用地无房屋照片
  292. iconImage: "", // 左上角图标
  293. homeImage: this.form.propertyImages.map(item => item.url).join(','), // 产权证照片
  294. homeMp4: this.form.videos.map(item => item.url).join(','), // 视频
  295. latitude: this.form.latitude,
  296. longitude: this.form.longitude,
  297. // 新增字段用于标识经营性用地
  298. category: 'commercial',
  299. contactName: this.form.contactName,
  300. contactPhone: this.form.contactPhone
  301. };
  302. console.log('经营性用地提交参数:', params);
  303. uni.showLoading({
  304. title: '提交中...'
  305. });
  306. // 调用统一API
  307. saveOrUpdateHouse(params).then(response => {
  308. uni.hideLoading();
  309. uni.showToast({
  310. title: response.message || '提交成功',
  311. icon: 'success'
  312. });
  313. setTimeout(() => {
  314. uni.redirectTo({
  315. url: "/pages_subpack/successful-apply/index"
  316. });
  317. }, 2000);
  318. }).catch(error => {
  319. uni.hideLoading();
  320. uni.showToast({
  321. title: error.message || '提交失败',
  322. icon: 'none'
  323. });
  324. console.error('经营性用地提交失败:', error);
  325. });
  326. }).catch(errors => {
  327. console.log('表单验证失败:', errors);
  328. uni.showToast({
  329. title: '请补全必填项',
  330. icon: 'none'
  331. });
  332. });
  333. }
  334. }
  335. }
  336. </script>
  337. <style scoped>
  338. .container {
  339. min-height: 100vh;
  340. background-color: #f5f5f5;
  341. }
  342. .header {
  343. background: linear-gradient(135deg, #1EC77A 0%, #4CAF50 100%);
  344. padding: 40rpx 40rpx 60rpx;
  345. color: white;
  346. }
  347. .title {
  348. font-size: 36rpx;
  349. font-weight: bold;
  350. text-align: center;
  351. }
  352. .form-container {
  353. background: white;
  354. margin: -30rpx 20rpx 20rpx;
  355. border-radius: 20rpx;
  356. padding: 40rpx;
  357. box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.1);
  358. }
  359. .section-title {
  360. font-size: 32rpx;
  361. font-weight: bold;
  362. color: #333;
  363. margin: 40rpx 0 30rpx;
  364. padding-left: 20rpx;
  365. border-left: 6rpx solid #1EC77A;
  366. }
  367. .section-title:first-child {
  368. margin-top: 0;
  369. }
  370. .input-with-unit {
  371. display: flex;
  372. align-items: center;
  373. gap: 10rpx;
  374. }
  375. .unit {
  376. font-size: 26rpx;
  377. color: #666;
  378. margin-left: 10rpx;
  379. }
  380. .input-tip {
  381. font-size: 22rpx;
  382. color: #999;
  383. margin-top: 10rpx;
  384. line-height: 1.4;
  385. }
  386. .upload-tip {
  387. font-size: 24rpx;
  388. color: #666;
  389. margin-bottom: 10rpx;
  390. line-height: 1.5;
  391. }
  392. .price-container {
  393. display: flex;
  394. align-items: center;
  395. gap: 10rpx;
  396. }
  397. .price-unit {
  398. font-size: 26rpx;
  399. color: #FF6B35;
  400. font-weight: bold;
  401. margin-left: 10rpx;
  402. }
  403. </style>