浏览代码

no message

xiaoxin 2 年之前
父节点
当前提交
d851d36141
共有 60 个文件被更改,包括 2497 次插入863 次删除
  1. 14 6
      components/listView.vue
  2. 21 0
      components/noData.vue
  3. 23 1
      components/tabber.vue
  4. 1 1
      pages.json
  5. 6 2
      pages/grade/grade.vue
  6. 37 37
      pages/home/home.vue
  7. 216 4
      pages/index/index.vue
  8. 2 2
      pages/student/student.vue
  9. 69 6
      pagesReservation/backlog/backlog.vue
  10. 77 44
      pagesReservation/record/record.vue
  11. 298 33
      pagesReservation/register/register.vue
  12. 10 5
      pagesReservation/reservation/reservation.vue
  13. 二进制
      static/images/noData.png
  14. 9 0
      uni_modules/uv-code/changelog.md
  15. 35 0
      uni_modules/uv-code/components/uv-code/props.js
  16. 136 0
      uni_modules/uv-code/components/uv-code/uv-code.vue
  17. 87 0
      uni_modules/uv-code/package.json
  18. 11 0
      uni_modules/uv-code/readme.md
  19. 4 0
      uni_modules/uv-ui-tools/changelog.md
  20. 2 2
      uni_modules/uv-ui-tools/libs/config/config.js
  21. 107 72
      uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
  22. 15 14
      uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js
  23. 141 138
      uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
  24. 4 4
      uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js
  25. 27 23
      uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
  26. 4 1
      uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js
  27. 105 82
      uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
  28. 7 7
      uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
  29. 42 47
      uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js
  30. 3 3
      uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js
  31. 4 4
      uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js
  32. 184 103
      uni_modules/uv-ui-tools/libs/luch-request/index.d.ts
  33. 0 1
      uni_modules/uv-ui-tools/libs/luch-request/index.js
  34. 50 46
      uni_modules/uv-ui-tools/libs/luch-request/utils.js
  35. 1 1
      uni_modules/uv-ui-tools/package.json
  36. 32 2
      unpackage/dist/dev/mp-weixin/common/vendor.js
  37. 14 6
      unpackage/dist/dev/mp-weixin/components/listView.js
  38. 20 1
      unpackage/dist/dev/mp-weixin/components/tabber.js
  39. 5 2
      unpackage/dist/dev/mp-weixin/pages/grade/grade.js
  40. 37 43
      unpackage/dist/dev/mp-weixin/pages/home/home.js
  41. 1 1
      unpackage/dist/dev/mp-weixin/pages/home/home.wxml
  42. 82 2
      unpackage/dist/dev/mp-weixin/pages/index/index.js
  43. 4 2
      unpackage/dist/dev/mp-weixin/pages/index/index.json
  44. 1 1
      unpackage/dist/dev/mp-weixin/pages/index/index.wxml
  45. 72 1
      unpackage/dist/dev/mp-weixin/pages/index/index.wxss
  46. 4 6
      unpackage/dist/dev/mp-weixin/pages/student/student.js
  47. 1 1
      unpackage/dist/dev/mp-weixin/pages/student/student.wxml
  48. 55 11
      unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.js
  49. 1 1
      unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.wxml
  50. 4 2
      unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.wxss
  51. 70 56
      unpackage/dist/dev/mp-weixin/pagesReservation/record/record.js
  52. 2 1
      unpackage/dist/dev/mp-weixin/pagesReservation/record/record.json
  53. 1 1
      unpackage/dist/dev/mp-weixin/pagesReservation/record/record.wxml
  54. 8 2
      unpackage/dist/dev/mp-weixin/pagesReservation/record/record.wxss
  55. 263 25
      unpackage/dist/dev/mp-weixin/pagesReservation/register/register.js
  56. 1 1
      unpackage/dist/dev/mp-weixin/pagesReservation/register/register.wxml
  57. 3 0
      unpackage/dist/dev/mp-weixin/pagesReservation/register/register.wxss
  58. 12 5
      unpackage/dist/dev/mp-weixin/pagesReservation/reservation/reservation.js
  59. 1 1
      unpackage/dist/dev/mp-weixin/pagesReservation/reservation/reservation.wxml
  60. 51 0
      utils/api.js

+ 14 - 6
components/listView.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="box">
-		<view class="box_item" v-for="item in list" :key="item.id" @click="goPage('/pages/student/student', item.id)">
+		<view class="box_item" v-for="item in list" :key="item.id" @click="goPage(item.id)">
 			{{ item.name }}({{ item.number }})
 			<img class="item_img" src="../../static/images/right.png" />
 		</view>
@@ -12,17 +12,25 @@
 import { onLoad } from '@dcloudio/uni-app'
 
 const props = defineProps({
-	list: Array
+	list: Array,
+	appType: String
 })
 
 onLoad(() => {})
 
 // 点击每一个学生回调
-const goPage = (url, id) => {
+const goPage = (id) => {
 	console.log(id)
-	uni.navigateTo({
-		url
-	})
+
+	if (props.appType == '通讯录') {
+		uni.navigateTo({
+			url: '/pages/student/student'
+		})
+	} else {
+		uni.navigateTo({
+			url: '/pages/track/track'
+		})
+	}
 }
 </script>
 

+ 21 - 0
components/noData.vue

@@ -0,0 +1,21 @@
+<template>
+	<view class="container">
+		<img class="img" src="@/static/images/noData.png" />
+		暂无数据
+	</view>
+</template>
+
+<script></script>
+
+<style lang="scss" scoped>
+.container {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+
+	.img {
+		margin-top: 160rpx;
+		width: 480rpx;
+	}
+}
+</style>

+ 23 - 1
components/tabber.vue

@@ -1,6 +1,6 @@
 <template>
 	<uv-tabbar :customStyle="customStyle" activeColor="#0061FF" inactiveColor="#A6A6A6" :value="activeIndex">
-		<uv-tabbar-item v-for="(item, index) in tabList" :key="item.id" :text="item.text" :icon="item.icon" @click="handleChange(index, item)"></uv-tabbar-item>
+		<uv-tabbar-item v-for="(item, index) in allList" :key="item.id" :text="item.text" :icon="item.icon" @click="handleChange(index, item)"></uv-tabbar-item>
 	</uv-tabbar>
 </template>
 
@@ -8,6 +8,7 @@
 import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
 
+const allList = ref([])
 // 导航栏数组
 const tabList = ref([
 	{
@@ -27,6 +28,19 @@ const tabList = ref([
 	}
 ])
 
+const tabList2 = ref([
+	{
+		id: 1,
+		text: '访客预约',
+		icon: 'account'
+	},
+	{
+		id: 3,
+		text: '预约记录',
+		icon: 'clock'
+	}
+])
+
 // 当前高亮索引
 const activeIndex = ref(0)
 
@@ -36,7 +50,15 @@ const customStyle = {
 }
 
 onLoad(() => {
+	const userType = uni.getStorageSync('userType')
+
+	if (userType == 0) {
+		allList.value = tabList2.value
+	} else {
+		allList.value = tabList.value
+	}
 	const i = uni.getStorageSync('Tab-activeIndex')
+
 	i ? (activeIndex.value = i) : (activeIndex.value = 0)
 })
 

+ 1 - 1
pages.json

@@ -2,7 +2,7 @@
 	"pages": [{
 			"path": "pages/index/index",
 			"style": {
-				"navigationBarTitleText": "uni-app"
+				"navigationBarTitleText": "登录"
 			}
 		},
 		{

+ 6 - 2
pages/grade/grade.vue

@@ -8,7 +8,7 @@
 		<view class="school">万载三中/七年级/3班</view>
 
 		<!-- 学生列表区域 -->
-		<listView :list="list" />
+		<listView :list="list" :appType="appType" />
 	</view>
 </template>
 
@@ -42,7 +42,11 @@ const list = ref([
 	}
 ])
 
-onLoad(() => {})
+const appType = ref('')
+
+onLoad((options) => {
+	appType.value = options.type
+})
 
 // 输入框组件自定义事件
 const changeInputValue = (data) => {

+ 37 - 37
pages/home/home.vue

@@ -19,7 +19,7 @@
 			<!-- 学生姓名区域 -->
 			<view class="header_name">张三</view>
 			<!-- 学生年级区域 -->
-			<view class="header_grade">初二</view>
+			<view class="header_grade">{{ userType === 0 ? '家长' : '教师' }}</view>
 			<!-- 二维码区域 -->
 			<view class="header_code">
 				<uv-qrcode ref="qrcodeRef" size="82rpx" :value="QRCodeUrl" :options="options" @click="handleClickCode"></uv-qrcode>
@@ -29,7 +29,7 @@
 		<!-- 详细信息区域 -->
 		<view class="body">
 			<!-- 个人信息区域 -->
-			<view class="body_header">
+			<view class="body_header" v-if="userType == 0">
 				<img class="info_bg" src="../../static/images/info-bg.png" />
 
 				<img class="info_img" src="../../static/images/user-photo.png" />
@@ -49,7 +49,7 @@
 			<!-- 应用列表区域 -->
 			<view class="body_list">
 				<!-- 每一个应用区域 -->
-				<view class="list_box" v-for="item in list" :key="item.id" @click="goPage(item.path)">
+				<view class="list_box" v-for="item in useAppList" :key="item.id" @click="goPage(item.path)">
 					<img class="box_img" :src="item.url" />
 					{{ item.title }}
 				</view>
@@ -73,8 +73,18 @@ onLoad(() => {
 			customBarH.value = custom.height
 		}
 	})
+
+	userType.value = uni.getStorageSync('userType')
+	console.log('身份类型', userType.value)
+
+	// 获取权限app
+	const appList = uni.getStorageSync('appList')
+	if (appList) {
+		useAppList.value = filterApp(list.value, appList)
+	}
 })
 
+// 页面下拉刷新回调
 onPullDownRefresh(() => {
 	qrcodeRef.value.remake()
 	setTimeout(() => {
@@ -89,6 +99,9 @@ onPageScroll((e) => {
 		showHeader.value = false
 	}
 })
+
+const userType = ref()
+
 // 顶部导航栏显示隐藏控制
 const showHeader = ref(false)
 
@@ -101,40 +114,14 @@ const customBarH = ref(0)
 // 二维码元素引用标记
 const qrcodeRef = ref(null)
 
-// 应用列表数据
+// 全部应用列表数据
 const list = ref([
-	// {
-	// 	id: 1,
-	// 	title: '考勤管理',
-	// 	url: '../../static/images/icon.png'
-	// },
-	// {
-	// 	id: 2,
-	// 	title: '课表查询',
-	// 	url: '../../static/images/icon.png',
-	// 	path: ''
-	// },
 	{
 		id: 3,
 		title: '学生轨迹',
 		url: '../../static/images/icon.png',
 		path: '/pages/track/track'
 	},
-	// {
-	// 	id: 4,
-	// 	title: '打卡接龙',
-	// 	url: '../../static/images/icon.png'
-	// },
-	// {
-	// 	id: 5,
-	// 	title: '人脸采集',
-	// 	url: '../../static/images/icon.png'
-	// },
-	// {
-	// 	id: 6,
-	// 	title: '智慧教学',
-	// 	url: '../../static/images/icon.png'
-	// },
 	{
 		id: 7,
 		title: '消息通知',
@@ -147,11 +134,6 @@ const list = ref([
 		url: '../../static/images/icon.png',
 		path: '/pagesReservation/reservation/reservation'
 	},
-	// {
-	// 	id: 9,
-	// 	title: '课后作业',
-	// 	url: '../../static/images/icon.png'
-	// },
 	{
 		id: 10,
 		title: '校园预警',
@@ -162,10 +144,13 @@ const list = ref([
 		id: 11,
 		title: '通讯录',
 		url: '../../static/images/icon.png',
-		path: '/pages/addressBook/addressBook'
+		path: '/pages/grade/grade?type=通讯录'
 	}
 ])
 
+// 展示的app列表
+const useAppList = ref([])
+
 // 二维码信息
 const QRCodeUrl = ref('123')
 
@@ -178,6 +163,14 @@ const options = {
 
 // 跳转页面函数
 const goPage = (url) => {
+	if (url === '/pages/track/track') {
+		if (userType.value == 1) {
+			uni.navigateTo({
+				url: '/pages/grade/grade?type=学生轨迹'
+			})
+			return
+		}
+	}
 	if (url === '/pagesReservation/reservation/reservation') {
 		uni.setStorageSync('Tab-activeIndex', 0)
 	}
@@ -192,6 +185,13 @@ const handleClickCode = () => {
 		url: `/pages/quickMark/quickMark?value=${QRCodeUrl.value}`
 	})
 }
+
+// 过滤方法
+const filterApp = (arr1, arr2) => {
+	return arr1.filter((item) => {
+		return arr2.includes(item.title)
+	})
+}
 </script>
 
 <style lang="scss" scoped>
@@ -394,4 +394,4 @@ const handleClickCode = () => {
 		}
 	}
 }
-</style>
+</style>

+ 216 - 4
pages/index/index.vue

@@ -1,19 +1,231 @@
 <template>
-	<view class="container"></view>
+	<view class="container">
+		<img class="img" src="@/static/images/school-logo.jpg" />
+		<view class="logo_name">万载三中</view>
+
+		<!-- 手机号码输入框区域 -->
+		<view class="phone">
+			<input class="phone_input" type="text" placeholder="手机号" placeholder-style="color:#CCCCCC;" v-model="phone" />
+		</view>
+
+		<!-- 验证码区域 -->
+		<view class="code">
+			<input class="code_input" type="text" placeholder="验证码" placeholder-style="color:#CCCCCC;" v-model="codeValue" />
+
+			<uv-code uniqueKey="login" keepRunning ref="codeDom" @change="codeChange"></uv-code>
+			<view class="code_box" @click="getCode">{{ tips }}</view>
+		</view>
+
+		<!-- 登录按钮区域 -->
+		<view class="loginBtn" :class="{ active: btnFlag }" @click="handleLogin">登录</view>
+	</view>
 </template>
 
 <script setup>
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
+import { myRequest } from '@/utils/api.js'
+
+// 手机号码
+const phone = ref('')
+// 验证码
+const codeValue = ref('')
+// 验证码Dom
+const codeDom = ref(null)
+// 登录按钮是否高亮
+const btnFlag = computed(() => {
+	// 手机号码验证规则
+	const regPhone = /^1[3-9]\d{9}$/
+	if (phone.value && regPhone.test(phone.value) && codeValue.value) {
+		return true
+	} else {
+		return false
+	}
+})
+
+// 提示语
+const tips = ref('')
+
+// 家长
+const plist = ref(['学生轨迹', '消息通知', '访客预约', '校园预警'])
 
-onLoad(() => {
+// 老师
+const tlist = ref(['学生轨迹', '消息通知', '访客预约', '校园预警', '通讯录'])
+
+onLoad(() => {})
+
+// 获取验证码按钮点击回调
+const getCode = () => {
+	// 手机号码验证规则
+	const regPhone = /^1[3-9]\d{9}$/
+	if (phone.value && regPhone.test(phone.value)) {
+		if (codeDom.value.canGetCode) {
+			// 模拟向后端请求验证码
+			uni.showLoading({
+				title: '正在获取验证码'
+			})
+			setTimeout(() => {
+				uni.hideLoading()
+				uni.showToast({
+					title: '验证码已发送',
+					icon: 'none'
+				})
+				codeDom.value.start()
+			}, 2000)
+		} else {
+			uni.showToast({
+				title: '倒计时结束后再发送',
+				icon: 'none'
+			})
+		}
+	} else {
+		uni.showToast({
+			title: '请先输入正确的手机号码',
+			icon: 'none'
+		})
+	}
+}
+
+// 登录按钮回调
+const handleLogin = () => {
+	// const flag = verifyValue()
+	// if (flag) {
+	// 	uni.setStorageSync('userId', 25)
+	// 	uni.setStorageSync('userType', 1)
+	// 	uni.navigateTo({
+	// 		url: '/pages/home/home'
+	// 	})
+	// }
+	// 0 代表家长  1 代表老师
+	let userType = 1
+	uni.setStorageSync('userType', userType)
+	if (userType == 0) {
+		uni.setStorageSync('appList', plist.value)
+		uni.setStorageSync('userId', 25)
+	} else {
+		uni.setStorageSync('appList', tlist.value)
+		uni.setStorageSync('userId', 26)
+	}
 	uni.navigateTo({
 		url: '/pages/home/home'
 	})
-})
+}
+
+// 验证表格数据是否符合规范
+const verifyValue = () => {
+	// 手机号码验证规则
+	const regPhone = /^1[3-9]\d{9}$/
+
+	if (!phone.value) {
+		uni.showToast({
+			title: '请输入手机号',
+			icon: 'none'
+		})
+		return false
+	}
+
+	if (!regPhone.test(phone.value)) {
+		uni.showToast({
+			title: '手机号码格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+
+	if (!codeValue.value) {
+		uni.showToast({
+			title: '请输入验证码',
+			icon: 'none'
+		})
+		return false
+	}
+	return true
+}
+
+const codeChange = (text) => {
+	tips.value = text
+}
 </script>
 
 <style lang="scss" scoped>
 .container {
+	display: flex;
+	flex-direction: column;
+	align-items: center;
+	min-height: 100vh;
+	background-color: #f8f8fa;
+
+	.img {
+		margin-top: 120rpx;
+		width: 200rpx;
+		height: 200rpx;
+		border-radius: 20rpx;
+	}
+
+	.logo_name {
+		margin-top: 25rpx;
+		font-size: 36rpx;
+	}
+
+	.phone {
+		box-sizing: border-box;
+		margin-top: 80rpx;
+		padding: 0 20rpx;
+		width: 538rpx;
+		height: 80rpx;
+		border-radius: 8rpx;
+		box-shadow: 0 0 10rpx #ccc;
+		background-color: #fff;
+
+		.phone_input {
+			height: 100%;
+		}
+	}
+
+	.code {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		box-sizing: border-box;
+		margin-top: 40rpx;
+		padding: 0 20rpx;
+		width: 538rpx;
+		height: 80rpx;
+		border-radius: 8rpx;
+		box-shadow: 0 0 10rpx #ccc;
+		background-color: #fff;
+
+		.code_input {
+			width: 55%;
+			height: 100%;
+		}
+
+		.code_box {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 35%;
+			height: 80rpx;
+			color: #3c9cff;
+			font-size: 26rpx;
+		}
+	}
+
+	.loginBtn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin-top: 50rpx;
+		width: 538rpx;
+		height: 80rpx;
+		color: #a0a1a4;
+		border-radius: 8rpx;
+		background-color: #e5e6eb;
+	}
+
+	.active {
+		color: #fff;
+		background-color: #0061ff;
+	}
 }
 </style>

+ 2 - 2
pages/student/student.vue

@@ -12,7 +12,7 @@
 				<view class="info_phone">13677985689</view>
 			</view>
 
-			<view class="box_btn" @click="callPhone">呼叫</view>
+			<!-- <view class="box_btn" @click="callPhone">呼叫</view> -->
 		</view>
 
 		<!-- 家长信息区域 -->
@@ -22,7 +22,7 @@
 			<view class="box_info">
 				<view class="info_name">
 					{{ item.name }}
-					<view class="info_type">{{ item.identity }}</view>
+					<view class="info_type">家长</view>
 				</view>
 				<view class="info_phone">{{ item.phone }}</view>
 			</view>

+ 69 - 6
pagesReservation/backlog/backlog.vue

@@ -18,6 +18,10 @@
 				</view>
 				<view class="box_info">
 					<view class="info_box">
+						<view class="box_key">类别</view>
+						<view class="box_value">{{ item.status === 0 ? '学生家长预约' : '其他访客预约' }}</view>
+					</view>
+					<view class="info_box">
 						<view class="box_key">来访时间</view>
 						<view class="box_value">{{ item.time }}</view>
 					</view>
@@ -25,6 +29,10 @@
 						<view class="box_key">访问事由</view>
 						<view class="box_value">{{ item.desc }}</view>
 					</view>
+					<view class="info_box">
+						<view class="box_key">{{ item.status === 0 ? '受访学生' : '受访人' }}</view>
+						<view class="box_value">{{ item.name2 }}</view>
+					</view>
 				</view>
 				<view class="box_btn" v-if="item.type == '待审核'">
 					<view class="button reject" @click.stop="handleReject">拒绝</view>
@@ -105,10 +113,19 @@
 
 <script setup>
 import { ref } from 'vue'
+import { onLoad, onReachBottom } from '@dcloudio/uni-app'
 import tabber from '@/components/tabber.vue'
+import { myRequest } from '@/utils/api.js'
 
 // 分段器当前索引
 const activeCurrent = ref(0)
+
+// 当前页
+const currentPage = ref(1)
+
+// 记录总条数
+const total = ref(0)
+
 // 分段器数组
 const controlList = ['待审核', '已拒绝', '已推送']
 
@@ -119,21 +136,27 @@ const list = ref([
 		name: '张三',
 		time: '2023-12-13  10:23',
 		type: '待审核',
-		desc: '给孩子送棉被'
+		desc: '给孩子送棉被',
+		status: 0,
+		name2: '小刘'
 	},
 	{
 		id: 2,
 		name: '张三',
 		time: '2023-12-13  10:23',
 		type: '已拒绝',
-		desc: '给孩子送棉被'
+		desc: '给孩子送棉被',
+		status: 0,
+		name2: '小刘'
 	},
 	{
 		id: 3,
 		name: '张三',
 		time: '2023-12-13  10:23',
 		type: '已推送',
-		desc: '给孩子送棉被'
+		desc: '给孩子送棉被',
+		status: 0,
+		name2: '小刘'
 	}
 ])
 
@@ -143,9 +166,47 @@ const popup = ref(null)
 // 弹窗详细信息
 const popObj = ref({})
 
+onLoad(() => {
+	getData()
+})
+
+// 页面上拉到最底部时触发的回调
+onReachBottom(() => {
+	if (total.value > list.value.length) {
+		currentPage.value++
+		getData()
+	} else {
+		uni.showToast({
+			title: '没有更多数据了',
+			icon: 'none'
+		})
+	}
+})
+
+// 获取到访代办数据
+const getData = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartVisitor/visitingAgencys',
+		data: {
+			currentPage: currentPage.value,
+			pageCount: 6,
+			userId: uni.getStorageSync('userId'),
+			type: activeCurrent.value - 0 + 1
+		}
+	})
+	// console.log(res)
+	total.value = res.data.totalCount
+	list.value = [...list.value, ...res.data.list]
+}
+
 // 切换分段器时的回调
 const onClickItem = (e) => {
-	console.log(e)
+	if (activeCurrent.value != e.currentIndex) {
+		activeCurrent.value = e.currentIndex
+		currentPage.value = 1
+		list.value = []
+		getData()
+	}
 }
 
 // 点击每一条待办记录时的回调
@@ -172,6 +233,8 @@ const closePop = () => {
 
 <style lang="scss" scoped>
 .container {
+	box-sizing: border-box;
+	padding-bottom: 30rpx;
 	min-height: 100vh;
 	background-color: #f1f6fe;
 
@@ -225,15 +288,15 @@ const closePop = () => {
 			.box_info {
 				display: flex;
 				flex-direction: column;
-				justify-content: space-evenly;
-				height: 140rpx;
 
 				.info_box {
 					display: flex;
 					align-items: center;
+					height: 65rpx;
 					font-size: 24rpx;
 
 					.box_key {
+						width: 120rpx;
 						color: #a6a6a6;
 					}
 

+ 77 - 44
pagesReservation/record/record.vue

@@ -8,29 +8,32 @@
 			<view class="body_box" v-for="item in list" :key="item.id" @click="handleClick(item)">
 				<view class="box_title">
 					<view class="title_msg">
-						<view class="msg_name">{{ item.name }}</view>
-						<view class="msg_time">/{{ item.time }}</view>
+						<view class="msg_name">{{ item.userName }}</view>
+						<view class="msg_time">/{{ item.createTime }}</view>
 					</view>
-					<view class="title_type" v-if="item.type == '待审核'">{{ item.type }}</view>
-					<view class="title_type red" v-if="item.type == '已拒绝'">{{ item.type }}</view>
-					<view class="title_type green" v-if="item.type == '已推送'">{{ item.type }}</view>
+					<view class="title_type" v-if="item.statuStr == '待审核'">{{ item.statuStr }}</view>
+					<view class="title_type red" v-if="item.statuStr == '已拒绝'">{{ item.statuStr }}</view>
+					<view class="title_type green" v-if="item.statuStr == '已推送'">{{ item.statuStr }}</view>
 				</view>
 				<view class="box_info">
 					<view class="info_box">
 						<view class="box_key">来访时间</view>
-						<view class="box_value">{{ item.time }}</view>
+						<view class="box_value">{{ item.visitorTime }}</view>
 					</view>
 					<view class="info_box">
 						<view class="box_key">访问事由</view>
-						<view class="box_value">{{ item.desc }}</view>
+						<view class="box_value">{{ item.visitReason }}</view>
 					</view>
 				</view>
-				<view class="box_btn" v-if="item.type == '待审核'">
+				<view class="box_btn" v-if="item.statuStr == '待审核'">
 					<view class="button" @click.stop="handleCancel">取消预约</view>
 				</view>
 			</view>
 		</view>
 
+		<!-- 没有数据时展示的页面 -->
+		<NoData v-if="!list.length" />
+
 		<!-- 详情弹窗区域 -->
 		<uni-popup ref="popup" type="center" :is-mask-click="false">
 			<view class="popup_box">
@@ -43,14 +46,14 @@
 				<!-- 弹窗详细信息区域 -->
 				<view class="pop_info">
 					<view class="info_key">状态:</view>
-					<view class="info_value blue" v-if="popObj.type == '待审核'">{{ popObj.type }}</view>
-					<view class="info_value red" v-if="popObj.type == '已拒绝'">{{ popObj.type }}</view>
-					<view class="info_value green" v-if="popObj.type == '已推送'">{{ popObj.type }}</view>
+					<view class="info_value blue" v-if="popObj.statuStr == '待审核'">{{ popObj.statuStr }}</view>
+					<view class="info_value red" v-if="popObj.statuStr == '已拒绝'">{{ popObj.statuStr }}</view>
+					<view class="info_value green" v-if="popObj.statuStr == '已推送'">{{ popObj.statuStr }}</view>
 				</view>
 
 				<view class="pop_info">
 					<view class="info_key">访客姓名:</view>
-					<view class="info_value">{{ popObj.name }}</view>
+					<view class="info_value">{{ popObj.userName }}</view>
 				</view>
 
 				<view class="pop_info">
@@ -60,7 +63,7 @@
 
 				<view class="pop_info">
 					<view class="info_key">来访时间:</view>
-					<view class="info_value">{{ popObj.time }}</view>
+					<view class="info_value">{{ popObj.visitorTime }}</view>
 				</view>
 
 				<view class="pop_info">
@@ -70,7 +73,7 @@
 
 				<view class="pop_info">
 					<view class="info_key">访问事由:</view>
-					<view class="info_value">{{ popObj.desc }}</view>
+					<view class="info_value">{{ popObj.visitReason }}</view>
 				</view>
 
 				<view class="pop_info">
@@ -91,50 +94,69 @@
 		</uni-popup>
 
 		<!-- 底部导航栏区域 -->
-		<tabber />
+		<Tabber />
 	</view>
 </template>
 
 <script setup>
 import { ref } from 'vue'
-import { onLoad } from '@dcloudio/uni-app'
-import tabber from '@/components/tabber.vue'
+import { onLoad, onReachBottom } from '@dcloudio/uni-app'
+import Tabber from '@/components/tabber.vue'
+import NoData from '@/components/noData.vue'
+import { myRequest } from '@/utils/api.js'
 
 // 分段器当前索引
 const activeCurrent = ref(0)
+
+// 当前页
+const currentPage = ref(1)
+
+// 记录总条数
+const total = ref(0)
+
 // 分段器数组
 const controlList = ['全部', '待审核', '已拒绝', '已推送']
+
 // 预约记录数组
-const list = ref([
-	{
-		id: 1,
-		name: '张三',
-		time: '2023-12-13  10:23',
-		type: '待审核',
-		desc: '给孩子送棉被'
-	},
-	{
-		id: 2,
-		name: '张三',
-		time: '2023-12-13  10:23',
-		type: '已拒绝',
-		desc: '给孩子送棉被'
-	},
-	{
-		id: 3,
-		name: '张三',
-		time: '2023-12-13  10:23',
-		type: '已推送',
-		desc: '给孩子送棉被'
-	}
-])
+const list = ref([])
 // 弹窗元素标记
 const popup = ref(null)
 
 // 弹窗详细信息
 const popObj = ref({})
 
-onLoad(() => {})
+onLoad(() => {
+	getData()
+})
+
+// 页面上拉到最底部时触发的回调
+onReachBottom(() => {
+	if (total.value > list.value.length) {
+		currentPage.value++
+		getData()
+	} else {
+		uni.showToast({
+			title: '没有更多数据了',
+			icon: 'none'
+		})
+	}
+})
+
+// 获取预约记录数据
+const getData = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartVisitor/appointmentPageRecord',
+		data: {
+			currentPage: currentPage.value,
+			pageCount: 6,
+			userId: uni.getStorageSync('userId'),
+			type: activeCurrent.value
+		}
+	})
+	// console.log(res)
+	total.value = res.data.totalCount
+	list.value = [...list.value, ...res.data.list]
+}
 
 // 点击每一条预约记录时的回调
 const handleClick = (item) => {
@@ -144,7 +166,12 @@ const handleClick = (item) => {
 
 // 切换分段器时的回调
 const onClickItem = (e) => {
-	console.log(e)
+	if (activeCurrent.value != e.currentIndex) {
+		activeCurrent.value = e.currentIndex
+		currentPage.value = 1
+		list.value = []
+		getData()
+	}
 }
 
 // 点击取消按钮回调
@@ -160,6 +187,8 @@ const closePop = () => {
 
 <style lang="scss" scoped>
 .container {
+	box-sizing: border-box;
+	padding-bottom: 30rpx;
 	min-height: 100vh;
 	background-color: #f1f6fe;
 
@@ -213,20 +242,24 @@ const closePop = () => {
 			.box_info {
 				display: flex;
 				flex-direction: column;
-				justify-content: space-evenly;
-				height: 140rpx;
 
 				.info_box {
 					display: flex;
 					align-items: center;
+					height: 65rpx;
 					font-size: 24rpx;
 
 					.box_key {
+						width: 120rpx;
 						color: #a6a6a6;
 					}
 
 					.box_value {
+						flex: 1;
 						margin-left: 95rpx;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
 					}
 				}
 			}

+ 298 - 33
pagesReservation/register/register.vue

@@ -8,7 +8,7 @@
 					访客姓名
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入访客姓名" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入访客姓名" placeholder-style="color:#CCCCCC;" v-model="visName" />
 				</view>
 			</view>
 
@@ -19,7 +19,7 @@
 					访客手机号
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入访客手机号" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入访客手机号" placeholder-style="color:#CCCCCC;" v-model="visPhone" />
 				</view>
 			</view>
 
@@ -30,8 +30,8 @@
 					来访时间
 				</view>
 				<view class="box_value">
-					<uni-datetime-picker>
-						<view class="value_time">请选择来访时间 ></view>
+					<uni-datetime-picker v-model="visStartTime" @change="changeStart">
+						<view class="value_time" :class="{ activeTime: visStartTime }">{{ visStartTime || '请选择来访时间 >' }}</view>
 					</uni-datetime-picker>
 				</view>
 			</view>
@@ -42,9 +42,9 @@
 					来访结束时间
 				</view>
 				<view class="box_value">
-					<uni-datetime-picker>
-						<view class="value_time">请选择来访结束时间 ></view>
-					</uni-datetime-picker>
+					<!-- <uni-datetime-picker v-model="visEndTime" :start="visStartTime"> -->
+					<view class="value_time" :class="{ activeTime: visEndTime }">{{ visEndTime || '来访时间为4小时' }}</view>
+					<!-- </uni-datetime-picker> -->
 				</view>
 			</view>
 
@@ -55,7 +55,7 @@
 					证件号
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入访客证件号" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入访客证件号" placeholder-style="color:#CCCCCC;" v-model="visIdNumber" />
 				</view>
 			</view>
 
@@ -66,7 +66,7 @@
 					访问事由
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入访问事由" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入访问事由" placeholder-style="color:#CCCCCC;" v-model="visReason" maxlength="100" />
 				</view>
 			</view>
 
@@ -74,7 +74,7 @@
 			<view class="body_box">
 				<view class="box_key">车牌号</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="(选填)驾车请填写车牌号" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="(选填)驾车请填写车牌号" placeholder-style="color:#CCCCCC;" v-model="visCarNumber" />
 				</view>
 			</view>
 
@@ -82,7 +82,7 @@
 			<view class="body_box">
 				<view class="box_key">同行人数</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入同行的人数" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="number" placeholder="请输入同行的人数" placeholder-style="color:#CCCCCC;" v-model.number="visPeopleNum" />
 					<text class="value_text">人</text>
 				</view>
 			</view>
@@ -94,18 +94,18 @@
 					受访者姓名
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入受访者姓名" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入受访者姓名" placeholder-style="color:#CCCCCC;" v-model="passiveName" />
 				</view>
 			</view>
 
-			<!-- 受访者电话区域 -->
+			<!-- 受访者手机号区域 -->
 			<view class="body_box" v-if="type == 2">
 				<view class="box_key">
 					<text class="key_icon">*</text>
-					受访者电话
+					受访者手机号
 				</view>
 				<view class="box_value">
-					<input class="value_input" type="text" placeholder="请输入受访者电话" placeholder-style="color:#CCCCCC;" />
+					<input class="value_input" type="text" placeholder="请输入受访者手机号" placeholder-style="color:#CCCCCC;" v-model="passivePhone" />
 				</view>
 			</view>
 
@@ -122,7 +122,7 @@
 				<!-- 每一个学生区域 -->
 				<view class="student" v-for="item in list" :key="item.id" @click="handleClick(item)">
 					<radio class="student_checked" color="#0061FF" :checked="item.isChecked" />
-					<view class="student_info">{{ item.name }}({{ item.number }})</view>
+					<view class="student_info">{{ item.name }}({{ item.cardNo }})</view>
 				</view>
 			</view>
 		</view>
@@ -134,40 +134,301 @@
 		</label>
 
 		<!-- 按钮区域 -->
-		<view class="btn" :class="{ active: authValue }">访客预约</view>
+		<view class="btn" :class="{ active: btnFlag }" @click="handleSubmit">访客预约</view>
 	</view>
 </template>
 
 <script setup>
-import { ref } from 'vue'
+import { ref, computed } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
+import { myRequest } from '@/utils/api.js'
+import { time_format } from '@/utils/formatTime.js'
 
 // 判断是哪种身份 1为学生家长 2为其他访客
 const type = ref('')
 
-// 是否授权
-const authValue = ref(false)
+// 访客姓名
+const visName = ref('')
+
+// 访客手机号
+const visPhone = ref('')
+
+// 来访开始时间
+const visStartTime = ref('')
+
+// 来访结束时间
+const visEndTime = ref('')
+
+// 证件号
+const visIdNumber = ref('')
+
+// 访问事由
+const visReason = ref('')
+
+// 车牌号
+const visCarNumber = ref('')
+
+// 同行人数
+const visPeopleNum = ref('')
 
 // 受访学生列表数据
-const list = ref([
-	{
-		id: 1,
-		name: '张三',
-		number: '145225225425',
-		isChecked: false
-	},
-	{
-		id: 2,
-		name: '李四',
-		number: '145225225425',
-		isChecked: true
+const list = ref([])
+
+// 受访者姓名
+const passiveName = ref('')
+
+// 受访者电话
+const passivePhone = ref('')
+
+// 是否授权证件号
+const authValue = ref(false)
+
+// 预约按钮是否高亮展示
+const btnFlag = computed(() => {
+	const tem = list.value.some((item) => item.isChecked)
+	if (
+		visName.value &&
+		visPhone.value &&
+		visStartTime.value &&
+		visEndTime.value &&
+		visIdNumber.value &&
+		visReason.value && [type.value === '1' && !list.value.length] && [type.value === '1' && !tem] && [type.value === '2' && !passiveName.value] && [
+			type.value === '2' && !passivePhone.value
+		] &&
+		authValue.value
+	) {
+		return true
+	} else {
+		return false
 	}
-])
+})
 
 onLoad((options) => {
 	type.value = options.type
+	if (type.value === '1') {
+		getList()
+	}
 })
 
+// 获取家长绑定学生数组
+const getList = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/queryAffiliateUserById',
+		data: {
+			id: uni.getStorageSync('userId')
+		}
+	})
+	// console.log(res)
+	list.value = res.data
+}
+
+// 访客预约按钮回调
+const handleSubmit = () => {
+	const flag = verifyValue()
+	if (flag) {
+		if (type.value === '1') {
+			parentAppointment()
+		} else {
+			otherAppointment()
+		}
+	}
+}
+
+// 家长预约请求
+const parentAppointment = async () => {
+	let temList = []
+	list.value.forEach((ele) => {
+		if (ele.isChecked) {
+			temList.push(ele)
+		}
+	})
+
+	const res = await myRequest({
+		url: '/wanzai/api/smartVisitor/parentsAppointment',
+		method: 'post',
+		data: {
+			userId: uni.getStorageSync('userId'),
+			visitorTime: visStartTime.value,
+			visitReason: visReason.value,
+			carNum: visCarNumber.value,
+			peerNum: visPeopleNum.value ? visPeopleNum.value : 0,
+			students: temList
+		}
+	})
+	// console.log(res)
+	uni.showToast({
+		title: res.message,
+		icon: 'none',
+		duration: 2000
+	})
+	setTimeout(() => {
+		uni.navigateBack(1)
+	}, 2000)
+}
+
+// 其他访客预约请求
+const otherAppointment = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartVisitor/otherAppointment',
+		method: 'post',
+		data: {
+			userId: uni.getStorageSync('userId'),
+			visitorTime: visStartTime.value,
+			visitReason: visReason.value,
+			carNum: visCarNumber.value,
+			peerNum: visPeopleNum.value ? visPeopleNum.value : 0,
+			respondentName: passiveName.value,
+			respondentPhone: passivePhone.value
+		}
+	})
+	console.log(res)
+	uni.showToast({
+		title: res.message,
+		icon: 'none',
+		duration: 2000
+	})
+	setTimeout(() => {
+		uni.navigateBack(1)
+	}, 2000)
+}
+
+// 选择来访开始时间时的回调
+const changeStart = (e) => {
+	// 兼容ios部分系统转换时间格式
+	const temTime = e.replace(/-/g, '/')
+	// 转化成时间戳
+	const timestamp = Date.parse(new Date(temTime))
+	// 默认访问时间4小时
+	const addTime = 1000 * 60 * 60 * 4
+
+	visEndTime.value = time_format(timestamp + addTime)
+}
+
+// 验证表格数据是否符合规范
+const verifyValue = () => {
+	// 姓名验证规则
+	const regName = /^[\u4e00-\u9fa5]{2,4}$/
+	// 手机号码验证规则
+	const regPhone = /^1[3-9]\d{9}$/
+	// 身份证号码验证规则
+	const regIdentity = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
+
+	if (!visName.value) {
+		uni.showToast({
+			title: '请输入访客姓名',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!regName.test(visName.value)) {
+		uni.showToast({
+			title: '姓名格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!visPhone.value) {
+		uni.showToast({
+			title: '请输入访客手机号',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!regPhone.test(visPhone.value)) {
+		uni.showToast({
+			title: '手机号码格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!visStartTime.value) {
+		uni.showToast({
+			title: '请选择来访时间',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!visEndTime.value) {
+		uni.showToast({
+			title: '请选择来访结束时间',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!visIdNumber.value) {
+		uni.showToast({
+			title: '请输入访客证件号',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!regIdentity.test(visIdNumber.value)) {
+		uni.showToast({
+			title: '证件号格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!visReason.value) {
+		uni.showToast({
+			title: '请输入访问事由',
+			icon: 'none'
+		})
+		return false
+	}
+	if (type.value === '1' && !list.value.length) {
+		uni.showToast({
+			title: '请绑定学生后再开始预约',
+			icon: 'none'
+		})
+		return false
+	}
+	const tem = list.value.some((item) => item.isChecked)
+	if (type.value === '1' && !tem) {
+		uni.showToast({
+			title: '请选择受访学生',
+			icon: 'none'
+		})
+		return false
+	}
+	if (type.value === '2' && !passiveName.value) {
+		uni.showToast({
+			title: '请输入受访者姓名',
+			icon: 'none'
+		})
+		return false
+	}
+	if (type.value === '2' && !regName.test(passiveName.value)) {
+		uni.showToast({
+			title: '受访者姓名格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+	if (type.value === '2' && !passivePhone.value) {
+		uni.showToast({
+			title: '请输入受访者电话',
+			icon: 'none'
+		})
+		return false
+	}
+	if (type.value === '2' && !regPhone.test(passivePhone.value)) {
+		uni.showToast({
+			title: '受访者手机号格式错误',
+			icon: 'none'
+		})
+		return false
+	}
+	if (!authValue.value) {
+		uni.showToast({
+			title: '请同意授权证件号',
+			icon: 'none'
+		})
+		return false
+	}
+	return true
+}
+
 // 点击每一个学生回调
 const handleClick = (item) => {
 	item.isChecked = !item.isChecked
@@ -224,6 +485,10 @@ const handleAuth = () => {
 					text-align: end;
 					color: #cccccc;
 				}
+
+				.activeTime {
+					color: #000;
+				}
 			}
 		}
 

+ 10 - 5
pagesReservation/reservation/reservation.vue

@@ -12,25 +12,25 @@
 			<view class="body_title">选择预约方式</view>
 
 			<!-- 学生家长预约选项区域 -->
-			<view class="body_box" @click="goPage('/pagesReservation/register/register?type=1')">
+			<view class="body_box" @click="goPage('/pagesReservation/register/register?type=1')" v-if="userType == 0">
 				<img class="box_img" src="../../static/images/reservation.png" />
 				<view class="box_text">学生家长预约</view>
 				<img class="box_icon" src="../../static/images/right-blue.png" />
 			</view>
 
 			<!-- 其他访客预约选项区域 -->
-			<view class="body_box" @click="goPage('/pagesReservation/register/register?type=2')">
+			<view class="body_box" @click="goPage('/pagesReservation/register/register?type=2')" v-if="userType == 1">
 				<img class="box_img" src="../../static/images/reservation2.png" />
 				<view class="box_text">其他访客预约</view>
 				<img class="box_icon" src="../../static/images/right-blue.png" />
 			</view>
 
 			<!-- 生成邀请预约码选项区域 -->
-			<view class="body_box" @click="goPage('/pagesReservation/QRCode/QRCode')">
+			<!-- <view class="body_box" @click="goPage('/pagesReservation/QRCode/QRCode')">
 				<img class="box_img" src="../../static/images/reservation3.png" />
 				<view class="box_text">生成邀请预约码</view>
 				<img class="box_icon" src="../../static/images/right-blue.png" />
-			</view>
+			</view> -->
 		</view>
 
 		<!-- 底部导航栏区域 -->
@@ -43,7 +43,12 @@ import { ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
 import tabber from '@/components/tabber.vue'
 
-onLoad(() => {})
+const userType = ref('')
+
+onLoad(() => {
+	userType.value = uni.getStorageSync('userType')
+	console.log(userType.value)
+})
 const goPage = (url) => {
 	uni.navigateTo({
 		url

二进制
static/images/noData.png


+ 9 - 0
uni_modules/uv-code/changelog.md

@@ -0,0 +1,9 @@
+## 1.0.3(2023-10-13)
+1. 优化
+## 1.0.2(2023-10-13)
+1. unmounted兼容vue3
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+uv-code 验证码倒计时

+ 35 - 0
uni_modules/uv-code/components/uv-code/props.js

@@ -0,0 +1,35 @@
+export default {
+	props: {
+		// 倒计时总秒数
+		seconds: {
+			type: [String, Number],
+			default: 60
+		},
+		// 尚未开始时提示
+		startText: {
+			type: String,
+			default: '获取验证码'
+		},
+		// 正在倒计时中的提示
+		changeText: {
+			type: String,
+			default: 'X秒重新获取'
+		},
+		// 倒计时结束时的提示
+		endText: {
+			type: String,
+			default: '重新获取'
+		},
+		// 是否在H5刷新或各端返回再进入时继续倒计时
+		keepRunning: {
+			type: Boolean,
+			default: false
+		},
+		// 为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
+		uniqueKey: {
+			type: String,
+			default: ''
+		},
+		...uni.$uv?.props?.code
+	}
+}

+ 136 - 0
uni_modules/uv-code/components/uv-code/uv-code.vue

@@ -0,0 +1,136 @@
+<template>
+	<view class="uv-code">
+		<!-- 此组件功能由js完成,无需写html逻辑 -->
+	</view>
+</template>
+<script>
+	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
+	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
+	import props from './props.js';
+	/**
+	 * Code 验证码倒计时
+	 * @description 考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件不提供界面显示,只提供倒计时文本,由用户将文本嵌入到具体的场景
+	 * @tutorial https://www.uvui.cn/components/code.html
+	 * @property {String | Number}	seconds			倒计时所需的秒数(默认 60 )
+	 * @property {String}			startText		开始前的提示语,见官网说明(默认 '获取验证码' )
+	 * @property {String}			changeText		倒计时期间的提示语,必须带有字母"x",见官网说明(默认 'X秒重新获取' )
+	 * @property {String}			endText			倒计结束的提示语,见官网说明(默认 '重新获取' )
+	 * @property {Boolean}			keepRunning		是否在H5刷新或各端返回再进入时继续倒计时( 默认false )
+	 * @property {String}			uniqueKey		为了区分多个页面,或者一个页面多个倒计时组件本地存储的继续倒计时变了
+	 *
+	 * @event {Function}	change	倒计时期间,每秒触发一次
+	 * @event {Function}	start	开始倒计时触发
+	 * @event {Function}	end		结束倒计时触发
+	 * @example <uv-code ref="uCode" @change="codeChange" seconds="20"></uv-code>
+	 */
+	export default {
+		name: "uv-code",
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+				secNum: this.seconds,
+				timer: null,
+				canGetCode: true, // 是否可以执行验证码操作
+			}
+		},
+		mounted() {
+			this.checkKeepRunning()
+		},
+		watch: {
+			seconds: {
+				immediate: true,
+				handler(n) {
+					this.secNum = n
+				}
+			}
+		},
+		methods: {
+			checkKeepRunning() {
+				// 获取上一次退出页面(H5还包括刷新)时的时间戳,如果没有上次的保存,此值可能为空
+				let lastTimestamp = Number(uni.getStorageSync(this.uniqueKey + '_$uCountDownTimestamp'))
+				if (!lastTimestamp) return this.changeEvent(this.startText)
+				// 当前秒的时间戳
+				let nowTimestamp = Math.floor((+new Date()) / 1000)
+				// 判断当前的时间戳,是否小于上一次的本该按设定结束,却提前结束的时间戳
+				if (this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
+					// 剩余尚未执行完的倒计秒数
+					this.secNum = lastTimestamp - nowTimestamp
+					// 清除本地保存的变量
+					uni.removeStorageSync(this.uniqueKey + '_$uCountDownTimestamp')
+					// 开始倒计时
+					this.start()
+				} else {
+					// 如果不存在需要继续上一次的倒计时,执行正常的逻辑
+					this.changeEvent(this.startText)
+				}
+			},
+			// 开始倒计时
+			start() {
+				// 防止快速点击获取验证码的按钮而导致内部产生多个定时器导致混乱
+				if (this.timer) {
+					clearInterval(this.timer)
+					this.timer = null
+				}
+				this.$emit('start')
+				this.canGetCode = false
+				// 这里放这句,是为了一开始时就提示,否则要等setInterval的1秒后才会有提示
+				this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
+				this.timer = setInterval(() => {
+					if (--this.secNum) {
+						// 用当前倒计时的秒数替换提示字符串中的"x"字母
+						this.changeEvent(this.changeText.replace(/x|X/, this.secNum))
+					} else {
+						clearInterval(this.timer)
+						this.timer = null
+						this.changeEvent(this.endText)
+						this.secNum = this.seconds
+						this.$emit('end')
+						this.canGetCode = true
+					}
+				}, 1000)
+				this.setTimeToStorage()
+			},
+			// 重置,可以让用户再次获取验证码
+			reset() {
+				this.canGetCode = true
+				clearInterval(this.timer)
+				this.secNum = this.seconds
+				this.changeEvent(this.endText)
+			},
+			changeEvent(text) {
+				this.$emit('change', text)
+			},
+			// 保存时间戳,为了防止倒计时尚未结束,H5刷新或者各端的右上角返回上一页再进来
+			setTimeToStorage() {
+				if (!this.keepRunning || !this.timer) return
+				// 记录当前的时间戳,为了下次进入页面,如果还在倒计时内的话,继续倒计时
+				// 倒计时尚未结束,结果大于0;倒计时已经开始,就会小于初始值,如果等于初始值,说明没有开始倒计时,无需处理
+				if (this.secNum > 0 && this.secNum <= this.seconds) {
+					// 获取当前时间戳(+ new Date()为特殊写法),除以1000变成秒,再去除小数部分
+					let nowTimestamp = Math.floor((+new Date()) / 1000)
+					// 将本该结束时候的时间戳保存起来 => 当前时间戳 + 剩余的秒数
+					uni.setStorage({
+						key: this.uniqueKey + '_$uCountDownTimestamp',
+						data: nowTimestamp + Number(this.secNum)
+					})
+				}
+			}
+		},
+		// #ifdef VUE2
+		// 组件销毁的时候,清除定时器,否则定时器会继续存在,系统不会自动清除
+		beforeDestroy() {
+			this.setTimeToStorage()
+			clearTimeout(this.timer)
+			this.timer = null
+		},
+		// #endif
+		// #ifdef VUE3
+		// 组件销毁,兼容vue3
+		unmounted() {
+			this.setTimeToStorage()
+			clearTimeout(this.timer)
+			this.timer = null
+		}
+		// #endif
+	}
+</script>

+ 87 - 0
uni_modules/uv-code/package.json

@@ -0,0 +1,87 @@
+{
+  "id": "uv-code",
+  "displayName": "uv-code 验证码倒计时 全面兼容小程序、nvue、vue2、vue3等多端",
+  "version": "1.0.3",
+  "description": "考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件不提供界面显示,只提供倒计时文本,由用户将文本嵌入到具体的场景。",
+  "keywords": [
+    "uv-code",
+    "uvui",
+    "uv-ui",
+    "code",
+    "验证码倒计时"
+],
+  "repository": "",
+  "engines": {
+    "HBuilderX": "^3.1.0"
+  },
+  "dcloudext": {
+    "type": "component-vue",
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+    	"ads": "无",
+    	"data": "插件不采集任何数据",
+    	"permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [
+			"uv-ui-tools"
+		],
+    "encrypt": [],
+    "platforms": {
+			"cloud": {
+				"tcb": "y",
+				"aliyun": "y"
+			},
+			"client": {
+				"Vue": {
+					"vue2": "y",
+					"vue3": "y"
+				},
+				"App": {
+					"app-vue": "y",
+					"app-nvue": "y"
+				},
+				"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",
+					"飞书": "u",
+					"京东": "u"
+				},
+				"快应用": {
+					"华为": "u",
+					"联盟": "u"
+				}
+			}
+		}
+  }
+}

+ 11 - 0
uni_modules/uv-code/readme.md

@@ -0,0 +1,11 @@
+## Code 验证码输入框
+
+> **组件名:uv-code**
+
+考虑到用户实际发送验证码的场景,可能是一个按钮,也可能是一段文字,提示语各有不同,所以本组件不提供界面显示,只提供倒计时文本,由用户将文本嵌入到具体的场景。
+
+### <a href="https://www.uvui.cn/components/code.html" target="_blank">查看文档</a>
+
+### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 4 - 0
uni_modules/uv-ui-tools/changelog.md

@@ -1,3 +1,7 @@
+## 1.1.24(2023-12-21)
+1. luch-request更新
+## 1.1.23(2023-12-12)
+1. 1.1.19版本
 ## 1.1.22(2023-11-28)
 1. 优化
 ## 1.1.21(2023-11-10)

+ 2 - 2
uni_modules/uv-ui-tools/libs/config/config.js

@@ -1,5 +1,5 @@
-// 此版本发布于2023-11-28
-const version = '1.1.18'
+// 此版本发布于2023-12-12
+const version = '1.1.19'
 
 // 开发环境才提示,生产环境不会提示
 if (process.env.NODE_ENV === 'development') {

+ 107 - 72
uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js

@@ -1,7 +1,7 @@
 import buildURL from '../helpers/buildURL'
 import buildFullPath from '../core/buildFullPath'
 import settle from '../core/settle'
-import { isUndefined } from '../utils'
+import {isUndefined} from "../utils"
 
 /**
  * 返回可选值存在的配置
@@ -10,88 +10,123 @@ import { isUndefined } from '../utils'
  * @return {{}} - 存在的配置项
  */
 const mergeKeys = (keys, config2) => {
-    const config = {}
-    keys.forEach((prop) => {
-        if (!isUndefined(config2[prop])) {
-            config[prop] = config2[prop]
-        }
-    })
-    return config
+  let config = {}
+  keys.forEach(prop => {
+    if (!isUndefined(config2[prop])) {
+      config[prop] = config2[prop]
+    }
+  })
+  return config
 }
-export default (config) => new Promise((resolve, reject) => {
-    const fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params)
+export default (config) => {
+  return new Promise((resolve, reject) => {
+    let fullPath = buildURL(buildFullPath(config.baseURL, config.url), config.params, config.paramsSerializer)
     const _config = {
-        url: fullPath,
-        header: config.header,
-        complete: (response) => {
-            config.fullPath = fullPath
-            response.config = config
-            try {
-                // 对可能字符串不是json 的情况容错
-                if (typeof response.data === 'string') {
-                    response.data = JSON.parse(response.data)
-                }
-                // eslint-disable-next-line no-empty
-            } catch (e) {
-            }
-            settle(resolve, reject, response)
+      url: fullPath,
+      header: config.header,
+      complete: (response) => {
+        config.fullPath = fullPath
+        response.config = config
+        response.rawData = response.data
+        try {
+          let jsonParseHandle = false
+          const forcedJSONParsingType = typeof config.forcedJSONParsing
+          if (forcedJSONParsingType === 'boolean') {
+            jsonParseHandle = config.forcedJSONParsing
+          } else if (forcedJSONParsingType === 'object') {
+            const includesMethod = config.forcedJSONParsing.include || []
+            jsonParseHandle = includesMethod.includes(config.method)
+          }
+
+          // 对可能字符串不是json 的情况容错
+          if (jsonParseHandle && typeof response.data === 'string') {
+            response.data = JSON.parse(response.data)
+          }
+          // eslint-disable-next-line no-empty
+        } catch (e) {
         }
+        settle(resolve, reject, response)
+      }
     }
     let requestTask
     if (config.method === 'UPLOAD') {
-        delete _config.header['content-type']
-        delete _config.header['Content-Type']
-        const otherConfig = {
+      delete _config.header['content-type']
+      delete _config.header['Content-Type']
+      let otherConfig = {
         // #ifdef MP-ALIPAY
-            fileType: config.fileType,
-            // #endif
-            filePath: config.filePath,
-            name: config.name
-        }
-        const optionalKeys = [
+        fileType: config.fileType,
+        // #endif
+        filePath: config.filePath,
+        name: config.name
+      }
+      const optionalKeys = [
         // #ifdef APP-PLUS || H5
-            'files',
-            // #endif
-            // #ifdef H5
-            'file',
-            // #endif
-            // #ifdef H5 || APP-PLUS
-            'timeout',
-            // #endif
-            'formData'
-        ]
-        requestTask = uni.uploadFile({ ..._config, ...otherConfig, ...mergeKeys(optionalKeys, config) })
+        'files',
+        // #endif
+        // #ifdef H5
+        'file',
+        // #endif
+        // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+        'timeout',
+        // #endif
+        'formData'
+      ]
+      requestTask = uni.uploadFile({..._config, ...otherConfig, ...mergeKeys(optionalKeys, config)})
     } else if (config.method === 'DOWNLOAD') {
-        // #ifdef H5 || APP-PLUS
-        if (!isUndefined(config.timeout)) {
-            _config.timeout = config.timeout
-        }
+      const optionalKeys = [
+        // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+        'timeout',
         // #endif
-        requestTask = uni.downloadFile(_config)
+        // #ifdef MP
+        'filePath',
+        // #endif
+      ]
+      requestTask = uni.downloadFile({..._config, ...mergeKeys(optionalKeys, config)})
     } else {
-        const optionalKeys = [
-            'data',
-            'method',
-            // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-            'timeout',
-            // #endif
-            'dataType',
-            // #ifndef MP-ALIPAY
-            'responseType',
-            // #endif
-            // #ifdef APP-PLUS
-            'sslVerify',
-            // #endif
-            // #ifdef H5
-            'withCredentials',
-            // #endif
-            // #ifdef APP-PLUS
-            'firstIpv4'
-        // #endif
-        ]
-        requestTask = uni.request({ ..._config, ...mergeKeys(optionalKeys, config) })
+      const optionalKeys = [
+        'data',
+        'method',
+        // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
+        'timeout',
+        // #endif
+        'dataType',
+        // #ifndef MP-ALIPAY
+        'responseType',
+        // #endif
+        // #ifdef APP-PLUS
+        'sslVerify',
+        // #endif
+        // #ifdef H5
+        'withCredentials',
+        // #endif
+        // #ifdef APP-PLUS
+        'firstIpv4',
+        // #endif
+        // #ifdef MP-WEIXIN
+        'enableHttp2',
+        'enableQuic',
+        // #endif
+        // #ifdef MP-TOUTIAO || MP-WEIXIN
+        'enableCache',
+        // #endif
+        // #ifdef MP-WEIXIN
+        'enableHttpDNS',
+        'httpDNSServiceId',
+        'enableChunked',
+        'forceCellularNetwork',
+        // #endif
+        // #ifdef MP-ALIPAY
+        'enableCookie',
+        // #endif
+        // #ifdef MP-BAIDU
+        'cloudCache',
+        'defer'
+        // #endif
+      ]
+      requestTask = uni.request({..._config, ...mergeKeys(optionalKeys, config)})
     }
     if (config.getTask) {
-        config.getTask(requestTask, config)
+      config.getTask(requestTask, config)
     }
-})
+  })
+}

+ 15 - 14
uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js

@@ -1,7 +1,8 @@
 'use strict'
 
+
 function InterceptorManager() {
-    this.handlers = []
+  this.handlers = []
 }
 
 /**
@@ -13,11 +14,11 @@ function InterceptorManager() {
  * @return {Number} An ID used to remove interceptor later
  */
 InterceptorManager.prototype.use = function use(fulfilled, rejected) {
-    this.handlers.push({
-        fulfilled,
-        rejected
-    })
-    return this.handlers.length - 1
+  this.handlers.push({
+    fulfilled: fulfilled,
+    rejected: rejected
+  })
+  return this.handlers.length - 1
 }
 
 /**
@@ -26,9 +27,9 @@ InterceptorManager.prototype.use = function use(fulfilled, rejected) {
  * @param {Number} id The ID that was returned by `use`
  */
 InterceptorManager.prototype.eject = function eject(id) {
-    if (this.handlers[id]) {
-        this.handlers[id] = null
-    }
+  if (this.handlers[id]) {
+    this.handlers[id] = null
+  }
 }
 
 /**
@@ -40,11 +41,11 @@ InterceptorManager.prototype.eject = function eject(id) {
  * @param {Function} fn The function to call for each interceptor
  */
 InterceptorManager.prototype.forEach = function forEach(fn) {
-    this.handlers.forEach((h) => {
-        if (h !== null) {
-            fn(h)
-        }
-    })
+  this.handlers.forEach(h => {
+    if (h !== null) {
+      fn(h)
+    }
+  })
 }
 
 export default InterceptorManager

+ 141 - 138
uni_modules/uv-ui-tools/libs/luch-request/core/Request.js

@@ -1,16 +1,14 @@
 /**
  * @Class Request
  * @description luch-request http请求插件
- * @version 3.0.7
  * @Author lu-ch
- * @Date 2021-09-04
  * @Email webwork.s@qq.com
  * 文档: https://www.quanzhan.co/luch-request/
  * github: https://github.com/lei-mu/luch-request
  * DCloud: http://ext.dcloud.net.cn/plugin?id=392
- * HBuilderX: beat-3.0.4 alpha-3.0.4
  */
 
+
 import dispatchRequest from './dispatchRequest'
 import InterceptorManager from './InterceptorManager'
 import mergeConfig from './mergeConfig'
@@ -19,7 +17,7 @@ import { isPlainObject } from '../utils'
 import clone from '../utils/clone'
 
 export default class Request {
-    /**
+  /**
    * @param {Object} arg - 全局配置
    * @param {String} arg.baseURL - 全局根路径
    * @param {Object} arg.header - 全局header
@@ -33,47 +31,47 @@ export default class Request {
    * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
    * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
    */
-    constructor(arg = {}) {
-        if (!isPlainObject(arg)) {
-            arg = {}
-            console.warn('设置全局参数必须接收一个Object')
-        }
-        this.config = clone({ ...defaults, ...arg })
-        this.interceptors = {
-            request: new InterceptorManager(),
-            response: new InterceptorManager()
-        }
+  constructor(arg = {}) {
+    if (!isPlainObject(arg)) {
+      arg = {}
+      console.warn('设置全局参数必须接收一个Object')
+    }
+    this.config = clone({...defaults, ...arg})
+    this.interceptors = {
+      request: new InterceptorManager(),
+      response: new InterceptorManager()
     }
+  }
 
-    /**
+  /**
    * @Function
    * @param {Request~setConfigCallback} f - 设置全局默认配置
    */
-    setConfig(f) {
-        this.config = f(this.config)
-    }
+  setConfig(f) {
+    this.config = f(this.config)
+  }
 
-    middleware(config) {
-        config = mergeConfig(this.config, config)
-        const chain = [dispatchRequest, undefined]
-        let promise = Promise.resolve(config)
+  middleware(config) {
+    config = mergeConfig(this.config, config)
+    let chain = [dispatchRequest, undefined]
+    let promise = Promise.resolve(config)
 
-        this.interceptors.request.forEach((interceptor) => {
-            chain.unshift(interceptor.fulfilled, interceptor.rejected)
-        })
+    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
+      chain.unshift(interceptor.fulfilled, interceptor.rejected)
+    })
 
-        this.interceptors.response.forEach((interceptor) => {
-            chain.push(interceptor.fulfilled, interceptor.rejected)
-        })
+    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
+      chain.push(interceptor.fulfilled, interceptor.rejected)
+    })
 
-        while (chain.length) {
-            promise = promise.then(chain.shift(), chain.shift())
-        }
-
-        return promise
+    while (chain.length) {
+      promise = promise.then(chain.shift(), chain.shift())
     }
 
-    /**
+    return promise
+  }
+
+  /**
    * @Function
    * @param {Object} config - 请求配置项
    * @prop {String} options.url - 请求路径
@@ -84,112 +82,117 @@ export default class Request {
    * @prop {Object} [options.method = config.method] - 请求方法
    * @returns {Promise<unknown>}
    */
-    request(config = {}) {
-        return this.middleware(config)
-    }
-
-    get(url, options = {}) {
-        return this.middleware({
-            url,
-            method: 'GET',
-            ...options
-        })
-    }
-
-    post(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'POST',
-            ...options
-        })
-    }
-
-    // #ifndef MP-ALIPAY
-    put(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'PUT',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
-    delete(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'DELETE',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef H5 || MP-WEIXIN
-    connect(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'CONNECT',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef  H5 || MP-WEIXIN || MP-BAIDU
-    head(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'HEAD',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
-    options(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'OPTIONS',
-            ...options
-        })
-    }
-
-    // #endif
-
-    // #ifdef H5 || MP-WEIXIN
-    trace(url, data, options = {}) {
-        return this.middleware({
-            url,
-            data,
-            method: 'TRACE',
-            ...options
-        })
-    }
-
-    // #endif
-
-    upload(url, config = {}) {
-        config.url = url
-        config.method = 'UPLOAD'
-        return this.middleware(config)
-    }
-
-    download(url, config = {}) {
-        config.url = url
-        config.method = 'DOWNLOAD'
-        return this.middleware(config)
-    }
+  request(config = {}) {
+    return this.middleware(config)
+  }
+
+  get(url, options = {}) {
+    return this.middleware({
+      url,
+      method: 'GET',
+      ...options
+    })
+  }
+
+  post(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'POST',
+      ...options
+    })
+  }
+
+  // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
+  put(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'PUT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  delete(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'DELETE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  connect(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'CONNECT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef  H5 || MP-WEIXIN || MP-BAIDU
+  head(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'HEAD',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  options(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'OPTIONS',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  trace(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'TRACE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  upload(url, config = {}) {
+    config.url = url
+    config.method = 'UPLOAD'
+    return this.middleware(config)
+  }
+
+  download(url, config = {}) {
+    config.url = url
+    config.method = 'DOWNLOAD'
+    return this.middleware(config)
+  }
+
+  get version () {
+    return '3.1.0'
+  }
 }
 
+
 /**
  * setConfig回调
  * @return {Object} - 返回操作后的config

+ 4 - 4
uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js

@@ -13,8 +13,8 @@ import combineURLs from '../helpers/combineURLs'
  * @returns {string} The combined full path
  */
 export default function buildFullPath(baseURL, requestedURL) {
-    if (baseURL && !isAbsoluteURL(requestedURL)) {
-        return combineURLs(baseURL, requestedURL)
-    }
-    return requestedURL
+  if (baseURL && !isAbsoluteURL(requestedURL)) {
+    return combineURLs(baseURL, requestedURL)
+  }
+  return requestedURL
 }

+ 27 - 23
uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js

@@ -2,28 +2,32 @@
  * 默认的全局配置
  */
 
+
 export default {
-    baseURL: '',
-    header: {},
-    method: 'GET',
-    dataType: 'json',
-    // #ifndef MP-ALIPAY
-    responseType: 'text',
-    // #endif
-    custom: {},
-    // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-    timeout: 60000,
-    // #endif
-    // #ifdef APP-PLUS
-    sslVerify: true,
-    // #endif
-    // #ifdef H5
-    withCredentials: false,
-    // #endif
-    // #ifdef APP-PLUS
-    firstIpv4: false,
-    // #endif
-    validateStatus: function validateStatus(status) {
-        return status >= 200 && status < 300
-    }
+  baseURL: '',
+  header: {},
+  method: 'GET',
+  dataType: 'json',
+  paramsSerializer: null,
+  // #ifndef MP-ALIPAY
+  responseType: 'text',
+  // #endif
+  custom: {},
+  // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+  timeout: 60000,
+  // #endif
+  // #ifdef APP-PLUS
+  sslVerify: true,
+  // #endif
+  // #ifdef H5
+  withCredentials: false,
+  // #endif
+  // #ifdef APP-PLUS
+  firstIpv4: false,
+  // #endif
+  validateStatus: function validateStatus(status) {
+    return status >= 200 && status < 300
+  },
+  // 是否尝试将响应数据json化
+  forcedJSONParsing: true
 }

+ 4 - 1
uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js

@@ -1,3 +1,6 @@
 import adapter from '../adapters/index'
 
-export default (config) => adapter(config)
+
+export default (config) => {
+  return adapter(config)
+}

+ 105 - 82
uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js

@@ -1,4 +1,4 @@
-import { deepMerge, isUndefined } from '../utils'
+import {deepMerge, isUndefined} from '../utils'
 
 /**
  * 合并局部配置优先的配置,如果局部有该配置项则用局部,如果全局有该配置项则用全局
@@ -8,15 +8,15 @@ import { deepMerge, isUndefined } from '../utils'
  * @return {{}}
  */
 const mergeKeys = (keys, globalsConfig, config2) => {
-    const config = {}
-    keys.forEach((prop) => {
-        if (!isUndefined(config2[prop])) {
-            config[prop] = config2[prop]
-        } else if (!isUndefined(globalsConfig[prop])) {
-            config[prop] = globalsConfig[prop]
-        }
-    })
-    return config
+  let config = {}
+  keys.forEach(prop => {
+    if (!isUndefined(config2[prop])) {
+      config[prop] = config2[prop]
+    } else if (!isUndefined(globalsConfig[prop])) {
+      config[prop] = globalsConfig[prop]
+    }
+  })
+  return config
 }
 /**
  *
@@ -25,79 +25,102 @@ const mergeKeys = (keys, globalsConfig, config2) => {
  * @return - 合并后的配置
  */
 export default (globalsConfig, config2 = {}) => {
-    const method = config2.method || globalsConfig.method || 'GET'
-    let config = {
-        baseURL: globalsConfig.baseURL || '',
-        method,
-        url: config2.url || '',
-        params: config2.params || {},
-        custom: { ...(globalsConfig.custom || {}), ...(config2.custom || {}) },
-        header: deepMerge(globalsConfig.header || {}, config2.header || {})
-    }
-    const defaultToConfig2Keys = ['getTask', 'validateStatus']
-    config = { ...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2) }
+  const method = config2.method || globalsConfig.method || 'GET'
+  let config = {
+    baseURL: config2.baseURL || globalsConfig.baseURL || '',
+    method: method,
+    url: config2.url || '',
+    params: config2.params || {},
+    custom: {...(globalsConfig.custom || {}), ...(config2.custom || {})},
+    header: deepMerge(globalsConfig.header || {}, config2.header || {})
+  }
+  const defaultToConfig2Keys = ['getTask', 'validateStatus', 'paramsSerializer', 'forcedJSONParsing']
+  config = {...config, ...mergeKeys(defaultToConfig2Keys, globalsConfig, config2)}
 
-    // eslint-disable-next-line no-empty
-    if (method === 'DOWNLOAD') {
-    // #ifdef H5 || APP-PLUS
-        if (!isUndefined(config2.timeout)) {
-            config.timeout = config2.timeout
-        } else if (!isUndefined(globalsConfig.timeout)) {
-            config.timeout = globalsConfig.timeout
-        }
-    // #endif
-    } else if (method === 'UPLOAD') {
-        delete config.header['content-type']
-        delete config.header['Content-Type']
-        const uploadKeys = [
-            // #ifdef APP-PLUS || H5
-            'files',
-            // #endif
-            // #ifdef MP-ALIPAY
-            'fileType',
-            // #endif
-            // #ifdef H5
-            'file',
-            // #endif
-            'filePath',
-            'name',
-            // #ifdef H5 || APP-PLUS
-            'timeout',
-            // #endif
-            'formData'
-        ]
-        uploadKeys.forEach((prop) => {
-            if (!isUndefined(config2[prop])) {
-                config[prop] = config2[prop]
-            }
-        })
-        // #ifdef H5 || APP-PLUS
-        if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
-            config.timeout = globalsConfig.timeout
-        }
-    // #endif
-    } else {
-        const defaultsKeys = [
-            'data',
-            // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
-            'timeout',
-            // #endif
-            'dataType',
-            // #ifndef MP-ALIPAY
-            'responseType',
-            // #endif
-            // #ifdef APP-PLUS
-            'sslVerify',
-            // #endif
-            // #ifdef H5
-            'withCredentials',
-            // #endif
-            // #ifdef APP-PLUS
-            'firstIpv4'
-            // #endif
-        ]
-        config = { ...config, ...mergeKeys(defaultsKeys, globalsConfig, config2) }
+  // eslint-disable-next-line no-empty
+  if (method === 'DOWNLOAD') {
+    const downloadKeys = [
+      // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+      'timeout',
+      // #endif
+      // #ifdef MP
+      'filePath',
+      // #endif
+    ]
+    config = {...config, ...mergeKeys(downloadKeys, globalsConfig, config2)}
+  } else if (method === 'UPLOAD') {
+    delete config.header['content-type']
+    delete config.header['Content-Type']
+    const uploadKeys = [
+      // #ifdef APP-PLUS || H5
+      'files',
+      // #endif
+      // #ifdef MP-ALIPAY
+      'fileType',
+      // #endif
+      // #ifdef H5
+      'file',
+      // #endif
+      'filePath',
+      'name',
+      // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+      'timeout',
+      // #endif
+      'formData',
+    ]
+    uploadKeys.forEach(prop => {
+      if (!isUndefined(config2[prop])) {
+        config[prop] = config2[prop]
+      }
+    })
+    // #ifdef H5 || APP-PLUS || MP-WEIXIN || MP-ALIPAY || MP-TOUTIAO || MP-KUAISHOU
+    if (isUndefined(config.timeout) && !isUndefined(globalsConfig.timeout)) {
+      config['timeout'] = globalsConfig['timeout']
     }
+    // #endif
+  } else {
+    const defaultsKeys = [
+      'data',
+      // #ifdef H5 || APP-PLUS || MP-ALIPAY || MP-WEIXIN
+      'timeout',
+      // #endif
+      'dataType',
+      // #ifndef MP-ALIPAY
+      'responseType',
+      // #endif
+      // #ifdef APP-PLUS
+      'sslVerify',
+      // #endif
+      // #ifdef H5
+      'withCredentials',
+      // #endif
+      // #ifdef APP-PLUS
+      'firstIpv4',
+      // #endif
+      // #ifdef MP-WEIXIN
+      'enableHttp2',
+      'enableQuic',
+      // #endif
+      // #ifdef MP-TOUTIAO || MP-WEIXIN
+      'enableCache',
+      // #endif
+      // #ifdef MP-WEIXIN
+      'enableHttpDNS',
+      'httpDNSServiceId',
+      'enableChunked',
+      'forceCellularNetwork',
+      // #endif
+      // #ifdef MP-ALIPAY
+      'enableCookie',
+      // #endif
+      // #ifdef MP-BAIDU
+      'cloudCache',
+      'defer'
+      // #endif
+
+    ]
+    config = {...config, ...mergeKeys(defaultsKeys, globalsConfig, config2)}
+  }
 
-    return config
+  return config
 }

+ 7 - 7
uni_modules/uv-ui-tools/libs/luch-request/core/settle.js

@@ -6,11 +6,11 @@
  * @param {object} response The response.
  */
 export default function settle(resolve, reject, response) {
-    const { validateStatus } = response.config
-    const status = response.statusCode
-    if (status && (!validateStatus || validateStatus(status))) {
-        resolve(response)
-    } else {
-        reject(response)
-    }
+  const validateStatus = response.config.validateStatus
+  const status = response.statusCode
+  if (status && (!validateStatus || validateStatus(status))) {
+    resolve(response)
+  } else {
+    reject(response)
+  }
 }

+ 42 - 47
uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js

@@ -1,16 +1,9 @@
 'use strict'
 
-import * as utils from '../utils'
+import * as utils from './../utils'
 
 function encode(val) {
-    return encodeURIComponent(val)
-        .replace(/%40/gi, '@')
-        .replace(/%3A/gi, ':')
-        .replace(/%24/g, '$')
-        .replace(/%2C/gi, ',')
-        .replace(/%20/g, '+')
-        .replace(/%5B/gi, '[')
-        .replace(/%5D/gi, ']')
+  return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, '+').replace(/%5B/gi, '[').replace(/%5D/gi, ']')
 }
 
 /**
@@ -20,50 +13,52 @@ function encode(val) {
  * @param {object} [params] The params to be appended
  * @returns {string} The formatted url
  */
-export default function buildURL(url, params) {
-    /* eslint no-param-reassign:0 */
-    if (!params) {
-        return url
-    }
-
-    let serializedParams
-    if (utils.isURLSearchParams(params)) {
-        serializedParams = params.toString()
-    } else {
-        const parts = []
-
-        utils.forEach(params, (val, key) => {
-            if (val === null || typeof val === 'undefined') {
-                return
-            }
+export default function buildURL(url, params, paramsSerializer) {
+  /*eslint no-param-reassign:0*/
+  if (!params) {
+    return url
+  }
 
-            if (utils.isArray(val)) {
-                key = `${key}[]`
-            } else {
-                val = [val]
-            }
+  var serializedParams
+  if (paramsSerializer) {
+    serializedParams = paramsSerializer(params)
+  } else if (utils.isURLSearchParams(params)) {
+    serializedParams = params.toString()
+  } else {
+    var parts = []
 
-            utils.forEach(val, (v) => {
-                if (utils.isDate(v)) {
-                    v = v.toISOString()
-                } else if (utils.isObject(v)) {
-                    v = JSON.stringify(v)
-                }
-                parts.push(`${encode(key)}=${encode(v)}`)
-            })
-        })
+    utils.forEach(params, function serialize(val, key) {
+      if (val === null || typeof val === 'undefined') {
+        return
+      }
 
-        serializedParams = parts.join('&')
-    }
+      if (utils.isArray(val)) {
+        key = key + '[]'
+      } else {
+        val = [val]
+      }
 
-    if (serializedParams) {
-        const hashmarkIndex = url.indexOf('#')
-        if (hashmarkIndex !== -1) {
-            url = url.slice(0, hashmarkIndex)
+      utils.forEach(val, function parseValue(v) {
+        if (utils.isDate(v)) {
+          v = v.toISOString()
+        } else if (utils.isObject(v)) {
+          v = JSON.stringify(v)
         }
+        parts.push(encode(key) + '=' + encode(v))
+      })
+    })
+
+    serializedParams = parts.join('&')
+  }
 
-        url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
+  if (serializedParams) {
+    var hashmarkIndex = url.indexOf('#')
+    if (hashmarkIndex !== -1) {
+      url = url.slice(0, hashmarkIndex)
     }
 
-    return url
+    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams
+  }
+
+  return url
 }

+ 3 - 3
uni_modules/uv-ui-tools/libs/luch-request/helpers/combineURLs.js

@@ -8,7 +8,7 @@
  * @returns {string} The combined URL
  */
 export default function combineURLs(baseURL, relativeURL) {
-    return relativeURL
-        ? `${baseURL.replace(/\/+$/, '')}/${relativeURL.replace(/^\/+/, '')}`
-        : baseURL
+  return relativeURL
+    ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '')
+    : baseURL
 }

+ 4 - 4
uni_modules/uv-ui-tools/libs/luch-request/helpers/isAbsoluteURL.js

@@ -7,8 +7,8 @@
  * @returns {boolean} True if the specified URL is absolute, otherwise false
  */
 export default function isAbsoluteURL(url) {
-    // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
-    // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
-    // by any combination of letters, digits, plus, period, or hyphen.
-    return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
+  // A URL is considered absolute if it begins with "<scheme>://" or "//" (protocol-relative URL).
+  // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed
+  // by any combination of letters, digits, plus, period, or hyphen.
+  return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url)
 }

+ 184 - 103
uni_modules/uv-ui-tools/libs/luch-request/index.d.ts

@@ -1,116 +1,197 @@
-type AnyObject = Record<string | number | symbol, any>
-type HttpPromise<T> = Promise<HttpResponse<T>>;
-type Tasks = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask
-export interface RequestTask {
-  abort: () => void;
-  offHeadersReceived: () => void;
-  onHeadersReceived: () => void;
-}
-export interface HttpRequestConfig<T = Tasks> {
-  /** 请求基地址 */
-  baseURL?: string;
-  /** 请求服务器接口地址 */
-  url?: string;
-
-  /** 请求查询参数,自动拼接为查询字符串 */
-  params?: AnyObject;
-  /** 请求体参数 */
-  data?: AnyObject;
-
-  /** 文件对应的 key */
-  name?: string;
-  /** HTTP 请求中其他额外的 form data */
-  formData?: AnyObject;
-  /** 要上传文件资源的路径。 */
-  filePath?: string;
-  /** 需要上传的文件列表。使用 files 时,filePath 和 name 不生效,App、H5( 2.6.15+) */
-  files?: Array<{
-    name?: string;
+export type HttpTask = UniApp.RequestTask | UniApp.UploadTask | UniApp.DownloadTask;
+
+export type HttpRequestTask = UniApp.RequestTask;
+
+export type HttpUploadTask = UniApp.UploadTask;
+
+export type HttpDownloadTask = UniApp.DownloadTask;
+
+export type HttpMethod =
+    "GET"
+    | "POST"
+    | "PUT"
+    | "DELETE"
+    | "CONNECT"
+    | "HEAD"
+    | "OPTIONS"
+    | "TRACE"
+    | "UPLOAD"
+    | "DOWNLOAD";
+
+export type HttpRequestHeader = Record<string, string>;
+
+export type HttpParams = Record<string, any>;
+
+export type HttpData = Record<string, any>;
+
+export type HttpResponseType = 'arraybuffer' | 'text';
+
+export type HttpCustom = Record<string, any>;
+
+export type HttpFileType = 'image' | 'video' | 'audio';
+
+export type HttpFormData = Record<string, any>;
+
+export type HttpResponseHeader = Record<string, string> & {
+    "set-cookie"?: string[]
+};
+
+export interface HttpRequestConfig<T = HttpTask> {
+    /** @desc 请求服务器接口地址 */
+    url?: string;
+    /** @desc 请求方式,默认为 GET */
+    method?: HttpMethod;
+    /** @desc 请求基地址 */
+    baseURL?: string;
+    /** @desc 请求头信息,不能设置 Referer,App、H5 端会自动带上 cookie,且 H5 端不可手动修改 */
+    header?: HttpRequestHeader;
+    /** @desc 请求查询参数,自动拼接为查询字符串 */
+    params?: HttpParams;
+    /** @desc 请求体参数 */
+    data?: HttpData;
+    /** @desc 超时时间,单位 ms,默认为 60000,仅 H5 (HBuilderX 2.9.9+)、APP (HBuilderX 2.9.9+)、微信小程序 (2.10.0)、支付宝小程序支持 */
+    timeout?: number;
+    /** @desc 跨域请求时是否携带凭证 (cookies),默认为 false,仅 H5 (HBuilderX 2.6.15+) 支持 */
+    withCredentials?: boolean;
+    /** @desc 设置响应的数据类型,支付宝小程序不支持 */
+    responseType?: HttpResponseType;
+    /** @desc 全局自定义验证器 */
+    validateStatus?: ((statusCode: number) => boolean) | null;
+
+
+    /** params 参数自定义处理 */
+    paramsSerializer?: (params: AnyObject) => string | void;
+
+    /** @desc 默认为 json,如果设为 json,会尝试对返回的数据做一次 JSON.parse */
+    dataType?: string;
+    /** @desc DNS 解析时是否优先使用 ipv4,默认为 false,仅 App-Android (HBuilderX 2.8.0+) 支持 */
+    firstIpv4?: boolean;
+    /** @desc 是否验证 SSL 证书,默认为 true,仅 App-Android (HBuilderX 2.3.3+) 支持 */
+    sslVerify?: boolean;
+
+    /** @desc 开启 http2;微信小程序 */
+    enableHttp2?: boolean;
+
+    /** @desc 开启 quic;微信小程序 */
+    enableQuic?: boolean;
+    /** @desc 开启 cache;微信小程序、字节跳动小程序 2.31.0+ */
+    enableCache?: boolean;
+    /** @desc 开启 httpDNS;微信小程序 */
+    enableHttpDNS?: boolean;
+    /** @desc httpDNS 服务商;微信小程序 */
+    httpDNSServiceId?: string;
+    /** @desc 开启 transfer-encoding chunked;微信小程序 */
+    enableChunked?: boolean;
+    /** @desc wifi下使用移动网络发送请求;微信小程序 */
+    forceCellularNetwork?: boolean;
+    /** @desc 开启后可在headers中编辑cookie;支付宝小程序 10.2.33+ */
+    enableCookie?: boolean;
+    /** @desc 是否开启云加速;百度小程序 3.310.11+ */
+    cloudCache?: boolean | object;
+    /** @desc 控制当前请求是否延时至首屏内容渲染后发送;百度小程序 3.310.11+ */
+    defer?: boolean;
+
+    /** @desc 自定义参数 */
+    custom?: HttpCustom;
+
+    /** @desc 返回当前请求的 task 和 options,不要在这里修改 options */
+    getTask?: (task: T, options: HttpRequestConfig<T>) => void;
+
+    /** @desc 需要上传的文件列表,使用 files 时,filePath 和 name 不生效,仅支持 App、H5 (2.6.15+) */
+    files?: { name?: string; file?: File; uri: string; }[];
+    /** @desc 文件类型,仅支付宝小程序支持且为必填项 */
+    fileType?: HttpFileType;
+    /** @desc 要上传的文件对象,仅 H5 (2.6.15+) 支持 */
     file?: File;
-    uri: string;
-  }>;
-  /** 要上传的文件对象,仅H5(2.6.15+)支持 */
-  file?: File;
-
-  /** 请求头信息 */
-  header?: AnyObject;
-  /** 请求方式 */
-  method?: "GET" | "POST" | "PUT" | "DELETE" | "CONNECT" | "HEAD" | "OPTIONS" | "TRACE" | "UPLOAD" | "DOWNLOAD";
-  /** 如果设为 json,会尝试对返回的数据做一次 JSON.parse */
-  dataType?: string;
-  /** 设置响应的数据类型,支付宝小程序不支持 */
-  responseType?: "text" | "arraybuffer";
-  /** 自定义参数 */
-  custom?: AnyObject;
-  /** 超时时间,仅微信小程序(2.10.0)、支付宝小程序支持 */
-  timeout?: number;
-  /** DNS解析时优先使用ipv4,仅 App-Android 支持 (HBuilderX 2.8.0+) */
-  firstIpv4?: boolean;
-  /** 验证 ssl 证书 仅5+App安卓端支持(HBuilderX 2.3.3+) */
-  sslVerify?: boolean;
-  /** 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+) */
-  withCredentials?: boolean;
-
-  /** 返回当前请求的task, options。请勿在此处修改options。 */
-  getTask?: (task: T, options: HttpRequestConfig<T>) => void;
-  /**  全局自定义验证器 */
-  validateStatus?: (statusCode: number) => boolean | void;
+    /** @desc 要上传文件资源的路径,使用 files 时,filePath 和 name 不生效 */
+    filePath?: string;
+    /** @desc 文件对应的 key,开发者在服务器端通过这个 key 可以获取到文件二进制内容,使用 files 时,filePath 和 name 不生效 */
+    name?: string;
+    /** @desc 请求中其他额外的 form data */
+    formData?: HttpFormData;
 }
-export interface HttpResponse<T = any> {
-  config: HttpRequestConfig;
-  statusCode: number;
-  cookies: Array<string>;
-  data: T;
-  errMsg: string;
-  header: AnyObject;
+
+export interface HttpResponse<T = any, D = HttpTask> {
+    data: T;
+    statusCode: number;
+    header: HttpResponseHeader;
+    config: HttpRequestConfig<D>;
+    cookies: string[];
+    errMsg: string;
+    rawData: any;
 }
-export interface HttpUploadResponse<T = any> {
-  config: HttpRequestConfig;
-  statusCode: number;
-  data: T;
-  errMsg: string;
+
+export interface HttpUploadResponse<T = any, D = HttpTask> {
+    data: T;
+    statusCode: number;
+    config: HttpRequestConfig<D>;
+    errMsg: string;
+    rawData: any;
 }
+
 export interface HttpDownloadResponse extends HttpResponse {
-  tempFilePath: string;
+    tempFilePath: string;
+    apFilePath?: string;
+    filePath?: string;
+    fileContent?: string;
 }
-export interface HttpError {
-  config: HttpRequestConfig;
-  statusCode?: number;
-  cookies?: Array<string>;
-  data?: any;
-  errMsg: string;
-  header?: AnyObject;
+
+export interface HttpError<T = any, D = HttpTask> {
+    data?: T;
+    statusCode?: number;
+    header?: HttpResponseHeader;
+    config: HttpRequestConfig<D>;
+    cookies?: string[];
+    errMsg: string;
 }
+
+export interface HttpPromise<T = any> extends Promise<HttpResponse<T>> {
+}
+
 export interface HttpInterceptorManager<V, E = V> {
-  use(
-    onFulfilled?: (config: V) => Promise<V> | V,
-    onRejected?: (config: E) => Promise<E> | E
-  ): void;
-  eject(id: number): void;
+    use(onFulfilled?: (value: V) => V | Promise<V>, onRejected?: (error: E) => T | Promise<E>): void;
+
+    eject(id: number): void;
 }
+
 export abstract class HttpRequestAbstract {
-  constructor(config?: HttpRequestConfig);
-  config: HttpRequestConfig;
-  interceptors: {
-    request: HttpInterceptorManager<HttpRequestConfig, HttpRequestConfig>;
-    response: HttpInterceptorManager<HttpResponse, HttpError>;
-  }
-  middleware<T = any>(config: HttpRequestConfig): HttpPromise<T>;
-  request<T = any>(config: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  get<T = any>(url: string, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  upload<T = any>(url: string, config?: HttpRequestConfig<UniApp.UploadTask>): HttpPromise<T>;
-  delete<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  head<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  post<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  put<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  connect<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  options<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-  trace<T = any>(url: string, data?: AnyObject, config?: HttpRequestConfig<UniApp.RequestTask>): HttpPromise<T>;
-
-  download(url: string, config?: HttpRequestConfig<UniApp.DownloadTask>): Promise<HttpDownloadResponse>;
-
-  setConfig(onSend: (config: HttpRequestConfig) => HttpRequestConfig): void;
+    constructor(config?: HttpRequestConfig);
+
+    interceptors: {
+        request: HttpInterceptorManager<HttpRequestConfig>;
+        response: HttpInterceptorManager<HttpResponse, HttpError>;
+    }
+
+    request<T = any, R = HttpResponse<T>, D = HttpRequestTask>(config: HttpRequestConfig<D>): Promise<R>;
+
+    get<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    delete<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    head<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    options<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    post<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    put<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    config: HttpRequestConfig;
+
+    setConfig<D = HttpTask>(onSend: (config: HttpRequestConfig<D>) => HttpRequestConfig<D>): void;
+
+    connect<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    trace<T = any, R = HttpResponse<T>, D = HttpRequestTask>(url: string, data?: HttpData, config?: HttpRequestConfig<D>): Promise<R>;
+
+    upload<T = any, R = HttpUploadResponse<T>, D = HttpUploadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    download<T = any, R = HttpDownloadResponse<T>, D = HttpDownloadTask>(url: string, config?: HttpRequestConfig<D>): Promise<R>;
+
+    middleware<T = any, R = HttpResponse<T>, D = HttpTask>(config: HttpRequestConfig<D>): Promise<R>;
+}
+
+declare class HttpRequest extends HttpRequestAbstract {
 }
 
-declare class HttpRequest extends HttpRequestAbstract { }
 export default HttpRequest;

+ 0 - 1
uni_modules/uv-ui-tools/libs/luch-request/index.js

@@ -1,3 +1,2 @@
 import Request from './core/Request'
-
 export default Request

+ 50 - 46
uni_modules/uv-ui-tools/libs/luch-request/utils.js

@@ -2,7 +2,7 @@
 
 // utils is a library of generic helper functions non-specific to axios
 
-const { toString } = Object.prototype
+var toString = Object.prototype.toString
 
 /**
  * Determine if a value is an Array
@@ -10,18 +10,19 @@ const { toString } = Object.prototype
  * @param {Object} val The value to test
  * @returns {boolean} True if value is an Array, otherwise false
  */
-export function isArray(val) {
-    return toString.call(val) === '[object Array]'
+export function isArray (val) {
+  return toString.call(val) === '[object Array]'
 }
 
+
 /**
  * Determine if a value is an Object
  *
  * @param {Object} val The value to test
  * @returns {boolean} True if value is an Object, otherwise false
  */
-export function isObject(val) {
-    return val !== null && typeof val === 'object'
+export function isObject (val) {
+  return val !== null && typeof val === 'object'
 }
 
 /**
@@ -30,8 +31,8 @@ export function isObject(val) {
  * @param {Object} val The value to test
  * @returns {boolean} True if value is a Date, otherwise false
  */
-export function isDate(val) {
-    return toString.call(val) === '[object Date]'
+export function isDate (val) {
+  return toString.call(val) === '[object Date]'
 }
 
 /**
@@ -40,10 +41,11 @@ export function isDate(val) {
  * @param {Object} val The value to test
  * @returns {boolean} True if value is a URLSearchParams object, otherwise false
  */
-export function isURLSearchParams(val) {
-    return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
+export function isURLSearchParams (val) {
+  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
 }
 
+
 /**
  * Iterate over an Array or an Object invoking a function for each item.
  *
@@ -56,31 +58,31 @@ export function isURLSearchParams(val) {
  * @param {Object|Array} obj The object to iterate
  * @param {Function} fn The callback to invoke for each item
  */
-export function forEach(obj, fn) {
-    // Don't bother if no value provided
-    if (obj === null || typeof obj === 'undefined') {
-        return
-    }
+export function forEach (obj, fn) {
+  // Don't bother if no value provided
+  if (obj === null || typeof obj === 'undefined') {
+    return
+  }
 
-    // Force an array if not already something iterable
-    if (typeof obj !== 'object') {
-    /* eslint no-param-reassign:0 */
-        obj = [obj]
-    }
+  // Force an array if not already something iterable
+  if (typeof obj !== 'object') {
+    /*eslint no-param-reassign:0*/
+    obj = [obj]
+  }
 
-    if (isArray(obj)) {
+  if (isArray(obj)) {
     // Iterate over array values
-        for (let i = 0, l = obj.length; i < l; i++) {
-            fn.call(null, obj[i], i, obj)
-        }
-    } else {
+    for (var i = 0, l = obj.length; i < l; i++) {
+      fn.call(null, obj[i], i, obj)
+    }
+  } else {
     // Iterate over object keys
-        for (const key in obj) {
-            if (Object.prototype.hasOwnProperty.call(obj, key)) {
-                fn.call(null, obj[key], key, obj)
-            }
-        }
+    for (var key in obj) {
+      if (Object.prototype.hasOwnProperty.call(obj, key)) {
+        fn.call(null, obj[key], key, obj)
+      }
     }
+  }
 }
 
 /**
@@ -89,7 +91,7 @@ export function forEach(obj, fn) {
  * @returns {boolean}
  */
 export function isBoolean(val) {
-    return typeof val === 'boolean'
+  return typeof val === 'boolean'
 }
 
 /**
@@ -98,9 +100,11 @@ export function isBoolean(val) {
  * @returns {boolean}
  */
 export function isPlainObject(obj) {
-    return Object.prototype.toString.call(obj) === '[object Object]'
+  return Object.prototype.toString.call(obj) === '[object Object]'
 }
 
+
+
 /**
  * Function equal to merge with the difference being that no reference
  * to original objects is kept.
@@ -110,22 +114,22 @@ export function isPlainObject(obj) {
  * @returns {Object} Result of all merge properties
  */
 export function deepMerge(/* obj1, obj2, obj3, ... */) {
-    const result = {}
-    function assignValue(val, key) {
-        if (typeof result[key] === 'object' && typeof val === 'object') {
-            result[key] = deepMerge(result[key], val)
-        } else if (typeof val === 'object') {
-            result[key] = deepMerge({}, val)
-        } else {
-            result[key] = val
-        }
-    }
-    for (let i = 0, l = arguments.length; i < l; i++) {
-        forEach(arguments[i], assignValue)
+  let result = {}
+  function assignValue(val, key) {
+    if (typeof result[key] === 'object' && typeof val === 'object') {
+      result[key] = deepMerge(result[key], val)
+    } else if (typeof val === 'object') {
+      result[key] = deepMerge({}, val)
+    } else {
+      result[key] = val
     }
-    return result
+  }
+  for (let i = 0, l = arguments.length; i < l; i++) {
+    forEach(arguments[i], assignValue)
+  }
+  return result
 }
 
-export function isUndefined(val) {
-    return typeof val === 'undefined'
+export function isUndefined (val) {
+  return typeof val === 'undefined'
 }

+ 1 - 1
uni_modules/uv-ui-tools/package.json

@@ -1,7 +1,7 @@
 {
   "id": "uv-ui-tools",
   "displayName": "uv-ui-tools 工具集 全面兼容vue3+2、app、h5、小程序等多端",
-  "version": "1.1.22",
+  "version": "1.1.24",
   "description": "uv-ui-tools,集成工具库,强大的Http请求封装,清晰的文档说明,开箱即用。方便使用,可以全局使用",
   "keywords": [
     "uv-ui-tools,uv-ui组件库,工具集,uvui,uView2.x"

+ 32 - 2
unpackage/dist/dev/mp-weixin/common/vendor.js

@@ -159,6 +159,10 @@ const looseToNumber = (val) => {
   const n2 = parseFloat(val);
   return isNaN(n2) ? val : n2;
 };
+const toNumber = (val) => {
+  const n2 = isString(val) ? Number(val) : NaN;
+  return isNaN(n2) ? val : n2;
+};
 const LINEFEED = "\n";
 const SLOT_DEFAULT_NAME = "d";
 const ON_SHOW = "onShow";
@@ -4375,7 +4379,7 @@ function resolveMergedOptions(instance) {
   } else {
     resolved = {};
     if (globalMixins.length) {
-      globalMixins.forEach((m) => mergeOptions(resolved, m, optionMergeStrategies, true));
+      globalMixins.forEach((m2) => mergeOptions(resolved, m2, optionMergeStrategies, true));
     }
     mergeOptions(resolved, base, optionMergeStrategies);
   }
@@ -4390,7 +4394,7 @@ function mergeOptions(to, from, strats, asMixin = false) {
     mergeOptions(to, extendsOptions, strats, true);
   }
   if (mixins) {
-    mixins.forEach((m) => mergeOptions(to, m, strats, true));
+    mixins.forEach((m2) => mergeOptions(to, m2, strats, true));
   }
   for (const key in from) {
     if (asMixin && key === "expose") {
@@ -6299,6 +6303,27 @@ function setRef(ref2, id, opts = {}) {
   const { $templateRefs } = getCurrentInstance();
   $templateRefs.push({ i: id, r: ref2, k: opts.k, f: opts.f });
 }
+function withModelModifiers(fn, { number, trim }, isComponent = false) {
+  if (isComponent) {
+    return (...args) => {
+      if (trim) {
+        args = args.map((a) => a.trim());
+      } else if (number) {
+        args = args.map(toNumber);
+      }
+      return fn(...args);
+    };
+  }
+  return (event) => {
+    const value = event.detail.value;
+    if (trim) {
+      event.detail.value = value.trim();
+    } else if (number) {
+      event.detail.value = toNumber(value);
+    }
+    return fn(event);
+  };
+}
 const o = (value, key) => vOn(value, key);
 const f = (source, renderItem) => vFor(source, renderItem);
 const r = (name, props, key) => renderSlot(name, props, key);
@@ -6308,6 +6333,7 @@ const n = (value) => normalizeClass(value);
 const t = (val) => toDisplayString(val);
 const p = (props) => renderProps(props);
 const sr = (ref2, id, opts) => setRef(ref2, id, opts);
+const m = (fn, modifiers, isComponent = false) => withModelModifiers(fn, modifiers, isComponent);
 function createApp$1(rootComponent, rootProps = null) {
   rootComponent && (rootComponent.mpType = "app");
   return createVueApp(rootComponent, rootProps).use(plugin);
@@ -7143,19 +7169,23 @@ const createHook = (lifecycle) => (hook, target = getCurrentInstance()) => {
 const onLoad = /* @__PURE__ */ createHook(ON_LOAD);
 const onUnload = /* @__PURE__ */ createHook(ON_UNLOAD);
 const onPageScroll = /* @__PURE__ */ createHook(ON_PAGE_SCROLL);
+const onReachBottom = /* @__PURE__ */ createHook(ON_REACH_BOTTOM);
 const onPullDownRefresh = /* @__PURE__ */ createHook(ON_PULL_DOWN_REFRESH);
 exports._export_sfc = _export_sfc;
+exports.computed = computed;
 exports.createSSRApp = createSSRApp;
 exports.e = e;
 exports.f = f;
 exports.index = index;
 exports.initVueI18n = initVueI18n;
+exports.m = m;
 exports.n = n;
 exports.nextTick$1 = nextTick$1;
 exports.o = o;
 exports.onLoad = onLoad;
 exports.onPageScroll = onPageScroll;
 exports.onPullDownRefresh = onPullDownRefresh;
+exports.onReachBottom = onReachBottom;
 exports.onUnload = onUnload;
 exports.p = p;
 exports.r = r;

+ 14 - 6
unpackage/dist/dev/mp-weixin/components/listView.js

@@ -3,16 +3,24 @@ const common_vendor = require("../common/vendor.js");
 const _sfc_main = {
   __name: "listView",
   props: {
-    list: Array
+    list: Array,
+    appType: String
   },
   setup(__props) {
+    const props = __props;
     common_vendor.onLoad(() => {
     });
-    const goPage = (url, id) => {
+    const goPage = (id) => {
       console.log(id);
-      common_vendor.index.navigateTo({
-        url
-      });
+      if (props.appType == "通讯录") {
+        common_vendor.index.navigateTo({
+          url: "/pages/student/student"
+        });
+      } else {
+        common_vendor.index.navigateTo({
+          url: "/pages/track/track"
+        });
+      }
     };
     return (_ctx, _cache) => {
       return common_vendor.e({
@@ -21,7 +29,7 @@ const _sfc_main = {
             a: common_vendor.t(item.name),
             b: common_vendor.t(item.number),
             c: item.id,
-            d: common_vendor.o(($event) => goPage("/pages/student/student", item.id), item.id)
+            d: common_vendor.o(($event) => goPage(item.id), item.id)
           };
         }),
         b: !__props.list.length

+ 20 - 1
unpackage/dist/dev/mp-weixin/components/tabber.js

@@ -13,6 +13,7 @@ if (!Math) {
 const _sfc_main = {
   __name: "tabber",
   setup(__props) {
+    const allList = common_vendor.ref([]);
     const tabList = common_vendor.ref([
       {
         id: 1,
@@ -30,11 +31,29 @@ const _sfc_main = {
         icon: "clock"
       }
     ]);
+    const tabList2 = common_vendor.ref([
+      {
+        id: 1,
+        text: "访客预约",
+        icon: "account"
+      },
+      {
+        id: 3,
+        text: "预约记录",
+        icon: "clock"
+      }
+    ]);
     const activeIndex = common_vendor.ref(0);
     const customStyle = {
       height: "120rpx"
     };
     common_vendor.onLoad(() => {
+      const userType = common_vendor.index.getStorageSync("userType");
+      if (userType == 0) {
+        allList.value = tabList2.value;
+      } else {
+        allList.value = tabList.value;
+      }
       const i = common_vendor.index.getStorageSync("Tab-activeIndex");
       i ? activeIndex.value = i : activeIndex.value = 0;
     });
@@ -59,7 +78,7 @@ const _sfc_main = {
     };
     return (_ctx, _cache) => {
       return {
-        a: common_vendor.f(tabList.value, (item, index, i0) => {
+        a: common_vendor.f(allList.value, (item, index, i0) => {
           return {
             a: item.id,
             b: common_vendor.o(($event) => handleChange(index, item), item.id),

+ 5 - 2
unpackage/dist/dev/mp-weixin/pages/grade/grade.js

@@ -30,7 +30,9 @@ const _sfc_main = {
         number: 8262662
       }
     ]);
-    common_vendor.onLoad(() => {
+    const appType = common_vendor.ref("");
+    common_vendor.onLoad((options) => {
+      appType.value = options.type;
     });
     const changeInputValue = (data) => {
       console.log(data);
@@ -39,7 +41,8 @@ const _sfc_main = {
       return {
         a: common_vendor.o(changeInputValue),
         b: common_vendor.p({
-          list: list.value
+          list: list.value,
+          appType: appType.value
         })
       };
     };

+ 37 - 43
unpackage/dist/dev/mp-weixin/pages/home/home.js

@@ -22,6 +22,12 @@ const _sfc_main = {
           customBarH.value = custom.height;
         }
       });
+      userType.value = common_vendor.index.getStorageSync("userType");
+      console.log("身份类型", userType.value);
+      const appList = common_vendor.index.getStorageSync("appList");
+      if (appList) {
+        useAppList.value = filterApp(list.value, appList);
+      }
     });
     common_vendor.onPullDownRefresh(() => {
       qrcodeRef.value.remake();
@@ -36,43 +42,18 @@ const _sfc_main = {
         showHeader.value = false;
       }
     });
+    const userType = common_vendor.ref();
     const showHeader = common_vendor.ref(false);
     const statusBarH = common_vendor.ref(0);
     const customBarH = common_vendor.ref(0);
     const qrcodeRef = common_vendor.ref(null);
     const list = common_vendor.ref([
-      // {
-      // 	id: 1,
-      // 	title: '考勤管理',
-      // 	url: '../../static/images/icon.png'
-      // },
-      // {
-      // 	id: 2,
-      // 	title: '课表查询',
-      // 	url: '../../static/images/icon.png',
-      // 	path: ''
-      // },
       {
         id: 3,
         title: "学生轨迹",
         url: "../../static/images/icon.png",
         path: "/pages/track/track"
       },
-      // {
-      // 	id: 4,
-      // 	title: '打卡接龙',
-      // 	url: '../../static/images/icon.png'
-      // },
-      // {
-      // 	id: 5,
-      // 	title: '人脸采集',
-      // 	url: '../../static/images/icon.png'
-      // },
-      // {
-      // 	id: 6,
-      // 	title: '智慧教学',
-      // 	url: '../../static/images/icon.png'
-      // },
       {
         id: 7,
         title: "消息通知",
@@ -85,11 +66,6 @@ const _sfc_main = {
         url: "../../static/images/icon.png",
         path: "/pagesReservation/reservation/reservation"
       },
-      // {
-      // 	id: 9,
-      // 	title: '课后作业',
-      // 	url: '../../static/images/icon.png'
-      // },
       {
         id: 10,
         title: "校园预警",
@@ -100,9 +76,10 @@ const _sfc_main = {
         id: 11,
         title: "通讯录",
         url: "../../static/images/icon.png",
-        path: "/pages/addressBook/addressBook"
+        path: "/pages/grade/grade?type=通讯录"
       }
     ]);
+    const useAppList = common_vendor.ref([]);
     const QRCodeUrl = common_vendor.ref("123");
     const options = {
       typeNumber: 4,
@@ -110,6 +87,14 @@ const _sfc_main = {
       foregroundImageSrc: "/static/images/school-logo.jpg"
     };
     const goPage = (url) => {
+      if (url === "/pages/track/track") {
+        if (userType.value == 1) {
+          common_vendor.index.navigateTo({
+            url: "/pages/grade/grade?type=学生轨迹"
+          });
+          return;
+        }
+      }
       if (url === "/pagesReservation/reservation/reservation") {
         common_vendor.index.setStorageSync("Tab-activeIndex", 0);
       }
@@ -122,8 +107,13 @@ const _sfc_main = {
         url: `/pages/quickMark/quickMark?value=${QRCodeUrl.value}`
       });
     };
+    const filterApp = (arr1, arr2) => {
+      return arr1.filter((item) => {
+        return arr2.includes(item.title);
+      });
+    };
     return (_ctx, _cache) => {
-      return {
+      return common_vendor.e({
         a: common_vendor.o(($event) => goPage("/pages/myCenter/myCenter")),
         b: customBarH.value * 2 + "rpx",
         c: statusBarH.value * 2 + "rpx",
@@ -131,20 +121,24 @@ const _sfc_main = {
         e: customBarH.value * 2 + "rpx",
         f: statusBarH.value * 2 + "rpx",
         g: showHeader.value,
-        h: common_vendor.sr(qrcodeRef, "07e72d3c-0", {
+        h: common_vendor.t(userType.value === 0 ? "家长" : "教师"),
+        i: common_vendor.sr(qrcodeRef, "07e72d3c-0", {
           "k": "qrcodeRef"
         }),
-        i: common_vendor.o(handleClickCode),
-        j: common_vendor.p({
+        j: common_vendor.o(handleClickCode),
+        k: common_vendor.p({
           size: "82rpx",
           value: QRCodeUrl.value,
           options
         }),
-        k: common_vendor.o(($event) => goPage("/pages/myMsg/myMsg")),
-        l: common_vendor.o(($event) => goPage("/pages/change/change")),
-        m: common_vendor.o(($event) => goPage("/pages/bind/bind")),
-        n: common_vendor.o(($event) => goPage("/pages/bind/bind")),
-        o: common_vendor.f(list.value, (item, k0, i0) => {
+        l: userType.value == 0
+      }, userType.value == 0 ? {
+        m: common_vendor.o(($event) => goPage("/pages/myMsg/myMsg")),
+        n: common_vendor.o(($event) => goPage("/pages/change/change")),
+        o: common_vendor.o(($event) => goPage("/pages/bind/bind")),
+        p: common_vendor.o(($event) => goPage("/pages/bind/bind"))
+      } : {}, {
+        q: common_vendor.f(useAppList.value, (item, k0, i0) => {
           return {
             a: item.url,
             b: common_vendor.t(item.title),
@@ -152,8 +146,8 @@ const _sfc_main = {
             d: common_vendor.o(($event) => goPage(item.path), item.id)
           };
         }),
-        p: common_vendor.s(_ctx.__cssVars())
-      };
+        r: common_vendor.s(_ctx.__cssVars())
+      });
     };
   }
 };

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/home/home.wxml


+ 82 - 2
unpackage/dist/dev/mp-weixin/pages/index/index.js

@@ -1,15 +1,95 @@
 "use strict";
 const common_vendor = require("../../common/vendor.js");
+const common_assets = require("../../common/assets.js");
+if (!Array) {
+  const _easycom_uv_code2 = common_vendor.resolveComponent("uv-code");
+  _easycom_uv_code2();
+}
+const _easycom_uv_code = () => "../../uni_modules/uv-code/components/uv-code/uv-code.js";
+if (!Math) {
+  _easycom_uv_code();
+}
 const _sfc_main = {
   __name: "index",
   setup(__props) {
+    const phone = common_vendor.ref("");
+    const codeValue = common_vendor.ref("");
+    const codeDom = common_vendor.ref(null);
+    const btnFlag = common_vendor.computed(() => {
+      const regPhone = /^1[3-9]\d{9}$/;
+      if (phone.value && regPhone.test(phone.value) && codeValue.value) {
+        return true;
+      } else {
+        return false;
+      }
+    });
+    const tips = common_vendor.ref("");
+    common_vendor.ref(["学生轨迹", "消息通知", "访客预约", "校园预警"]);
+    const tlist = common_vendor.ref(["学生轨迹", "消息通知", "访客预约", "校园预警", "通讯录"]);
     common_vendor.onLoad(() => {
+    });
+    const getCode = () => {
+      const regPhone = /^1[3-9]\d{9}$/;
+      if (phone.value && regPhone.test(phone.value)) {
+        if (codeDom.value.canGetCode) {
+          common_vendor.index.showLoading({
+            title: "正在获取验证码"
+          });
+          setTimeout(() => {
+            common_vendor.index.hideLoading();
+            common_vendor.index.showToast({
+              title: "验证码已发送",
+              icon: "none"
+            });
+            codeDom.value.start();
+          }, 2e3);
+        } else {
+          common_vendor.index.showToast({
+            title: "倒计时结束后再发送",
+            icon: "none"
+          });
+        }
+      } else {
+        common_vendor.index.showToast({
+          title: "请先输入正确的手机号码",
+          icon: "none"
+        });
+      }
+    };
+    const handleLogin = () => {
+      let userType = 1;
+      common_vendor.index.setStorageSync("userType", userType);
+      {
+        common_vendor.index.setStorageSync("appList", tlist.value);
+        common_vendor.index.setStorageSync("userId", 26);
+      }
       common_vendor.index.navigateTo({
         url: "/pages/home/home"
       });
-    });
+    };
+    const codeChange = (text) => {
+      tips.value = text;
+    };
     return (_ctx, _cache) => {
-      return {};
+      return {
+        a: common_assets._imports_0,
+        b: phone.value,
+        c: common_vendor.o(($event) => phone.value = $event.detail.value),
+        d: codeValue.value,
+        e: common_vendor.o(($event) => codeValue.value = $event.detail.value),
+        f: common_vendor.sr(codeDom, "1cf27b2a-0", {
+          "k": "codeDom"
+        }),
+        g: common_vendor.o(codeChange),
+        h: common_vendor.p({
+          uniqueKey: "login",
+          keepRunning: true
+        }),
+        i: common_vendor.t(tips.value),
+        j: common_vendor.o(getCode),
+        k: common_vendor.unref(btnFlag) ? 1 : "",
+        l: common_vendor.o(handleLogin)
+      };
     };
   }
 };

+ 4 - 2
unpackage/dist/dev/mp-weixin/pages/index/index.json

@@ -1,4 +1,6 @@
 {
-  "navigationBarTitleText": "uni-app",
-  "usingComponents": {}
+  "navigationBarTitleText": "登录",
+  "usingComponents": {
+    "uv-code": "../../uni_modules/uv-code/components/uv-code/uv-code"
+  }
 }

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/index/index.wxml


+ 72 - 1
unpackage/dist/dev/mp-weixin/pages/index/index.wxss

@@ -1,2 +1,73 @@
 /* 水平间距 */
-/* 水平间距 */
+/* 水平间距 */
+.container.data-v-1cf27b2a {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  min-height: 100vh;
+  background-color: #f8f8fa;
+}
+.container .img.data-v-1cf27b2a {
+  margin-top: 120rpx;
+  width: 200rpx;
+  height: 200rpx;
+  border-radius: 20rpx;
+}
+.container .logo_name.data-v-1cf27b2a {
+  margin-top: 25rpx;
+  font-size: 36rpx;
+}
+.container .phone.data-v-1cf27b2a {
+  box-sizing: border-box;
+  margin-top: 80rpx;
+  padding: 0 20rpx;
+  width: 538rpx;
+  height: 80rpx;
+  border-radius: 8rpx;
+  box-shadow: 0 0 10rpx #ccc;
+  background-color: #fff;
+}
+.container .phone .phone_input.data-v-1cf27b2a {
+  height: 100%;
+}
+.container .code.data-v-1cf27b2a {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  box-sizing: border-box;
+  margin-top: 40rpx;
+  padding: 0 20rpx;
+  width: 538rpx;
+  height: 80rpx;
+  border-radius: 8rpx;
+  box-shadow: 0 0 10rpx #ccc;
+  background-color: #fff;
+}
+.container .code .code_input.data-v-1cf27b2a {
+  width: 55%;
+  height: 100%;
+}
+.container .code .code_box.data-v-1cf27b2a {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  width: 35%;
+  height: 80rpx;
+  color: #3c9cff;
+  font-size: 26rpx;
+}
+.container .loginBtn.data-v-1cf27b2a {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  margin-top: 50rpx;
+  width: 538rpx;
+  height: 80rpx;
+  color: #a0a1a4;
+  border-radius: 8rpx;
+  background-color: #e5e6eb;
+}
+.container .active.data-v-1cf27b2a {
+  color: #fff;
+  background-color: #0061ff;
+}

+ 4 - 6
unpackage/dist/dev/mp-weixin/pages/student/student.js

@@ -31,14 +31,12 @@ const _sfc_main = {
     };
     return (_ctx, _cache) => {
       return {
-        a: common_vendor.o(callPhone),
-        b: common_vendor.f(familyList.value, (item, k0, i0) => {
+        a: common_vendor.f(familyList.value, (item, k0, i0) => {
           return {
             a: common_vendor.t(item.name),
-            b: common_vendor.t(item.identity),
-            c: common_vendor.t(item.phone),
-            d: common_vendor.o(callPhone, item.id),
-            e: item.id
+            b: common_vendor.t(item.phone),
+            c: common_vendor.o(callPhone, item.id),
+            d: item.id
           };
         })
       };

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pages/student/student.wxml


+ 55 - 11
unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.js

@@ -1,5 +1,6 @@
 "use strict";
 const common_vendor = require("../../common/vendor.js");
+const utils_api = require("../../utils/api.js");
 if (!Array) {
   const _easycom_uni_segmented_control2 = common_vendor.resolveComponent("uni-segmented-control");
   const _easycom_uni_popup2 = common_vendor.resolveComponent("uni-popup");
@@ -15,6 +16,8 @@ const _sfc_main = {
   __name: "backlog",
   setup(__props) {
     const activeCurrent = common_vendor.ref(0);
+    const currentPage = common_vendor.ref(1);
+    const total = common_vendor.ref(0);
     const controlList = ["待审核", "已拒绝", "已推送"];
     const list = common_vendor.ref([
       {
@@ -22,27 +25,65 @@ const _sfc_main = {
         name: "张三",
         time: "2023-12-13  10:23",
         type: "待审核",
-        desc: "给孩子送棉被"
+        desc: "给孩子送棉被",
+        status: 0,
+        name2: "小刘"
       },
       {
         id: 2,
         name: "张三",
         time: "2023-12-13  10:23",
         type: "已拒绝",
-        desc: "给孩子送棉被"
+        desc: "给孩子送棉被",
+        status: 0,
+        name2: "小刘"
       },
       {
         id: 3,
         name: "张三",
         time: "2023-12-13  10:23",
         type: "已推送",
-        desc: "给孩子送棉被"
+        desc: "给孩子送棉被",
+        status: 0,
+        name2: "小刘"
       }
     ]);
     const popup = common_vendor.ref(null);
     const popObj = common_vendor.ref({});
+    common_vendor.onLoad(() => {
+      getData();
+    });
+    common_vendor.onReachBottom(() => {
+      if (total.value > list.value.length) {
+        currentPage.value++;
+        getData();
+      } else {
+        common_vendor.index.showToast({
+          title: "没有更多数据了",
+          icon: "none"
+        });
+      }
+    });
+    const getData = async () => {
+      const res = await utils_api.myRequest({
+        url: "/wanzai/api/smartVisitor/visitingAgencys",
+        data: {
+          currentPage: currentPage.value,
+          pageCount: 6,
+          userId: common_vendor.index.getStorageSync("userId"),
+          type: activeCurrent.value - 0 + 1
+        }
+      });
+      total.value = res.data.totalCount;
+      list.value = [...list.value, ...res.data.list];
+    };
     const onClickItem = (e) => {
-      console.log(e);
+      if (activeCurrent.value != e.currentIndex) {
+        activeCurrent.value = e.currentIndex;
+        currentPage.value = 1;
+        list.value = [];
+        getData();
+      }
     };
     const handleClick = (item) => {
       popObj.value = item;
@@ -82,15 +123,18 @@ const _sfc_main = {
           }, item.type == "已推送" ? {
             h: common_vendor.t(item.type)
           } : {}, {
-            i: common_vendor.t(item.time),
-            j: common_vendor.t(item.desc),
-            k: item.type == "待审核"
+            i: common_vendor.t(item.status === 0 ? "学生家长预约" : "其他访客预约"),
+            j: common_vendor.t(item.time),
+            k: common_vendor.t(item.desc),
+            l: common_vendor.t(item.status === 0 ? "受访学生" : "受访人"),
+            m: common_vendor.t(item.name2),
+            n: item.type == "待审核"
           }, item.type == "待审核" ? {
-            l: common_vendor.o(handleReject, item.id),
-            m: common_vendor.o(handleAgree, item.id)
+            o: common_vendor.o(handleReject, item.id),
+            p: common_vendor.o(handleAgree, item.id)
           } : {}, {
-            n: item.id,
-            o: common_vendor.o(($event) => handleClick(item), item.id)
+            q: item.id,
+            r: common_vendor.o(($event) => handleClick(item), item.id)
           });
         }),
         d: common_vendor.o(closePop),

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.wxml


+ 4 - 2
unpackage/dist/dev/mp-weixin/pagesReservation/backlog/backlog.wxss

@@ -1,6 +1,8 @@
 /* 水平间距 */
 /* 水平间距 */
 .container.data-v-a46ecdc3 {
+  box-sizing: border-box;
+  padding-bottom: 30rpx;
   min-height: 100vh;
   background-color: #f1f6fe;
 }
@@ -47,15 +49,15 @@
 .container .body .body_box .box_info.data-v-a46ecdc3 {
   display: flex;
   flex-direction: column;
-  justify-content: space-evenly;
-  height: 140rpx;
 }
 .container .body .body_box .box_info .info_box.data-v-a46ecdc3 {
   display: flex;
   align-items: center;
+  height: 65rpx;
   font-size: 24rpx;
 }
 .container .body .body_box .box_info .info_box .box_key.data-v-a46ecdc3 {
+  width: 120rpx;
   color: #a6a6a6;
 }
 .container .body .body_box .box_info .info_box .box_value.data-v-a46ecdc3 {

+ 70 - 56
unpackage/dist/dev/mp-weixin/pagesReservation/record/record.js

@@ -1,5 +1,6 @@
 "use strict";
 const common_vendor = require("../../common/vendor.js");
+const utils_api = require("../../utils/api.js");
 if (!Array) {
   const _easycom_uni_segmented_control2 = common_vendor.resolveComponent("uni-segmented-control");
   const _easycom_uni_popup2 = common_vendor.resolveComponent("uni-popup");
@@ -8,47 +9,58 @@ if (!Array) {
 const _easycom_uni_segmented_control = () => "../../uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control.js";
 const _easycom_uni_popup = () => "../../uni_modules/uni-popup/components/uni-popup/uni-popup.js";
 if (!Math) {
-  (_easycom_uni_segmented_control + _easycom_uni_popup + tabber)();
+  (_easycom_uni_segmented_control + NoData + _easycom_uni_popup + Tabber)();
 }
-const tabber = () => "../../components/tabber.js";
+const Tabber = () => "../../components/tabber.js";
+const NoData = () => "../../components/noData.js";
 const _sfc_main = {
   __name: "record",
   setup(__props) {
     const activeCurrent = common_vendor.ref(0);
+    const currentPage = common_vendor.ref(1);
+    const total = common_vendor.ref(0);
     const controlList = ["全部", "待审核", "已拒绝", "已推送"];
-    const list = common_vendor.ref([
-      {
-        id: 1,
-        name: "张三",
-        time: "2023-12-13  10:23",
-        type: "待审核",
-        desc: "给孩子送棉被"
-      },
-      {
-        id: 2,
-        name: "张三",
-        time: "2023-12-13  10:23",
-        type: "已拒绝",
-        desc: "给孩子送棉被"
-      },
-      {
-        id: 3,
-        name: "张三",
-        time: "2023-12-13  10:23",
-        type: "已推送",
-        desc: "给孩子送棉被"
-      }
-    ]);
+    const list = common_vendor.ref([]);
     const popup = common_vendor.ref(null);
     const popObj = common_vendor.ref({});
     common_vendor.onLoad(() => {
+      getData();
+    });
+    common_vendor.onReachBottom(() => {
+      if (total.value > list.value.length) {
+        currentPage.value++;
+        getData();
+      } else {
+        common_vendor.index.showToast({
+          title: "没有更多数据了",
+          icon: "none"
+        });
+      }
     });
+    const getData = async () => {
+      const res = await utils_api.myRequest({
+        url: "/wanzai/api/smartVisitor/appointmentPageRecord",
+        data: {
+          currentPage: currentPage.value,
+          pageCount: 6,
+          userId: common_vendor.index.getStorageSync("userId"),
+          type: activeCurrent.value
+        }
+      });
+      total.value = res.data.totalCount;
+      list.value = [...list.value, ...res.data.list];
+    };
     const handleClick = (item) => {
       popObj.value = item;
       popup.value.open();
     };
     const onClickItem = (e) => {
-      console.log(e);
+      if (activeCurrent.value != e.currentIndex) {
+        activeCurrent.value = e.currentIndex;
+        currentPage.value = 1;
+        list.value = [];
+        getData();
+      }
     };
     const handleCancel = () => {
       console.log("取消");
@@ -67,50 +79,52 @@ const _sfc_main = {
         }),
         c: common_vendor.f(list.value, (item, k0, i0) => {
           return common_vendor.e({
-            a: common_vendor.t(item.name),
-            b: common_vendor.t(item.time),
-            c: item.type == "待审核"
-          }, item.type == "待审核" ? {
-            d: common_vendor.t(item.type)
+            a: common_vendor.t(item.userName),
+            b: common_vendor.t(item.createTime),
+            c: item.statuStr == "待审核"
+          }, item.statuStr == "待审核" ? {
+            d: common_vendor.t(item.statuStr)
           } : {}, {
-            e: item.type == "已拒绝"
-          }, item.type == "已拒绝" ? {
-            f: common_vendor.t(item.type)
+            e: item.statuStr == "已拒绝"
+          }, item.statuStr == "已拒绝" ? {
+            f: common_vendor.t(item.statuStr)
           } : {}, {
-            g: item.type == "已推送"
-          }, item.type == "已推送" ? {
-            h: common_vendor.t(item.type)
+            g: item.statuStr == "已推送"
+          }, item.statuStr == "已推送" ? {
+            h: common_vendor.t(item.statuStr)
           } : {}, {
-            i: common_vendor.t(item.time),
-            j: common_vendor.t(item.desc),
-            k: item.type == "待审核"
-          }, item.type == "待审核" ? {
+            i: common_vendor.t(item.visitorTime),
+            j: common_vendor.t(item.visitReason),
+            k: item.statuStr == "待审核"
+          }, item.statuStr == "待审核" ? {
             l: common_vendor.o(handleCancel, item.id)
           } : {}, {
             m: item.id,
             n: common_vendor.o(($event) => handleClick(item), item.id)
           });
         }),
-        d: common_vendor.o(closePop),
-        e: popObj.value.type == "待审核"
-      }, popObj.value.type == "待审核" ? {
-        f: common_vendor.t(popObj.value.type)
+        d: !list.value.length
+      }, !list.value.length ? {} : {}, {
+        e: common_vendor.o(closePop),
+        f: popObj.value.statuStr == "待审核"
+      }, popObj.value.statuStr == "待审核" ? {
+        g: common_vendor.t(popObj.value.statuStr)
       } : {}, {
-        g: popObj.value.type == "已拒绝"
-      }, popObj.value.type == "已拒绝" ? {
-        h: common_vendor.t(popObj.value.type)
+        h: popObj.value.statuStr == "已拒绝"
+      }, popObj.value.statuStr == "已拒绝" ? {
+        i: common_vendor.t(popObj.value.statuStr)
       } : {}, {
-        i: popObj.value.type == "已推送"
-      }, popObj.value.type == "已推送" ? {
-        j: common_vendor.t(popObj.value.type)
+        j: popObj.value.statuStr == "已推送"
+      }, popObj.value.statuStr == "已推送" ? {
+        k: common_vendor.t(popObj.value.statuStr)
       } : {}, {
-        k: common_vendor.t(popObj.value.name),
-        l: common_vendor.t(popObj.value.time),
-        m: common_vendor.t(popObj.value.desc),
-        n: common_vendor.sr(popup, "00bd71c9-1", {
+        l: common_vendor.t(popObj.value.userName),
+        m: common_vendor.t(popObj.value.visitorTime),
+        n: common_vendor.t(popObj.value.visitReason),
+        o: common_vendor.sr(popup, "00bd71c9-2", {
           "k": "popup"
         }),
-        o: common_vendor.p({
+        p: common_vendor.p({
           type: "center",
           ["is-mask-click"]: false
         })

+ 2 - 1
unpackage/dist/dev/mp-weixin/pagesReservation/record/record.json

@@ -4,6 +4,7 @@
   "usingComponents": {
     "uni-segmented-control": "../../uni_modules/uni-segmented-control/components/uni-segmented-control/uni-segmented-control",
     "uni-popup": "../../uni_modules/uni-popup/components/uni-popup/uni-popup",
-    "tabber": "../../components/tabber"
+    "tabber": "../../components/tabber",
+    "no-data": "../../components/noData"
   }
 }

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pagesReservation/record/record.wxml


+ 8 - 2
unpackage/dist/dev/mp-weixin/pagesReservation/record/record.wxss

@@ -1,6 +1,8 @@
 /* 水平间距 */
 /* 水平间距 */
 .container.data-v-00bd71c9 {
+  box-sizing: border-box;
+  padding-bottom: 30rpx;
   min-height: 100vh;
   background-color: #f1f6fe;
 }
@@ -47,19 +49,23 @@
 .container .body .body_box .box_info.data-v-00bd71c9 {
   display: flex;
   flex-direction: column;
-  justify-content: space-evenly;
-  height: 140rpx;
 }
 .container .body .body_box .box_info .info_box.data-v-00bd71c9 {
   display: flex;
   align-items: center;
+  height: 65rpx;
   font-size: 24rpx;
 }
 .container .body .body_box .box_info .info_box .box_key.data-v-00bd71c9 {
+  width: 120rpx;
   color: #a6a6a6;
 }
 .container .body .body_box .box_info .info_box .box_value.data-v-00bd71c9 {
+  flex: 1;
   margin-left: 95rpx;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 .container .body .body_box .box_btn.data-v-00bd71c9 {
   display: flex;

+ 263 - 25
unpackage/dist/dev/mp-weixin/pagesReservation/register/register.js

@@ -1,5 +1,7 @@
 "use strict";
 const common_vendor = require("../../common/vendor.js");
+const utils_api = require("../../utils/api.js");
+const utils_formatTime = require("../../utils/formatTime.js");
 if (!Array) {
   const _easycom_uni_datetime_picker2 = common_vendor.resolveComponent("uni-datetime-picker");
   _easycom_uni_datetime_picker2();
@@ -12,24 +14,230 @@ const _sfc_main = {
   __name: "register",
   setup(__props) {
     const type = common_vendor.ref("");
+    const visName = common_vendor.ref("");
+    const visPhone = common_vendor.ref("");
+    const visStartTime = common_vendor.ref("");
+    const visEndTime = common_vendor.ref("");
+    const visIdNumber = common_vendor.ref("");
+    const visReason = common_vendor.ref("");
+    const visCarNumber = common_vendor.ref("");
+    const visPeopleNum = common_vendor.ref("");
+    const list = common_vendor.ref([]);
+    const passiveName = common_vendor.ref("");
+    const passivePhone = common_vendor.ref("");
     const authValue = common_vendor.ref(false);
-    const list = common_vendor.ref([
-      {
-        id: 1,
-        name: "张三",
-        number: "145225225425",
-        isChecked: false
-      },
-      {
-        id: 2,
-        name: "李四",
-        number: "145225225425",
-        isChecked: true
-      }
-    ]);
+    const btnFlag = common_vendor.computed(() => {
+      const tem = list.value.some((item) => item.isChecked);
+      if (visName.value && visPhone.value && visStartTime.value && visEndTime.value && visIdNumber.value && visReason.value && [type.value === "1" && !list.value.length] && [type.value === "1" && !tem] && [type.value === "2" && !passiveName.value] && [
+        type.value === "2" && !passivePhone.value
+      ] && authValue.value) {
+        return true;
+      } else {
+        return false;
+      }
+    });
     common_vendor.onLoad((options) => {
       type.value = options.type;
+      if (type.value === "1") {
+        getList();
+      }
     });
+    const getList = async () => {
+      const res = await utils_api.myRequest({
+        url: "/wanzai/api/smartUser/queryAffiliateUserById",
+        data: {
+          id: common_vendor.index.getStorageSync("userId")
+        }
+      });
+      list.value = res.data;
+    };
+    const handleSubmit = () => {
+      const flag = verifyValue();
+      if (flag) {
+        if (type.value === "1") {
+          parentAppointment();
+        } else {
+          otherAppointment();
+        }
+      }
+    };
+    const parentAppointment = async () => {
+      let temList = [];
+      list.value.forEach((ele) => {
+        if (ele.isChecked) {
+          temList.push(ele);
+        }
+      });
+      const res = await utils_api.myRequest({
+        url: "/wanzai/api/smartVisitor/parentsAppointment",
+        method: "post",
+        data: {
+          userId: common_vendor.index.getStorageSync("userId"),
+          visitorTime: visStartTime.value,
+          visitReason: visReason.value,
+          carNum: visCarNumber.value,
+          peerNum: visPeopleNum.value ? visPeopleNum.value : 0,
+          students: temList
+        }
+      });
+      common_vendor.index.showToast({
+        title: res.message,
+        icon: "none",
+        duration: 2e3
+      });
+      setTimeout(() => {
+        common_vendor.index.navigateBack(1);
+      }, 2e3);
+    };
+    const otherAppointment = async () => {
+      const res = await utils_api.myRequest({
+        url: "/wanzai/api/smartVisitor/otherAppointment",
+        method: "post",
+        data: {
+          userId: common_vendor.index.getStorageSync("userId"),
+          visitorTime: visStartTime.value,
+          visitReason: visReason.value,
+          carNum: visCarNumber.value,
+          peerNum: visPeopleNum.value ? visPeopleNum.value : 0,
+          respondentName: passiveName.value,
+          respondentPhone: passivePhone.value
+        }
+      });
+      console.log(res);
+      common_vendor.index.showToast({
+        title: res.message,
+        icon: "none",
+        duration: 2e3
+      });
+      setTimeout(() => {
+        common_vendor.index.navigateBack(1);
+      }, 2e3);
+    };
+    const changeStart = (e) => {
+      const temTime = e.replace(/-/g, "/");
+      const timestamp = Date.parse(new Date(temTime));
+      const addTime = 1e3 * 60 * 60 * 4;
+      visEndTime.value = utils_formatTime.time_format(timestamp + addTime);
+    };
+    const verifyValue = () => {
+      const regName = /^[\u4e00-\u9fa5]{2,4}$/;
+      const regPhone = /^1[3-9]\d{9}$/;
+      const regIdentity = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
+      if (!visName.value) {
+        common_vendor.index.showToast({
+          title: "请输入访客姓名",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!regName.test(visName.value)) {
+        common_vendor.index.showToast({
+          title: "姓名格式错误",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!visPhone.value) {
+        common_vendor.index.showToast({
+          title: "请输入访客手机号",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!regPhone.test(visPhone.value)) {
+        common_vendor.index.showToast({
+          title: "手机号码格式错误",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!visStartTime.value) {
+        common_vendor.index.showToast({
+          title: "请选择来访时间",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!visEndTime.value) {
+        common_vendor.index.showToast({
+          title: "请选择来访结束时间",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!visIdNumber.value) {
+        common_vendor.index.showToast({
+          title: "请输入访客证件号",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!regIdentity.test(visIdNumber.value)) {
+        common_vendor.index.showToast({
+          title: "证件号格式错误",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!visReason.value) {
+        common_vendor.index.showToast({
+          title: "请输入访问事由",
+          icon: "none"
+        });
+        return false;
+      }
+      if (type.value === "1" && !list.value.length) {
+        common_vendor.index.showToast({
+          title: "请绑定学生后再开始预约",
+          icon: "none"
+        });
+        return false;
+      }
+      const tem = list.value.some((item) => item.isChecked);
+      if (type.value === "1" && !tem) {
+        common_vendor.index.showToast({
+          title: "请选择受访学生",
+          icon: "none"
+        });
+        return false;
+      }
+      if (type.value === "2" && !passiveName.value) {
+        common_vendor.index.showToast({
+          title: "请输入受访者姓名",
+          icon: "none"
+        });
+        return false;
+      }
+      if (type.value === "2" && !regName.test(passiveName.value)) {
+        common_vendor.index.showToast({
+          title: "受访者姓名格式错误",
+          icon: "none"
+        });
+        return false;
+      }
+      if (type.value === "2" && !passivePhone.value) {
+        common_vendor.index.showToast({
+          title: "请输入受访者电话",
+          icon: "none"
+        });
+        return false;
+      }
+      if (type.value === "2" && !regPhone.test(passivePhone.value)) {
+        common_vendor.index.showToast({
+          title: "受访者手机号格式错误",
+          icon: "none"
+        });
+        return false;
+      }
+      if (!authValue.value) {
+        common_vendor.index.showToast({
+          title: "请同意授权证件号",
+          icon: "none"
+        });
+        return false;
+      }
+      return true;
+    };
     const handleClick = (item) => {
       item.isChecked = !item.isChecked;
     };
@@ -38,27 +246,57 @@ const _sfc_main = {
     };
     return (_ctx, _cache) => {
       return common_vendor.e({
-        a: type.value == 2
-      }, type.value == 2 ? {} : {}, {
-        b: type.value == 2
-      }, type.value == 2 ? {} : {}, {
-        c: type.value == 1
+        a: visName.value,
+        b: common_vendor.o(($event) => visName.value = $event.detail.value),
+        c: visPhone.value,
+        d: common_vendor.o(($event) => visPhone.value = $event.detail.value),
+        e: common_vendor.t(visStartTime.value || "请选择来访时间 >"),
+        f: visStartTime.value ? 1 : "",
+        g: common_vendor.o(changeStart),
+        h: common_vendor.o(($event) => visStartTime.value = $event),
+        i: common_vendor.p({
+          modelValue: visStartTime.value
+        }),
+        j: common_vendor.t(visEndTime.value || "来访时间为4小时"),
+        k: visEndTime.value ? 1 : "",
+        l: visIdNumber.value,
+        m: common_vendor.o(($event) => visIdNumber.value = $event.detail.value),
+        n: visReason.value,
+        o: common_vendor.o(($event) => visReason.value = $event.detail.value),
+        p: visCarNumber.value,
+        q: common_vendor.o(($event) => visCarNumber.value = $event.detail.value),
+        r: visPeopleNum.value,
+        s: common_vendor.o(common_vendor.m(($event) => visPeopleNum.value = $event.detail.value, {
+          number: true
+        })),
+        t: type.value == 2
+      }, type.value == 2 ? {
+        v: passiveName.value,
+        w: common_vendor.o(($event) => passiveName.value = $event.detail.value)
+      } : {}, {
+        x: type.value == 2
+      }, type.value == 2 ? {
+        y: passivePhone.value,
+        z: common_vendor.o(($event) => passivePhone.value = $event.detail.value)
+      } : {}, {
+        A: type.value == 1
       }, type.value == 1 ? {} : {}, {
-        d: type.value == 1
+        B: type.value == 1
       }, type.value == 1 ? {
-        e: common_vendor.f(list.value, (item, k0, i0) => {
+        C: common_vendor.f(list.value, (item, k0, i0) => {
           return {
             a: item.isChecked,
             b: common_vendor.t(item.name),
-            c: common_vendor.t(item.number),
+            c: common_vendor.t(item.cardNo),
             d: item.id,
             e: common_vendor.o(($event) => handleClick(item), item.id)
           };
         })
       } : {}, {
-        f: authValue.value,
-        g: common_vendor.o(handleAuth),
-        h: authValue.value ? 1 : ""
+        D: authValue.value,
+        E: common_vendor.o(handleAuth),
+        F: common_vendor.unref(btnFlag) ? 1 : "",
+        G: common_vendor.o(handleSubmit)
       });
     };
   }

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pagesReservation/register/register.wxml


+ 3 - 0
unpackage/dist/dev/mp-weixin/pagesReservation/register/register.wxss

@@ -39,6 +39,9 @@
   text-align: end;
   color: #cccccc;
 }
+.container .body .body_box .box_value .activeTime.data-v-0b2c2ae2 {
+  color: #000;
+}
 .container .body .no_border.data-v-0b2c2ae2 {
   border: none;
 }

+ 12 - 5
unpackage/dist/dev/mp-weixin/pagesReservation/reservation/reservation.js

@@ -7,7 +7,10 @@ const tabber = () => "../../components/tabber.js";
 const _sfc_main = {
   __name: "reservation",
   setup(__props) {
+    const userType = common_vendor.ref("");
     common_vendor.onLoad(() => {
+      userType.value = common_vendor.index.getStorageSync("userType");
+      console.log(userType.value);
     });
     const goPage = (url) => {
       common_vendor.index.navigateTo({
@@ -15,11 +18,15 @@ const _sfc_main = {
       });
     };
     return (_ctx, _cache) => {
-      return {
-        a: common_vendor.o(($event) => goPage("/pagesReservation/register/register?type=1")),
-        b: common_vendor.o(($event) => goPage("/pagesReservation/register/register?type=2")),
-        c: common_vendor.o(($event) => goPage("/pagesReservation/QRCode/QRCode"))
-      };
+      return common_vendor.e({
+        a: userType.value == 0
+      }, userType.value == 0 ? {
+        b: common_vendor.o(($event) => goPage("/pagesReservation/register/register?type=1"))
+      } : {}, {
+        c: userType.value == 1
+      }, userType.value == 1 ? {
+        d: common_vendor.o(($event) => goPage("/pagesReservation/register/register?type=2"))
+      } : {});
     };
   }
 };

文件差异内容过多而无法显示
+ 1 - 1
unpackage/dist/dev/mp-weixin/pagesReservation/reservation/reservation.wxml


+ 51 - 0
utils/api.js

@@ -0,0 +1,51 @@
+// 民宿接口前缀
+const BASE_URL = "https://www.campussmartlife.com/smartApi"
+
+export const myRequest = (options) => {
+	uni.showLoading({
+		title: "加载中",
+		mask: true,
+	});
+	return new Promise((resolve, reject) => {
+		uni.request({
+			url: BASE_URL + options.url,
+			method: options.method || "GET",
+			// header: options.header || {
+			// 	'userId': uni.getStorageSync('userInfo').id
+			// },
+			data: options.data || {},
+			timeout: 10000,
+			success: (res) => {
+				if (res.data.code == 200) {
+					resolve(res.data)
+				} else {
+
+				}
+			},
+			fail: (err) => {
+				uni.showToast({
+					title: "请求发送失败",
+					icon: "none",
+					mask: true
+				})
+				reject(err)
+			},
+			complete: (res) => {
+				uni.hideLoading({
+					complete: (hide) => {
+						if (res.data.code == 200) {
+
+						} else {
+							uni.showToast({
+								title: res.data.message ? res.data.message :
+									'报错',
+								icon: "none",
+								mask: true
+							})
+						}
+					}
+				});
+			}
+		})
+	})
+}