Browse Source

no message

xiaoxin 2 năm trước cách đây
mục cha
commit
61aa5234de
38 tập tin đã thay đổi với 5394 bổ sung368 xóa
  1. 40 1
      pages.json
  2. 177 11
      pages/affirmOrder/affirmOrder.vue
  3. 53 28
      pages/collect/collect.vue
  4. 259 0
      pages/complaint/complaint.vue
  5. 86 0
      pages/complaintStatus/complaintStatus.vue
  6. 46 27
      pages/couponCenter/couponCenter.vue
  7. 375 4
      pages/detail/detail.vue
  8. 31 12
      pages/detailInfo/detailInfo.vue
  9. 444 0
      pages/evaluate/evaluate.vue
  10. 276 0
      pages/evaluateStatus/evaluateStatus.vue
  11. 38 15
      pages/home/home.vue
  12. 998 0
      pages/home3/home3.vue
  13. 5 5
      pages/my/my.vue
  14. 72 53
      pages/myComplaint/myComplaint.vue
  15. 73 54
      pages/myCoupon/myCoupon.vue
  16. 96 42
      pages/myEvaluate/myEvaluate.vue
  17. 96 44
      pages/orderDetail/orderDetail.vue
  18. 80 29
      pages/orderManage/orderManage.vue
  19. 100 43
      pages/push/push.vue
  20. 174 0
      pages/strategyDetatil/strategyDetatil.vue
  21. BIN
      static/index/1.png
  22. BIN
      static/index/2.png
  23. BIN
      static/index/close2.png
  24. BIN
      static/index/coupon.png
  25. BIN
      static/index/hotel2.png
  26. BIN
      static/index/left2.png
  27. BIN
      static/index/photo.png
  28. BIN
      static/index/star.png
  29. BIN
      static/my/headerImg.png
  30. 67 0
      uni_modules/uni-file-picker/changelog.md
  31. 224 0
      uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js
  32. 667 0
      uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue
  33. 325 0
      uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
  34. 292 0
      uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue
  35. 109 0
      uni_modules/uni-file-picker/components/uni-file-picker/utils.js
  36. 83 0
      uni_modules/uni-file-picker/package.json
  37. 11 0
      uni_modules/uni-file-picker/readme.md
  38. 97 0
      util/imageCompress.js

+ 40 - 1
pages.json

@@ -1,6 +1,14 @@
 {
 {
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
 	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
 		{
 		{
+			"path": "pages/home3/home3",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		},
+		{
 			"path": "pages/home/home",
 			"path": "pages/home/home",
 			"style": {
 			"style": {
 				"navigationBarTitleText": "靖安人家乡村民宿",
 				"navigationBarTitleText": "靖安人家乡村民宿",
@@ -202,6 +210,37 @@
 				"navigationBarTitleText": "进度详情",
 				"navigationBarTitleText": "进度详情",
 				"enablePullDownRefresh": false
 				"enablePullDownRefresh": false
 			}
 			}
+		}, {
+			"path": "pages/evaluate/evaluate",
+			"style": {
+				"navigationBarTitleText": "评价",
+				"enablePullDownRefresh": false,
+				"navigationStyle": "custom"
+			}
+		}, {
+			"path": "pages/evaluateStatus/evaluateStatus",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
+		}, {
+			"path": "pages/strategyDetatil/strategyDetatil",
+			"style": {
+				"navigationBarTitleText": "攻略详情",
+				"enablePullDownRefresh": false
+			}
+		}, {
+			"path": "pages/complaint/complaint",
+			"style": {
+				"navigationBarTitleText": "我要投诉",
+				"enablePullDownRefresh": false
+			}
+		}, {
+			"path": "pages/complaintStatus/complaintStatus",
+			"style": {
+				"navigationBarTitleText": "",
+				"enablePullDownRefresh": false
+			}
 		}
 		}
 	],
 	],
 	"tabBar": {
 	"tabBar": {
@@ -210,7 +249,7 @@
 		"borderStyle": "black",
 		"borderStyle": "black",
 		"backgroundColor": "#ffffff",
 		"backgroundColor": "#ffffff",
 		"list": [{
 		"list": [{
-				"pagePath": "pages/home/home",
+				"pagePath": "pages/home3/home3",
 				"iconPath": "static/images/index.png",
 				"iconPath": "static/images/index.png",
 				"selectedIconPath": "static/images/index-active.png",
 				"selectedIconPath": "static/images/index-active.png",
 				"text": "首页"
 				"text": "首页"

+ 177 - 11
pages/affirmOrder/affirmOrder.vue

@@ -2,12 +2,12 @@
 	<view class="container">
 	<view class="container">
 		<!-- 导航栏图片区域 -->
 		<!-- 导航栏图片区域 -->
 		<view class="header">
 		<view class="header">
-			<img src="../../static/my/headerImg.png" />
+			<img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
 
 
 			<!-- 标题区域 -->
 			<!-- 标题区域 -->
-			<view class="header_title">{{ hotelName }}</view>
+			<view class="header_title" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">{{ hotelName }}</view>
 			<!-- 返回图标区域 -->
 			<!-- 返回图标区域 -->
-			<view class="header_icon" @click="handleBack">
+			<view class="header_icon" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }" @click="handleBack">
 				<img src="../../static/index/left.png" />
 				<img src="../../static/index/left.png" />
 			</view>
 			</view>
 		</view>
 		</view>
@@ -79,7 +79,22 @@
 				></uv-datetime-picker>
 				></uv-datetime-picker>
 			</view>
 			</view>
 
 
-			<!-- 费用信息区域 -->
+			<!-- 本单可享区域 -->
+			<view class="coupon" v-if="couponNum">
+				<view class="coupon_title">本单可享</view>
+				<view class="coupon_box">
+					<view class="box_key">
+						<img src="../../static/index/coupon.png" />
+						优惠券
+					</view>
+					<view class="box_value" @click="handleGoPage">
+						<view class="value_count">{{ couponNum }}张可用</view>
+						<img src="../../static/index/right2.png" />
+					</view>
+				</view>
+			</view>
+
+			<!-- 费用明细区域 -->
 			<view class="price">
 			<view class="price">
 				<view class="price_title">费用明细</view>
 				<view class="price_title">费用明细</view>
 				<view class="price_box">
 				<view class="price_box">
@@ -92,6 +107,7 @@
 				</view>
 				</view>
 			</view>
 			</view>
 
 
+			<!-- 房费区域 -->
 			<view class="all">
 			<view class="all">
 				<view class="all_title">
 				<view class="all_title">
 					<text>房费</text>
 					<text>房费</text>
@@ -105,6 +121,21 @@
 					<view class="box_total">{{ roomCount }}间 x {{ info.nightNum }}晚 x ¥{{ info.item.price }}</view>
 					<view class="box_total">{{ roomCount }}间 x {{ info.nightNum }}晚 x ¥{{ info.item.price }}</view>
 				</view>
 				</view>
 			</view>
 			</view>
+
+			<!-- 优惠区域 -->
+			<view class="sale" v-if="couponNum">
+				<view class="sale_top">
+					<view class="top_key">优惠</view>
+					<view class="top_value">- ¥70</view>
+				</view>
+				<view class="sale_bottom">
+					<view class="bottom_key">
+						<img src="../../static/index/coupon.png" />
+						折扣卷
+					</view>
+					<view class="bottom_value">- ¥70</view>
+				</view>
+			</view>
 		</view>
 		</view>
 
 
 		<!-- 底部提交订单区域 -->
 		<!-- 底部提交订单区域 -->
@@ -134,9 +165,27 @@ export default {
 			// 当前时间
 			// 当前时间
 			timeValue: Number(new Date()),
 			timeValue: Number(new Date()),
 			// 民宿名称
 			// 民宿名称
-			hotelName: ''
+			hotelName: '',
+			// 状态栏高度
+			statusBarH: 0,
+			// 胶囊按钮栏高度
+			customBarH: 0,
+			// 优惠券数量
+			couponNum: 0
 		}
 		}
 	},
 	},
+	created() {
+		// 获取系统信息
+		uni.getSystemInfo({
+			success: (e) => {
+				// 获取状态栏高度
+				this.statusBarH = e.statusBarHeight + 10
+				// // 获取菜单按钮栏高度
+				let custom = uni.getMenuButtonBoundingClientRect()
+				this.customBarH = custom.height + 10
+			}
+		})
+	},
 	onLoad(options) {
 	onLoad(options) {
 		this.info = JSON.parse(options.info)
 		this.info = JSON.parse(options.info)
 		this.hotelName = this.info.hotelName
 		this.hotelName = this.info.hotelName
@@ -253,6 +302,11 @@ export default {
 		},
 		},
 		handleBack() {
 		handleBack() {
 			uni.navigateBack(1)
 			uni.navigateBack(1)
+		},
+		handleGoPage() {
+			uni.navigateTo({
+				url: '/pages/coupon/coupon'
+			})
 		}
 		}
 	}
 	}
 }
 }
@@ -269,7 +323,7 @@ export default {
 
 
 	.header {
 	.header {
 		position: relative;
 		position: relative;
-		height: 145rpx;
+		height: 180rpx;
 		overflow: hidden;
 		overflow: hidden;
 
 
 		img {
 		img {
@@ -278,7 +332,7 @@ export default {
 
 
 		.header_title {
 		.header_title {
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 182rpx;
 			left: 182rpx;
 			width: 50%;
 			width: 50%;
 			color: #fff;
 			color: #fff;
@@ -291,7 +345,7 @@ export default {
 
 
 		.header_icon {
 		.header_icon {
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 5rpx;
 			left: 5rpx;
 			width: 47rpx;
 			width: 47rpx;
 			height: 70rpx;
 			height: 70rpx;
@@ -304,7 +358,7 @@ export default {
 	}
 	}
 
 
 	.body {
 	.body {
-		height: calc(100vh - 271rpx);
+		height: calc(100vh - 306rpx);
 		overflow-y: auto;
 		overflow-y: auto;
 
 
 		.info {
 		.info {
@@ -458,6 +512,65 @@ export default {
 			}
 			}
 		}
 		}
 
 
+		.coupon {
+			box-sizing: border-box;
+			padding-left: 26rpx;
+			margin: 20rpx auto 0;
+			width: 710rpx;
+			height: 197rpx;
+			border-radius: 15rpx;
+			background-color: #fff;
+
+			.coupon_title {
+				line-height: 92rpx;
+				font-size: 28rpx;
+				font-weight: bold;
+				border-bottom: 1rpx solid #e6e6e6;
+			}
+
+			.coupon_box {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				height: 105rpx;
+
+				.box_key {
+					display: flex;
+					align-items: center;
+					font-size: 28rpx;
+
+					img {
+						margin-right: 10rpx;
+						width: 40rpx;
+						height: 40rpx;
+					}
+				}
+
+				.box_value {
+					display: flex;
+					align-items: center;
+
+					.value_count {
+						display: flex;
+						justify-content: center;
+						align-items: center;
+						width: 105rpx;
+						height: 45rpx;
+						color: #fff;
+						font-size: 24rpx;
+						border-radius: 7rpx;
+						background-color: #ff5733;
+					}
+
+					img {
+						margin-right: 17rpx;
+						width: 40rpx;
+						height: 40rpx;
+					}
+				}
+			}
+		}
+
 		.price {
 		.price {
 			box-sizing: border-box;
 			box-sizing: border-box;
 			padding-left: 26rpx;
 			padding-left: 26rpx;
@@ -505,7 +618,7 @@ export default {
 		.all {
 		.all {
 			box-sizing: border-box;
 			box-sizing: border-box;
 			padding-left: 26rpx;
 			padding-left: 26rpx;
-			margin: 0 auto 60rpx;
+			margin: 0 auto 20rpx;
 			width: 710rpx;
 			width: 710rpx;
 			border-radius: 15rpx;
 			border-radius: 15rpx;
 			background-color: #fff;
 			background-color: #fff;
@@ -547,6 +660,59 @@ export default {
 				}
 				}
 			}
 			}
 		}
 		}
+
+		.sale {
+			margin: 0 auto 20rpx;
+			box-sizing: border-box;
+			padding: 0 30rpx;
+			width: 710rpx;
+			height: 209rpx;
+			border-radius: 15rpx;
+			background-color: #fff;
+
+			.sale_top {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				height: 92rpx;
+				font-size: 28rpx;
+				font-weight: bold;
+
+				.top_key {
+				}
+
+				.top_value {
+					color: #ff5733;
+				}
+			}
+
+			.sale_bottom {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				box-sizing: border-box;
+				padding: 0 26rpx;
+				width: 650rpx;
+				height: 80rpx;
+				font-size: 24rpx;
+				border-radius: 7rpx;
+				background-color: #f2f2f2;
+
+				.bottom_key {
+					display: flex;
+					align-items: center;
+
+					img {
+						margin-right: 10rpx;
+						width: 34rpx;
+						height: 34rpx;
+					}
+				}
+
+				.bottom_value {
+				}
+			}
+		}
 	}
 	}
 
 
 	.foot {
 	.foot {
@@ -585,4 +751,4 @@ export default {
 		}
 		}
 	}
 	}
 }
 }
-</style>
+</style>

+ 53 - 28
pages/collect/collect.vue

@@ -27,6 +27,11 @@
 					<view class="price_msg">起</view>
 					<view class="price_msg">起</view>
 				</view>
 				</view>
 			</view>
 			</view>
+
+			<view class="noData" v-if="list.length === 0">
+				<img lazy-load :lazy-load-margin="0" src="../../static/images/noData.png" />
+				{{ noDataMsg }}
+			</view>
 		</scroll-view>
 		</scroll-view>
 	</view>
 	</view>
 </template>
 </template>
@@ -41,34 +46,35 @@ export default {
 			headerList: ['收藏', '住过'],
 			headerList: ['收藏', '住过'],
 			// 列表数据
 			// 列表数据
 			list: [
 			list: [
-				{
-					id: 1,
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '民宿名称',
-					rate: '5.0',
-					town: '宝峰镇',
-					price: 748,
-					msg: '超棒'
-				},
-				{
-					id: 2,
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '开心民宿',
-					rate: '5.0',
-					town: '木叶村',
-					price: 999,
-					msg: '超棒'
-				},
-				{
-					id: 3,
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '快乐民宿',
-					rate: '5.0',
-					town: '砂隐村',
-					price: 888,
-					msg: '超棒'
-				}
-			]
+				// {
+				// 	id: 1,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '民宿名称',
+				// 	rate: '5.0',
+				// 	town: '宝峰镇',
+				// 	price: 748,
+				// 	msg: '超棒'
+				// },
+				// {
+				// 	id: 2,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '开心民宿',
+				// 	rate: '5.0',
+				// 	town: '木叶村',
+				// 	price: 999,
+				// 	msg: '超棒'
+				// },
+				// {
+				// 	id: 3,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '快乐民宿',
+				// 	rate: '5.0',
+				// 	town: '砂隐村',
+				// 	price: 888,
+				// 	msg: '超棒'
+				// }
+			],
+			noDataMsg: '暂无收藏数据'
 		}
 		}
 	},
 	},
 	methods: {
 	methods: {
@@ -76,6 +82,11 @@ export default {
 		onClickItem(e) {
 		onClickItem(e) {
 			if (this.current !== e.currentIndex) {
 			if (this.current !== e.currentIndex) {
 				this.current = e.currentIndex
 				this.current = e.currentIndex
+				if (this.current === 0) {
+					this.noDataMsg = '暂无收藏数据'
+				} else {
+					this.noDataMsg = '暂无住过数据'
+				}
 			}
 			}
 		},
 		},
 		// 列表下拉到底部回调
 		// 列表下拉到底部回调
@@ -181,6 +192,20 @@ export default {
 				}
 				}
 			}
 			}
 		}
 		}
+
+		.noData {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			padding-bottom: 20rpx;
+
+			img {
+				margin-top: 160rpx;
+				width: 600rpx;
+				height: 600rpx;
+			}
+		}
 	}
 	}
 }
 }
 </style>
 </style>

+ 259 - 0
pages/complaint/complaint.vue

@@ -0,0 +1,259 @@
+<template>
+	<view class="container">
+		<!-- 标题区域 -->
+		<view class="title">
+			<view class="title_key">标题</view>
+			<view class="title_value">
+				<input maxlength="10" type="text" placeholder="请输入标题,不要超过10个字哦~" placeholder-style="color:#B3B3B3;fontSize:28rpx;" />
+			</view>
+		</view>
+
+		<!-- 评价上传图片视频区域 -->
+		<view class="operation">
+			<!-- 输入框区域 -->
+			<view class="operation_input">
+				<textarea
+					maxlength="1000"
+					class="textarea"
+					placeholder-style="color:#B3B3B3;font-size:24rpx"
+					placeholder="写出你的相关问题"
+					v-model="textareaValue"
+					@input="handleInput"
+				/>
+				<view class="operation_count">({{ textareaValuelength }}/1000)</view>
+			</view>
+
+			<!-- 上传区域 -->
+			<view class="operation_uploading">
+				<view class="uploading_box" @click="handleUpLoad">
+					<img class="img" src="../../static/index/photo.png" />
+					<view class="msg">照片/视频</view>
+				</view>
+				<view class="uploading_box" v-for="(ele, index) in subImgList" :key="index">
+					<img class="img2" mode="aspectFill" :src="ele" />
+					<view class="icon" @click="handleDelete(index)">
+						<img src="../../static/index/close2.png" />
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 提交按钮区域 -->
+		<view class="btn" @click="handleSub">提交</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			// 评价绑定数据
+			textareaValue: '',
+			// 评价文字长度
+			textareaValuelength: 0,
+			// 上传的图片数据
+			subImgList: []
+		}
+	},
+	methods: {
+		// 评价输入框输入回调
+		handleInput(e) {
+			this.textareaValuelength = e.detail.cursor
+		},
+		handleUpLoad() {
+			uni.chooseMedia({
+				count: 9,
+				maxDuration: 15,
+				success: (res) => {
+					console.log(res)
+					console.log(res.tempFiles)
+					if (this.subImgList.length + res.tempFiles.length > 9) {
+						uni.showToast({
+							title: '最多只能上传9个图片/视频',
+							icon: 'none'
+						})
+						return
+					}
+					uni.showLoading({
+						title: '上传中'
+					})
+					// reverse()
+					res.tempFiles.forEach((ele) => {
+						uni.uploadFile({
+							url: `https://chtech.ncjti.edu.cn/hotelReservation/mhotel/mhotel/uploadhimage.action`,
+							filePath: ele.tempFilePath,
+							name: 'myFile',
+							success: (uploadFileRes) => {
+								console.log(JSON.parse(uploadFileRes.data))
+								let temRes = JSON.parse(uploadFileRes.data)
+								if (temRes.code === 200) {
+									this.subImgList.push(temRes.data.url)
+									console.log(this.subImgList)
+									uni.hideLoading()
+								} else {
+									uni.showToast({
+										title: temRes.message,
+										icon: 'none'
+									})
+								}
+							},
+							fail: () => {
+								uni.showToast({
+									title: '上传失败',
+									icon: 'error'
+								})
+							}
+						})
+					})
+				}
+			})
+		},
+		handleSub() {
+			uni.navigateTo({
+				url: `/pages/complaintStatus/complaintStatus?status=1`
+			})
+		},
+		// 删除图片回调
+		handleDelete(index) {
+			this.subImgList.splice(index, 1)
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	display: flex;
+	flex-direction: column;
+	min-height: 100vh;
+	background-color: #f2f3f5;
+
+	.title {
+		display: flex;
+		align-items: center;
+		margin: 20rpx 0;
+		padding: 0 20rpx;
+		height: 144rpx;
+		background-color: #fff;
+
+		.title_key {
+			font-size: 28rpx;
+			font-weight: bold;
+		}
+
+		.title_value {
+			display: flex;
+			align-items: center;
+			box-sizing: border-box;
+			padding: 0 26rpx;
+			margin-left: 30rpx;
+			width: 625rpx;
+			height: 80rpx;
+			border-radius: 11rpx;
+			background-color: #f2f2f2;
+
+			input {
+				width: 100%;
+			}
+		}
+	}
+
+	.operation {
+		padding: 20rpx 20rpx 33rpx;
+		margin-bottom: 20rpx;
+		background-color: #fff;
+
+		.operation_input {
+			box-sizing: border-box;
+			padding: 20rpx;
+			width: 710rpx;
+			height: 282rpx;
+			border-radius: 9rpx;
+			background-color: #f2f2f2;
+
+			.textarea {
+				width: 100%;
+				height: 203rpx;
+			}
+
+			.operation_count {
+				height: 39rpx;
+				text-align: end;
+				color: #b3b3b3;
+				font-size: 24rpx;
+			}
+		}
+
+		.operation_uploading {
+			display: grid;
+			gap: 21rpx;
+			grid-template-columns: repeat(auto-fill, 124rpx);
+			margin-top: 20rpx;
+
+			::v-deep .uni-file-picker__item {
+				background-color: red;
+			}
+
+			.uploading_box {
+				position: relative;
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
+				align-items: center;
+				width: 124rpx;
+				height: 124rpx;
+				border-radius: 7rpx;
+				background-color: #f2f2f2;
+
+				.img {
+					width: 40rpx;
+					height: 40rpx;
+				}
+
+				.msg {
+					margin-top: 5rpx;
+					color: #a6a6a6;
+					font-size: 20rpx;
+				}
+
+				.img2 {
+					width: 124rpx;
+					height: 124rpx;
+					border-radius: 7rpx;
+				}
+
+				.icon {
+					position: absolute;
+					top: 0;
+					right: 0;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					width: 30rpx;
+					height: 30rpx;
+					border-radius: 7rpx;
+					background-color: rgba(000, 000, 000, 0.5);
+
+					img {
+						width: 30rpx;
+						height: 30rpx;
+					}
+				}
+			}
+		}
+	}
+
+	.btn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin: 368rpx auto 78rpx;
+		width: 710rpx;
+		height: 96rpx;
+		color: #fff;
+		font-size: 32rpx;
+		border-radius: 64rpx;
+		background-color: #096562;
+	}
+}
+</style>

+ 86 - 0
pages/complaintStatus/complaintStatus.vue

@@ -0,0 +1,86 @@
+<template>
+	<view class="container">
+		<!-- 图标区域 -->
+		<img class="img" :src="status === '1' ? '../../static/index/success.png' : '../../static/index/fail.png'" />
+		<view class="msg">{{ msg }}</view>
+		<!-- 按钮区域 -->
+		<view class="btn" @click="handleClickBtn">{{ btnMsg }}</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			// 投诉是否成功
+			status: null,
+			// 投诉状态信息
+			msg: '',
+			// 按钮文字信息
+			btnMsg: ''
+		}
+	},
+	onLoad(options) {
+		this.status = options.status
+		if (this.status === '1') {
+			uni.setNavigationBarTitle({
+				title: '投诉成功'
+			})
+			this.msg = '投诉成功'
+			this.btnMsg = '查看投诉进度'
+		} else {
+			uni.setNavigationBarTitle({
+				title: '投诉失败'
+			})
+			this.msg = '投诉失败'
+			this.btnMsg = '返回'
+		}
+	},
+	methods: {
+		handleClickBtn() {
+			if (this.status === '1') {
+				uni.navigateTo({
+					url: '/pages/complaintProgress/complaintProgress'
+				})
+			} else {
+				uni.navigateBack(1)
+			}
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	min-height: 100vh;
+	background-color: #fff;
+
+	.img {
+		margin-top: 80rpx;
+		width: 134rpx;
+		height: 134rpx;
+	}
+
+	.msg {
+		margin-top: 40rpx;
+		font-size: 32rpx;
+		font-weight: bold;
+	}
+
+	.btn {
+		margin-top: 87rpx;
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 330rpx;
+		height: 84rpx;
+		color: #fff;
+		font-size: 28rpx;
+		border-radius: 22rpx;
+		background-color: #096562;
+	}
+}
+</style>

+ 46 - 27
pages/couponCenter/couponCenter.vue

@@ -30,6 +30,11 @@
 			</view>
 			</view>
 		</view>
 		</view>
 
 
+		<view class="noData" v-if="list.length === 0">
+			<img lazy-load :lazy-load-margin="0" src="../../static/images/noData.png" />
+			暂无数据
+		</view>
+
 		<!-- 指定民宿弹窗区域 -->
 		<!-- 指定民宿弹窗区域 -->
 		<uni-popup ref="popup" type="center" :is-mask-click="false">
 		<uni-popup ref="popup" type="center" :is-mask-click="false">
 			<view class="popup_body">
 			<view class="popup_body">
@@ -51,33 +56,33 @@ export default {
 		return {
 		return {
 			// 优惠券列表数据
 			// 优惠券列表数据
 			list: [
 			list: [
-				{
-					id: 1,
-					name: '7.5折折扣卷',
-					type: 1,
-					info: '7.5折',
-					isFull: false,
-					time: '2023.09.01  12:00 - 2023.10.01  12:00',
-					tags: ['可通用', '全民宿']
-				},
-				{
-					id: 2,
-					name: '20元代金券',
-					type: 2,
-					info: '¥20',
-					isFull: true,
-					time: '2023.09.01  12:00 - 2023.10.01  12:00',
-					tags: ['可通用', '指定民宿']
-				},
-				{
-					id: 3,
-					name: '7.5折折扣卷',
-					type: 1,
-					info: '7.5折',
-					isFull: false,
-					time: '2023.09.01  12:00 - 2023.10.01  12:00',
-					tags: ['可通用', '全民宿']
-				}
+				// {
+				// 	id: 1,
+				// 	name: '7.5折折扣卷',
+				// 	type: 1,
+				// 	info: '7.5折',
+				// 	isFull: false,
+				// 	time: '2023.09.01  12:00 - 2023.10.01  12:00',
+				// 	tags: ['可通用', '全民宿']
+				// },
+				// {
+				// 	id: 2,
+				// 	name: '20元代金券',
+				// 	type: 2,
+				// 	info: '¥20',
+				// 	isFull: true,
+				// 	time: '2023.09.01  12:00 - 2023.10.01  12:00',
+				// 	tags: ['可通用', '指定民宿']
+				// },
+				// {
+				// 	id: 3,
+				// 	name: '7.5折折扣卷',
+				// 	type: 1,
+				// 	info: '7.5折',
+				// 	isFull: false,
+				// 	time: '2023.09.01  12:00 - 2023.10.01  12:00',
+				// 	tags: ['可通用', '全民宿']
+				// }
 			]
 			]
 		}
 		}
 	},
 	},
@@ -226,6 +231,20 @@ export default {
 		}
 		}
 	}
 	}
 
 
+	.noData {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		padding-bottom: 20rpx;
+
+		img {
+			margin-top: 220rpx;
+			width: 600rpx;
+			height: 600rpx;
+		}
+	}
+
 	.popup_body {
 	.popup_body {
 		display: flex;
 		display: flex;
 		flex-direction: column;
 		flex-direction: column;

+ 375 - 4
pages/detail/detail.vue

@@ -1,5 +1,10 @@
 <template>
 <template>
 	<view class="container" :style="'overflow:' + (showPage ? 'hidden' : 'visible')" v-if="info">
 	<view class="container" :style="'overflow:' + (showPage ? 'hidden' : 'visible')" v-if="info">
+		<!-- 顶部分段器区域 -->
+		<view class="control">
+			<uni-segmented-control :current="activeIndex" :values="headerList" style-type="text" active-color="#096562" @clickItem="onClickItem" />
+		</view>
+
 		<!-- 顶部民宿图片区域 -->
 		<!-- 顶部民宿图片区域 -->
 		<view class="banner">
 		<view class="banner">
 			<swiper autoplay circular class="swiper">
 			<swiper autoplay circular class="swiper">
@@ -78,6 +83,7 @@
 				end-text="离店"
 				end-text="离店"
 				color="#096562"
 				color="#096562"
 				confirmColor="#096562"
 				confirmColor="#096562"
+				:selected="selected"
 				:startDate="earlyTime"
 				:startDate="earlyTime"
 				:endDate="lateTime"
 				:endDate="lateTime"
 				@confirm="handleConfirm"
 				@confirm="handleConfirm"
@@ -173,6 +179,89 @@
 				暂无数据
 				暂无数据
 			</view>
 			</view>
 		</view>
 		</view>
+
+		<!-- 评价区域 -->
+		<view class="evaluate">
+			<view class="evaluate_title">评价</view>
+			<view class="evaluate_body">
+				<!-- 评分区域 -->
+				<view class="header">
+					<view class="header_box">
+						<!-- 总评分区域 -->
+						<view class="box_left">4.6</view>
+						<view class="box_right">
+							<!-- 位置评分区域 -->
+							<view class="right_item">
+								<view class="item_info">位置 4.6</view>
+								<view class="item_progress">
+									<progress activeColor="#0BAD8B" backgroundColor="#CCCCCC" stroke-width="10" border-radius="92" :percent="(4.6 / 5) * 100" />
+								</view>
+							</view>
+							<!-- 设施评分区域 -->
+							<view class="right_item">
+								<view class="item_info">设施 4.6</view>
+								<view class="item_progress">
+									<progress activeColor="#0BAD8B" backgroundColor="#CCCCCC" stroke-width="10" border-radius="92" :percent="(4.6 / 5) * 100" />
+								</view>
+							</view>
+							<!-- 服务评分区域 -->
+							<view class="right_item">
+								<view class="item_info">服务 4.6</view>
+								<view class="item_progress">
+									<progress activeColor="#0BAD8B" backgroundColor="#CCCCCC" stroke-width="10" border-radius="92" :percent="(4.6 / 5) * 100" />
+								</view>
+							</view>
+							<!-- 卫生评分区域 -->
+							<view class="right_item">
+								<view class="item_info">卫生 4.6</view>
+								<view class="item_progress">
+									<progress activeColor="#0BAD8B" backgroundColor="#CCCCCC" stroke-width="10" border-radius="92" :percent="(4.6 / 5) * 100" />
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+
+				<!-- 每一个评价区域 -->
+				<view class="evaluate_box" v-for="item in commentList" :key="item.id">
+					<!-- 用户信息区域 -->
+					<view class="box_userInfo" @click="handleGoDetail(item)">
+						<img mode="aspectFill" :src="item.imgUrl" />
+						<view class="userInfo_msg">
+							<view class="msg_name">{{ item.name }}</view>
+							<view class="msg_star">
+								<uni-rate readonly activeColor="#FFC300" :size="16" :value="item.rate" />
+							</view>
+						</view>
+					</view>
+
+					<!-- 入住时间区域 -->
+					<view class="box_time">{{ item.liveTime }}入住,{{ item.subTime }}发表 | {{ item.type }}</view>
+
+					<!-- 评价内容区域 -->
+					<uv-read-more show-height="85rpx" closeText="全文" color="#096663" fontSize="24rpx" textIndent="0" :toggle="true" :shadowStyle="shadowStyle">
+						<view class="box_content">
+							{{ item.content }}
+						</view>
+					</uv-read-more>
+
+					<!-- 图片区域 -->
+					<view class="box_img">
+						<img v-for="(ele, index) in item.imgList" :key="index" mode="aspectFill" :src="ele" @click="handleClickImg(item.imgList, index)" />
+					</view>
+				</view>
+
+				<view class="foot" @click="handleGoPage" v-if="commentList.length">
+					查看全部{{ commentList.length }}条评价
+					<img src="../../static/index/right.png" />
+				</view>
+
+				<view class="noData" v-if="commentList.length === 0">
+					<img src="../../static/images/noData.png" />
+					暂无评论
+				</view>
+			</view>
+		</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
@@ -205,7 +294,71 @@ export default {
 			// 日历可以选择的最早日期
 			// 日历可以选择的最早日期
 			earlyTime: '',
 			earlyTime: '',
 			// 日历可以选择的最晚日期
 			// 日历可以选择的最晚日期
-			lateTime: ''
+			lateTime: '',
+			activeIndex: 0,
+			headerList: ['预定', '评价'],
+			// 评价列表数据
+			commentList: [
+				// {
+				// 	id: 1,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '张三',
+				// 	rate: 4.6,
+				// 	liveTime: '2023-07',
+				// 	subTime: '2023-08-01',
+				// 	type: '大床房',
+				// 	content:
+				// 		'评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富',
+				// 	imgList: [
+				// 		'https://img1.baidu.com/it/u=2776549017,1408541252&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
+				// 		'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F201912%2F28%2F20191228151619_wxioq.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1695352503&t=cf595866bbcbd5c6a01ffe69913da7e0'
+				// 	],
+				// 	count: 12
+				// },
+				// {
+				// 	id: 2,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '李四',
+				// 	rate: 4.1,
+				// 	liveTime: '2023-08',
+				// 	subTime: '2023-08-11',
+				// 	type: '双人房',
+				// 	content:
+				// 		'评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富',
+				// 	imgList: [
+				// 		'https://img1.baidu.com/it/u=2776549017,1408541252&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500',
+				// 		'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 		'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F201912%2F28%2F20191228151619_wxioq.thumb.1000_0.jpg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1695352503&t=cf595866bbcbd5c6a01ffe69913da7e0',
+				// 		'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F70a86822-e473-4ad8-9147-fad3e5cbc5ec%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1695352600&t=689d4a86e77580db11cdc227291ef6f7'
+				// 	],
+				// 	count: 8
+				// },
+				// {
+				// 	id: 3,
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '王八',
+				// 	rate: 3.8,
+				// 	liveTime: '2023-07',
+				// 	subTime: '2023-07-11',
+				// 	type: '普通房',
+				// 	content:
+				// 		'评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容评价内容的丰富的丰富',
+				// 	imgList: [],
+				// 	count: 26
+				// }
+			],
+			queryDom: null,
+			domTop: null,
+			selected: [
+				// {
+				// 	date: '2023-09-07',
+				// 	topinfo: '¥456'
+				// },
+				// {
+				// 	date: '2023-09-08',
+				// 	topinfo: '¥888'
+				// }
+			]
 		}
 		}
 	},
 	},
 	onLoad(options) {
 	onLoad(options) {
@@ -219,6 +372,22 @@ export default {
 			}
 			}
 		})
 		})
 	},
 	},
+	onPageScroll(e) {
+		if (!this.queryDom) {
+			this.queryDom = uni.createSelectorQuery().in(this)
+			this.queryDom
+				.select('.evaluate')
+				.boundingClientRect((data) => {
+					this.domTop = data.top
+				})
+				.exec()
+		}
+		if (e.scrollTop > this.domTop) {
+			this.activeIndex = 1
+		} else {
+			this.activeIndex = 0
+		}
+	},
 	methods: {
 	methods: {
 		async getHotelInfo() {
 		async getHotelInfo() {
 			const res = await this.$myRequest({
 			const res = await this.$myRequest({
@@ -238,6 +407,18 @@ export default {
 				})
 				})
 			}
 			}
 		},
 		},
+		onClickItem(e) {
+			this.activeIndex = e.currentIndex
+			if (this.activeIndex === 1) {
+				uni.pageScrollTo({
+					selector: '.evaluate'
+				})
+			} else {
+				uni.pageScrollTo({
+					scrollTop: 0
+				})
+			}
+		},
 		// 选择日期确定回调
 		// 选择日期确定回调
 		handleConfirm(e) {
 		handleConfirm(e) {
 			this.startTime = e.range.before
 			this.startTime = e.range.before
@@ -398,6 +579,26 @@ export default {
 			uni.navigateTo({
 			uni.navigateTo({
 				url: `/pages/web/web?url=${url}`
 				url: `/pages/web/web?url=${url}`
 			})
 			})
+		},
+		// 点击每一个评价回调
+		handleGoDetail(item) {
+			let info = encodeURIComponent(JSON.stringify(item))
+			uni.navigateTo({
+				url: `/pages/appraiseDetail/appraiseDetail?info=${info}`
+			})
+		},
+		// 点击评价图片回调
+		handleClickImg(url, index) {
+			// 预览图片
+			uni.previewImage({
+				current: index,
+				urls: url
+			})
+		},
+		handleGoPage() {
+			uni.navigateTo({
+				url: '/pages/appraise/appraise'
+			})
 		}
 		}
 	}
 	}
 }
 }
@@ -410,11 +611,19 @@ export default {
 	align-items: center;
 	align-items: center;
 	position: relative;
 	position: relative;
 	min-height: 100vh;
 	min-height: 100vh;
-	background-color: #ebeced;
+	background-color: #f2f3f5;
+
+	.control {
+		z-index: 999;
+		position: sticky;
+		top: 0;
+		width: 100%;
+		height: 100rpx;
+		background-color: #fff;
+	}
 
 
 	.banner {
 	.banner {
 		position: relative;
 		position: relative;
-		margin-top: 20rpx;
 		width: 750rpx;
 		width: 750rpx;
 		height: 422rpx;
 		height: 422rpx;
 
 
@@ -577,7 +786,7 @@ export default {
 	.body {
 	.body {
 		float: left;
 		float: left;
 		margin-top: 20rpx;
 		margin-top: 20rpx;
-		padding-bottom: 30rpx;
+		// padding-bottom: 30rpx;
 		width: 710rpx;
 		width: 710rpx;
 		border-radius: 10rpx;
 		border-radius: 10rpx;
 		background-color: #fff;
 		background-color: #fff;
@@ -923,5 +1132,167 @@ export default {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	.evaluate {
+		width: 710rpx;
+		background-color: #f2f3f5;
+
+		.evaluate_title {
+			line-height: 83rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+		}
+
+		.evaluate_body {
+			display: flex;
+			flex-direction: column;
+			margin-bottom: 20rpx;
+			width: 710rpx;
+			border-radius: 11rpx;
+			background-color: #fff;
+
+			.header {
+				display: flex;
+				align-items: center;
+				margin: 25rpx 20rpx;
+				width: 670rpx;
+				height: 120rpx;
+				border-radius: 13rpx;
+				background-color: #e4f0ef;
+
+				.header_box {
+					display: flex;
+					height: 70rpx;
+
+					.box_left {
+						display: flex;
+						justify-content: center;
+						align-items: center;
+						width: 140rpx;
+						color: #096562;
+						font-size: 60rpx;
+						font-weight: 900;
+						border-right: 1rpx solid #cccccc;
+					}
+
+					.box_right {
+						flex: 1;
+						display: flex;
+						flex-wrap: wrap;
+						color: #808080;
+						font-size: 24rpx;
+
+						.right_item {
+							display: flex;
+							align-items: center;
+							width: 50%;
+
+							.item_info {
+								margin-left: 33rpx;
+							}
+
+							.item_progress {
+								margin-right: 20rpx;
+								padding: 0 13rpx;
+								flex: 1;
+							}
+						}
+					}
+				}
+			}
+
+			.evaluate_box {
+				box-sizing: border-box;
+				padding: 0 20rpx;
+				margin: 0 auto 20rpx;
+				width: 710rpx;
+				border-radius: 18rpx;
+				background-color: #fff;
+
+				.box_userInfo {
+					display: flex;
+					align-items: center;
+					height: 115rpx;
+
+					img {
+						width: 70rpx;
+						height: 70rpx;
+						border-radius: 50%;
+					}
+
+					.userInfo_msg {
+						margin-left: 18rpx;
+
+						.msg_name {
+							font-size: 28rpx;
+						}
+
+						.msg_star {
+							margin-left: -5rpx;
+							margin-top: 5rpx;
+						}
+					}
+				}
+
+				.box_time {
+					display: flex;
+					align-items: center;
+					color: #a6a6a6;
+					font-size: 24rpx;
+				}
+
+				.box_content {
+					margin-top: 15rpx;
+					font-size: 24rpx;
+					color: #000;
+				}
+
+				.box_img {
+					display: grid;
+					grid-template-columns: 1fr 1fr 1fr;
+					grid-auto-rows: auto;
+					gap: 10rpx;
+					margin-top: 20rpx;
+
+					img {
+						width: 216rpx;
+						height: 216rpx;
+						border-radius: 20rpx;
+					}
+				}
+			}
+
+			.foot {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				padding-bottom: 20rpx;
+				height: 68rpx;
+				font-size: 24rpx;
+				font-weight: bold;
+				color: #096663;
+
+				img {
+					margin-left: 10rpx;
+					width: 10rpx;
+					height: 18rpx;
+				}
+			}
+
+			.noData {
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
+				align-items: center;
+				padding-bottom: 60rpx;
+
+				img {
+					margin-top: 160rpx;
+					width: 600rpx;
+					height: 600rpx;
+				}
+			}
+		}
+	}
 }
 }
 </style>
 </style>

+ 31 - 12
pages/detailInfo/detailInfo.vue

@@ -2,20 +2,22 @@
 	<view class="container" v-if="detailInfo">
 	<view class="container" v-if="detailInfo">
 		<!-- 顶部民宿信息区域 -->
 		<!-- 顶部民宿信息区域 -->
 		<view class="header">
 		<view class="header">
-			<img src="../../static/my/headerImg.png" />
+			<img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
 			<!-- 标题区域 -->
 			<!-- 标题区域 -->
-			<view class="header_title">设施详情</view>
+			<view class="header_title" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">设施详情</view>
 			<!-- 返回图标区域 -->
 			<!-- 返回图标区域 -->
-			<view class="header_icon" @click="handleBack">
+			<view class="header_icon" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }" @click="handleBack">
 				<img src="../../static/index/left.png" />
 				<img src="../../static/index/left.png" />
 			</view>
 			</view>
 
 
 			<!-- 民宿名称区域 -->
 			<!-- 民宿名称区域 -->
-			<view class="header_name">{{ detailInfo.hotel_name }}</view>
+			<view class="header_name" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }">{{ detailInfo.hotel_name }}</view>
 			<!-- 开业时间区域 -->
 			<!-- 开业时间区域 -->
-			<view class="header_info">{{ detailInfo.openTime }}开业 I {{ detailInfo.fitupTime }}装修 I {{ detailInfo.room_number_calc }}间客房</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }">
+				{{ detailInfo.openTime }}开业 I {{ detailInfo.fitupTime }}装修 I {{ detailInfo.room_number_calc }}间客房
+			</view>
 			<!-- 类型区域 -->
 			<!-- 类型区域 -->
-			<view class="header_types">
+			<view class="header_types" :style="{ paddingTop: statusBarH * 2 + 200 + 'rpx' }">
 				<view class="types_item">{{ detailInfo.hTypeName }}</view>
 				<view class="types_item">{{ detailInfo.hTypeName }}</view>
 			</view>
 			</view>
 		</view>
 		</view>
@@ -61,9 +63,25 @@ export default {
 			// 民宿ID
 			// 民宿ID
 			hotelId: '',
 			hotelId: '',
 			// 详细信息
 			// 详细信息
-			detailInfo: null
+			detailInfo: null,
+			// 状态栏高度
+			statusBarH: 0,
+			// 胶囊按钮栏高度
+			customBarH: 0
 		}
 		}
 	},
 	},
+	created() {
+		// 获取系统信息
+		uni.getSystemInfo({
+			success: (e) => {
+				// 获取状态栏高度
+				this.statusBarH = e.statusBarHeight + 10
+				// // 获取菜单按钮栏高度
+				let custom = uni.getMenuButtonBoundingClientRect()
+				this.customBarH = custom.height + 10
+			}
+		})
+	},
 	onLoad(options) {
 	onLoad(options) {
 		this.hotelId = options.hotelId
 		this.hotelId = options.hotelId
 		this.getDetailInfo()
 		this.getDetailInfo()
@@ -150,15 +168,16 @@ export default {
 
 
 		.header_title {
 		.header_title {
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 308rpx;
 			left: 308rpx;
 			color: #fff;
 			color: #fff;
 			font-size: 28rpx;
 			font-size: 28rpx;
 		}
 		}
 
 
 		.header_icon {
 		.header_icon {
+			z-index: 2;
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 5rpx;
 			left: 5rpx;
 			width: 47rpx;
 			width: 47rpx;
 			height: 70rpx;
 			height: 70rpx;
@@ -171,7 +190,7 @@ export default {
 
 
 		.header_name {
 		.header_name {
 			position: absolute;
 			position: absolute;
-			top: 155rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 40rpx;
 			font-size: 40rpx;
 			font-weight: bold;
 			font-weight: bold;
@@ -179,14 +198,14 @@ export default {
 
 
 		.header_info {
 		.header_info {
 			position: absolute;
 			position: absolute;
-			top: 230rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 24rpx;
 			font-size: 24rpx;
 		}
 		}
 
 
 		.header_types {
 		.header_types {
 			position: absolute;
 			position: absolute;
-			top: 281rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			display: flex;
 			display: flex;
 			font-size: 20rpx;
 			font-size: 20rpx;

+ 444 - 0
pages/evaluate/evaluate.vue

@@ -0,0 +1,444 @@
+<template>
+	<view class="container">
+		<!-- 页面标题区域 -->
+		<view class="header" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">
+			<img src="../../static/index/left2.png" :style="{ paddingTop: statusBarH * 2 + 'rpx' }" @click="handleBack" />
+			<view class="header_text">评价</view>
+		</view>
+
+		<!-- 评分区域 -->
+		<view class="rate">
+			<view class="rate_key">民宿评分</view>
+			<uni-rate v-model="rateValue" size="18" @change="onChange" />
+			<view class="rate_value">非常好</view>
+		</view>
+
+		<!-- 评价上传图片视频区域 -->
+		<view class="operation">
+			<!-- 输入框区域 -->
+			<view class="operation_input">
+				<textarea
+					maxlength="1000"
+					class="textarea"
+					placeholder-style="color:#B3B3B3;font-size:24rpx"
+					placeholder="写出你的感受,可以帮助其他小伙伴哦~"
+					v-model="textareaValue"
+					@input="handleInput"
+				/>
+				<view class="operation_count">({{ textareaValuelength }}/1000)</view>
+			</view>
+
+			<!-- 上传区域 -->
+			<view class="operation_uploading">
+				<view class="uploading_box" @click="handleUpLoad">
+					<img class="img" src="../../static/index/photo.png" />
+					<view class="msg">照片/视频</view>
+				</view>
+
+				<view class="uploading_box" v-for="(ele, index) in subImgList" :key="index">
+					<img class="img2" mode="aspectFill" :src="ele" />
+					<view class="icon" @click="handleDelete(index)">
+						<img src="../../static/index/close2.png" />
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 总体评价区域 -->
+		<view class="foot">
+			<!-- 民宿位置评价 -->
+			<view class="foot_box">
+				<view class="box_key">民宿位置</view>
+				<uni-rate v-model="rateLocation" size="18" @change="onChange" />
+				<view class="box_value">非常好</view>
+			</view>
+			<!-- 民宿设施评价 -->
+			<view class="foot_box">
+				<view class="box_key">民宿设施</view>
+				<uni-rate v-model="rateLocation" size="18" @change="onChange" />
+				<view class="box_value">非常好</view>
+			</view>
+			<!-- 民宿服务评价 -->
+			<view class="foot_box">
+				<view class="box_key">民宿服务</view>
+				<uni-rate v-model="rateLocation" size="18" @change="onChange" />
+				<view class="box_value">非常好</view>
+			</view>
+			<!-- 民宿卫生评价 -->
+			<view class="foot_box">
+				<view class="box_key">民宿卫生</view>
+				<uni-rate v-model="rateLocation" size="18" @change="onChange" />
+				<view class="box_value">非常好</view>
+			</view>
+		</view>
+
+		<!-- 提交按钮区域 -->
+		<view class="foot_btn" @click="handleSub">提交</view>
+
+		<!-- 用于图片压缩的canvas画布 -->
+		<canvas
+			:style="{
+				width: cw + 'px',
+				height: cw + 'px',
+				position: 'absolute',
+				zIndex: -1,
+				left: '-10000rpx',
+				top: '-10000rpx'
+			}"
+			canvas-id="zipCanvas"
+		></canvas>
+		<!--画布结束-->
+	</view>
+</template>
+
+<script>
+// 图片压缩方法
+import getLessLimitSizeImage from '@/util/imageCompress.js'
+export default {
+	data() {
+		return {
+			// 状态栏高度
+			statusBarH: 0,
+			// 胶囊按钮栏高度
+			customBarH: 0,
+			// 民宿评分
+			rateValue: 2,
+			// 评价绑定数据
+			textareaValue: '',
+			// 评价文字长度
+			textareaValuelength: 0,
+			// 显示的图片数据
+			imgList: [],
+			// 上传的图片数据
+			subImgList: [],
+			// 图片上传框的样式
+			imageStyles: {
+				width: '60px',
+				height: 60,
+				border: {
+					// 如果为 Boolean 值,可以控制边框显示与否
+					color: '#eee', // 边框颜色
+					width: '1px', // 边框宽度
+					style: 'solid', // 边框样式
+					radius: '50%' // 边框圆角,支持百分比
+				}
+			},
+			// 民宿位置评分
+			rateLocation: 3
+		}
+	},
+	created() {
+		// 获取系统信息
+		uni.getSystemInfo({
+			success: (e) => {
+				// 获取状态栏高度
+				this.statusBarH = e.statusBarHeight + 10
+				// // 获取菜单按钮栏高度
+				let custom = uni.getMenuButtonBoundingClientRect()
+				this.customBarH = custom.height + 10
+			}
+		})
+	},
+	methods: {
+		// 点击页面标题返回箭头回调
+		handleBack() {
+			uni.showModal({
+				content: '确认退出评价吗,已编辑的内容将不保存',
+				cancelText: '退出评价',
+				cancelColor: '#808080',
+				confirmText: '继续写评',
+				confirmColor: '#000000',
+				success: (res) => {
+					if (res.confirm) {
+					} else if (res.cancel) {
+						uni.navigateBack(1)
+					}
+				}
+			})
+		},
+		// 点击提交按钮回调
+		handleSub() {
+			uni.navigateTo({
+				url: `/pages/evaluateStatus/evaluateStatus?status=2`
+			})
+		},
+		handleUpLoad() {
+			uni.chooseMedia({
+				count: 9,
+				maxDuration: 15,
+				success: (res) => {
+					console.log(res)
+					console.log(res.tempFiles)
+					if (this.subImgList.length + res.tempFiles.length > 9) {
+						uni.showToast({
+							title: '最多只能上传9个图片/视频',
+							icon: 'none'
+						})
+						return
+					}
+					uni.showLoading({
+						title: '上传中'
+					})
+					// reverse()
+					res.tempFiles.forEach((ele) => {
+						uni.uploadFile({
+							url: `https://chtech.ncjti.edu.cn/hotelReservation/mhotel/mhotel/uploadhimage.action`,
+							filePath: ele.tempFilePath,
+							name: 'myFile',
+							success: (uploadFileRes) => {
+								console.log(JSON.parse(uploadFileRes.data))
+								let temRes = JSON.parse(uploadFileRes.data)
+								if (temRes.code === 200) {
+									this.subImgList.push(temRes.data.url)
+									console.log(this.subImgList)
+									uni.hideLoading()
+								} else {
+									uni.showToast({
+										title: temRes.message,
+										icon: 'none'
+									})
+								}
+							},
+							fail: () => {
+								uni.showToast({
+									title: '上传失败',
+									icon: 'error'
+								})
+							}
+						})
+					})
+				}
+			})
+		},
+		// 评分改变回调
+		onChange(e) {
+			console.log(e.value)
+		},
+		// 评价输入框输入回调
+		handleInput(e) {
+			this.textareaValuelength = e.detail.cursor
+		},
+		// 选择图片回调
+		select(e) {
+			// console.log(e)
+			e.tempFiles.forEach((item) => {
+				//这里的id和页面中写的html代码的canvas的id要一致
+				let canvasId = 'zipCanvas'
+				//原图的路径
+				let imagePath = item.path
+				//大小限制1024kb
+				let limitSize = 1024
+				//初始绘画区域是画布自身的宽度也就是屏幕宽度
+				let drawWidth = uni.getSystemInfoSync().windowWidth
+
+				getLessLimitSizeImage(canvasId, imagePath, limitSize, drawWidth, (resPath) => {
+					uni.showLoading({
+						title: '上传中'
+					})
+					uni.uploadFile({
+						url: `https://chtech.ncjti.edu.cn/hotelReservation/mhotel/mhotel/uploadhimage.action`,
+						filePath: resPath,
+						name: 'myFile',
+						success: (uploadFileRes) => {
+							console.log(JSON.parse(uploadFileRes.data))
+							let temRes = JSON.parse(uploadFileRes.data)
+							if (temRes.code === 200) {
+								this.subImgList.push(temRes.data.url)
+								this.imgList.push({
+									url: item.path,
+									name: ''
+								})
+								uni.hideLoading()
+							}
+						},
+						fail: () => {
+							uni.showToast({
+								title: '上传失败',
+								icon: 'error'
+							})
+						}
+					})
+				})
+			})
+		},
+		// 删除图片回调
+		handleDelete(index) {
+			// console.log(e);
+			// const num = this.imgList.findIndex((v) => v.url === e.tempFilePath)
+			this.subImgList.splice(index, 1)
+			// this.imgList.splice(num, 1)
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	min-height: 100vh;
+	background-color: #f2f3f5;
+
+	.header {
+		display: flex;
+		justify-content: center;
+		position: relative;
+		background-color: #fff;
+
+		img {
+			position: absolute;
+			top: 0;
+			left: 0;
+			width: 47rpx;
+			height: 47rpx;
+		}
+
+		.header_text {
+			font-size: 34rpx;
+		}
+	}
+
+	.rate {
+		display: flex;
+		align-items: center;
+		margin: 20rpx 0;
+		height: 107rpx;
+		background-color: #fff;
+
+		.rate_key {
+			margin: 0 18rpx;
+			font-size: 28rpx;
+			font-weight: bold;
+		}
+
+		.rate_value {
+			margin-left: 100rpx;
+			color: #808080;
+			font-size: 24rpx;
+		}
+	}
+
+	.operation {
+		padding: 20rpx 20rpx 33rpx;
+		margin-bottom: 20rpx;
+		background-color: #fff;
+
+		.operation_input {
+			box-sizing: border-box;
+			padding: 20rpx;
+			width: 710rpx;
+			height: 282rpx;
+			border-radius: 9rpx;
+			background-color: #f2f2f2;
+
+			.textarea {
+				width: 100%;
+				height: 203rpx;
+			}
+
+			.operation_count {
+				height: 39rpx;
+				text-align: end;
+				color: #b3b3b3;
+				font-size: 24rpx;
+			}
+		}
+
+		.operation_uploading {
+			display: grid;
+			gap: 21rpx;
+			grid-template-columns: repeat(auto-fill, 124rpx);
+			margin-top: 20rpx;
+
+			::v-deep .uni-file-picker__item {
+				background-color: red;
+			}
+
+			.uploading_box {
+				position: relative;
+				display: flex;
+				flex-direction: column;
+				justify-content: center;
+				align-items: center;
+				width: 124rpx;
+				height: 124rpx;
+				border-radius: 7rpx;
+				background-color: #f2f2f2;
+
+				.img {
+					width: 40rpx;
+					height: 40rpx;
+				}
+
+				.msg {
+					margin-top: 5rpx;
+					color: #a6a6a6;
+					font-size: 20rpx;
+				}
+
+				.img2 {
+					width: 124rpx;
+					height: 124rpx;
+					border-radius: 7rpx;
+				}
+
+				.icon {
+					position: absolute;
+					top: 0;
+					right: 0;
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					width: 30rpx;
+					height: 30rpx;
+					border-radius: 7rpx;
+					background-color: rgba(000, 000, 000, 0.5);
+
+					img {
+						width: 30rpx;
+						height: 30rpx;
+					}
+				}
+			}
+		}
+	}
+
+	.foot {
+		display: flex;
+		flex-direction: column;
+		justify-content: space-between;
+		box-sizing: border-box;
+		padding: 30rpx 20rpx 50rpx;
+		height: 320rpx;
+		background-color: #fff;
+
+		.foot_box {
+			display: flex;
+			align-items: center;
+
+			.box_key {
+				margin-right: 18rpx;
+				font-size: 28rpx;
+				font-weight: bold;
+			}
+
+			.box_value {
+				margin-left: 100rpx;
+				color: #808080;
+				font-size: 24rpx;
+			}
+		}
+	}
+
+	.foot_btn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin: 65rpx auto 78rpx;
+		width: 710rpx;
+		height: 96rpx;
+		color: #fff;
+		font-size: 32rpx;
+		border-radius: 64rpx;
+		background-color: #096562;
+	}
+}
+</style>

+ 276 - 0
pages/evaluateStatus/evaluateStatus.vue

@@ -0,0 +1,276 @@
+<template>
+	<view class="container">
+		<!-- 评价状态区域 -->
+		<view class="status">
+			<img v-if="status === '1'" src="../../static/index/success.png" />
+			<img v-if="status === '2'" src="../../static/index/fail.png" />
+			<view class="status_msg">{{ msg }}</view>
+			<view class="status_btn">{{ btnMsg }}</view>
+		</view>
+
+		<!-- 民宿信息区域 -->
+		<view class="info">
+			<img mode="aspectFill" src="https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375" />
+			<view class="info_name">
+				<view class="top">民宿名称</view>
+				<view class="bottom">500人收藏</view>
+			</view>
+			<view class="info_btn">收藏</view>
+		</view>
+
+		<!-- 订单列表区域 -->
+		<view class="body">
+			<!-- 每一个订单区域 -->
+			<view class="body_box">
+				<!-- 标题区域 -->
+				<view class="box_header">
+					<img class="img" src="../../static/my/hotel.png" />
+					<view class="title">民宿名称</view>
+					<view class="type">已消费</view>
+				</view>
+
+				<!-- 酒店信息区域 -->
+				<view class="box_info">
+					<img class="img" mode="aspectFill" src="https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375" />
+					<view class="info_right">
+						<view class="info_right_item">1间,大床房</view>
+						<view class="info_right_item">2023-07-26 - 2023-07-27</view>
+						<view class="info_right_item">总价:¥666</view>
+					</view>
+				</view>
+
+				<!-- 按钮区域 -->
+				<view class="box_btn">
+					<view class="btn_item" @click="handleEvaluate">去评价</view>
+				</view>
+			</view>
+			<view class="body_box">
+				<!-- 标题区域 -->
+				<view class="box_header">
+					<img class="img" src="../../static/my/hotel.png" />
+					<view class="title">民宿名称</view>
+					<view class="type">已消费</view>
+				</view>
+
+				<!-- 酒店信息区域 -->
+				<view class="box_info">
+					<img class="img" mode="aspectFill" src="https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375" />
+					<view class="info_right">
+						<view class="info_right_item">1间,大床房</view>
+						<view class="info_right_item">2023-07-26 - 2023-07-27</view>
+						<view class="info_right_item">总价:¥666</view>
+					</view>
+				</view>
+
+				<!-- 按钮区域 -->
+				<view class="box_btn">
+					<view class="btn_item" @click="handleEvaluate">去评价</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			// 评价是否成功 1成功 2失败
+			status: null,
+			// 评价状态信息
+			msg: '',
+			// 按钮文字信息
+			btnMsg: ''
+		}
+	},
+	onLoad(options) {
+		// console.log(options)
+		this.status = options.status
+		if (this.status === '1') {
+			uni.setNavigationBarTitle({
+				title: '评价成功'
+			})
+			this.msg = '评价成功'
+			this.btnMsg = '查看我的评价'
+		} else {
+			uni.setNavigationBarTitle({
+				title: '评价失败'
+			})
+			this.msg = '评价失败'
+			this.btnMsg = '重新评价'
+		}
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	min-height: 100vh;
+	background-color: #f7f7f7;
+
+	.status {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		height: 554rpx;
+		background-color: #fff;
+
+		img {
+			margin: 80rpx 0 40rpx;
+			width: 134rpx;
+			height: 134rpx;
+		}
+
+		.status_msg {
+			font-size: 32rpx;
+		}
+
+		.status_btn {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin-top: 87rpx;
+			width: 330rpx;
+			height: 84rpx;
+			color: #fff;
+			font-size: 28rpx;
+			border-radius: 22rpx;
+			background-color: #096562;
+		}
+	}
+
+	.info {
+		display: flex;
+		align-items: center;
+		margin: 20rpx 0;
+		padding: 0 30rpx;
+		height: 144rpx;
+		background-color: #fff;
+
+		img {
+			width: 80rpx;
+			height: 80rpx;
+			border-radius: 9rpx;
+		}
+
+		.info_name {
+			display: flex;
+			flex-direction: column;
+			justify-content: space-between;
+			margin-left: 24rpx;
+			height: 80rpx;
+
+			.top {
+				font-weight: bold;
+				font-size: 32rpx;
+			}
+			.bottom {
+				color: #a6a6a6;
+				font-size: 24rpx;
+			}
+		}
+
+		.info_btn {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin-left: auto;
+			width: 137rpx;
+			height: 71rpx;
+			color: #fff;
+			font-size: 28rpx;
+			border-radius: 22rpx;
+			background-color: #096562;
+		}
+	}
+
+	.body {
+		padding-bottom: 20rpx;
+
+		.body_box {
+			margin-top: 20rpx;
+			box-sizing: border-box;
+			padding: 0 40rpx;
+			background-color: #fff;
+
+			.box_header {
+				display: flex;
+				align-items: center;
+				height: 94rpx;
+
+				.img {
+					width: 47rpx;
+					height: 47rpx;
+				}
+
+				.title {
+					margin-left: 16rpx;
+					width: 350rpx;
+					font-size: 32rpx;
+					font-weight: bold;
+					overflow: hidden;
+					white-space: nowrap;
+					text-overflow: ellipsis;
+				}
+
+				.type {
+					display: flex;
+					justify-content: flex-end;
+					align-items: center;
+					margin-left: auto;
+					margin-right: 25rpx;
+					width: 285rpx;
+					color: #808080;
+					font-size: 28rpx;
+				}
+			}
+
+			.box_info {
+				display: flex;
+				height: 140rpx;
+
+				.img {
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 9rpx;
+				}
+
+				.info_right {
+					display: flex;
+					flex-direction: column;
+					justify-content: space-around;
+					margin-top: -5rpx;
+					margin-left: 18rpx;
+					height: 120rpx;
+					color: #808080;
+					font-size: 28rpx;
+
+					.info_right_item {
+						flex: 1;
+					}
+				}
+			}
+
+			.box_btn {
+				display: flex;
+				justify-content: flex-end;
+				margin-top: -10rpx;
+				height: 100rpx;
+
+				.btn_item {
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					margin-left: 20rpx;
+					width: 178rpx;
+					height: 68rpx;
+					border-radius: 64rpx;
+					color: #808080;
+					font-size: 28rpx;
+					border: 1rpx solid #808080;
+				}
+			}
+		}
+	}
+}
+</style>

+ 38 - 15
pages/home/home.vue

@@ -20,11 +20,11 @@
 			</uv-row>
 			</uv-row>
 		</view>
 		</view>
 
 
-		<scroll-view scroll-y class="main" @scroll="handleScroll" @scrolltolower="handleRefresh">
+		<view class="main">
 			<!-- 添加一层view解决 css属性 sticky 不生效问题 -->
 			<!-- 添加一层view解决 css属性 sticky 不生效问题 -->
 			<view>
 			<view>
 				<!-- 图标区域 -->
 				<!-- 图标区域 -->
-				<view class="icons">
+				<!-- <view class="icons">
 					<view class="icon_item" @click="handleTest">
 					<view class="icon_item" @click="handleTest">
 						<view class="item_top color">
 						<view class="item_top color">
 							<img src="../../static/index/icon.png" />
 							<img src="../../static/index/icon.png" />
@@ -58,7 +58,7 @@
 						</view>
 						</view>
 						<view class="item_bottom">其他</view>
 						<view class="item_bottom">其他</view>
 					</view>
 					</view>
-				</view>
+				</view> -->
 
 
 				<!-- 分段器区域 -->
 				<!-- 分段器区域 -->
 				<view class="control" :class="{ sticky: isSticky }">
 				<view class="control" :class="{ sticky: isSticky }">
@@ -95,7 +95,7 @@
 					暂无数据
 					暂无数据
 				</view>
 				</view>
 			</view>
 			</view>
-		</scroll-view>
+		</view>
 
 
 		<!-- 选择乡镇弹窗区域 -->
 		<!-- 选择乡镇弹窗区域 -->
 		<uni-popup ref="popup" :is-mask-click="false" type="center">
 		<uni-popup ref="popup" :is-mask-click="false" type="center">
@@ -170,9 +170,33 @@ export default {
 			popList: []
 			popList: []
 		}
 		}
 	},
 	},
-	onLoad() {
-		this.openPop()
-		this.getResidueCount()
+	onLoad(options) {
+		console.log(options)
+		this.keywords = options.keywords
+		if (!options.level || options.level === '白金') {
+			this.current = 0
+		} else if (options.level === '金宿') {
+			this.current = 1
+		} else if (options.level === '银宿') {
+			this.current = 2
+		}
+		uni.setNavigationBarTitle({
+			title: options.town || '靖安县'
+		})
+		this.getTownList(options.town)
+		// this.openPop()
+		// this.getResidueCount()
+	},
+	onReachBottom() {
+		if (this.hotelList.length < this.total) {
+			this.page++
+			this.getHotelList()
+		} else {
+			uni.showToast({
+				title: '没有更多数据了',
+				icon: 'none'
+			})
+		}
 	},
 	},
 	// 页面下拉刷新回调
 	// 页面下拉刷新回调
 	onPullDownRefresh() {
 	onPullDownRefresh() {
@@ -248,7 +272,7 @@ export default {
 			}
 			}
 		},
 		},
 		// 获取乡镇集合
 		// 获取乡镇集合
-		async getTownList() {
+		async getTownList(town) {
 			const res = await this.$myRequest({
 			const res = await this.$myRequest({
 				url: '/mhotel/hotelqueryList.action',
 				url: '/mhotel/hotelqueryList.action',
 				method: 'get',
 				method: 'get',
@@ -261,11 +285,13 @@ export default {
 				this.placeList = [...this.placeList, ...res.data]
 				this.placeList = [...this.placeList, ...res.data]
 				let temindex
 				let temindex
 				this.placeList.forEach((ele, index) => {
 				this.placeList.forEach((ele, index) => {
-					if (ele.name === this.town) {
+					if (ele.name === town) {
 						temindex = index
 						temindex = index
 					}
 					}
 				})
 				})
-				this.placeIndex = temindex
+				this.placeIndex = temindex || 0
+				this.getLocation()
+				console.log(this.placeIndex)
 			}
 			}
 		},
 		},
 		// 获取用户当前位置
 		// 获取用户当前位置
@@ -423,10 +449,10 @@ export default {
 	display: flex;
 	display: flex;
 	flex-direction: column;
 	flex-direction: column;
 	width: 750rpx;
 	width: 750rpx;
-	height: 100vh;
+	min-height: 100vh;
 	padding: 0 30rpx;
 	padding: 0 30rpx;
 	box-sizing: border-box;
 	box-sizing: border-box;
-	overflow: hidden;
+	overflow-y: auto;
 	background-color: #f7f7f7;
 	background-color: #f7f7f7;
 
 
 	.content {
 	.content {
@@ -502,9 +528,6 @@ export default {
 	}
 	}
 
 
 	.main {
 	.main {
-		margin-top: 10rpx;
-		height: calc(100vh - 120rpx);
-
 		.icons {
 		.icons {
 			display: flex;
 			display: flex;
 			justify-content: space-around;
 			justify-content: space-around;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 998 - 0
pages/home3/home3.vue


+ 5 - 5
pages/my/my.vue

@@ -5,7 +5,7 @@
 
 
 		<!-- 顶部用户信息区域 -->
 		<!-- 顶部用户信息区域 -->
 		<view class="header">
 		<view class="header">
-			<img src="../../static/my/headerImg.png" />
+			<img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
 			<!-- 头像区域 -->
 			<!-- 头像区域 -->
 			<img class="img" mode="aspectFill" v-if="flag" :src="userInfo.headPhoto" />
 			<img class="img" mode="aspectFill" v-if="flag" :src="userInfo.headPhoto" />
 			<img class="img" v-else src="../../static/my/portrait.png" />
 			<img class="img" v-else src="../../static/my/portrait.png" />
@@ -71,18 +71,18 @@
 			</view>
 			</view>
 
 
 			<!-- 我是商户区域 -->
 			<!-- 我是商户区域 -->
-			<view class="body_item" @click="handleClick(1)">
+			<!-- <view class="body_item" @click="handleClick(1)">
 				<img class="img2" src="../../static/my/shop.png" />
 				<img class="img2" src="../../static/my/shop.png" />
 				我是商户
 				我是商户
 				<img class="img_icon" src="../../static/my/right3.png" />
 				<img class="img_icon" src="../../static/my/right3.png" />
-			</view>
+			</view> -->
 
 
 			<!-- 我是业主区域 -->
 			<!-- 我是业主区域 -->
-			<view class="body_item" @click="handleClick(2)">
+			<!-- <view class="body_item" @click="handleClick(2)">
 				<img class="img2" src="../../static/my/shop2.png" />
 				<img class="img2" src="../../static/my/shop2.png" />
 				我是业主
 				我是业主
 				<img class="img_icon" src="../../static/my/right3.png" />
 				<img class="img_icon" src="../../static/my/right3.png" />
-			</view>
+			</view> -->
 
 
 			<!-- 设置区域 -->
 			<!-- 设置区域 -->
 			<view class="body_item" @click="handleGoPage('/pages/set/set')">
 			<view class="body_item" @click="handleGoPage('/pages/set/set')">

+ 72 - 53
pages/myComplaint/myComplaint.vue

@@ -28,6 +28,11 @@
 				</view>
 				</view>
 			</view>
 			</view>
 		</view>
 		</view>
+
+		<view class="noData" v-if="list.length === 0">
+			<img lazy-load :lazy-load-margin="0" src="../../static/images/noData.png" />
+			暂无数据
+		</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
@@ -37,58 +42,58 @@ export default {
 		return {
 		return {
 			// 投诉列表区域
 			// 投诉列表区域
 			list: [
 			list: [
-				{
-					id: 1,
-					title: '标题',
-					type: '处理中',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '开心民宿',
-					time: '2023-07-26  -  2023-07-27',
-					status: '支付超时',
-					price: 666,
-					time2: '2023-08-15  15:15:15',
-					count: 1,
-					roomType: '双人标间'
-				},
-				{
-					id: 2,
-					title: '我要投诉',
-					type: '已处理',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '快乐民宿',
-					time: '2023-07-26  -  2023-07-27',
-					status: '支付超时',
-					price: 888,
-					time2: '2023-08-15  15:15:15',
-					count: 1,
-					roomType: '单人标间'
-				},
-				{
-					id: 3,
-					title: '投诉',
-					type: '处理中',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '健康民宿',
-					time: '2023-07-26  -  2023-07-27',
-					status: '支付超时',
-					price: 1288,
-					time2: '2023-08-15  15:15:15',
-					count: 1,
-					roomType: '双人标间'
-				},
-				{
-					id: 4,
-					title: '投诉投诉投诉投诉',
-					type: '投诉',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					name: '木叶村',
-					time: '2023-07-26  -  2023-07-27',
-					status: '支付超时',
-					price: 8888,
-					time2: '2023-08-15  15:15:15',
-					count: 1,
-					roomType: '火影标间'
-				}
+				// {
+				// 	id: 1,
+				// 	title: '标题',
+				// 	type: '处理中',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '开心民宿',
+				// 	time: '2023-07-26  -  2023-07-27',
+				// 	status: '支付超时',
+				// 	price: 666,
+				// 	time2: '2023-08-15  15:15:15',
+				// 	count: 1,
+				// 	roomType: '双人标间'
+				// },
+				// {
+				// 	id: 2,
+				// 	title: '我要投诉',
+				// 	type: '已处理',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '快乐民宿',
+				// 	time: '2023-07-26  -  2023-07-27',
+				// 	status: '支付超时',
+				// 	price: 888,
+				// 	time2: '2023-08-15  15:15:15',
+				// 	count: 1,
+				// 	roomType: '单人标间'
+				// },
+				// {
+				// 	id: 3,
+				// 	title: '投诉',
+				// 	type: '处理中',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '健康民宿',
+				// 	time: '2023-07-26  -  2023-07-27',
+				// 	status: '支付超时',
+				// 	price: 1288,
+				// 	time2: '2023-08-15  15:15:15',
+				// 	count: 1,
+				// 	roomType: '双人标间'
+				// },
+				// {
+				// 	id: 4,
+				// 	title: '投诉投诉投诉投诉',
+				// 	type: '投诉',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	name: '木叶村',
+				// 	time: '2023-07-26  -  2023-07-27',
+				// 	status: '支付超时',
+				// 	price: 8888,
+				// 	time2: '2023-08-15  15:15:15',
+				// 	count: 1,
+				// 	roomType: '火影标间'
+				// }
 			]
 			]
 		}
 		}
 	},
 	},
@@ -208,5 +213,19 @@ export default {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	.noData {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		align-items: center;
+		padding-bottom: 20rpx;
+
+		img {
+			margin-top: 160rpx;
+			width: 600rpx;
+			height: 600rpx;
+		}
+	}
 }
 }
-</style>
+</style>

+ 73 - 54
pages/myCoupon/myCoupon.vue

@@ -46,6 +46,11 @@
 				<!-- 代金券按钮区域 -->
 				<!-- 代金券按钮区域 -->
 				<view class="box_btn">去使用</view>
 				<view class="box_btn">去使用</view>
 			</view>
 			</view>
+
+			<view class="noData" v-if="list.length === 0">
+				<img lazy-load :lazy-load-margin="0" src="../../static/images/noData.png" />
+				暂无数据
+			</view>
 		</scroll-view>
 		</scroll-view>
 	</view>
 	</view>
 </template>
 </template>
@@ -59,60 +64,60 @@ export default {
 			// 分段器数组
 			// 分段器数组
 			headerList: ['全部', '代金券', '折扣券'],
 			headerList: ['全部', '代金券', '折扣券'],
 			list: [
 			list: [
-				{
-					id: 1,
-					type: '折扣券',
-					count: 5,
-					name: '7.5折折扣卷',
-					time: '2023.09.01',
-					msg: '7.5折',
-					info: '满200可用'
-				},
-				{
-					id: 2,
-					type: '代金券',
-					count: 2,
-					name: '20元代金券',
-					time: '2023.10.01',
-					msg: '¥10',
-					info: '无门槛'
-				},
-				{
-					id: 1,
-					type: '折扣券',
-					count: 5,
-					name: '7.5折折扣卷',
-					time: '2023.09.01',
-					msg: '7.5折',
-					info: '满200可用'
-				},
-				{
-					id: 2,
-					type: '代金券',
-					count: 2,
-					name: '20元代金券',
-					time: '2023.10.01',
-					msg: '¥10',
-					info: '无门槛'
-				},
-				{
-					id: 1,
-					type: '折扣券',
-					count: 5,
-					name: '7.5折折扣卷',
-					time: '2023.09.01',
-					msg: '7.5折',
-					info: '满200可用'
-				},
-				{
-					id: 2,
-					type: '代金券',
-					count: 2,
-					name: '20元代金券',
-					time: '2023.10.01',
-					msg: '¥10',
-					info: '无门槛'
-				}
+				// {
+				// 	id: 1,
+				// 	type: '折扣券',
+				// 	count: 5,
+				// 	name: '7.5折折扣卷',
+				// 	time: '2023.09.01',
+				// 	msg: '7.5折',
+				// 	info: '满200可用'
+				// },
+				// {
+				// 	id: 2,
+				// 	type: '代金券',
+				// 	count: 2,
+				// 	name: '20元代金券',
+				// 	time: '2023.10.01',
+				// 	msg: '¥10',
+				// 	info: '无门槛'
+				// },
+				// {
+				// 	id: 1,
+				// 	type: '折扣券',
+				// 	count: 5,
+				// 	name: '7.5折折扣卷',
+				// 	time: '2023.09.01',
+				// 	msg: '7.5折',
+				// 	info: '满200可用'
+				// },
+				// {
+				// 	id: 2,
+				// 	type: '代金券',
+				// 	count: 2,
+				// 	name: '20元代金券',
+				// 	time: '2023.10.01',
+				// 	msg: '¥10',
+				// 	info: '无门槛'
+				// },
+				// {
+				// 	id: 1,
+				// 	type: '折扣券',
+				// 	count: 5,
+				// 	name: '7.5折折扣卷',
+				// 	time: '2023.09.01',
+				// 	msg: '7.5折',
+				// 	info: '满200可用'
+				// },
+				// {
+				// 	id: 2,
+				// 	type: '代金券',
+				// 	count: 2,
+				// 	name: '20元代金券',
+				// 	time: '2023.10.01',
+				// 	msg: '¥10',
+				// 	info: '无门槛'
+				// }
 			]
 			]
 		}
 		}
 	},
 	},
@@ -303,6 +308,20 @@ export default {
 				background-color: #096562;
 				background-color: #096562;
 			}
 			}
 		}
 		}
+
+		.noData {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			padding-bottom: 20rpx;
+
+			img {
+				margin-top: 75rpx;
+				width: 600rpx;
+				height: 600rpx;
+			}
+		}
 	}
 	}
 }
 }
 </style>
 </style>

+ 96 - 42
pages/myEvaluate/myEvaluate.vue

@@ -28,9 +28,14 @@
 
 
 				<!-- 按钮区域 -->
 				<!-- 按钮区域 -->
 				<view class="box_btn">
 				<view class="box_btn">
-					<view class="btn_eva">去评价</view>
+					<view class="btn_eva" @click="handleGoPage">去评价</view>
 				</view>
 				</view>
 			</view>
 			</view>
+
+			<view class="noData" v-if="list.length === 0">
+				<img lazy-load :lazy-load-margin="0" src="../../static/images/noData.png" />
+				{{ noDataMsg }}
+			</view>
 		</scroll-view>
 		</scroll-view>
 	</view>
 	</view>
 </template>
 </template>
@@ -45,59 +50,94 @@ export default {
 			headerList: ['待评价', '已评价'],
 			headerList: ['待评价', '已评价'],
 			// 列表数据
 			// 列表数据
 			list: [
 			list: [
-				{
-					id: 1,
-					name: '民宿名称',
-					type: '已消费',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					count: 1,
-					roomType: '大床房',
-					time: '2023-07-26  -  2023-07-27',
-					total: 229
-				},
-				{
-					id: 2,
-					name: '开心民宿',
-					type: '已消费',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					count: 2,
-					roomType: '双人房',
-					time: '2023-07-27  -  2023-07-27',
-					total: 299
-				},
-				{
-					id: 3,
-					name: '开心民宿',
-					type: '已消费',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					count: 2,
-					roomType: '双人房',
-					time: '2023-07-27  -  2023-07-27',
-					total: 299
-				},
-				{
-					id: 4,
-					name: '开心民宿',
-					type: '已消费',
-					imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
-					count: 2,
-					roomType: '双人房',
-					time: '2023-07-27  -  2023-07-27',
-					total: 299
-				}
-			]
+				// {
+				// 	id: 1,
+				// 	name: '民宿名称',
+				// 	type: '已消费',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	count: 1,
+				// 	roomType: '大床房',
+				// 	time: '2023-07-26  -  2023-07-27',
+				// 	total: 229
+				// },
+				// {
+				// 	id: 2,
+				// 	name: '开心民宿',
+				// 	type: '已消费',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	count: 2,
+				// 	roomType: '双人房',
+				// 	time: '2023-07-27  -  2023-07-27',
+				// 	total: 299
+				// },
+				// {
+				// 	id: 3,
+				// 	name: '开心民宿',
+				// 	type: '已消费',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	count: 2,
+				// 	roomType: '双人房',
+				// 	time: '2023-07-27  -  2023-07-27',
+				// 	total: 299
+				// },
+				// {
+				// 	id: 4,
+				// 	name: '开心民宿',
+				// 	type: '已消费',
+				// 	imgUrl: 'https://img1.baidu.com/it/u=4085584268,3308739054&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=375',
+				// 	count: 2,
+				// 	roomType: '双人房',
+				// 	time: '2023-07-27  -  2023-07-27',
+				// 	total: 299
+				// }
+			],
+			noDataMsg: '暂无待评价数据',
+			// 当前页
+			page: 1,
+			// 每页多少条
+			rows: 6,
+			// 总条数
+			total: null
 		}
 		}
 	},
 	},
+	onLoad() {
+		this.getData()
+	},
 	methods: {
 	methods: {
+		getData() {
+			uni.request({
+				url: 'http://192.168.161.224:8088/mhotel/abcapersonageComment.action',
+				method: 'get',
+				data: {
+					usersId: uni.getStorageSync('userInfo').id,
+					status: 1,
+					page: this.page,
+					rows: this.rows
+				},
+				success: (res) => {
+					console.log(res.data)
+				}
+			})
+		},
 		// 切换分段器回调
 		// 切换分段器回调
 		onClickItem(e) {
 		onClickItem(e) {
 			if (this.current !== e.currentIndex) {
 			if (this.current !== e.currentIndex) {
 				this.current = e.currentIndex
 				this.current = e.currentIndex
+				if (this.current === 0) {
+					this.noDataMsg = '暂无待评价数据'
+				} else {
+					this.noDataMsg = '暂无已评价数据'
+				}
 			}
 			}
 		},
 		},
 		// 列表下拉到底部回调
 		// 列表下拉到底部回调
 		handlePull() {
 		handlePull() {
 			console.log(111)
 			console.log(111)
+		},
+		handleGoPage() {
+			uni.navigateTo({
+				url: '/pages/evaluate/evaluate'
+			})
 		}
 		}
 	}
 	}
 }
 }
@@ -188,6 +228,20 @@ export default {
 				}
 				}
 			}
 			}
 		}
 		}
+
+		.noData {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			padding-bottom: 20rpx;
+
+			img {
+				margin-top: 160rpx;
+				width: 600rpx;
+				height: 600rpx;
+			}
+		}
 	}
 	}
 }
 }
 </style>
 </style>

+ 96 - 44
pages/orderDetail/orderDetail.vue

@@ -3,40 +3,40 @@
 		<!-- 顶部订单状态信息区域 -->
 		<!-- 顶部订单状态信息区域 -->
 		<view class="header">
 		<view class="header">
 			<!-- 背景图片区域 -->
 			<!-- 背景图片区域 -->
-			<img src="../../static/my/headerImg.png" />
+			<img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
 			<!-- 标题区域 -->
 			<!-- 标题区域 -->
-			<view class="header_title">订单详情</view>
+			<view class="header_title" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">订单详情</view>
 			<!-- 返回图标区域 -->
 			<!-- 返回图标区域 -->
-			<view class="header_icon" @click="handleBack">
+			<view class="header_icon" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }" @click="handleBack">
 				<img src="../../static/index/left.png" />
 				<img src="../../static/index/left.png" />
 			</view>
 			</view>
 
 
-			<view class="header_type" v-if="info.orderStatus === '1'">待支付</view>
-			<view class="header_time" v-if="info.orderStatus === '1'">
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '1'">待支付</view>
+			<view class="header_time" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '1'">
 				剩余
 				剩余
 				<uv-count-down v-if="info.countDownTime" :time="info.countDownTime" format="mm:ss" @finish="finish(info)"></uv-count-down>
 				<uv-count-down v-if="info.countDownTime" :time="info.countDownTime" format="mm:ss" @finish="finish(info)"></uv-count-down>
 			</view>
 			</view>
-			<view class="header_info" v-if="info.orderStatus === '1'">超时后,订单将会自动取消</view>
-			<view class="header_type" v-if="info.orderStatus === '2'">已支付</view>
-			<view class="header_info" v-if="info.orderStatus === '2'">订单已支付,请等待商家接单</view>
-			<view class="header_type" v-if="info.orderStatus === '3'">待入住</view>
-			<view class="header_info" v-if="info.orderStatus === '3'">订单已被商家接单,请前往办理入住</view>
-			<view class="header_type" v-if="info.orderStatus === '4'">已入住</view>
-			<view class="header_info" v-if="info.orderStatus === '4'">订单已办理入住</view>
-			<view class="header_type" v-if="info.orderStatus === '5'">已消费</view>
-			<view class="header_info" v-if="info.orderStatus === '5'">您的订单已消费,期待您再次预定哦</view>
-			<view class="header_type" v-if="info.orderStatus === '6'">支付超时</view>
-			<view class="header_info" v-if="info.orderStatus === '6'">订单已超过可支付时间,请重新下单</view>
-			<view class="header_type" v-if="info.orderStatus === '7'">已取消</view>
-			<view class="header_info" v-if="info.orderStatus === '7'">订单已取消,请重新下单</view>
-			<view class="header_type" v-if="info.orderStatus === '8'">已退单</view>
-			<view class="header_info" v-if="info.orderStatus === '8'">订单已被商家退单,请重新下单</view>
-			<view class="header_type" v-if="info.orderStatus === '9'">已退款</view>
-			<view class="header_info" v-if="info.orderStatus === '9'">订单已被商家退款</view>
-			<view class="header_type" v-if="info.orderStatus === '10'">退款中</view>
-			<view class="header_info" v-if="info.orderStatus === '10'">正在退款中...</view>
-
-			<view class="header_btn">
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '1'">超时后,订单将会自动取消</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '2'">已支付</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '2'">订单已支付,请等待商家接单</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '3'">待入住</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '3'">订单已被商家接单,请前往办理入住</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '4'">已入住</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '4'">订单已办理入住</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '5'">已消费</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '5'">您的订单已消费,期待您再次预定哦</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '6'">支付超时</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '6'">订单已超过可支付时间,请重新下单</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '7'">已取消</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '7'">订单已取消,请重新下单</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '8'">已退单</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '8'">订单已被商家退单,请重新下单</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '9'">已退款</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '9'">订单已被商家退款</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="info.orderStatus === '10'">退款中</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }" v-if="info.orderStatus === '10'">正在退款中...</view>
+
+			<view class="header_btn" :style="{ paddingTop: statusBarH * 2 + 200 + 'rpx' }">
 				<view class="btn_box" v-if="info.orderStatus === '1'" @click="handlePay">去支付 ¥{{ info.houseTotalPrice }}</view>
 				<view class="btn_box" v-if="info.orderStatus === '1'" @click="handlePay">去支付 ¥{{ info.houseTotalPrice }}</view>
 				<!-- hotelIsCanorder  1可取消,0不可 -->
 				<!-- hotelIsCanorder  1可取消,0不可 -->
 				<view class="btn_box" v-if="(info.orderStatus === '2' || info.orderStatus === '3') && info.hotelIsCanorder === '1'" @click="handleCancel">取消订单</view>
 				<view class="btn_box" v-if="(info.orderStatus === '2' || info.orderStatus === '3') && info.hotelIsCanorder === '1'" @click="handleCancel">取消订单</view>
@@ -56,8 +56,6 @@
 					删除订单
 					删除订单
 				</view>
 				</view>
 			</view>
 			</view>
-
-			<!-- <view class="header_msg" v-if="info.orderStatus === '1'">预定成功后,07月26日12:00前可免费取消</view> -->
 		</view>
 		</view>
 
 
 		<!-- 主体内容区域 -->
 		<!-- 主体内容区域 -->
@@ -140,6 +138,19 @@
 					<view class="container_value">{{ (info.createTime || '').slice(0, 19) }}</view>
 					<view class="container_value">{{ (info.createTime || '').slice(0, 19) }}</view>
 				</view>
 				</view>
 			</view>
 			</view>
+
+			<!-- 投诉 服务热线区域 -->
+			<view class="body_box3">
+				<view class="box" @click="handleGoPage">
+					<img src="../../static/index/1.png" />
+					我要投诉
+				</view>
+				<!-- @click="handlePhone('18320846714')" -->
+				<view class="box">
+					<img src="../../static/index/2.png" />
+					服务热线
+				</view>
+			</view>
 		</view>
 		</view>
 	</view>
 	</view>
 </template>
 </template>
@@ -153,7 +164,11 @@ export default {
 			// 订单ID
 			// 订单ID
 			id: '',
 			id: '',
 			// 距离差
 			// 距离差
-			distance: ''
+			distance: '',
+			// 状态栏高度
+			statusBarH: 0,
+			// 胶囊按钮栏高度
+			customBarH: 0
 		}
 		}
 	},
 	},
 	onLoad(options) {
 	onLoad(options) {
@@ -161,6 +176,18 @@ export default {
 		this.distance = options.distance
 		this.distance = options.distance
 		this.getData()
 		this.getData()
 	},
 	},
+	created() {
+		// 获取系统信息
+		uni.getSystemInfo({
+			success: (e) => {
+				// 获取状态栏高度
+				this.statusBarH = e.statusBarHeight + 10
+				// // 获取菜单按钮栏高度
+				let custom = uni.getMenuButtonBoundingClientRect()
+				this.customBarH = custom.height + 10
+			}
+		})
+	},
 	methods: {
 	methods: {
 		// 获取订单信息
 		// 获取订单信息
 		async getData() {
 		async getData() {
@@ -348,6 +375,15 @@ export default {
 			if (res.code === 200) {
 			if (res.code === 200) {
 				item.orderStatus = '6'
 				item.orderStatus = '6'
 			}
 			}
+		},
+		handleGoPage() {
+			uni.showToast({
+				title: '功能开发中',
+				icon: 'none'
+			})
+			// uni.navigateTo({
+			// 	url: `/pages/complaint/complaint`
+			// })
 		}
 		}
 	}
 	}
 }
 }
@@ -369,18 +405,18 @@ export default {
 
 
 		.header_title {
 		.header_title {
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 308rpx;
 			left: 308rpx;
 			color: #fff;
 			color: #fff;
 			font-size: 28rpx;
 			font-size: 28rpx;
 		}
 		}
 
 
 		.header_icon {
 		.header_icon {
+			z-index: 2;
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 10rpx;
 			left: 10rpx;
 			width: 47rpx;
 			width: 47rpx;
-			height: 70rpx;
 
 
 			img {
 			img {
 				width: 47rpx;
 				width: 47rpx;
@@ -390,7 +426,7 @@ export default {
 
 
 		.header_type {
 		.header_type {
 			position: absolute;
 			position: absolute;
-			top: 162rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 40rpx;
 			font-size: 40rpx;
 			font-weight: bold;
 			font-weight: bold;
@@ -398,7 +434,7 @@ export default {
 
 
 		.header_time {
 		.header_time {
 			position: absolute;
 			position: absolute;
-			top: 162rpx;
+			top: 0;
 			left: 530rpx;
 			left: 530rpx;
 			display: flex;
 			display: flex;
 			align-items: center;
 			align-items: center;
@@ -408,14 +444,14 @@ export default {
 
 
 		.header_info {
 		.header_info {
 			position: absolute;
 			position: absolute;
-			top: 235rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 24rpx;
 			font-size: 24rpx;
 		}
 		}
 
 
 		.header_btn {
 		.header_btn {
 			position: absolute;
 			position: absolute;
-			top: 290rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			right: 30rpx;
 			right: 30rpx;
 			display: flex;
 			display: flex;
@@ -433,13 +469,6 @@ export default {
 				background-color: #fff;
 				background-color: #fff;
 			}
 			}
 		}
 		}
-
-		.header_msg {
-			position: absolute;
-			top: 378rpx;
-			left: 30rpx;
-			font-size: 24rpx;
-		}
 	}
 	}
 
 
 	.body {
 	.body {
@@ -538,7 +567,7 @@ export default {
 				.btn_item {
 				.btn_item {
 					display: flex;
 					display: flex;
 					align-items: center;
 					align-items: center;
-					width: 200rpx;
+					width: 220rpx;
 
 
 					.img {
 					.img {
 						margin-right: 14rpx;
 						margin-right: 14rpx;
@@ -651,6 +680,29 @@ export default {
 				}
 				}
 			}
 			}
 		}
 		}
+
+		.body_box3 {
+			display: flex;
+			align-items: center;
+			justify-content: space-around;
+			box-sizing: border-box;
+			padding: 0 110rpx;
+			height: 95rpx;
+			border-radius: 14rpx;
+			background-color: #fff;
+
+			.box {
+				display: flex;
+				align-items: center;
+				color: #096562;
+				font-size: 28rpx;
+
+				img {
+					width: 36rpx;
+					height: 36rpx;
+				}
+			}
+		}
 	}
 	}
 }
 }
 
 

+ 80 - 29
pages/orderManage/orderManage.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-	<view class="container">
+	<view class="container" v-if="total !== null">
 		<!-- 每一个订单区域 -->
 		<!-- 每一个订单区域 -->
 		<uni-swipe-action>
 		<uni-swipe-action>
 			<uni-swipe-action-item v-for="item in orderList" :key="item.id">
 			<uni-swipe-action-item v-for="item in orderList" :key="item.id">
@@ -41,6 +41,7 @@
 
 
 					<!-- 按钮区域 -->
 					<!-- 按钮区域 -->
 					<view class="box_btn" v-if="item.orderStatus === '1' || item.orderStatus === '6'">
 					<view class="box_btn" v-if="item.orderStatus === '1' || item.orderStatus === '6'">
+						<view class="btn_item" v-if="item.orderStatus === '5'" @click="handleEvaluate">去评价</view>
 						<view class="btn_item pay" v-if="item.orderStatus === '1'" @click.stop="goPagePay(item)">去支付</view>
 						<view class="btn_item pay" v-if="item.orderStatus === '1'" @click.stop="goPagePay(item)">去支付</view>
 						<view class="btn_item" v-if="item.orderStatus === '6'" @click.stop="goPageDetail(item)">再次预定</view>
 						<view class="btn_item" v-if="item.orderStatus === '6'" @click.stop="goPageDetail(item)">再次预定</view>
 					</view>
 					</view>
@@ -50,7 +51,7 @@
 
 
 		<view class="noData" v-if="!orderList.length">
 		<view class="noData" v-if="!orderList.length">
 			<img src="../../static/images/noData.png" />
 			<img src="../../static/images/noData.png" />
-			暂无数据
+			暂无订单数据
 		</view>
 		</view>
 	</view>
 	</view>
 </template>
 </template>
@@ -68,25 +69,32 @@ export default {
 			// 每页多少条数据
 			// 每页多少条数据
 			rows: 6,
 			rows: 6,
 			// 一共多少条数据
 			// 一共多少条数据
-			total: '',
+			total: null,
 			// 是否显示距离差
 			// 是否显示距离差
 			showdDistance: false,
 			showdDistance: false,
 			// 用户定位经度
 			// 用户定位经度
 			myLng: 0,
 			myLng: 0,
 			// 用户定位纬度
 			// 用户定位纬度
-			myLat: 0
+			myLat: 0,
+			// 删除数组
+			deleteList: []
 		}
 		}
 	},
 	},
 	onLoad() {
 	onLoad() {
 		this.getLocation()
 		this.getLocation()
 	},
 	},
-	// onShow() {
-	// 	this.page = 1
-	// 	this.orderList = []
-	// 	this.getLocation()
-	// },
+	onUnload() {
+		this.handleDeleteList()
+	},
+	onShow() {
+		// this.page = 1
+		// this.orderList = []
+		// this.getLocation()
+		this.deleteList = []
+	},
 	// 下拉刷新
 	// 下拉刷新
 	onPullDownRefresh() {
 	onPullDownRefresh() {
+		this.handleDeleteList()
 		setTimeout(() => {
 		setTimeout(() => {
 			this.orderList = []
 			this.orderList = []
 			this.page = 1
 			this.page = 1
@@ -234,7 +242,7 @@ export default {
 			// 	}
 			// 	}
 			// })
 			// })
 		},
 		},
-		// 点击预定按钮回调
+		// 点击去支付按钮回调
 		goPagePay(item) {
 		goPagePay(item) {
 			console.log(item.countDownTime)
 			console.log(item.countDownTime)
 			if (item.countDownTime <= 0) {
 			if (item.countDownTime <= 0) {
@@ -260,6 +268,7 @@ export default {
 					}
 					}
 				})
 				})
 			} else {
 			} else {
+				this.handleDeleteList()
 				uni.navigateTo({
 				uni.navigateTo({
 					url: `/pages/pay/pay?id=${item.id}`
 					url: `/pages/pay/pay?id=${item.id}`
 				})
 				})
@@ -267,6 +276,7 @@ export default {
 		},
 		},
 		// 点击再次预定按钮回调
 		// 点击再次预定按钮回调
 		goPageDetail(item) {
 		goPageDetail(item) {
+			this.handleDeleteList()
 			uni.navigateTo({
 			uni.navigateTo({
 				url: `/pages/detail/detail?id=${item.hotelId}&distance=${item.distance}`
 				url: `/pages/detail/detail?id=${item.hotelId}&distance=${item.distance}`
 			})
 			})
@@ -307,6 +317,7 @@ export default {
 		},
 		},
 		// 点击每一个订单回调
 		// 点击每一个订单回调
 		goPageOrderDetail(item) {
 		goPageOrderDetail(item) {
+			this.handleDeleteList()
 			// console.log(item)
 			// console.log(item)
 			uni.navigateTo({
 			uni.navigateTo({
 				url: `/pages/orderDetail/orderDetail?id=${item.id}&distance=${item.distance}`
 				url: `/pages/orderDetail/orderDetail?id=${item.id}&distance=${item.distance}`
@@ -326,27 +337,37 @@ export default {
 				uni.showModal({
 				uni.showModal({
 					title: '提示',
 					title: '提示',
 					content: '确定删除吗?删除后不可恢复',
 					content: '确定删除吗?删除后不可恢复',
-					success: async (res) => {
+					// async
+					success: (res) => {
 						if (res.confirm) {
 						if (res.confirm) {
-							const res = await this.$myRequest({
-								url: '/mhotel/abkdelBooking.action',
-								data: {
-									bookingId: item.id
-								}
+							// const res = await this.$myRequest({
+							// 	url: '/mhotel/abkdelBooking.action',
+							// 	data: {
+							// 		bookingId: item.id
+							// 	}
+							// })
+							// // console.log(res)
+							// if (res.code === 200) {
+							// 	uni.showToast({
+							// 		title: '删除成功',
+							// 		icon: 'success',
+							// 		mask: true
+							// 	})
+							// 	setTimeout(() => {
+							// 		this.orderList = []
+							// 		this.page = 1
+							// 		this.getOrderList()
+							// 	}, 1500)
+							// }
+
+							this.deleteList.push(item.id)
+							const num = this.orderList.findIndex((v) => v.id === item.id)
+							this.orderList.splice(num, 1)
+							uni.showToast({
+								title: '删除成功',
+								icon: 'success',
+								mask: true
 							})
 							})
-							// console.log(res)
-							if (res.code === 200) {
-								uni.showToast({
-									title: '删除成功',
-									icon: 'success',
-									mask: true
-								})
-								setTimeout(() => {
-									this.orderList = []
-									this.page = 1
-									this.getOrderList()
-								}, 1500)
-							}
 						}
 						}
 					}
 					}
 				})
 				})
@@ -358,6 +379,36 @@ export default {
 				})
 				})
 			}
 			}
 		},
 		},
+		// 批量删除
+		handleDeleteList() {
+			this.deleteList.forEach(async (ele) => {
+				const res = await this.$myRequest({
+					url: '/mhotel/abkdelBooking.action',
+					data: {
+						bookingId: ele
+					}
+				})
+				// console.log(res)
+				if (res.code === 200) {
+					// uni.showToast({
+					// 	title: '删除成功',
+					// 	icon: 'success',
+					// 	mask: true
+					// })
+					// setTimeout(() => {
+					// 	this.orderList = []
+					// 	this.page = 1
+					// 	this.getOrderList()
+					// }, 1500)
+				}
+			})
+		},
+		handleEvaluate() {
+			this.handleDeleteList()
+			uni.navigateTo({
+				url: `/pages/evaluate/evaluate`
+			})
+		},
 		// 计算两个点之间的距离
 		// 计算两个点之间的距离
 		calculateDistance(lat, lng) {
 		calculateDistance(lat, lng) {
 			let centerLat = lat
 			let centerLat = lat

+ 100 - 43
pages/push/push.vue

@@ -3,23 +3,23 @@
 		<!-- 顶部订单状态信息区域 -->
 		<!-- 顶部订单状态信息区域 -->
 		<view class="header">
 		<view class="header">
 			<!-- 背景图片区域 -->
 			<!-- 背景图片区域 -->
-			<img src="../../static/my/headerImg.png" />
+			<img src="https://chtech.ncjti.edu.cn/hotelReservation/image/18.png" />
 			<!-- 标题区域 -->
 			<!-- 标题区域 -->
-			<view class="header_title">订单详情</view>
+			<view class="header_title" :style="{ height: customBarH * 2 + 'rpx', paddingTop: statusBarH * 2 + 'rpx' }">订单详情</view>
 			<!-- 返回图标区域 -->
 			<!-- 返回图标区域 -->
-			<img class="header_icon" src="../../static/index/left.png" @click="handleBack" />
-
-			<view class="header_type" v-if="orderInfo.orderStatus === '1'">待支付</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '2'">已支付</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '3'">待入住</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '4'">已入住</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '5'">已消费</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '6'">支付超时</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '7'">已取消</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '8'">已退单</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '9'">已退款</view>
-			<view class="header_type" v-if="orderInfo.orderStatus === '10'">退款中</view>
-			<view class="header_info">订单号:{{ orderInfo.orderNum }}</view>
+			<!-- <img class="header_icon" src="../../static/index/left.png" @click="handleBack" /> -->
+
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '1'">待支付</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '2'">已支付</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '3'">待入住</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '4'">已入住</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '5'">已消费</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '6'">支付超时</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '7'">已取消</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '8'">已退单</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '9'">已退款</view>
+			<view class="header_type" :style="{ paddingTop: statusBarH * 2 + 72 + 'rpx' }" v-if="orderInfo.orderStatus === '10'">退款中</view>
+			<view class="header_info" :style="{ paddingTop: statusBarH * 2 + 145 + 'rpx' }">订单号:{{ orderInfo.orderNum }}</view>
 		</view>
 		</view>
 
 
 		<!-- 主体内容区域 -->
 		<!-- 主体内容区域 -->
@@ -78,6 +78,15 @@
 				<view class="btn_item type2" v-if="orderInfo.orderStatus === '2'" @click="handleOrder(1)">接单</view>
 				<view class="btn_item type2" v-if="orderInfo.orderStatus === '2'" @click="handleOrder(1)">接单</view>
 			</view>
 			</view>
 		</view>
 		</view>
+
+		<!-- 状态弹窗区域 -->
+		<uni-popup ref="popup" :is-mask-click="false" type="center">
+			<view class="popup_body">
+				<img src="../../static/index/success.png" />
+				<view class="msg">{{ msg }}</view>
+				<navigator class="btn" target="miniProgram" open-type="exit">确定</navigator>
+			</view>
+		</uni-popup>
 	</view>
 	</view>
 </template>
 </template>
 
 
@@ -88,14 +97,33 @@ export default {
 			// 订单id
 			// 订单id
 			id: '',
 			id: '',
 			// 订单信息
 			// 订单信息
-			orderInfo: null
+			orderInfo: null,
+			// 弹窗信息
+			msg: '',
+			// 状态栏高度
+			statusBarH: 0,
+			// 胶囊按钮栏高度
+			customBarH: 0
 		}
 		}
 	},
 	},
+	created() {
+		// 获取系统信息
+		uni.getSystemInfo({
+			success: (e) => {
+				// 获取状态栏高度
+				this.statusBarH = e.statusBarHeight + 10
+				// // 获取菜单按钮栏高度
+				let custom = uni.getMenuButtonBoundingClientRect()
+				this.customBarH = custom.height + 10
+			}
+		})
+	},
 	onLoad(options) {
 	onLoad(options) {
 		this.id = options.id
 		this.id = options.id
 		this.getData()
 		this.getData()
 	},
 	},
 	methods: {
 	methods: {
+		// 获取订单信息
 		async getData() {
 		async getData() {
 			const res = await this.$myRequest({
 			const res = await this.$myRequest({
 				url: '/mhotel/ampgetBookingById.action',
 				url: '/mhotel/ampgetBookingById.action',
@@ -137,16 +165,8 @@ export default {
 			})
 			})
 			// console.log(res)
 			// console.log(res)
 			if (res.code === 200) {
 			if (res.code === 200) {
-				uni.showToast({
-					title: `接单成功`,
-					icon: 'success',
-					mask: true
-				})
-				setTimeout(() => {
-					uni.switchTab({
-						url: '/pages/home/home'
-					})
-				}, 1500)
+				this.msg = '接单成功'
+				this.$refs.popup.open()
 			}
 			}
 		},
 		},
 		async chargeback() {
 		async chargeback() {
@@ -158,16 +178,8 @@ export default {
 			})
 			})
 			// console.log(res)
 			// console.log(res)
 			if (res.code === 200) {
 			if (res.code === 200) {
-				uni.showToast({
-					title: res.message,
-					icon: 'none',
-					mask: true
-				})
-				setTimeout(() => {
-					uni.switchTab({
-						url: '/pages/home/home'
-					})
-				}, 1500)
+				this.msg = '退单成功'
+				this.$refs.popup.open()
 			}
 			}
 		},
 		},
 		// 点击左上角返回按钮回调
 		// 点击左上角返回按钮回调
@@ -215,7 +227,7 @@ export default {
 
 
 		.header_title {
 		.header_title {
 			position: absolute;
 			position: absolute;
-			top: 65rpx;
+			top: 0;
 			left: 308rpx;
 			left: 308rpx;
 			color: #fff;
 			color: #fff;
 			font-size: 28rpx;
 			font-size: 28rpx;
@@ -223,7 +235,7 @@ export default {
 
 
 		.header_icon {
 		.header_icon {
 			position: absolute;
 			position: absolute;
-			top: 76rpx;
+			top: 0;
 			left: 10rpx;
 			left: 10rpx;
 			width: 47rpx;
 			width: 47rpx;
 			height: 47rpx;
 			height: 47rpx;
@@ -231,7 +243,7 @@ export default {
 
 
 		.header_type {
 		.header_type {
 			position: absolute;
 			position: absolute;
-			top: 144rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 40rpx;
 			font-size: 40rpx;
 			font-weight: bold;
 			font-weight: bold;
@@ -239,7 +251,7 @@ export default {
 
 
 		.header_info {
 		.header_info {
 			position: absolute;
 			position: absolute;
-			top: 215rpx;
+			top: 0;
 			left: 30rpx;
 			left: 30rpx;
 			font-size: 24rpx;
 			font-size: 24rpx;
 		}
 		}
@@ -247,12 +259,12 @@ export default {
 
 
 	.body {
 	.body {
 		position: absolute;
 		position: absolute;
-		top: 278rpx;
+		top: 320rpx;
 		left: 0;
 		left: 0;
 		right: 0;
 		right: 0;
 		box-sizing: border-box;
 		box-sizing: border-box;
-		padding: 20rpx;
-		height: calc(100vh - 278rpx);
+		padding: 20rpx 20rpx 60rpx;
+		height: calc(100vh - 320rpx);
 		border-radius: 20rpx 20rpx 0 0;
 		border-radius: 20rpx 20rpx 0 0;
 		background-color: #ebeced;
 		background-color: #ebeced;
 		overflow-y: auto;
 		overflow-y: auto;
@@ -483,6 +495,51 @@ export default {
 				background-color: #096562;
 				background-color: #096562;
 			}
 			}
 		}
 		}
+
+		.close_btn {
+			margin: 32rpx;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 300rpx;
+			height: 96rpx;
+			border-radius: 64rpx;
+			font-size: 32rpx;
+			color: #d43030;
+			border: 1rpx solid #d43030;
+		}
+	}
+
+	.popup_body {
+		display: flex;
+		flex-direction: column;
+		justify-content: space-evenly;
+		align-items: center;
+		width: 481rpx;
+		height: 404rpx;
+		border-radius: 23rpx;
+		background-color: #fff;
+
+		img {
+			width: 134rpx;
+			height: 134rpx;
+		}
+
+		.msg {
+			font-size: 26rpx;
+		}
+
+		.btn {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 200rpx;
+			height: 76rpx;
+			font-size: 26rpx;
+			color: #fff;
+			border-radius: 43rpx;
+			background: linear-gradient(90deg, rgba(11, 193, 150, 1) 0%, rgba(9, 101, 98, 1) 100%);
+		}
 	}
 	}
 }
 }
 </style>
 </style>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 174 - 0
pages/strategyDetatil/strategyDetatil.vue


BIN
static/index/1.png


BIN
static/index/2.png


BIN
static/index/close2.png


BIN
static/index/coupon.png


BIN
static/index/hotel2.png


BIN
static/index/left2.png


BIN
static/index/photo.png


BIN
static/index/star.png


BIN
static/my/headerImg.png


+ 67 - 0
uni_modules/uni-file-picker/changelog.md

@@ -0,0 +1,67 @@
+## 1.0.4(2023-03-29)
+- 修复 手动上传删除一个文件后不能再上传的bug
+## 1.0.3(2022-12-19)
+- 新增 sourceType 属性, 可以自定义图片和视频选择的来源
+## 1.0.2(2022-07-04)
+- 修复 在uni-forms下样式不生效的bug
+## 1.0.1(2021-11-23)
+- 修复 参数为对象的情况下,url在某些情况显示错误的bug
+## 1.0.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-file-picker](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+## 0.2.16(2021-11-08)
+- 修复 传入空对象 ,显示错误的Bug
+## 0.2.15(2021-08-30)
+- 修复 return-type="object" 时且存在v-model时,无法删除文件的Bug
+## 0.2.14(2021-08-23)
+- 新增 参数中返回 fileID 字段
+## 0.2.13(2021-08-23)
+- 修复 腾讯云传入fileID 不能回显的bug
+- 修复 选择图片后,不能放大的问题
+## 0.2.12(2021-08-17)
+- 修复 由于 0.2.11 版本引起的不能回显图片的Bug
+## 0.2.11(2021-08-16)
+- 新增 clearFiles(index) 方法,可以手动删除指定文件
+- 修复 v-model 值设为 null 报错的Bug
+## 0.2.10(2021-08-13)
+- 修复 return-type="object" 时,无法删除文件的Bug
+## 0.2.9(2021-08-03)
+- 修复 auto-upload 属性失效的Bug
+## 0.2.8(2021-07-31)
+- 修复 fileExtname属性不指定值报错的Bug
+## 0.2.7(2021-07-31)
+- 修复 在某种场景下图片不回显的Bug
+## 0.2.6(2021-07-30)
+- 修复 return-type为object下,返回值不正确的Bug
+## 0.2.5(2021-07-30)
+- 修复(重要) H5 平台下如果和uni-forms组件一同使用导致页面卡死的问题
+## 0.2.3(2021-07-28)
+- 优化 调整示例代码
+## 0.2.2(2021-07-27)
+- 修复 vue3 下赋值错误的Bug
+- 优化 h5平台下上传文件导致页面卡死的问题
+## 0.2.0(2021-07-13)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 0.1.1(2021-07-02)
+- 修复 sourceType 缺少默认值导致 ios 无法选择文件
+## 0.1.0(2021-06-30)
+- 优化 解耦与uniCloud的强绑定关系 ,如不绑定服务空间,默认autoUpload为false且不可更改
+## 0.0.11(2021-06-30)
+- 修复 由 0.0.10 版本引发的 returnType 属性失效的问题
+## 0.0.10(2021-06-29)
+- 优化 文件上传后进度条消失时机
+## 0.0.9(2021-06-29)
+- 修复 在uni-forms 中,删除文件 ,获取的值不对的Bug
+## 0.0.8(2021-06-15)
+- 修复 删除文件时无法触发 v-model 的Bug
+## 0.0.7(2021-05-12)
+- 新增 组件示例地址
+## 0.0.6(2021-04-09)
+- 修复 选择的文件非 file-extname 字段指定的扩展名报错的Bug
+## 0.0.5(2021-04-09)
+- 优化 更新组件示例
+## 0.0.4(2021-04-09)
+- 优化 file-extname 字段支持字符串写法,多个扩展名需要用逗号分隔
+## 0.0.3(2021-02-05)
+- 调整为uni_modules目录规范
+- 修复 微信小程序不指定 fileExtname 属性选择失败的Bug

+ 224 - 0
uni_modules/uni-file-picker/components/uni-file-picker/choose-and-upload-file.js

@@ -0,0 +1,224 @@
+'use strict';
+
+const ERR_MSG_OK = 'chooseAndUploadFile:ok';
+const ERR_MSG_FAIL = 'chooseAndUploadFile:fail';
+
+function chooseImage(opts) {
+	const {
+		count,
+		sizeType = ['original', 'compressed'],
+		sourceType,
+		extension
+	} = opts
+	return new Promise((resolve, reject) => {
+		uni.chooseImage({
+			count,
+			sizeType,
+			sourceType,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res, 'image'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseImage:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseVideo(opts) {
+	const {
+		camera,
+		compressed,
+		maxDuration,
+		sourceType,
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		uni.chooseVideo({
+			camera,
+			compressed,
+			maxDuration,
+			sourceType,
+			extension,
+			success(res) {
+				const {
+					tempFilePath,
+					duration,
+					size,
+					height,
+					width
+				} = res;
+				resolve(normalizeChooseAndUploadFileRes({
+					errMsg: 'chooseVideo:ok',
+					tempFilePaths: [tempFilePath],
+					tempFiles: [
+					{
+						name: (res.tempFile && res.tempFile.name) || '',
+						path: tempFilePath,
+						size,
+						type: (res.tempFile && res.tempFile.type) || '',
+						width,
+						height,
+						duration,
+						fileType: 'video',
+						cloudPath: '',
+					}, ],
+				}, 'video'));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseVideo:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function chooseAll(opts) {
+	const {
+		count,
+		extension
+	} = opts;
+	return new Promise((resolve, reject) => {
+		let chooseFile = uni.chooseFile;
+		if (typeof wx !== 'undefined' &&
+			typeof wx.chooseMessageFile === 'function') {
+			chooseFile = wx.chooseMessageFile;
+		}
+		if (typeof chooseFile !== 'function') {
+			return reject({
+				errMsg: ERR_MSG_FAIL + ' 请指定 type 类型,该平台仅支持选择 image 或 video。',
+			});
+		}
+		chooseFile({
+			type: 'all',
+			count,
+			extension,
+			success(res) {
+				resolve(normalizeChooseAndUploadFileRes(res));
+			},
+			fail(res) {
+				reject({
+					errMsg: res.errMsg.replace('chooseFile:fail', ERR_MSG_FAIL),
+				});
+			},
+		});
+	});
+}
+
+function normalizeChooseAndUploadFileRes(res, fileType) {
+	res.tempFiles.forEach((item, index) => {
+		if (!item.name) {
+			item.name = item.path.substring(item.path.lastIndexOf('/') + 1);
+		}
+		if (fileType) {
+			item.fileType = fileType;
+		}
+		item.cloudPath =
+			Date.now() + '_' + index + item.name.substring(item.name.lastIndexOf('.'));
+	});
+	if (!res.tempFilePaths) {
+		res.tempFilePaths = res.tempFiles.map((file) => file.path);
+	}
+	return res;
+}
+
+function uploadCloudFiles(files, max = 5, onUploadProgress) {
+	files = JSON.parse(JSON.stringify(files))
+	const len = files.length
+	let count = 0
+	let self = this
+	return new Promise(resolve => {
+		while (count < max) {
+			next()
+		}
+
+		function next() {
+			let cur = count++
+			if (cur >= len) {
+				!files.find(item => !item.url && !item.errMsg) && resolve(files)
+				return
+			}
+			const fileItem = files[cur]
+			const index = self.files.findIndex(v => v.uuid === fileItem.uuid)
+			fileItem.url = ''
+			delete fileItem.errMsg
+
+			uniCloud
+				.uploadFile({
+					filePath: fileItem.path,
+					cloudPath: fileItem.cloudPath,
+					fileType: fileItem.fileType,
+					onUploadProgress: res => {
+						res.index = index
+						onUploadProgress && onUploadProgress(res)
+					}
+				})
+				.then(res => {
+					fileItem.url = res.fileID
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+				.catch(res => {
+					fileItem.errMsg = res.errMsg || res.message
+					fileItem.index = index
+					if (cur < len) {
+						next()
+					}
+				})
+		}
+	})
+}
+
+
+
+
+
+function uploadFiles(choosePromise, {
+	onChooseFile,
+	onUploadProgress
+}) {
+	return choosePromise
+		.then((res) => {
+			if (onChooseFile) {
+				const customChooseRes = onChooseFile(res);
+				if (typeof customChooseRes !== 'undefined') {
+					return Promise.resolve(customChooseRes).then((chooseRes) => typeof chooseRes === 'undefined' ?
+						res : chooseRes);
+				}
+			}
+			return res;
+		})
+		.then((res) => {
+			if (res === false) {
+				return {
+					errMsg: ERR_MSG_OK,
+					tempFilePaths: [],
+					tempFiles: [],
+				};
+			}
+			return res
+		})
+}
+
+function chooseAndUploadFile(opts = {
+	type: 'all'
+}) {
+	if (opts.type === 'image') {
+		return uploadFiles(chooseImage(opts), opts);
+	}
+	else if (opts.type === 'video') {
+		return uploadFiles(chooseVideo(opts), opts);
+	}
+	return uploadFiles(chooseAll(opts), opts);
+}
+
+export {
+	chooseAndUploadFile,
+	uploadCloudFiles
+};

+ 667 - 0
uni_modules/uni-file-picker/components/uni-file-picker/uni-file-picker.vue

@@ -0,0 +1,667 @@
+<template>
+	<view class="uni-file-picker">
+		<view v-if="title" class="uni-file-picker__header">
+			<text class="file-title">{{ title }}</text>
+			<text class="file-count">{{ filesList.length }}/{{ limitLength }}</text>
+		</view>
+		<upload-image v-if="fileMediatype === 'image' && showType === 'grid'" :readonly="readonly"
+			:image-styles="imageStyles" :files-list="filesList" :limit="limitLength" :disablePreview="disablePreview"
+			:delIcon="delIcon" @uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+			<slot>
+				<view class="is-add">
+					<view class="icon-add"></view>
+					<view class="icon-add rotate"></view>
+				</view>
+			</slot>
+		</upload-image>
+		<upload-file v-if="fileMediatype !== 'image' || showType !== 'grid'" :readonly="readonly"
+			:list-styles="listStyles" :files-list="filesList" :showType="showType" :delIcon="delIcon"
+			@uploadFiles="uploadFiles" @choose="choose" @delFile="delFile">
+			<slot><button type="primary" size="mini">选择文件</button></slot>
+		</upload-file>
+	</view>
+</template>
+
+<script>
+	import {
+		chooseAndUploadFile,
+		uploadCloudFiles
+	} from './choose-and-upload-file.js'
+	import {
+		get_file_ext,
+		get_extname,
+		get_files_and_is_max,
+		get_file_info,
+		get_file_data
+	} from './utils.js'
+	import uploadImage from './upload-image.vue'
+	import uploadFile from './upload-file.vue'
+	let fileInput = null
+	/**
+	 * FilePicker 文件选择上传
+	 * @description 文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=4079
+	 * @property {Object|Array}	value	组件数据,通常用来回显 ,类型由return-type属性决定
+	 * @property {Boolean}	disabled = [true|false]	组件禁用
+	 * 	@value true 	禁用
+	 * 	@value false 	取消禁用
+	 * @property {Boolean}	readonly = [true|false]	组件只读,不可选择,不显示进度,不显示删除按钮
+	 * 	@value true 	只读
+	 * 	@value false 	取消只读
+	 * @property {String}	return-type = [array|object]	限制 value 格式,当为 object 时 ,组件只能单选,且会覆盖
+	 * 	@value array	规定 value 属性的类型为数组
+	 * 	@value object	规定 value 属性的类型为对象
+	 * @property {Boolean}	disable-preview = [true|false]	禁用图片预览,仅 mode:grid 时生效
+	 * 	@value true 	禁用图片预览
+	 * 	@value false 	取消禁用图片预览
+	 * @property {Boolean}	del-icon = [true|false]	是否显示删除按钮
+	 * 	@value true 	显示删除按钮
+	 * 	@value false 	不显示删除按钮
+	 * @property {Boolean}	auto-upload = [true|false]	是否自动上传,值为true则只触发@select,可自行上传
+	 * 	@value true 	自动上传
+	 * 	@value false 	取消自动上传
+	 * @property {Number|String}	limit	最大选择个数 ,h5 会自动忽略多选的部分
+	 * @property {String}	title	组件标题,右侧显示上传计数
+	 * @property {String}	mode = [list|grid]	选择文件后的文件列表样式
+	 * 	@value list 	列表显示
+	 * 	@value grid 	宫格显示
+	 * @property {String}	file-mediatype = [image|video|all]	选择文件类型
+	 * 	@value image	只选择图片
+	 * 	@value video	只选择视频
+	 * 	@value all		选择所有文件
+	 * @property {Array}	file-extname	选择文件后缀,根据 file-mediatype 属性而不同
+	 * @property {Object}	list-style	mode:list 时的样式
+	 * @property {Object}	image-styles	选择文件后缀,根据 file-mediatype 属性而不同
+	 * @event {Function} select 	选择文件后触发
+	 * @event {Function} progress 文件上传时触发
+	 * @event {Function} success 	上传成功触发
+	 * @event {Function} fail 		上传失败触发
+	 * @event {Function} delete 	文件从列表移除时触发
+	 */
+	export default {
+		name: 'uniFilePicker',
+		components: {
+			uploadImage,
+			uploadFile
+		},
+		options: {
+			virtualHost: true
+		},
+		emits: ['select', 'success', 'fail', 'progress', 'delete', 'update:modelValue', 'input'],
+		props: {
+			// #ifdef VUE3
+			modelValue: {
+				type: [Array, Object],
+				default () {
+					return []
+				}
+			},
+			// #endif
+
+			// #ifndef VUE3
+			value: {
+				type: [Array, Object],
+				default () {
+					return []
+				}
+			},
+			// #endif
+
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			disablePreview: {
+				type: Boolean,
+				default: false
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			// 自动上传
+			autoUpload: {
+				type: Boolean,
+				default: true
+			},
+			// 最大选择个数 ,h5只能限制单选或是多选
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			// 列表样式 grid | list | list-card
+			mode: {
+				type: String,
+				default: 'grid'
+			},
+			// 选择文件类型  image/video/all
+			fileMediatype: {
+				type: String,
+				default: 'image'
+			},
+			// 文件类型筛选
+			fileExtname: {
+				type: [Array, String],
+				default () {
+					return []
+				}
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			listStyles: {
+				type: Object,
+				default () {
+					return {
+						// 是否显示边框
+						border: true,
+						// 是否显示分隔线
+						dividline: true,
+						// 线条样式
+						borderStyle: {}
+					}
+				}
+			},
+			imageStyles: {
+				type: Object,
+				default () {
+					return {
+						width: 'auto',
+						height: 'auto'
+					}
+				}
+			},
+			readonly: {
+				type: Boolean,
+				default: false
+			},
+			returnType: {
+				type: String,
+				default: 'array'
+			},
+			sizeType: {
+				type: Array,
+				default () {
+					return ['original', 'compressed']
+				}
+			},
+			sourceType: {
+				type: Array,
+				default () {
+					return  ['album', 'camera']
+				}
+			}
+		},
+		data() {
+			return {
+				files: [],
+				localValue: []
+			}
+		},
+		watch: {
+			// #ifndef VUE3
+			value: {
+				handler(newVal, oldVal) {
+					this.setValue(newVal, oldVal)
+				},
+				immediate: true
+			},
+			// #endif
+			// #ifdef VUE3
+			modelValue: {
+				handler(newVal, oldVal) {
+					this.setValue(newVal, oldVal)
+				},
+				immediate: true
+			},
+			// #endif
+		},
+		computed: {
+			filesList() {
+				let files = []
+				this.files.forEach(v => {
+					files.push(v)
+				})
+				return files
+			},
+			showType() {
+				if (this.fileMediatype === 'image') {
+					return this.mode
+				}
+				return 'list'
+			},
+			limitLength() {
+				if (this.returnType === 'object') {
+					return 1
+				}
+				if (!this.limit) {
+					return 1
+				}
+				if (this.limit >= 9) {
+					return 9
+				}
+				return this.limit
+			}
+		},
+		created() {
+			// TODO 兼容不开通服务空间的情况
+			if (!(uniCloud.config && uniCloud.config.provider)) {
+				this.noSpace = true
+				uniCloud.chooseAndUploadFile = chooseAndUploadFile
+			}
+			this.form = this.getForm('uniForms')
+			this.formItem = this.getForm('uniFormsItem')
+			if (this.form && this.formItem) {
+				if (this.formItem.name) {
+					this.rename = this.formItem.name
+					this.form.inputChildrens.push(this)
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 公开用户使用,清空文件
+			 * @param {Object} index
+			 */
+			clearFiles(index) {
+				if (index !== 0 && !index) {
+					this.files = []
+					this.$nextTick(() => {
+						this.setEmit()
+					})
+				} else {
+					this.files.splice(index, 1)
+				}
+				this.$nextTick(() => {
+					this.setEmit()
+				})
+			},
+			/**
+			 * 公开用户使用,继续上传
+			 */
+			upload() {
+				let files = []
+				this.files.forEach((v, index) => {
+					if (v.status === 'ready' || v.status === 'error') {
+						files.push(Object.assign({}, v))
+					}
+				})
+				return this.uploadFiles(files)
+			},
+			async setValue(newVal, oldVal) {
+				const newData =  async (v) => {
+					const reg = /cloud:\/\/([\w.]+\/?)\S*/
+					let url = ''
+					if(v.fileID){
+						url = v.fileID
+					}else{
+						url = v.url
+					}
+					if (reg.test(url)) {
+						v.fileID = url
+						v.url = await this.getTempFileURL(url)
+					}
+					if(v.url) v.path = v.url
+					return v
+				}
+				if (this.returnType === 'object') {
+					if (newVal) {
+						await newData(newVal)
+					} else {
+						newVal = {}
+					}
+				} else {
+					if (!newVal) newVal = []
+					for(let i =0 ;i < newVal.length ;i++){
+						let v = newVal[i]
+						await newData(v)
+					}
+				}
+				this.localValue = newVal
+				if (this.form && this.formItem &&!this.is_reset) {
+					this.is_reset = false
+					this.formItem.setValue(this.localValue)
+				}
+				let filesData = Object.keys(newVal).length > 0 ? newVal : [];
+				this.files = [].concat(filesData)
+			},
+
+			/**
+			 * 选择文件
+			 */
+			choose() {
+
+				if (this.disabled) return
+				if (this.files.length >= Number(this.limitLength) && this.showType !== 'grid' && this.returnType ===
+					'array') {
+					uni.showToast({
+						title: `您最多选择 ${this.limitLength} 个文件`,
+						icon: 'none'
+					})
+					return
+				}
+				this.chooseFiles()
+			},
+
+			/**
+			 * 选择文件并上传
+			 */
+			chooseFiles() {
+				const _extname = get_extname(this.fileExtname)
+				// 获取后缀
+				uniCloud
+					.chooseAndUploadFile({
+						type: this.fileMediatype,
+						compressed: false,
+						sizeType: this.sizeType,
+						sourceType: this.sourceType,
+						// TODO 如果为空,video 有问题
+						extension: _extname.length > 0 ? _extname : undefined,
+						count: this.limitLength - this.files.length, //默认9
+						onChooseFile: this.chooseFileCallback,
+						onUploadProgress: progressEvent => {
+							this.setProgress(progressEvent, progressEvent.index)
+						}
+					})
+					.then(result => {
+						this.setSuccessAndError(result.tempFiles)
+					})
+					.catch(err => {
+						console.log('选择失败', err)
+					})
+			},
+
+			/**
+			 * 选择文件回调
+			 * @param {Object} res
+			 */
+			async chooseFileCallback(res) {
+				const _extname = get_extname(this.fileExtname)
+				const is_one = (Number(this.limitLength) === 1 &&
+						this.disablePreview &&
+						!this.disabled) ||
+					this.returnType === 'object'
+				// 如果这有一个文件 ,需要清空本地缓存数据
+				if (is_one) {
+					this.files = []
+				}
+
+				let {
+					filePaths,
+					files
+				} = get_files_and_is_max(res, _extname)
+				if (!(_extname && _extname.length > 0)) {
+					filePaths = res.tempFilePaths
+					files = res.tempFiles
+				}
+
+				let currentData = []
+				for (let i = 0; i < files.length; i++) {
+					if (this.limitLength - this.files.length <= 0) break
+					files[i].uuid = Date.now()
+					let filedata = await get_file_data(files[i], this.fileMediatype)
+					filedata.progress = 0
+					filedata.status = 'ready'
+					this.files.push(filedata)
+					currentData.push({
+						...filedata,
+						file: files[i]
+					})
+				}
+				this.$emit('select', {
+					tempFiles: currentData,
+					tempFilePaths: filePaths
+				})
+				res.tempFiles = files
+				// 停止自动上传
+				if (!this.autoUpload || this.noSpace) {
+					res.tempFiles = []
+				}
+			},
+
+			/**
+			 * 批传
+			 * @param {Object} e
+			 */
+			uploadFiles(files) {
+				files = [].concat(files)
+				return uploadCloudFiles.call(this, files, 5, res => {
+						this.setProgress(res, res.index, true)
+					})
+					.then(result => {
+						this.setSuccessAndError(result)
+						return result;
+					})
+					.catch(err => {
+						console.log(err)
+					})
+			},
+
+			/**
+			 * 成功或失败
+			 */
+			async setSuccessAndError(res, fn) {
+				let successData = []
+				let errorData = []
+				let tempFilePath = []
+				let errorTempFilePath = []
+				for (let i = 0; i < res.length; i++) {
+					const item = res[i]
+					const index = item.uuid ? this.files.findIndex(p => p.uuid === item.uuid) : item.index
+
+					if (index === -1 || !this.files) break
+					if (item.errMsg === 'request:fail') {
+						this.files[index].url = item.path
+						this.files[index].status = 'error'
+						this.files[index].errMsg = item.errMsg
+						// this.files[index].progress = -1
+						errorData.push(this.files[index])
+						errorTempFilePath.push(this.files[index].url)
+					} else {
+						this.files[index].errMsg = ''
+						this.files[index].fileID = item.url
+						const reg = /cloud:\/\/([\w.]+\/?)\S*/
+						if (reg.test(item.url)) {
+							this.files[index].url = await this.getTempFileURL(item.url)
+						}else{
+							this.files[index].url = item.url
+						}
+
+						this.files[index].status = 'success'
+						this.files[index].progress += 1
+						successData.push(this.files[index])
+						tempFilePath.push(this.files[index].fileID)
+					}
+				}
+
+				if (successData.length > 0) {
+					this.setEmit()
+					// 状态改变返回
+					this.$emit('success', {
+						tempFiles: this.backObject(successData),
+						tempFilePaths: tempFilePath
+					})
+				}
+
+				if (errorData.length > 0) {
+					this.$emit('fail', {
+						tempFiles: this.backObject(errorData),
+						tempFilePaths: errorTempFilePath
+					})
+				}
+			},
+
+			/**
+			 * 获取进度
+			 * @param {Object} progressEvent
+			 * @param {Object} index
+			 * @param {Object} type
+			 */
+			setProgress(progressEvent, index, type) {
+				const fileLenth = this.files.length
+				const percentNum = (index / fileLenth) * 100
+				const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total)
+				let idx = index
+				if (!type) {
+					idx = this.files.findIndex(p => p.uuid === progressEvent.tempFile.uuid)
+				}
+				if (idx === -1 || !this.files[idx]) return
+				// fix by mehaotian 100 就会消失,-1 是为了让进度条消失
+				this.files[idx].progress = percentCompleted - 1
+				// 上传中
+				this.$emit('progress', {
+					index: idx,
+					progress: parseInt(percentCompleted),
+					tempFile: this.files[idx]
+				})
+			},
+
+			/**
+			 * 删除文件
+			 * @param {Object} index
+			 */
+			delFile(index) {
+				this.$emit('delete', {
+					tempFile: this.files[index],
+					tempFilePath: this.files[index].url
+				})
+				this.files.splice(index, 1)
+				this.$nextTick(() => {
+					this.setEmit()
+				})
+			},
+
+			/**
+			 * 获取文件名和后缀
+			 * @param {Object} name
+			 */
+			getFileExt(name) {
+				const last_len = name.lastIndexOf('.')
+				const len = name.length
+				return {
+					name: name.substring(0, last_len),
+					ext: name.substring(last_len + 1, len)
+				}
+			},
+
+			/**
+			 * 处理返回事件
+			 */
+			setEmit() {
+				let data = []
+				if (this.returnType === 'object') {
+					data = this.backObject(this.files)[0]
+					this.localValue = data?data:null
+				} else {
+					data = this.backObject(this.files)
+					if (!this.localValue) {
+						this.localValue = []
+					}
+					this.localValue = [...data]
+				}
+				// #ifdef VUE3
+				this.$emit('update:modelValue', this.localValue)
+				// #endif
+				// #ifndef VUE3
+				this.$emit('input', this.localValue)
+				// #endif
+			},
+
+			/**
+			 * 处理返回参数
+			 * @param {Object} files
+			 */
+			backObject(files) {
+				let newFilesData = []
+				files.forEach(v => {
+					newFilesData.push({
+						extname: v.extname,
+						fileType: v.fileType,
+						image: v.image,
+						name: v.name,
+						path: v.path,
+						size: v.size,
+						fileID:v.fileID,
+						url: v.url,
+						// 修改删除一个文件后不能再上传的bug, #694
+            uuid: v.uuid,
+            status: v.status,
+            cloudPath: v.cloudPath
+					})
+				})
+				return newFilesData
+			},
+			async getTempFileURL(fileList) {
+				fileList = {
+					fileList: [].concat(fileList)
+				}
+				const urls = await uniCloud.getTempFileURL(fileList)
+				return urls.fileList[0].tempFileURL || ''
+			},
+			/**
+			 * 获取父元素实例
+			 */
+			getForm(name = 'uniForms') {
+				let parent = this.$parent;
+				let parentName = parent.$options.name;
+				while (parentName !== name) {
+					parent = parent.$parent;
+					if (!parent) return false;
+					parentName = parent.$options.name;
+				}
+				return parent;
+			}
+		}
+	}
+</script>
+
+<style>
+	.uni-file-picker {
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		overflow: hidden;
+		width: 100%;
+		/* #endif */
+		flex: 1;
+	}
+
+	.uni-file-picker__header {
+		padding-top: 5px;
+		padding-bottom: 10px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: space-between;
+	}
+
+	.file-title {
+		font-size: 14px;
+		color: #333;
+	}
+
+	.file-count {
+		font-size: 14px;
+		color: #999;
+	}
+
+	.is-add {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-add {
+		width: 50px;
+		height: 5px;
+		background-color: #f1f1f1;
+		border-radius: 2px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+</style>

+ 325 - 0
uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue

@@ -0,0 +1,325 @@
+<template>
+	<view class="uni-file-picker__files">
+		<view v-if="!readonly" class="files-button" @click="choose">
+			<slot></slot>
+		</view>
+		<!-- :class="{'is-text-box':showType === 'list'}" -->
+		<view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
+			<!-- ,'is-list-card':showType === 'list-card' -->
+
+			<view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
+				'files-border':index !== 0 && styles.dividline}"
+			 :style="index !== 0 && styles.dividline &&borderLineStyle">
+				<view class="uni-file-picker__item">
+					<!-- :class="{'is-text-image':showType === 'list'}" -->
+					<!-- 	<view class="files__image is-text-image">
+						<image class="header-image" :src="item.logo" mode="aspectFit"></image>
+					</view> -->
+					<view class="files__name">{{item.name}}</view>
+					<view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
+						<view class="icon-del icon-files"></view>
+						<view class="icon-del rotate"></view>
+					</view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+				</view>
+				<view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadFile",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			showType: {
+				type: String,
+				default: ''
+			},
+			listStyles: {
+				type: Object,
+				default () {
+					return {
+						// 是否显示边框
+						border: true,
+						// 是否显示分隔线
+						dividline: true,
+						// 线条样式
+						borderStyle: {}
+					}
+				}
+			},
+			readonly:{
+				type:Boolean,
+				default:false
+			}
+		},
+		computed: {
+			list() {
+				let files = []
+				this.filesList.forEach(v => {
+					files.push(v)
+				})
+				return files
+			},
+			styles() {
+				let styles = {
+					border: true,
+					dividline: true,
+					'border-style': {}
+				}
+				return Object.assign(styles, this.listStyles)
+			},
+			borderStyle() {
+				let {
+					borderStyle,
+					border
+				} = this.styles
+				let obj = {}
+				if (!border) {
+					obj.border = 'none'
+				} else {
+					let width = (borderStyle && borderStyle.width) || 1
+					width = this.value2px(width)
+					let radius = (borderStyle && borderStyle.radius) || 5
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (borderStyle && borderStyle.style) || 'solid',
+						'border-color': (borderStyle && borderStyle.color) || '#eee',
+						'border-radius': radius
+					}
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
+				}
+				return classles
+			},
+			borderLineStyle() {
+				let obj = {}
+				let {
+					borderStyle
+				} = this.styles
+				if (borderStyle && borderStyle.color) {
+					obj['border-color'] = borderStyle.color
+				}
+				if (borderStyle && borderStyle.width) {
+					let width = borderStyle && borderStyle.width || 1
+					let style = borderStyle && borderStyle.style || 0
+					if (typeof width === 'number') {
+						width += 'px'
+					} else {
+						width = width.indexOf('px') ? width : width + 'px'
+					}
+					obj['border-width'] = width
+
+					if (typeof style === 'number') {
+						style += 'px'
+					} else {
+						style = style.indexOf('px') ? style : style + 'px'
+					}
+					obj['border-top-style'] = style
+				}
+				let classles = ''
+				for (let i in obj) {
+					classles += `${i}:${obj[i]};`
+				}
+				return classles
+			}
+		},
+
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", {
+					item,
+					index
+				})
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					value = value.indexOf('px') !== -1 ? value : value + 'px'
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-file-picker__files {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex-direction: column;
+		justify-content: flex-start;
+	}
+
+	.files-button {
+		// border: 1px red solid;
+	}
+
+	.uni-file-picker__lists {
+		position: relative;
+		margin-top: 5px;
+		overflow: hidden;
+	}
+
+	.file-picker__mask {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 14px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.uni-file-picker__lists-box {
+		position: relative;
+	}
+
+	.uni-file-picker__item {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		padding: 8px 10px;
+		padding-right: 5px;
+		padding-left: 10px;
+	}
+
+	.files-border {
+		border-top: 1px #eee solid;
+	}
+
+	.files__name {
+		flex: 1;
+		font-size: 14px;
+		color: #666;
+		margin-right: 25px;
+		/* #ifndef APP-NVUE */
+		word-break: break-all;
+		word-wrap: break-word;
+		/* #endif */
+	}
+
+	.icon-files {
+		/* #ifndef APP-NVUE */
+		position: static;
+		background-color: initial;
+		/* #endif */
+	}
+
+	// .icon-files .icon-del {
+	// 	background-color: #333;
+	// 	width: 12px;
+	// 	height: 1px;
+	// }
+
+
+	.is-list-card {
+		border: 1px #eee solid;
+		margin-bottom: 5px;
+		border-radius: 5px;
+		box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
+		padding: 5px;
+	}
+
+	.files__image {
+		width: 40px;
+		height: 40px;
+		margin-right: 10px;
+	}
+
+	.header-image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.is-text-box {
+		border: 1px #eee solid;
+		border-radius: 5px;
+	}
+
+	.is-text-image {
+		width: 25px;
+		height: 25px;
+		margin-left: 5px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
+	.icon-del-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		margin: auto 0;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 0px;
+		bottom: 0;
+		right: 5px;
+		height: 26px;
+		width: 26px;
+		// border-radius: 50%;
+		// background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 1px;
+		background-color: #333;
+		// border-radius: 1px;
+	}
+
+	/* #ifdef H5 */
+	@media all and (min-width: 768px) {
+		.uni-file-picker__files {
+			max-width: 375px;
+		}
+	}
+
+	/* #endif */
+</style>

+ 292 - 0
uni_modules/uni-file-picker/components/uni-file-picker/upload-image.vue

@@ -0,0 +1,292 @@
+<template>
+	<view class="uni-file-picker__container">
+		<view class="file-picker__box" v-for="(item,index) in filesList" :key="index" :style="boxStyle">
+			<view class="file-picker__box-content" :style="borderStyle">
+				<image class="file-image" :src="item.url" mode="aspectFill" @click.stop="prviewImage(item,index)"></image>
+				<view v-if="delIcon && !readonly" class="icon-del-box" @click.stop="delFile(index)">
+					<view class="icon-del"></view>
+					<view class="icon-del rotate"></view>
+				</view>
+				<view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
+					<progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
+					 :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
+				</view>
+				<view v-if="item.errMsg" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
+					点击重试
+				</view>
+			</view>
+		</view>
+		<view v-if="filesList.length < limit && !readonly" class="file-picker__box" :style="boxStyle">
+			<view class="file-picker__box-content is-add" :style="borderStyle" @click="choose">
+				<slot>
+					<view class="icon-add"></view>
+					<view class="icon-add rotate"></view>
+				</slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "uploadImage",
+		emits:['uploadFiles','choose','delFile'],
+		props: {
+			filesList: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			disabled:{
+				type: Boolean,
+				default: false
+			},
+			disablePreview: {
+				type: Boolean,
+				default: false
+			},
+			limit: {
+				type: [Number, String],
+				default: 9
+			},
+			imageStyles: {
+				type: Object,
+				default () {
+					return {
+						width: 'auto',
+						height: 'auto',
+						border: {}
+					}
+				}
+			},
+			delIcon: {
+				type: Boolean,
+				default: true
+			},
+			readonly:{
+				type:Boolean,
+				default:false
+			}
+		},
+		computed: {
+			styles() {
+				let styles = {
+					width: 'auto',
+					height: 'auto',
+					border: {}
+				}
+				return Object.assign(styles, this.imageStyles)
+			},
+			boxStyle() {
+				const {
+					width = 'auto',
+						height = 'auto'
+				} = this.styles
+				let obj = {}
+				if (height === 'auto') {
+					if (width !== 'auto') {
+						obj.height = this.value2px(width)
+						obj['padding-top'] = 0
+					} else {
+						obj.height = 0
+					}
+				} else {
+					obj.height = this.value2px(height)
+					obj['padding-top'] = 0
+				}
+
+				if (width === 'auto') {
+					if (height !== 'auto') {
+						obj.width = this.value2px(height)
+					} else {
+						obj.width = '33.3%'
+					}
+				} else {
+					obj.width = this.value2px(width)
+				}
+
+				let classles = ''
+				for(let i in obj){
+					classles+= `${i}:${obj[i]};`
+				}
+				return classles
+			},
+			borderStyle() {
+				let {
+					border
+				} = this.styles
+				let obj = {}
+				const widthDefaultValue = 1
+				const radiusDefaultValue = 3
+				if (typeof border === 'boolean') {
+					obj.border = border ? '1px #eee solid' : 'none'
+				} else {
+					let width = (border && border.width) || widthDefaultValue
+					width = this.value2px(width)
+					let radius = (border && border.radius) || radiusDefaultValue
+					radius = this.value2px(radius)
+					obj = {
+						'border-width': width,
+						'border-style': (border && border.style) || 'solid',
+						'border-color': (border && border.color) || '#eee',
+						'border-radius': radius
+					}
+				}
+				let classles = ''
+				for(let i in obj){
+					classles+= `${i}:${obj[i]};`
+				}
+				return classles
+			}
+		},
+		methods: {
+			uploadFiles(item, index) {
+				this.$emit("uploadFiles", item)
+			},
+			choose() {
+				this.$emit("choose")
+			},
+			delFile(index) {
+				this.$emit('delFile', index)
+			},
+			prviewImage(img, index) {
+				let urls = []
+				if(Number(this.limit) === 1&&this.disablePreview&&!this.disabled){
+					this.$emit("choose")
+				}
+				if(this.disablePreview) return
+				this.filesList.forEach(i => {
+					urls.push(i.url)
+				})
+
+				uni.previewImage({
+					urls: urls,
+					current: index
+				});
+			},
+			value2px(value) {
+				if (typeof value === 'number') {
+					value += 'px'
+				} else {
+					if (value.indexOf('%') === -1) {
+						value = value.indexOf('px') !== -1 ? value : value + 'px'
+					}
+				}
+				return value
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.uni-file-picker__container {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		box-sizing: border-box;
+		/* #endif */
+		flex-wrap: wrap;
+		margin: -5px;
+	}
+
+	.file-picker__box {
+		position: relative;
+		// flex: 0 0 33.3%;
+		width: 33.3%;
+		height: 0;
+		padding-top: 33.33%;
+		/* #ifndef APP-NVUE */
+		box-sizing: border-box;
+		/* #endif */
+	}
+
+	.file-picker__box-content {
+		position: absolute;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		margin: 5px;
+		border: 1px #eee solid;
+		border-radius: 5px;
+		overflow: hidden;
+	}
+
+	.file-picker__progress {
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		/* border: 1px red solid; */
+		z-index: 2;
+	}
+
+	.file-picker__progress-item {
+		width: 100%;
+	}
+
+	.file-picker__mask {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		justify-content: center;
+		align-items: center;
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		left: 0;
+		color: #fff;
+		font-size: 12px;
+		background-color: rgba(0, 0, 0, 0.4);
+	}
+
+	.file-image {
+		width: 100%;
+		height: 100%;
+	}
+
+	.is-add {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+	}
+
+	.icon-add {
+		width: 50px;
+		height: 5px;
+		background-color: #f1f1f1;
+		border-radius: 2px;
+	}
+
+	.rotate {
+		position: absolute;
+		transform: rotate(90deg);
+	}
+
+	.icon-del-box {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		justify-content: center;
+		position: absolute;
+		top: 3px;
+		right: 3px;
+		height: 26px;
+		width: 26px;
+		border-radius: 50%;
+		background-color: rgba(0, 0, 0, 0.5);
+		z-index: 2;
+		transform: rotate(-45deg);
+	}
+
+	.icon-del {
+		width: 15px;
+		height: 2px;
+		background-color: #fff;
+		border-radius: 2px;
+	}
+</style>

+ 109 - 0
uni_modules/uni-file-picker/components/uni-file-picker/utils.js

@@ -0,0 +1,109 @@
+/**
+ * 获取文件名和后缀
+ * @param {String} name
+ */
+export const get_file_ext = (name) => {
+	const last_len = name.lastIndexOf('.')
+	const len = name.length
+	return {
+		name: name.substring(0, last_len),
+		ext: name.substring(last_len + 1, len)
+	}
+}
+
+/**
+ * 获取扩展名
+ * @param {Array} fileExtname
+ */
+export const get_extname = (fileExtname) => {
+	if (!Array.isArray(fileExtname)) {
+		let extname = fileExtname.replace(/(\[|\])/g, '')
+		return extname.split(',')
+	} else {
+		return fileExtname
+	}
+	return []
+}
+
+/**
+ * 获取文件和检测是否可选
+ */
+export const get_files_and_is_max = (res, _extname) => {
+	let filePaths = []
+	let files = []
+	if(!_extname || _extname.length === 0){
+		return {
+			filePaths,
+			files
+		}
+	}
+	res.tempFiles.forEach(v => {
+		let fileFullName = get_file_ext(v.name)
+		const extname = fileFullName.ext.toLowerCase()
+		if (_extname.indexOf(extname) !== -1) {
+			files.push(v)
+			filePaths.push(v.path)
+		}
+	})
+	if (files.length !== res.tempFiles.length) {
+		uni.showToast({
+			title: `当前选择了${res.tempFiles.length}个文件 ,${res.tempFiles.length - files.length} 个文件格式不正确`,
+			icon: 'none',
+			duration: 5000
+		})
+	}
+
+	return {
+		filePaths,
+		files
+	}
+}
+
+
+/**
+ * 获取图片信息
+ * @param {Object} filepath
+ */
+export const get_file_info = (filepath) => {
+	return new Promise((resolve, reject) => {
+		uni.getImageInfo({
+			src: filepath,
+			success(res) {
+				resolve(res)
+			},
+			fail(err) {
+				reject(err)
+			}
+		})
+	})
+}
+/**
+ * 获取封装数据
+ */
+export const get_file_data = async (files, type = 'image') => {
+	// 最终需要上传数据库的数据
+	let fileFullName = get_file_ext(files.name)
+	const extname = fileFullName.ext.toLowerCase()
+	let filedata = {
+		name: files.name,
+		uuid: files.uuid,
+		extname: extname || '',
+		cloudPath: files.cloudPath,
+		fileType: files.fileType,
+		url: files.path || files.path,
+		size: files.size, //单位是字节
+		image: {},
+		path: files.path,
+		video: {}
+	}
+	if (type === 'image') {
+		const imageinfo = await get_file_info(files.path)
+		delete filedata.video
+		filedata.image.width = imageinfo.width
+		filedata.image.height = imageinfo.height
+		filedata.image.location = imageinfo.path
+	} else {
+		delete filedata.image
+	}
+	return filedata
+}

+ 83 - 0
uni_modules/uni-file-picker/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "uni-file-picker",
+  "displayName": "uni-file-picker 文件选择上传",
+  "version": "1.0.4",
+  "description": "文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间",
+  "keywords": [
+    "uni-ui",
+    "uniui",
+    "图片上传",
+    "文件上传"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "y",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y"
+        },
+        "快应用": {
+          "华为": "u",
+          "联盟": "u"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

+ 11 - 0
uni_modules/uni-file-picker/readme.md

@@ -0,0 +1,11 @@
+
+## FilePicker 文件选择上传
+
+> **组件名:uni-file-picker**
+>  代码块: `uFilePicker`
+
+
+文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-file-picker)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 

+ 97 - 0
util/imageCompress.js

@@ -0,0 +1,97 @@
+ //通过canvas将图片压缩至指定大小
+
+ //判断图片大小是否满足需求,limitSize的单位是kb
+ function imageSizeIsLessLimitSize(imagePath, limitSize, lessCallback, moreCallback) {
+ 	//获取文件信息
+ 	wx.getFileSystemManager().getFileInfo({
+ 		filePath: imagePath,
+ 		success: (res) => {
+ 			// console.log("压缩前图片大小", res.size / 1024, 'kb');
+ 			//如果图片太大了走moreCallback
+ 			if (res.size > 1024 * limitSize) {
+ 				moreCallback()
+ 			}
+ 			//图片满足要求了走lessCallback
+ 			else {
+ 				lessCallback()
+ 			}
+ 		}
+ 	})
+ }
+
+ //将图片画在画布上并获取画好之后的图片的路径
+ function getCanvasImage(canvasId, imagePath, imageW, imageH, getImgSuccess) {
+ 	//创建画布内容
+ 	const ctx = wx.createCanvasContext(canvasId);
+ 	//图片画上去,imageW和imageH是画上去的尺寸,图像和画布间隔都是0
+ 	ctx.drawImage(imagePath, 0, 0, imageW, imageH);
+ 	//这里一定要加定时器,给足够的时间去画(所以每次递归最少要耗时200ms,多次递归很耗时!)
+ 	ctx.draw(false, setTimeout(function() {
+ 		//把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径
+ 		wx.canvasToTempFilePath({
+ 			canvasId: canvasId,
+ 			x: 0,
+ 			y: 0,
+ 			width: imageW,
+ 			height: imageH,
+ 			quality: 1, //最高质量
+ 			success: (res) => {
+ 				//将取出的图片路径通过回调函数返回
+ 				getImgSuccess(res.tempFilePath);
+ 			}
+ 		})
+ 	}, 200));
+ }
+
+ //主函数,默认限制大小1024kb即1mb,drawWidth是绘画区域的大小
+ //初始值传入为画布自身的边长(我们这是一个正方形的画布)
+ function getLessLimitSizeImage(canvasId, imagePath, limitSize = 1024, drawWidth, callback) {
+ 	//判断图片尺寸是否满足要求
+ 	imageSizeIsLessLimitSize(imagePath, limitSize,
+ 		(lessRes) => {
+ 			//满足要求走callback,将压缩后的文件路径返回
+ 			callback(imagePath);
+ 		},
+ 		(moreRes) => {
+ 			//不满足要求需要压缩的时候
+ 			wx.getImageInfo({
+ 				src: imagePath,
+ 				success: (imageInfo) => {
+ 					let maxSide = Math.max(imageInfo.width, imageInfo.height);
+ 					let windowW = drawWidth;
+ 					let scale = 1;
+ 					/*
+ 					这里的目的是当绘画区域缩小的比图片自身尺寸还要小的时候
+ 					取图片长宽的最大值,然后和当前绘画区域计算出需要放缩的比例
+ 					然后再画经过放缩后的尺寸,保证画出的一定是一个完整的图片。由于每次递归绘画区域都会缩小,
+ 					所以不用担心scale永远都是1绘画尺寸永远不变的情况,只要不满足压缩后体积的要求
+ 					就会缩小绘画区域,早晚会有绘画区域小于图片尺寸的情况发生
+ 					*/
+ 					if (maxSide > windowW) {
+ 						scale = windowW / maxSide;
+ 					}
+ 					//trunc是去掉小数
+ 					let imageW = Math.trunc(imageInfo.width * scale);
+ 					let imageH = Math.trunc(imageInfo.height * scale);
+ 					// console.log('调用压缩', imageW, imageH);
+ 					//图片在规定绘画区域上画并获取新的图片的path
+ 					getCanvasImage(canvasId, imagePath, imageW, imageH,
+ 						(pressImgPath) => {
+ 							/*
+ 							再去检查是否满足要求,始终缩小绘画区域,让图片适配绘画区域
+ 							这里乘以0.95是必须的,如果不缩小绘画区域,会出现尺寸比绘画区域小,
+ 							而体积比要求压缩体积大的情况出现,就会无穷递归下去,因为scale的值永远是1
+ 							但0.95不是固定的,你可以根据需要自己改,0到1之间,越小则绘画区域缩小的越快
+ 							但不建议取得太小,绘画区域缩小的太快,压出来的将总是很糊的
+ 							*/
+ 							getLessLimitSizeImage(canvasId, pressImgPath, limitSize, drawWidth *
+ 								0.95, callback);
+ 						}
+ 					)
+ 				}
+ 			})
+ 		}
+ 	)
+ }
+
+ export default getLessLimitSizeImage