xiaoxin před 1 rokem
rodič
revize
b8b0477e1d
77 změnil soubory, kde provedl 18466 přidání a 34 odebrání
  1. 55 0
      pages.json
  2. 320 0
      pages/addStudent/addStudent.vue
  3. 217 0
      pages/addStudentMsg/addStudentMsg.vue
  4. 288 0
      pages/check/check.vue
  5. 672 0
      pages/energy/energy.vue
  6. 4 0
      pages/home/home.vue
  7. 189 0
      pages/invitation/invitation.vue
  8. 183 0
      pages/late/late.vue
  9. 257 0
      pages/register/register.vue
  10. 139 0
      pages/set/set.vue
  11. 270 31
      pages/studentManage/studentManage.vue
  12. binární
      static/images/edit2.png
  13. binární
      static/images/time.png
  14. 320 0
      uni_modules/qiun-data-charts/changelog.md
  15. 1618 0
      uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
  16. 46 0
      uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue
  17. 162 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue
  18. 170 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue
  19. 173 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue
  20. 222 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue
  21. 229 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue
  22. 36 0
      uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue
  23. 422 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
  24. 606 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
  25. 5 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
  26. 7706 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
  27. 18 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js
  28. 201 0
      uni_modules/qiun-data-charts/license.md
  29. 81 0
      uni_modules/qiun-data-charts/package.json
  30. 84 0
      uni_modules/qiun-data-charts/readme.md
  31. 23 0
      uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
  32. 23 0
      uni_modules/qiun-data-charts/static/h5/echarts.min.js
  33. 34 0
      uni_modules/uv-datetime-picker/changelog.md
  34. 130 0
      uni_modules/uv-datetime-picker/components/uv-datetime-picker/props.js
  35. 360 0
      uni_modules/uv-datetime-picker/components/uv-datetime-picker/uv-datetime-picker.vue
  36. 89 0
      uni_modules/uv-datetime-picker/package.json
  37. 19 0
      uni_modules/uv-datetime-picker/readme.md
  38. 9 0
      uni_modules/uv-loading-icon/changelog.md
  39. 67 0
      uni_modules/uv-loading-icon/components/uv-loading-icon/props.js
  40. 347 0
      uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue
  41. 87 0
      uni_modules/uv-loading-icon/package.json
  42. 19 0
      uni_modules/uv-loading-icon/readme.md
  43. 9 0
      uni_modules/uv-overlay/changelog.md
  44. 25 0
      uni_modules/uv-overlay/components/uv-overlay/props.js
  45. 85 0
      uni_modules/uv-overlay/components/uv-overlay/uv-overlay.vue
  46. 88 0
      uni_modules/uv-overlay/package.json
  47. 11 0
      uni_modules/uv-overlay/readme.md
  48. 33 0
      uni_modules/uv-picker/changelog.md
  49. 95 0
      uni_modules/uv-picker/components/uv-picker/props.js
  50. 330 0
      uni_modules/uv-picker/components/uv-picker/uv-picker.vue
  51. 90 0
      uni_modules/uv-picker/package.json
  52. 21 0
      uni_modules/uv-picker/readme.md
  53. 18 0
      uni_modules/uv-popup/changelog.md
  54. 45 0
      uni_modules/uv-popup/components/uv-popup/keypress.js
  55. 539 0
      uni_modules/uv-popup/components/uv-popup/uv-popup.vue
  56. 92 0
      uni_modules/uv-popup/package.json
  57. 21 0
      uni_modules/uv-popup/readme.md
  58. 7 0
      uni_modules/uv-status-bar/changelog.md
  59. 8 0
      uni_modules/uv-status-bar/components/uv-status-bar/props.js
  60. 54 0
      uni_modules/uv-status-bar/components/uv-status-bar/uv-status-bar.vue
  61. 87 0
      uni_modules/uv-status-bar/package.json
  62. 10 0
      uni_modules/uv-status-bar/readme.md
  63. 2 0
      uni_modules/uv-toolbar/changelog.md
  64. 40 0
      uni_modules/uv-toolbar/components/uv-toolbar/props.js
  65. 109 0
      uni_modules/uv-toolbar/components/uv-toolbar/uv-toolbar.vue
  66. 87 0
      uni_modules/uv-toolbar/package.json
  67. 31 0
      uni_modules/uv-toolbar/readme.md
  68. 19 0
      uni_modules/uv-transition/changelog.md
  69. 131 0
      uni_modules/uv-transition/components/uv-transition/createAnimation.js
  70. 31 0
      uni_modules/uv-transition/components/uv-transition/props.js
  71. 320 0
      uni_modules/uv-transition/components/uv-transition/uv-transition.vue
  72. 87 0
      uni_modules/uv-transition/package.json
  73. 15 0
      uni_modules/uv-transition/readme.md
  74. 2 0
      uni_modules/uv-ui-tools/changelog.md
  75. 2 2
      uni_modules/uv-ui-tools/libs/config/config.js
  76. 1 1
      uni_modules/uv-ui-tools/package.json
  77. 21 0
      utils/getSystemInfo.js

+ 55 - 0
pages.json

@@ -152,6 +152,61 @@
 				"navigationBarTitleText": "社交亲密度",
 				"disableScroll": true
 			}
+		},
+		{
+			"path": "pages/energy/energy",
+			"style": {
+				"navigationBarTitleText": "能耗管理"
+			}
+		},
+		{
+			"path" : "pages/check/check",
+			"style" : 
+			{
+				"navigationBarTitleText" : "资料审批"
+			}
+		},
+		{
+			"path" : "pages/addStudent/addStudent",
+			"style" : 
+			{
+				"navigationBarTitleText" : "添加学生"
+			}
+		},
+		{
+			"path" : "pages/addStudentMsg/addStudentMsg",
+			"style" : 
+			{
+				"navigationBarTitleText" : "添加学生"
+			}
+		},
+		{
+			"path" : "pages/set/set",
+			"style" : 
+			{
+				"navigationBarTitleText" : "部门设置"
+			}
+		},
+		{
+			"path" : "pages/invitation/invitation",
+			"style" : 
+			{
+				"navigationBarTitleText" : "邀请家长"
+			}
+		},
+		{
+			"path" : "pages/late/late",
+			"style" : 
+			{
+				"navigationBarTitleText" : "迟到记录"
+			}
+		},
+		{
+			"path" : "pages/register/register",
+			"style" : 
+			{
+				"navigationBarTitleText" : "入学登记"
+			}
 		}
 	],
 	"subPackages": [{

+ 320 - 0
pages/addStudent/addStudent.vue

@@ -0,0 +1,320 @@
+<template>
+	<view class="container">
+		<!-- 背景图片区域 -->
+		<img class="img_bg" src="../../static/images/center-bg.png" />
+
+		<!-- 输入框和添加按钮区域 -->
+		<view class="header">
+			<view class="header_input">
+				<uni-icons type="search" size="28" color="#808080" @click="changeInputValue"></uni-icons>
+				<input v-model="keyWord" class="input" type="text" placeholder="请输入学生姓名" />
+			</view>
+			<view class="header_add" @click="goAddPage">
+				<uni-icons type="plus" size="28" color="#0061FF"></uni-icons>
+			</view>
+		</view>
+
+		<!-- 全选按钮区域 -->
+		<view class="all" v-if="dataList.length">
+			<view class="all_text" @click="handleAllCheck">
+				<radio color="#0061FF" style="transform: scale(0.7)" :checked="allChecked" />
+				全选
+			</view>
+
+			<view class="cancel" @click="handleCancel">
+				<uni-icons type="closeempty" size="17" color="#00BAAD"></uni-icons>
+				&nbsp;取消全选
+			</view>
+		</view>
+
+		<!-- 学生列表区域 -->
+		<view class="list" v-if="dataList.length">
+			<!-- 每一个学生区域 -->
+			<view class="list_item" v-for="item in dataList" :key="item.id" @click="handleClickItem(item)">
+				<radio color="#0061FF" style="transform: scale(0.7)" :checked="item.isChecked" />
+				<view class="item_info">
+					<image v-if="item.headImage" class="info_img" :src="item.headImage" mode="aspectFill"></image>
+					<image v-else class="info_img" src="/static/images/header.png" mode="aspectFill"></image>
+					<view class="info_msg">
+						<view class="msg_name">{{ item.name }}</view>
+						<view>{{ item.cardNo }}</view>
+					</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 确认按钮区域 -->
+		<view class="btn" v-if="dataList.length" @click="handleConfirm">确认</view>
+
+		<NoData v-if="!dataList.length" />
+	</view>
+</template>
+
+<script setup>
+import { onLoad } from '@dcloudio/uni-app'
+import { ref } from 'vue'
+import { myRequest } from '@/utils/api.js'
+import { decryptDes } from '@/utils/des.js'
+import NoData from '@/components/noData.vue'
+
+// 输入框绑定数据
+const keyWord = ref('')
+
+// 是否全选数据
+const allChecked = ref(false)
+
+// 列表数据
+const dataList = ref([])
+
+onLoad(() => {
+	// 查询未分组的学生
+	getData()
+})
+
+// 查询未分组的学生
+const getData = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/appListClass',
+		data: {
+			keyWord: keyWord.value
+		}
+	})
+	// console.log(res)
+	const result = JSON.parse(decryptDes(res.data))
+	// console.log(result)
+	dataList.value = result
+	dataList.value.forEach((ele) => {
+		ele.isChecked = false
+	})
+}
+
+// 输入框搜索回调
+const changeInputValue = () => {
+	getData()
+}
+
+// 点击添加图标回调
+const goAddPage = () => {
+	uni.navigateTo({
+		url: '/pages/addStudentMsg/addStudentMsg'
+	})
+}
+
+// 点击全选按钮回调
+const handleAllCheck = () => {
+	if (!allChecked.value) {
+		dataList.value.forEach((ele) => {
+			ele.isChecked = true
+		})
+	} else {
+		dataList.value.forEach((ele) => {
+			ele.isChecked = false
+		})
+	}
+	allChecked.value = !allChecked.value
+}
+
+// 点击取消按钮回调
+const handleCancel = () => {
+	if (allChecked.value) {
+		dataList.value.forEach((ele) => {
+			ele.isChecked = false
+		})
+	}
+	allChecked.value = false
+}
+
+// 点击每一个学生的回调
+const handleClickItem = (item) => {
+	item.isChecked = !item.isChecked
+
+	// 判断全选按钮的状态
+	allChecked.value = dataList.value.every((ele) => ele.isChecked)
+}
+
+// 确认按钮回调
+const handleConfirm = () => {
+	// 判断是否选择了学生
+	const flag = dataList.value.find((ele) => ele.isChecked)
+
+	if (!flag) {
+		uni.showToast({
+			title: '请至少选择一名学生',
+			icon: 'none',
+			mask: true
+		})
+	} else {
+		uni.showModal({
+			title: '提示',
+			content: '确定将未分组的学生添加到班级吗?',
+			success: (res) => {
+				if (res.confirm) {
+					let arr = []
+					dataList.value.forEach((ele) => {
+						if (ele.isChecked) {
+							arr.push(ele.id)
+						}
+					})
+					handleAddClass(arr)
+				}
+			}
+		})
+	}
+}
+
+// 添加请求
+const handleAddClass = async (ids) => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/appSaveClass',
+		method: 'post',
+		data: {
+			ids,
+			schoolClass: uni.getStorageSync('userInfo').schoolClass
+			// departmentId: uni.getStorageSync('userInfo').departmentId
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		uni.showToast({
+			title: res.message,
+			icon: 'success'
+		})
+		setTimeout(() => {
+			uni.reLaunch({
+				url: '/pages/studentManage/studentManage'
+			})
+		}, 1500)
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	box-sizing: border-box;
+	padding: 20rpx;
+	height: 100vh;
+	background-color: #f1f6fe;
+
+	// 背景图片区域样式
+	.img_bg {
+		position: absolute;
+		top: -70rpx;
+		right: 0;
+		width: 589rpx;
+		height: 320rpx;
+		pointer-events: none;
+	}
+
+	.header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding-top: 30rpx;
+
+		.header_input {
+			display: flex;
+			align-items: center;
+			box-sizing: border-box;
+			padding-left: 40rpx;
+			width: 589rpx;
+			height: 100rpx;
+			font-size: 28rpx;
+			border-radius: 13rpx;
+			border: 2rpx solid #cccccc;
+			background-color: #fff;
+
+			.input {
+				padding: 0 20rpx;
+				width: 425rpx;
+			}
+		}
+
+		.header_add {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 100rpx;
+			height: 100rpx;
+			border-radius: 13rpx;
+			border: 2rpx solid #cccccc;
+			background-color: #fff;
+		}
+	}
+
+	.all {
+		display: flex;
+		align-items: center;
+		margin-top: 30rpx;
+		font-size: 28rpx;
+
+		.all_text {
+			display: flex;
+			align-items: center;
+			color: #0061ff;
+		}
+
+		.cancel {
+			display: flex;
+			align-items: center;
+			margin-left: 50rpx;
+			color: #00baad;
+		}
+	}
+
+	.list {
+		margin-top: 30rpx;
+		height: calc(100vh - 500rpx);
+		overflow-y: auto;
+
+		.list_item {
+			display: flex;
+			align-items: center;
+			margin-bottom: 20rpx;
+
+			.item_info {
+				display: flex;
+				align-items: center;
+				flex: 1;
+				height: 167rpx;
+				border-radius: 8rpx 0 0 8rpx;
+				background-color: #fff;
+
+				.info_img {
+					margin-left: 20rpx;
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 50%;
+				}
+
+				.info_msg {
+					display: flex;
+					flex-direction: column;
+					justify-content: space-between;
+					margin-left: 28rpx;
+					height: 100rpx;
+					font-size: 28rpx;
+					color: #808080;
+
+					.msg_name {
+						color: #000000;
+						font-size: 32rpx;
+					}
+				}
+			}
+		}
+	}
+
+	.btn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin-top: 80rpx;
+		width: 710rpx;
+		height: 100rpx;
+		font-size: 32rpx;
+		color: #fff;
+		border-radius: 8rpx;
+		background-color: #0061ff;
+	}
+}
+</style>

+ 217 - 0
pages/addStudentMsg/addStudentMsg.vue

@@ -0,0 +1,217 @@
+<template>
+	<view class="container">
+		<!-- 姓名区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				孩子姓名
+			</view>
+			<view class="box_value">
+				<input class="input" type="text" placeholder="请输入孩子姓名" v-model="name" />
+			</view>
+		</view>
+
+		<!-- 性别区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				性别
+			</view>
+			<view class="box_value">
+				<view class="men" @click="handlegender(1)">
+					<radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 1" />
+					男
+				</view>
+
+				<view class="women" @click="handlegender(2)">
+					<radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 2" />
+					女
+				</view>
+			</view>
+		</view>
+
+		<!-- 人脸图片区域 -->
+		<view class="box2">
+			<view class="box_key">
+				<text class="text">*</text>
+				人脸图片
+			</view>
+			<view class="box_upload">
+				<uni-icons type="plusempty" size="30" color="#666666"></uni-icons>
+				上传照片
+			</view>
+		</view>
+		<view class="tips">注:支持.jpg .png,五官清晰无遮挡,大小不超过2M</view>
+
+		<!-- 时间组区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				时间组
+			</view>
+
+			<picker @change="bindPickerChange" :value="currentIndex" :range="array">
+				<view class="box_value" :class="{ unactive: !currentIndex }">
+					{{ currentIndex ? array[currentIndex] : '请选择' }}
+					<image class="value_img" src="/static/images/bottom2.png" mode="aspectFill"></image>
+				</view>
+			</picker>
+		</view>
+
+		<!-- 家属区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				家属
+			</view>
+			<view class="box_value">
+				<input class="input" type="text" placeholder="请输入姓名" />
+				<view class="value_icon">
+					<uni-icons type="plus" size="25" color="#0061FF"></uni-icons>
+				</view>
+			</view>
+		</view>
+
+		<!-- 手机号码区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				手机号码
+			</view>
+			<view class="box_value">
+				<input class="input" type="text" placeholder="请输入手机号码" />
+			</view>
+		</view>
+
+		<!-- 家属与本人的关系区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				家属与本人的关系
+			</view>
+			<view class="box_value">
+				<input class="input" type="text" placeholder="请输入家属与本人的关系" />
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+// 姓名
+const name = ref()
+// 性别
+const gender = ref(1)
+// 时间组当前激活索引
+const currentIndex = ref()
+// 时间组数据
+const array = ref(['上午', '下午'])
+// 切换性别回调
+const handlegender = (v) => {
+	gender.value = v
+}
+// 切换时间组回调
+const bindPickerChange = (e) => {
+	currentIndex.value = e.detail.value
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	padding: 10rpx 0 30rpx 15rpx;
+	height: 100vh;
+	font-size: 28rpx;
+
+	.box {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		height: 96rpx;
+		border-bottom: 2rpx solid #e6e6e6;
+
+		.box_key {
+			display: flex;
+			align-items: center;
+			font-weight: bold;
+
+			.text {
+				color: #d43030;
+			}
+		}
+
+		.box_value {
+			display: flex;
+			align-items: center;
+			justify-content: flex-end;
+			padding-right: 20rpx;
+			width: 320rpx;
+			height: 96rpx;
+
+			.input {
+				height: 100%;
+				text-align: end;
+			}
+
+			.men,
+			.women {
+				display: flex;
+				align-items: center;
+			}
+
+			.women {
+				margin-left: 20rpx;
+			}
+
+			.value_icon {
+				margin-left: 15rpx;
+			}
+
+			.value_img {
+				margin-left: 20rpx;
+				width: 27rpx;
+				height: 16rpx;
+			}
+		}
+
+		.unactive {
+			color: #6a6a6a;
+		}
+	}
+
+	.box2 {
+		display: flex;
+		margin-top: 40rpx;
+
+		.box_key {
+			display: flex;
+			font-weight: bold;
+
+			.text {
+				color: #d43030;
+			}
+		}
+
+		.box_upload {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			margin-left: 30rpx;
+			width: 160rpx;
+			height: 160rpx;
+			font-size: 24rpx;
+			color: #666666;
+			border-radius: 6rpx;
+			background-color: #f2f2f2;
+		}
+	}
+
+	.tips {
+		margin-top: 20rpx;
+		margin-bottom: 5rpx;
+		font-size: 24rpx;
+		color: #a6a6a6;
+	}
+}
+</style>

+ 288 - 0
pages/check/check.vue

@@ -0,0 +1,288 @@
+<template>
+	<view class="container">
+		<!-- 筛选区域 -->
+		<picker @change="bindPickerChange" :value="currentIndex" :range="array" range-key="text">
+			<view class="search">
+				<view>
+					{{ array[currentIndex].text }}
+				</view>
+				▼
+			</view>
+		</picker>
+
+		<!-- 列表区域 -->
+		<view class="list">
+			<!-- 每一个资料区域 -->
+			<view class="list_item" v-for="item in dataList" :key="item.id">
+				<!-- 标题区域 -->
+				<view class="item_title">
+					<view class="title_text">入学登记</view>
+					{{ item.createTime }}
+				</view>
+
+				<!-- 信息区域 -->
+				<view class="item_body">
+					<view class="type check" v-if="item.status == 0">待审批</view>
+					<view class="type pass" v-if="item.status == 1">已通过</view>
+					<view class="type reject" v-if="item.status == 2">已拒绝</view>
+					<view class="box">孩子姓名:{{ item.name }}</view>
+					<view class="box">性别:{{ item.sexId == 1 ? '男' : '女' }}</view>
+					<view class="box">
+						照片:
+						<image v-if="!item.headImage" class="box_img" src="/static/images/header.png" mode="aspectFill"></image>
+						<image v-else class="box_img" :src="item.headImage" mode="aspectFill"></image>
+					</view>
+					<view class="box">年级:{{ item.gradeName }}</view>
+					<view class="box">班级:{{ item.schoolClassName }}</view>
+
+					<!-- 家属数组区域 -->
+					<view v-for="(ele, index) in item.list" :key="index">
+						<view class="box">家属:{{ ele.name }}</view>
+						<view class="box">手机号码:{{ ele.phone }}</view>
+						<view class="box">家属与本人的关系:{{ ele.ship }}</view>
+					</view>
+
+					<view class="btns" v-if="item.status == 0">
+						<view class="btn reject" @click="clickBtn(item.id, 2)">拒绝</view>
+						<view class="btn agree" @click="clickBtn(item.id, 1)">同意</view>
+					</view>
+				</view>
+			</view>
+
+			<NoData v-if="!dataList.length" />
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { onLoad, onReachBottom } from '@dcloudio/uni-app'
+import { ref } from 'vue'
+import { myRequest } from '@/utils/api.js'
+import { decryptDes } from '@/utils/des.js'
+import NoData from '@/components/noData.vue'
+
+// 当前激活索引
+const currentIndex = ref(0)
+// 状态数组
+const array = ref([
+	{
+		text: '全部',
+		value: ''
+	},
+	{
+		text: '待审批',
+		value: 0
+	},
+	{
+		text: '已通过',
+		value: 1
+	},
+	{
+		text: '已拒绝',
+		value: 2
+	}
+])
+
+// 当前页
+const currentPage = ref(1)
+// 总条数
+const total = ref(0)
+// 资料审批数组
+const dataList = ref([])
+
+onLoad(() => {
+	// 获取资料审批数组
+	getData()
+})
+
+// 页面下拉刷新回调
+onReachBottom(() => {
+	if (total.value > dataList.value.length) {
+		currentPage.value++
+		getData()
+	} else {
+		uni.showToast({
+			title: '没有更多数据了~',
+			icon: 'none'
+		})
+	}
+})
+
+// 获取资料审批数组
+const getData = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartEnrollmentUser/list',
+		data: {
+			currentPage: currentPage.value,
+			pageCount: 4,
+			status: array.value[currentIndex.value].value
+		}
+	})
+	// console.log(res)
+	const result = JSON.parse(decryptDes(res.data))
+	// console.log(result)
+	dataList.value = [...dataList.value, ...result.list]
+	total.value = result.totalCount
+}
+
+// 切换状态时的回调
+const bindPickerChange = (e) => {
+	// console.log(e.detail.value)
+	if (e.detail.value != currentIndex.value) {
+		currentIndex.value = e.detail.value
+		currentPage.value = 1
+		dataList.value = []
+		getData()
+	}
+}
+
+// 点击同意拒绝按钮回调
+const clickBtn = (id, type) => {
+	uni.showModal({
+		title: '提示',
+		content: `确定${type == 1 ? '同意' : '拒绝'}该审批吗?`,
+		success: (res) => {
+			if (res.confirm) {
+				clickBtnReq(id, type)
+			}
+		}
+	})
+}
+
+// 审批请求
+const clickBtnReq = async (id, type) => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartEnrollmentUser/examine',
+		method: 'post',
+		data: {
+			id: id,
+			status: type
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		uni.showToast({
+			title: res.message,
+			icon: 'success'
+		})
+		setTimeout(() => {
+			currentPage.value = 1
+			dataList.value = []
+			getData()
+		}, 1500)
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	box-sizing: border-box;
+	padding: 30rpx 20rpx;
+	height: 100vh;
+	overflow-y: auto;
+	background: linear-gradient(180deg, #f2f7ff 0%, #f2f7ff 100%);
+
+	.search {
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		box-sizing: border-box;
+		padding: 0 30rpx;
+		width: 284rpx;
+		height: 80rpx;
+		font-size: 28rpx;
+		border-radius: 55rpx;
+		background-color: #fff;
+	}
+
+	.list {
+		margin-top: 30rpx;
+
+		.list_item {
+			margin-bottom: 30rpx;
+			border-radius: 8rpx;
+			background-color: #fff;
+
+			.item_title {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				padding: 0 30rpx;
+				height: 90rpx;
+				color: #808080;
+				font-size: 24rpx;
+				border-bottom: 2rpx solid #e6e6e6;
+
+				.title_text {
+					font-size: 28rpx;
+					font-weight: bold;
+					color: #000;
+				}
+			}
+
+			.item_body {
+				position: relative;
+				padding: 25rpx 30rpx;
+
+				.type {
+					position: absolute;
+					top: 16rpx;
+					right: 30rpx;
+					font-size: 28rpx;
+				}
+
+				.check {
+					color: #ff8d1a;
+				}
+
+				.pass {
+					color: #0061ff;
+				}
+
+				.reject {
+					color: #d43030;
+				}
+
+				.box {
+					display: flex;
+					margin-bottom: 20rpx;
+					font-size: 28rpx;
+					color: #383838;
+
+					.box_img {
+						width: 116rpx;
+						height: 155rpx;
+						border-radius: 4rpx;
+					}
+				}
+
+				.btns {
+					display: flex;
+					align-items: center;
+					justify-content: flex-end;
+
+					.btn {
+						display: flex;
+						justify-content: center;
+						align-items: center;
+						margin-left: 28rpx;
+						width: 146rpx;
+						height: 80rpx;
+						font-size: 28rpx;
+						color: #fff;
+						border-radius: 10rpx;
+					}
+
+					.reject {
+						background-color: #d43030;
+					}
+
+					.agree {
+						background-color: #0061ff;
+					}
+				}
+			}
+		}
+	}
+}
+</style>

+ 672 - 0
pages/energy/energy.vue

@@ -0,0 +1,672 @@
+<template>
+	<view class="container">
+		<!-- 水电表统计区域 -->
+		<view class="box">
+			<view class="box_title">水电表统计</view>
+
+			<!-- 水表区域 -->
+			<view class="box_info">
+				<view class="info_title">水表</view>
+				<view class="info_day">
+					<view class="top">
+						{{ waterDay }}
+						<view class="text">吨</view>
+					</view>
+					<view class="bottom">近24小时</view>
+				</view>
+				<view class="info_month">
+					<view class="top">
+						{{ waterMonth }}
+						<view class="text">吨</view>
+					</view>
+					<view class="bottom">近30天</view>
+				</view>
+				<view class="info_year">
+					<view class="top">
+						{{ waterYear }}
+						<view class="text">吨</view>
+					</view>
+					<view class="bottom">近1年</view>
+				</view>
+			</view>
+
+			<!-- 电表区域 -->
+			<view class="box_info">
+				<view class="info_title">电表</view>
+				<view class="info_day">
+					<view class="top">
+						{{ elcDay }}
+						<view class="text">度</view>
+					</view>
+					<view class="bottom">近24小时</view>
+				</view>
+				<view class="info_month">
+					<view class="top">
+						{{ elcMonth }}
+						<view class="text">度</view>
+					</view>
+					<view class="bottom">近30天</view>
+				</view>
+				<view class="info_year">
+					<view class="top">
+						{{ elcYear }}
+						<view class="text">度</view>
+					</view>
+					<view class="bottom">近1年</view>
+				</view>
+			</view>
+		</view>
+
+		<!-- 区域统计图表区域 -->
+		<view class="chart">
+			<view class="chart_title">区域统计</view>
+
+			<!-- 切换区域 -->
+			<view class="chart_switch">
+				<view class="switch_box" :class="{ switch_active: activeIndex == 1 }" @click="switchChange(1)">水</view>
+				<view class="switch_box" :class="{ switch_active: activeIndex == 2 }" @click="switchChange(2)">电</view>
+			</view>
+
+			<!-- 图表区域 -->
+			<view class="chart_box">
+				<qiun-data-charts type="column" :opts="opts" :chartData="chartData" />
+			</view>
+		</view>
+
+		<!-- 区域能耗统计表格区域 -->
+		<view class="form">
+			<view class="form_title">区域能耗统计</view>
+
+			<!-- 日期选择区域 -->
+			<view class="form_time" :class="{ active: time_area }" @click="handleOpen">
+				{{ time_area ? time_area : '请选择月份' }}
+				<view v-if="time_area" @click.stop="handleClose">
+					<uni-icons type="close" size="20" color="#808080"></uni-icons>
+				</view>
+				<image class="time_img" src="/static/images/time.png" mode="aspectFill"></image>
+				<uv-datetime-picker ref="datetimePicker" :value="Date.now()" mode="year-month" @confirm="handleConfirm"></uv-datetime-picker>
+			</view>
+
+			<!-- 表格区域 -->
+			<view class="form_table">
+				<uni-table ref="table" border emptyText="暂无更多数据">
+					<uni-tr>
+						<uni-th width="1" align="center">序号</uni-th>
+						<uni-th width="1" align="center">电(kw/h)</uni-th>
+						<uni-th width="1" align="center">水(L)</uni-th>
+						<uni-th width="1" align="center">&nbsp;楼栋&nbsp;</uni-th>
+						<uni-th width="1" align="center">日期</uni-th>
+					</uni-tr>
+					<uni-tr v-for="(item, index) in tableData_area" :key="item.id">
+						<uni-td align="center">
+							<view class="td">{{ index + 1 }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.eNum || 0 }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.wNum || 0 }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.name }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.date }}</view>
+						</uni-td>
+					</uni-tr>
+				</uni-table>
+			</view>
+
+			<!-- 分页器区域 -->
+			<view class="pagination">
+				<uni-pagination show-icon pageSize="4" :total="total_area" :current="currentPage_area" @change="changePage_area"></uni-pagination>
+			</view>
+		</view>
+
+		<!-- 实时抄表表格区域 -->
+		<view class="form">
+			<view class="form_title">实时抄表</view>
+
+			<!-- 筛选区域 -->
+			<view class="form_select">
+				<!-- 时间选择区域 -->
+				<view class="select_time" :class="{ active: time_now }" @click="handleOpen_now">
+					{{ time_now ? time_now : '请选择日期' }}
+					<view v-if="time_now" @click.stop="handleClose_now">
+						<uni-icons type="close" size="20" color="#808080"></uni-icons>
+					</view>
+					<image class="time_img" src="/static/images/time.png" mode="aspectFill"></image>
+					<uv-datetime-picker ref="datetimePicker_now" :value="Date.now()" mode="date" @confirm="handleConfirm_now"></uv-datetime-picker>
+				</view>
+
+				<view class="select_box">
+					<view class="box_item" :class="{ active: activeIndex_now == 0 }" @click="switchChange_now(0)">水</view>
+					<view class="box_item" :class="{ active: activeIndex_now == 1 }" @click="switchChange_now(1)">电</view>
+				</view>
+			</view>
+
+			<!-- 表格区域 -->
+			<view class="form_table">
+				<uni-table ref="table" border emptyText="暂无更多数据">
+					<uni-tr>
+						<uni-th width="1" align="center">序号</uni-th>
+						<uni-th width="1" align="center">位置</uni-th>
+						<uni-th width="1" align="center">{{ activeIndex_now == 0 ? '水表码数(吨)' : '电表码数(kw)' }}</uni-th>
+						<uni-th width="1" align="center">&nbsp;楼栋&nbsp;</uni-th>
+						<uni-th width="1" align="center">表号</uni-th>
+						<uni-th width="1" align="center">时间</uni-th>
+					</uni-tr>
+					<uni-tr v-for="(item, index) in tableData_now" :key="item.id">
+						<uni-td align="center">
+							<view class="td">{{ index + 1 }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.address }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.meterPowerRecord }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.buildAddress }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.meterNo }}</view>
+						</uni-td>
+						<uni-td align="center">
+							<view class="td">{{ item.createTime }}</view>
+						</uni-td>
+					</uni-tr>
+				</uni-table>
+			</view>
+
+			<!-- 分页器区域 -->
+			<view class="pagination">
+				<uni-pagination show-icon pageSize="4" :total="total_now" :current="currentPage_now" @change="changePage_now"></uni-pagination>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { myRequest } from '@/utils/api.js'
+import { decryptDes } from '@/utils/des.js'
+import dayjs from 'dayjs'
+
+// 水-日
+const waterDay = ref()
+// 水-月
+const waterMonth = ref()
+// 水-年
+const waterYear = ref()
+
+// 电-日
+const elcDay = ref()
+// 电-日
+const elcMonth = ref()
+// 电-日
+const elcYear = ref()
+
+// 图表激活索引
+const activeIndex = ref(1)
+// 图表配置
+const opts = ref({})
+// 图表数据
+const chartData = ref({})
+// 图表Y轴数据
+const categories = ref([])
+// 图表地点数据
+const seriesData = ref([
+	{
+		name: '',
+		data: []
+	},
+	{
+		name: '',
+		data: []
+	},
+	{
+		name: '',
+		data: []
+	}
+])
+
+// 区域能耗筛选时间组件DOM
+const datetimePicker = ref()
+// 区域能耗筛选时间
+const time_area = ref('')
+// 区域能耗表格数据总条数
+const total_area = ref(0)
+// 区域能耗表格当前页
+const currentPage_area = ref(1)
+// 区域能耗表格数据
+const tableData_area = ref([])
+
+// 实时抄表筛选时间组件DOM
+const datetimePicker_now = ref()
+// 实时抄表筛选时间
+const time_now = ref('')
+// 实时抄表当前激活索引
+const activeIndex_now = ref(0)
+// 实时抄表表格数据总条数
+const total_now = ref(0)
+// 实时抄表表格当前页
+const currentPage_now = ref(1)
+// 实时抄表表格数据
+const tableData_now = ref([])
+
+onLoad(() => {
+	// 获取水电能耗统计数据
+	getData_waterAndEle()
+	// 获取图表数据
+	getData_chart()
+	// 获取区域能耗统计表格数据
+	getData_area()
+	// 获取实时抄表数据
+	getData_now()
+})
+
+// 获取水电能耗统计数据
+const getData_waterAndEle = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/wechat/waterAndElectricityStatistics'
+	})
+	// console.log(res)
+	const result = JSON.parse(decryptDes(res.data))
+	// console.log(result)
+	waterDay.value = result.waterDay
+	waterMonth.value = result.waterMonth
+	waterYear.value = result.waterYear
+
+	elcDay.value = result.elcDay
+	elcMonth.value = result.elcMonth
+	elcYear.value = result.elcYear
+}
+
+// 获取图表数据
+const getData_chart = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/driver/getEnergyMonth',
+		data: {
+			type: activeIndex.value == 1 ? 0 : 1
+		}
+	})
+	// console.log(res)
+
+	categories.value = res.data.map((ele) => ele.month.slice(5, 7) + '月')
+
+	seriesData.value[0].name = res.data[0].data[0].name
+	res.data.forEach((ele) => {
+		ele.data.forEach((item) => {
+			if (item.name == seriesData.value[0].name) {
+				seriesData.value[0].data.push(item.num)
+			}
+		})
+	})
+
+	seriesData.value[1].name = res.data[0].data[1].name
+	res.data.forEach((ele) => {
+		ele.data.forEach((item) => {
+			if (item.name == seriesData.value[1].name) {
+				seriesData.value[1].data.push(item.num)
+			}
+		})
+	})
+
+	seriesData.value[2].name = res.data[0].data[2].name
+	res.data.forEach((ele) => {
+		ele.data.forEach((item) => {
+			if (item.name == seriesData.value[2].name) {
+				seriesData.value[2].data.push(item.num)
+			}
+		})
+	})
+
+	// console.log(seriesData.value)
+
+	// 初始化图表
+	initChart()
+}
+// 初始化图表
+const initChart = () => {
+	opts.value = {
+		color: ['#3A4DE9', '#00BAAD', '#FF8D1A'],
+		padding: [25, 15, 0, 5],
+		enableScroll: false,
+		dataLabel: false,
+		legend: {},
+		xAxis: {
+			disableGrid: true
+		},
+		yAxis: {
+			showTitle: true,
+			gridType: 'dash',
+			data: [
+				{
+					min: 0,
+					title: activeIndex.value == 1 ? '吨' : '度',
+					titleOffsetY: -10
+				}
+			]
+		},
+		extra: {
+			column: {
+				type: 'group',
+				width: 10,
+				activeBgColor: '#000000',
+				activeBgOpacity: 0.08
+			}
+		}
+	}
+
+	let res = {
+		categories: categories.value,
+		series: seriesData.value
+	}
+
+	chartData.value = JSON.parse(JSON.stringify(res))
+}
+// 水电图表切换回调
+const switchChange = (v) => {
+	activeIndex.value = v
+	seriesData.value[0].data = []
+	seriesData.value[1].data = []
+	seriesData.value[2].data = []
+	getData_chart()
+}
+
+// 获取区域能耗统计表格数据
+const getData_area = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/wechat/getAppMeterMonthPage',
+		data: {
+			currentPage: currentPage_area.value,
+			pageCount: 4,
+			date: time_area.value
+		}
+	})
+	// console.log(res)
+	const result = JSON.parse(decryptDes(res.data))
+	// console.log(result)
+
+	total_area.value = result.total
+	tableData_area.value = result.list
+}
+// 区域能耗统计时间组件打开回调
+const handleOpen = () => {
+	datetimePicker.value.open()
+}
+// 区域能耗统计时间组件关闭图标回调
+const handleClose = () => {
+	time_area.value = ''
+	currentPage_area.value = 1
+	getData_area()
+}
+// 区域能耗统计时间组件确定回调
+const handleConfirm = (e) => {
+	// console.log(e)
+	time_area.value = dayjs(e.value).format('YYYY-MM')
+	currentPage_area.value = 1
+	getData_area()
+}
+// 区域能耗统计表格切换当前页回调
+const changePage_area = (e) => {
+	currentPage_area.value = e.current
+	getData_area()
+}
+
+// 获取实时抄表数据
+const getData_now = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/wechat/getAppMeterDayPage',
+		data: {
+			currentPage: currentPage_now.value,
+			pageCount: 4,
+			date: time_now.value,
+			type: activeIndex_now.value
+		}
+	})
+	// console.log(res)
+	const result = JSON.parse(decryptDes(res.data))
+	// console.log(result)
+	total_now.value = result.total
+	tableData_now.value = result.list
+}
+// 区域能耗统计时间组件打开回调
+const handleOpen_now = () => {
+	datetimePicker_now.value.open()
+}
+// 区域能耗统计时间组件关闭图标回调
+const handleClose_now = () => {
+	time_now.value = ''
+	currentPage_now.value = 1
+	getData_now()
+}
+// 区域能耗统计时间组件确定回调
+const handleConfirm_now = (e) => {
+	// console.log(e)
+	time_now.value = dayjs(e.value).format('YYYY-MM-DD')
+	currentPage_now.value = 1
+	getData_now()
+}
+// 实时抄表切换类别回调
+const switchChange_now = (v) => {
+	activeIndex_now.value = v
+	currentPage_now.value = 1
+	time_now.value = ''
+	getData_now()
+}
+// 实时抄表表格切换当前页回调
+const changePage_now = (e) => {
+	// console.log(e)
+	currentPage_now.value = e.current
+	getData_now()
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	padding: 20rpx;
+
+	.box {
+		margin-top: 30rpx;
+
+		.box_title {
+			margin-bottom: 40rpx;
+			font-size: 32rpx;
+			font-weight: bold;
+		}
+
+		.box_info {
+			display: flex;
+			margin-bottom: 50rpx;
+			height: 80rpx;
+
+			.info_title {
+				width: 100rpx;
+				line-height: 80rpx;
+				font-size: 28rpx;
+				font-weight: bold;
+				border-right: 2rpx solid #000;
+			}
+
+			.info_day,
+			.info_month,
+			.info_year {
+				display: flex;
+				flex-direction: column;
+				align-items: center;
+				width: 200rpx;
+				height: 80rpx;
+				text-align: center;
+
+				.top {
+					margin-top: -18rpx;
+					width: 180rpx;
+					font-size: 28rpx;
+					font-weight: bold;
+					overflow: hidden;
+					white-space: nowrap;
+					text-overflow: ellipsis;
+
+					.text {
+						display: inline-block;
+						margin-top: -8rpx;
+						margin-left: -8rpx;
+						font-size: 22rpx;
+						font-weight: 400;
+					}
+				}
+
+				.bottom {
+					margin-top: 20rpx;
+					font-size: 22rpx;
+					color: #808080;
+				}
+			}
+		}
+	}
+
+	.chart {
+		.chart_title {
+			font-size: 32rpx;
+			font-weight: bold;
+		}
+
+		.chart_switch {
+			display: flex;
+			justify-content: space-between;
+			margin-top: 38rpx;
+			width: 280rpx;
+
+			.switch_box {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				width: 128rpx;
+				height: 66rpx;
+				border-radius: 6rpx;
+				font-size: 28rpx;
+				color: #a6a6a6;
+				background-color: #f2f2f2;
+			}
+
+			.switch_active {
+				color: #000;
+				border: 2rpx solid #0061ff;
+				background-color: #e8f1ff;
+			}
+		}
+
+		.chart_box {
+			margin-top: 30rpx;
+			width: 100%;
+			height: 550rpx;
+		}
+	}
+
+	.form {
+		margin-top: 20rpx;
+		padding-bottom: 40rpx;
+
+		.form_title {
+			font-size: 32rpx;
+			font-weight: bold;
+		}
+
+		.form_time {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			box-sizing: border-box;
+			padding: 0 20rpx;
+			margin-top: 38rpx;
+			width: 280rpx;
+			height: 66rpx;
+			font-size: 28rpx;
+			color: #a6a6a6;
+			border-radius: 6rpx;
+			border: 2rpx solid #999999;
+			background-color: #f2f2f2;
+
+			.time_img {
+				width: 36rpx;
+				height: 36rpx;
+			}
+		}
+
+		.active {
+			color: #000;
+		}
+
+		.form_select {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			margin-top: 38rpx;
+
+			.select_time {
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				box-sizing: border-box;
+				padding: 0 20rpx;
+				width: 280rpx;
+				height: 66rpx;
+				font-size: 28rpx;
+				color: #a6a6a6;
+				border-radius: 6rpx;
+				border: 2rpx solid #999999;
+				background-color: #f2f2f2;
+
+				.time_img {
+					width: 36rpx;
+					height: 36rpx;
+				}
+			}
+
+			.select_box {
+				display: flex;
+				justify-content: space-between;
+				width: 280rpx;
+
+				.box_item {
+					display: flex;
+					justify-content: center;
+					align-items: center;
+					width: 128rpx;
+					height: 66rpx;
+					border-radius: 6rpx;
+					font-size: 28rpx;
+					color: #a6a6a6;
+					background-color: #f2f2f2;
+				}
+
+				.active {
+					color: #000;
+					border: 2rpx solid #0061ff;
+					background-color: #e8f1ff;
+				}
+			}
+
+			.active {
+				color: #000;
+			}
+		}
+
+		.form_table {
+			margin-top: 40rpx;
+
+			.td {
+				font-size: 24rpx;
+				white-space: nowrap;
+			}
+		}
+
+		.pagination {
+			margin-top: 25rpx;
+		}
+	}
+}
+</style>

+ 4 - 0
pages/home/home.vue

@@ -174,6 +174,10 @@ const list = ref([
 		id: 11,
 		title: '通讯录',
 		path: '/pages/grade/grade'
+	},
+	{
+		title: '能耗管理',
+		path: '/pages/energy/energy'
 	}
 ])
 

+ 189 - 0
pages/invitation/invitation.vue

@@ -0,0 +1,189 @@
+<template>
+	<view class="container">
+		<!-- 二维码区域 -->
+		<view class="box">
+			<view class="box_top">
+				<view class="top_text">尊敬的家长:您好!七年级一班现诚邀您扫描下方二维码,填写相关信息加入班级,感谢您的配合,让我们携手为孩子的成长保驾护航!</view>
+				<view class="top_qrcode">
+					<view class="qrcode_box">
+						<uv-qrcode ref="qrcodeRef" size="350rpx" :value="QRCodeUrl"></uv-qrcode>
+					</view>
+					<view class="qrcode_info">
+						<image class="info_img" src="/static/images/school-logo.jpg" mode=""></image>
+						万载三中
+					</view>
+				</view>
+			</view>
+			<view class="box_bottom" @click="test">填写相关信息</view>
+		</view>
+
+		<view class="btns">
+			<view class="btn save" @click="handleSave">保存图片</view>
+			<view class="btn send">
+				发送到微信
+				<button class="share" open-type="share">发送到微信</button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { onShareAppMessage } from '@dcloudio/uni-app'
+import { ref } from 'vue'
+
+onShareAppMessage(() => {
+	if (res.from === 'button') {
+		// 来自页面内分享按钮
+		console.log(res.target)
+	}
+	return {
+		title: '自定义分享标题',
+		path: '/pages/test/test?id=123'
+	}
+})
+
+// 二维码元素引用标记
+const qrcodeRef = ref(null)
+
+// 二维码信息
+const QRCodeUrl = ref('https://chtech.ncjti.edu.cn/testingServer/repairManage/')
+
+// 保存图片按钮回调
+const handleSave = () => {
+	qrcodeRef.value.save({
+		success: (res) => {
+			console.log(res)
+
+			// uni.getImageInfo({
+			// 	url: res.tempFilePath,
+			// 	success: (res) => {
+			// 		console.log(res)
+			// 		uni.saveImageToPhotosAlbum({
+			// 			filePath: res.tempFilePath,
+			// 			success: function () {
+			// 				console.log('save success')
+			// 			}
+			// 		})
+			// 	}
+			// })
+		},
+		fail: (err) => {
+			console.log(err)
+		}
+	})
+}
+
+const test = () => {
+	uni.navigateTo({
+		url: '/pages/register/register'
+	})
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	box-sizing: border-box;
+	padding: 38rpx 0;
+	min-height: 100vh;
+	background: linear-gradient(180deg, rgba(242, 247, 255, 1) 0%, rgba(242, 247, 255, 0) 100%);
+
+	.box {
+		margin: auto;
+		width: 670rpx;
+		height: 910rpx;
+
+		.box_top {
+			display: flex;
+			flex-direction: column;
+			justify-content: space-between;
+			align-items: center;
+			box-sizing: border-box;
+			padding: 45rpx 50rpx;
+			height: 795rpx;
+			border-radius: 18rpx 18rpx 0 0;
+			background-color: #0061ff;
+
+			.top_text {
+				font-size: 28rpx;
+				line-height: 40rpx;
+				color: #fff;
+			}
+
+			.top_qrcode {
+				display: flex;
+				flex-direction: column;
+				justify-content: space-evenly;
+				align-items: center;
+				width: 456rpx;
+				height: 506rpx;
+				background-color: #fff;
+				border-radius: 0 30rpx 0 30rpx;
+
+				.qrcode_box {
+					width: 350rpx;
+					height: 350rpx;
+				}
+
+				.qrcode_info {
+					display: flex;
+					align-items: center;
+					font-size: 28rpx;
+
+					.info_img {
+						margin-right: 18rpx;
+						width: 40rpx;
+						height: 40rpx;
+					}
+				}
+			}
+		}
+
+		.box_bottom {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			height: 115rpx;
+			font-size: 38rpx;
+			font-weight: bold;
+			border-radius: 0 0 18rpx 18rpx;
+			border: 2rpx solid #0061ff;
+			background-color: #fff;
+		}
+	}
+
+	.btns {
+		display: flex;
+		justify-content: center;
+		margin-top: 90rpx;
+
+		.btn {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 300rpx;
+			height: 100rpx;
+			font-size: 32rpx;
+			border-radius: 8rpx;
+		}
+
+		.save {
+			color: #fff;
+			background-color: #0061ff;
+		}
+
+		.send {
+			margin-left: 20rpx;
+			color: #0061ff;
+			border: 2rpx solid #0061ff;
+		}
+
+		.share {
+			position: absolute;
+			width: 300rpx;
+			height: 100rpx;
+			border-radius: 8rpx;
+			opacity: 0;
+		}
+	}
+}
+</style>

+ 183 - 0
pages/late/late.vue

@@ -0,0 +1,183 @@
+<template>
+	<view class="container">
+		<!-- 背景图片区域 -->
+		<img class="img_bg" src="../../static/images/center-bg.png" />
+
+		<!-- 时间筛选区域 -->
+		<view class="time">
+			迟到时间
+			<view class="time_rang">
+				<uni-datetime-picker v-model="timeRang" type="daterange" @change="changeTime" />
+			</view>
+		</view>
+
+		<!-- 迟到列表区域 -->
+		<view class="list">
+			<uni-swipe-action>
+				<view v-for="(item, index) in list" :key="index">
+					<uni-swipe-action-item :right-options="options" @click="onClickItem(item)">
+						<!-- 每一个迟到记录区域 -->
+						<view class="item_box">
+							<view class="box_info">
+								<image class="info_img" src="/static/images/header.png" mode="aspectFill"></image>
+								<view class="info_msg">
+									<view class="msg_name">
+										{{ item.name }}
+									</view>
+									<view class="msg_no">
+										{{ item.cardNo }}
+									</view>
+								</view>
+							</view>
+							<view class="box_time">{{ item.timeGroup }}</view>
+						</view>
+					</uni-swipe-action-item>
+					<view style="height: 20rpx"></view>
+				</view>
+			</uni-swipe-action>
+		</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+const options = [
+	{
+		text: '删除',
+		style: {
+			backgroundColor: '#D43030'
+		}
+	}
+]
+
+const timeRang = ref([])
+
+const list = ref([
+	{
+		cardNo: '132',
+		name: '小明',
+		timeGroup: '时间组'
+	},
+	{
+		cardNo: '132',
+		name: '小明',
+		timeGroup: '时间组'
+	},
+	{
+		cardNo: '132',
+		name: '小明',
+		timeGroup: '时间组'
+	},
+	{
+		cardNo: '132',
+		name: '小明',
+		timeGroup: '时间组'
+	},
+	{
+		cardNo: '132',
+		name: '小明',
+		timeGroup: '时间组'
+	}
+])
+
+// 点击每一项删除回调
+const onClickItem = (item) => {
+	uni.showModal({
+		title: '提示',
+		content: `确定把${item.name}移除吗?`,
+		success: (res) => {
+			if (res.confirm) {
+				// handleDeleteReq([item.id])
+			}
+		}
+	})
+}
+
+// 切换时间回调
+const changeTime = (e) => {
+	timeRang.value = e
+	console.log(timeRang.value)
+	if (timeRang.value.length) {
+		console.log(1)
+	} else {
+		console.log(2)
+	}
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	box-sizing: border-box;
+	padding: 30rpx 20rpx;
+	height: 100vh;
+	background: linear-gradient(180deg, rgba(242, 247, 255, 1) 0%, rgba(242, 247, 255, 0) 100%);
+
+	// 背景图片区域样式
+	.img_bg {
+		position: absolute;
+		top: -70rpx;
+		right: 0;
+		width: 589rpx;
+		height: 320rpx;
+		pointer-events: none;
+	}
+
+	.time {
+		display: flex;
+		align-items: center;
+		margin-bottom: 30rpx;
+		height: 70rpx;
+		font-size: 28rpx;
+
+		.time_rang {
+			margin-left: 20rpx;
+			width: 500rpx;
+		}
+	}
+
+	.list {
+		height: calc(100vh - 160rpx);
+		overflow-y: auto;
+
+		.item_box {
+			display: flex;
+			justify-content: space-between;
+			align-items: center;
+			padding: 0 20rpx;
+			height: 167rpx;
+			font-size: 28rpx;
+			border-radius: 8rpx;
+			background-color: #fff;
+
+			.box_info {
+				display: flex;
+
+				.info_img {
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 50%;
+				}
+
+				.info_msg {
+					display: flex;
+					flex-direction: column;
+					justify-content: space-between;
+					margin-left: 28rpx;
+
+					.msg_name {
+						font-size: 32rpx;
+					}
+
+					.msg_no {
+						color: #808080;
+					}
+				}
+			}
+
+			.box_time {
+			}
+		}
+	}
+}
+</style>

+ 257 - 0
pages/register/register.vue

@@ -0,0 +1,257 @@
+<template>
+	<view class="container">
+		<!-- 提示信息区域 -->
+		<view class="header">
+			<view class="header_top">欢迎加入七年级一班!!</view>
+			<view>为确保您的信息顺利通过,请上传有效信息</view>
+		</view>
+
+		<!-- 姓名区域 -->
+		<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				孩子姓名
+			</view>
+			<view class="box_value">
+				<input class="input" type="text" placeholder="请输入孩子姓名" v-model="name" />
+			</view>
+		</view>
+
+		<!-- 性别区域 -->
+		<!-- 	<view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				性别
+			</view>
+			<view class="box_value">
+				<view class="men" @click="handlegender(1)">
+					<radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 1" />
+					男
+				</view>
+
+				<view class="women" @click="handlegender(2)">
+					<radio color="#0061FF" style="transform: scale(0.7)" :checked="gender == 2" />
+					女
+				</view>
+			</view>
+		</view> -->
+
+		<!-- 人脸图片区域 -->
+		<view class="box2">
+			<view class="box_key">
+				<text class="text">*</text>
+				人脸图片
+			</view>
+			<view class="box_upload">
+				<uni-icons type="plusempty" size="30" color="#666666"></uni-icons>
+				上传照片
+			</view>
+		</view>
+		<view class="tips">注:支持.jpg .png,五官清晰无遮挡,大小不超过2M</view>
+
+		<!-- 时间组区域 -->
+		<!-- <view class="box">
+			<view class="box_key">
+				<text class="text">*</text>
+				时间组
+			</view>
+
+			<picker @change="bindPickerChange" :value="currentIndex" :range="array">
+				<view class="box_value" :class="{ unactive: !currentIndex }">
+					{{ currentIndex ? array[currentIndex] : '请选择' }}
+					<image class="value_img" src="/static/images/bottom2.png" mode="aspectFill"></image>
+				</view>
+			</picker>
+		</view> -->
+
+		<view class="box_list">
+			<!-- 家属区域 -->
+			<view class="box">
+				<view class="box_key">
+					<text class="text">*</text>
+					家属
+				</view>
+				<view class="box_value">
+					<input class="input" type="text" placeholder="请输入姓名" />
+					<view class="value_icon">
+						<uni-icons type="plus" size="25" color="#0061FF"></uni-icons>
+					</view>
+				</view>
+			</view>
+
+			<!-- 手机号码区域 -->
+			<view class="box">
+				<view class="box_key">
+					<text class="text">*</text>
+					手机号码
+				</view>
+				<view class="box_value">
+					<input class="input" type="text" placeholder="请输入手机号码" />
+				</view>
+			</view>
+
+			<!-- 家属与本人的关系区域 -->
+			<view class="box">
+				<view class="box_key">
+					<text class="text">*</text>
+					家属与本人的关系
+				</view>
+				<view class="box_value">
+					<input class="input" type="text" placeholder="请输入家属与本人的关系" />
+				</view>
+			</view>
+		</view>
+
+		<view class="btn">确认</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+
+// 姓名
+const name = ref()
+// 性别
+const gender = ref(1)
+// 时间组当前激活索引
+const currentIndex = ref()
+// 时间组数据
+const array = ref(['上午', '下午'])
+// 切换性别回调
+const handlegender = (v) => {
+	gender.value = v
+}
+// 切换时间组回调
+const bindPickerChange = (e) => {
+	currentIndex.value = e.detail.value
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	box-sizing: border-box;
+	padding: 10rpx 0 30rpx 15rpx;
+	height: 100vh;
+	font-size: 28rpx;
+
+	.header {
+		display: flex;
+		flex-direction: column;
+		justify-content: center;
+		padding: 0 20rpx;
+		height: 137rpx;
+		font-size: 24rpx;
+		font-weight: bold;
+		background-color: #f2f7ff;
+
+		.header_top {
+			margin-bottom: 5rpx;
+			font-size: 32rpx;
+		}
+	}
+
+	.box {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		height: 96rpx;
+		border-bottom: 2rpx solid #e6e6e6;
+
+		.box_key {
+			display: flex;
+			align-items: center;
+			font-weight: bold;
+
+			.text {
+				color: #d43030;
+			}
+		}
+
+		.box_value {
+			display: flex;
+			align-items: center;
+			justify-content: flex-end;
+			padding-right: 20rpx;
+			width: 320rpx;
+			height: 96rpx;
+
+			.input {
+				height: 100%;
+				text-align: end;
+			}
+
+			.men,
+			.women {
+				display: flex;
+				align-items: center;
+			}
+
+			.women {
+				margin-left: 20rpx;
+			}
+
+			.value_icon {
+				margin-left: 15rpx;
+			}
+
+			.value_img {
+				margin-left: 20rpx;
+				width: 27rpx;
+				height: 16rpx;
+			}
+		}
+
+		.unactive {
+			color: #6a6a6a;
+		}
+	}
+
+	.box2 {
+		display: flex;
+		margin-top: 40rpx;
+
+		.box_key {
+			display: flex;
+			font-weight: bold;
+
+			.text {
+				color: #d43030;
+			}
+		}
+
+		.box_upload {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			align-items: center;
+			margin-left: 30rpx;
+			width: 160rpx;
+			height: 160rpx;
+			font-size: 24rpx;
+			color: #666666;
+			border-radius: 6rpx;
+			background-color: #f2f2f2;
+		}
+	}
+
+	.tips {
+		margin-top: 20rpx;
+		margin-bottom: 5rpx;
+		font-size: 24rpx;
+		color: #a6a6a6;
+	}
+
+	.btn {
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		margin: 200rpx auto 0;
+		width: 710rpx;
+		height: 100rpx;
+		color: #fff;
+		font-size: 32rpx;
+		border-radius: 8rpx;
+		background-color: #0061ff;
+	}
+}
+</style>

+ 139 - 0
pages/set/set.vue

@@ -0,0 +1,139 @@
+<template>
+	<view class="container">
+		<!-- 学生部门区域 -->
+		<view class="box">
+			<view class="box_key">学生部门</view>
+			<view class="box_input">
+				<uni-data-picker
+					placeholder="请选择部门"
+					popup-title="请选择部门"
+					:map="{ text: 'name', value: 'id' }"
+					:localdata="dataTree_student"
+					v-model="classes_student"
+					@change="onchange_student"
+				></uni-data-picker>
+			</view>
+		</view>
+
+		<!-- 家属部门区域 -->
+		<view class="box">
+			<view class="box_key">家属部门</view>
+			<view class="box_input">
+				<uni-data-picker
+					placeholder="请选择部门"
+					popup-title="请选择部门"
+					:map="{ text: 'name', value: 'id' }"
+					:localdata="dataTree_family"
+					v-model="classes_family"
+					@change="onchange_family"
+				></uni-data-picker>
+			</view>
+		</view>
+
+		<!-- 确认按钮区域 -->
+		<view class="btn" @click="clickBtn">确认</view>
+	</view>
+</template>
+
+<script setup>
+import { ref } from 'vue'
+import { onLoad } from '@dcloudio/uni-app'
+import { myRequest } from '@/utils/api.js'
+
+// 学生部门数组
+const dataTree_student = ref([])
+// 学生部门筛选框绑定数据
+const classes_student = ref()
+
+// 家属部门数组
+const dataTree_family = ref([])
+// 家属部门筛选框绑定数据
+const classes_family = ref()
+
+onLoad(() => {
+	// 获取学生部门数据
+	getData_student()
+
+	// 获取家属部门数据
+	getData_family()
+})
+
+// 获取学生部门数据
+const getData_student = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartDepartment/studentDepartment'
+	})
+	// console.log(res)
+	dataTree_student.value = res.data
+}
+
+// 获取家属部门数据
+const getData_family = async () => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartDepartment/patriarchDepartment'
+	})
+	// console.log(res)
+	dataTree_family.value = res.data
+}
+
+// 学生部门筛选框选择时的回调
+const onchange_student = (e) => {
+	console.log(e.detail.value)
+	console.log(classes_student.value)
+}
+
+// 家属部门筛选框选择时的回调
+const onchange_family = (e) => {
+	console.log(e.detail.value)
+	console.log(classes_family.value)
+}
+
+// 点击确认按钮回调
+const clickBtn = () => {
+	console.log(classes_student.value)
+	console.log(classes_family.value)
+	uni.reLaunch({
+		url: '/pages/studentManage/studentManage'
+	})
+}
+</script>
+
+<style lang="scss" scoped>
+.container {
+	padding: 20rpx;
+
+	.box {
+		display: flex;
+		align-items: center;
+		margin-bottom: 30rpx;
+		height: 80rpx;
+
+		.box_key {
+			width: 120rpx;
+			font-size: 28rpx;
+		}
+
+		.box_input {
+			flex: 1;
+			margin-left: 20rpx;
+			overflow: hidden;
+		}
+	}
+
+	.btn {
+		position: absolute;
+		left: 50%;
+		bottom: 50rpx;
+		transform: translateX(-50%);
+		display: flex;
+		justify-content: center;
+		align-items: center;
+		width: 300rpx;
+		height: 80rpx;
+		font-size: 28rpx;
+		color: #fff;
+		border-radius: 10rpx;
+		background-color: #0061ff;
+	}
+}
+</style>

+ 270 - 31
pages/studentManage/studentManage.vue

@@ -3,19 +3,43 @@
 		<!-- 背景图片区域 -->
 		<img class="img_bg" src="../../static/images/center-bg.png" />
 
-		<!-- input组件区域 -->
-		<HeaderInput placeholder="请输入学生姓名或时间组名称" @changeInputValue="changeInputValue" />
+		<!-- 输入框和设置按钮区域 -->
+		<view class="header">
+			<view class="header_input">
+				<uni-icons type="search" size="28" color="#808080" @click="changeInputValue"></uni-icons>
+				<input v-model="keyWord" class="input" type="text" placeholder="请输入学生姓名" />
+			</view>
+			<view class="header_set" @click="handleClickSet">
+				<uni-icons type="gear" size="28" color="#383838"></uni-icons>
+			</view>
+		</view>
 
-		<!-- 学校年级班级区域 -->
+		<!-- 功能按钮区域 -->
 		<view class="school" v-if="list.length">
-			<view class="">{{ classInfo }}</view>
-			<!-- 批量按钮区域 -->
-			<view v-if="!showEdit" class="school_edit" @click="handleEdit">
-				<img class="img" src="@/static/images/edit.png" />
-				批量
+			<!-- 邀请家长按钮区域 -->
+			<view v-if="!showEdit" class="invite" @click="handleInvitation">
+				<uni-icons type="personadd" size="22" color="#0061FF"></uni-icons>
+				&nbsp;邀请家长
+			</view>
+			<!-- 批量修改按钮区域 -->
+			<view v-if="!showEdit" class="school_edit" @click="handleEdit('修改')">
+				<img class="img" src="@/static/images/edit2.png" />
+				批量修改
+			</view>
+
+			<!-- 添加按钮区域 -->
+			<view v-if="!showEdit" class="add" @click="handleAdd">
+				<uni-icons type="plus" size="22" color="#0061FF"></uni-icons>
+				&nbsp;添加
+			</view>
+
+			<!-- 删除按钮区域 -->
+			<view v-if="!showEdit" class="delete" @click="handleDelete('删除')">
+				<uni-icons type="trash" size="22" color="#D43030"></uni-icons>
+				批量删除
 			</view>
 			<!-- 全选按钮区域 -->
-			<view v-else class="school_btn">
+			<view v-if="showEdit" class="school_btn">
 				<view class="cancel" @click="handleCancel">取消</view>
 
 				<radio color="#0061FF" style="transform: scale(0.7)" :checked="allChecked" @click="handleAllCheck" />
@@ -25,23 +49,48 @@
 
 		<!-- 学生列表区域 -->
 		<view class="list_box" v-if="list.length">
-			<!-- 每一个学生区域 -->
-			<view class="item_box" v-for="(item, index) in list" :key="index" @click="handleClickItem(item)">
-				<view class="box_name">{{ item.name }}({{ item.cardNo }})</view>
-				<view class="box_time">{{ item.timeGroup }}</view>
-
-				<radio v-if="showEdit" color="#0061FF" style="transform: scale(0.7)" :checked="item.isChecked" />
-			</view>
+			<uni-swipe-action>
+				<view v-for="(item, index) in list" :key="index">
+					<uni-swipe-action-item :right-options="options" @click="onClickItem(item)">
+						<!-- 每一个学生区域 -->
+						<view class="item_box" @click="handleClickItem(item)">
+							<view class="box_info">
+								<image class="info_img" src="/static/images/header.png" mode="aspectFill"></image>
+								<view class="info_msg">
+									<view class="msg_name">
+										{{ item.name }}
+									</view>
+									<view class="msg_no">
+										{{ item.cardNo }}
+									</view>
+								</view>
+							</view>
+							<view class="box_time">{{ item.timeGroup }}</view>
+
+							<radio v-if="showEdit" color="#0061FF" style="transform: scale(0.7)" :checked="item.isChecked" />
+						</view>
+					</uni-swipe-action-item>
+					<view style="height: 20rpx"></view>
+				</view>
+			</uni-swipe-action>
 		</view>
 
 		<!-- 关联时间组按钮区域 -->
-		<view class="btn" v-if="showEdit">
+		<view class="btn" v-if="showEdit && currentType == '修改'">
 			<view class="btn_box" @click="handleBind">
 				<uni-icons color="#fff" type="link" size="28"></uni-icons>
 				<text class="text">关联时间组</text>
 			</view>
 		</view>
 
+		<!-- 批量删除区域 -->
+		<view class="btn" v-if="showEdit && currentType == '删除'">
+			<view class="btn_box delete" @click="handleDeleteBatch">
+				<uni-icons color="#fff" type="trash" size="28"></uni-icons>
+				<text class="text">批量删除</text>
+			</view>
+		</view>
+
 		<!-- 没有数据时展示的页面 -->
 		<NoData v-if="!list.length" style="margin-top: 140rpx" />
 
@@ -106,6 +155,17 @@ const studentId = ref()
 // 滚动穿透控制
 const showPage = ref(false)
 
+const options = [
+	{
+		text: '删除',
+		style: {
+			backgroundColor: '#D43030'
+		}
+	}
+]
+
+const currentType = ref('')
+
 onLoad(() => {
 	getData()
 })
@@ -132,14 +192,37 @@ const getData = async () => {
 	})
 }
 
+// 点击邀请家长按钮回调
+const handleInvitation = () => {
+	uni.navigateTo({
+		url: '/pages/invitation/invitation'
+	})
+}
+
 // 点击批量按钮回调
-const handleEdit = () => {
+const handleEdit = (type) => {
+	currentType.value = type
+	showEdit.value = true
+	copyList.value = JSON.parse(JSON.stringify(list.value))
+}
+
+// 点击添加按钮回调
+const handleAdd = () => {
+	uni.navigateTo({
+		url: '/pages/addStudent/addStudent'
+	})
+}
+
+// 批量删除按钮回调
+const handleDelete = (type) => {
+	currentType.value = type
 	showEdit.value = true
 	copyList.value = JSON.parse(JSON.stringify(list.value))
 }
 
 // 点击取消按钮回调
 const handleCancel = () => {
+	currentType.value = ''
 	showEdit.value = false
 	allChecked.value = false
 	list.value = copyList.value
@@ -159,6 +242,43 @@ const handleAllCheck = () => {
 	allChecked.value = !allChecked.value
 }
 
+// 点击每一项删除回调
+const onClickItem = (item) => {
+	uni.showModal({
+		title: '提示',
+		content: `确定把${item.name}移除吗?`,
+		success: (res) => {
+			if (res.confirm) {
+				handleDeleteReq([item.id])
+			}
+		}
+	})
+}
+
+// 删除请求
+const handleDeleteReq = async (ids) => {
+	const res = await myRequest({
+		url: '/wanzai/api/smartUser/appRemoveClass',
+		method: 'post',
+		data: {
+			ids: ids
+		}
+	})
+	// console.log(res)
+	if (res.code == 200) {
+		uni.showToast({
+			title: res.message,
+			icon: 'success'
+		})
+		setTimeout(() => {
+			currentType.value = ''
+			showEdit.value = false
+			allChecked.value = false
+			getData()
+		}, 1500)
+	}
+}
+
 // 点击每一个学生时的回调
 const handleClickItem = (item) => {
 	if (showEdit.value) {
@@ -256,11 +376,47 @@ const handleBind = () => {
 	}
 }
 
+// 批量删除按钮回调
+const handleDeleteBatch = () => {
+	// 判断是否选择了学生
+	const flag = list.value.find((ele) => ele.isChecked)
+
+	if (!flag) {
+		uni.showToast({
+			title: '请至少选择一名学生',
+			icon: 'none',
+			mask: true
+		})
+	} else {
+		uni.showModal({
+			title: '提示',
+			content: '确定批量移除吗?',
+			success: (res) => {
+				if (res.confirm) {
+					let arr = []
+					list.value.forEach((ele) => {
+						if (ele.isChecked) {
+							arr.push(ele.id)
+						}
+					})
+					handleDeleteReq(arr)
+				}
+			}
+		})
+	}
+}
+
 // 输入框组件自定义事件
-const changeInputValue = (value) => {
-	keyWord.value = value
+const changeInputValue = () => {
 	getData()
 }
+
+// 设置图标点击回调
+const handleClickSet = () => {
+	uni.navigateTo({
+		url: '/pages/set/set'
+	})
+}
 </script>
 
 <style lang="scss" scoped>
@@ -281,28 +437,83 @@ const changeInputValue = (value) => {
 		pointer-events: none;
 	}
 
+	.header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		padding-top: 30rpx;
+
+		.header_input {
+			display: flex;
+			align-items: center;
+			box-sizing: border-box;
+			padding-left: 40rpx;
+			width: 589rpx;
+			height: 100rpx;
+			font-size: 28rpx;
+			border-radius: 13rpx;
+			border: 2rpx solid #cccccc;
+			background-color: #fff;
+
+			.input {
+				padding: 0 20rpx;
+				width: 425rpx;
+			}
+		}
+
+		.header_set {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			width: 100rpx;
+			height: 100rpx;
+			border-radius: 13rpx;
+			border: 2rpx solid #cccccc;
+			background-color: #fff;
+		}
+	}
+
 	// 学校名称区域样式
 	.school {
 		display: flex;
-		justify-content: space-between;
+		// justify-content: space-between;
 		align-items: center;
 		margin-top: 38rpx;
 		color: #808080;
 		font-size: 28rpx;
 
-		.school_edit {
+		.invite {
 			display: flex;
 			align-items: center;
 			margin-right: 30rpx;
 			color: #0061ff;
+		}
+
+		.school_edit {
+			display: flex;
+			align-items: center;
+			margin-right: 80rpx;
+			color: #00baad;
 
 			.img {
-				margin-right: 10rpx;
-				width: 30rpx;
-				height: 30rpx;
+				width: 45rpx;
+				height: 45rpx;
 			}
 		}
 
+		.add {
+			display: flex;
+			align-items: center;
+			color: #0061ff;
+		}
+
+		.delete {
+			display: flex;
+			align-items: center;
+			margin-left: auto;
+			color: #d43030;
+		}
+
 		.school_btn {
 			display: flex;
 			align-items: center;
@@ -319,19 +530,43 @@ const changeInputValue = (value) => {
 	}
 
 	.list_box {
-		padding: 0 30rpx 30rpx;
+		padding-bottom: 30rpx;
 		margin-top: 22rpx;
-		background-color: #fff;
+		background-color: #f1f6fe;
 
 		.item_box {
 			display: flex;
 			justify-content: space-between;
 			align-items: center;
-			height: 103rpx;
-			font-size: 24rpx;
-			border-bottom: 1rpx solid #e6e6e6;
+			padding: 0 20rpx;
+			height: 167rpx;
+			font-size: 28rpx;
+			border-radius: 8rpx;
+			background-color: #fff;
+
+			.box_info {
+				display: flex;
+
+				.info_img {
+					width: 100rpx;
+					height: 100rpx;
+					border-radius: 50%;
+				}
 
-			.box_name {
+				.info_msg {
+					display: flex;
+					flex-direction: column;
+					justify-content: space-between;
+					margin-left: 28rpx;
+
+					.msg_name {
+						font-size: 32rpx;
+					}
+
+					.msg_no {
+						color: #808080;
+					}
+				}
 			}
 
 			.box_time {
@@ -361,6 +596,10 @@ const changeInputValue = (value) => {
 				margin-left: 10rpx;
 			}
 		}
+
+		.delete {
+			background-color: #d43030;
+		}
 	}
 
 	.pop_up {

binární
static/images/edit2.png


binární
static/images/time.png


+ 320 - 0
uni_modules/qiun-data-charts/changelog.md

@@ -0,0 +1,320 @@
+## 2.5.0-20230101(2023-01-01)
+- 秋云图表组件 修改条件编译顺序,确保uniapp的cli方式的项目依赖不完整时可以正常显示
+- 秋云图表组件 恢复props属性directory的使用,以修复vue3项目中,开启echarts后,echarts目录识别错误的bug
+- uCharts.js 修复区域图、混合图只有一个数据时图表显示不正确的bug
+- uCharts.js 修复折线图、区域图中时间轴类别图表tooltip指示点显示不正确的bug
+- uCharts.js 修复x轴使用labelCount时,并且boundaryGap = 'justify' 并且关闭Y轴显示的时候,最后一个坐标值不显示的bug
+- uCharts.js 修复折线图只有一组数据时 ios16 渲染颜色不正确的bug
+- uCharts.js 修复玫瑰图半径显示不正确的bug
+- uCharts.js 柱状图、山峰图增加正负图功能,y轴网格如果需要显示0轴则由 min max 及 splitNumber 确定,后续版本优化自动显示0轴
+- uCharts.js 柱状图column增加 opts.extra.column.labelPosition,数据标签位置,有效值为 outside外部, insideTop内顶部, center内中间, bottom内底部
+- uCharts.js 雷达图radar增加 opts.extra.radar.labelShow,否显示各项标识文案是,默认true
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.boxPadding,提示窗边框填充距离,默认3px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.fontSize,提示窗字体大小配置,默认13px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.lineHeight,提示窗文字行高,默认20px
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShow,是否显示左侧图例,默认true
+- uCharts.js 提示窗tooltip增加 opts.extra.tooltip.legendShape,图例形状,图例标识样式,有效值为 auto自动跟随图例, diamond◆, circle●, triangle▲, square■, rect▬, line-
+- uCharts.js 标记线markLine增加 opts.extra.markLine.labelFontSize,字体大小配置,默认13px
+- uCharts.js 标记线markLine增加 opts.extra.markLine.labelPadding,标签边框内填充距离,默认6px
+- uCharts.js 折线图line增加 opts.extra.line.linearType,渐变色类型,可选值 none关闭渐变色,custom 自定义渐变色。使用自定义渐变色时请赋值serie.linearColor作为颜色值
+- uCharts.js 折线图line增加 serie.linearColor,渐变色数组,格式为2维数组[起始位置,颜色值],例如[[0,'#0EE2F8'],[0.3,'#2BDCA8'],[0.6,'#1890FF'],[1,'#9A60B4']]
+- uCharts.js 折线图line增加 opts.extra.line.onShadow,是否开启折线阴影,开启后请赋值serie.setShadow阴影设置
+- uCharts.js 折线图line增加 serie.setShadow,阴影配置,格式为4位数组:[offsetX,offsetY,blur,color]
+- uCharts.js 折线图line增加 opts.extra.line.animation,动画效果方向,可选值为vertical 垂直动画效果,horizontal 水平动画效果
+- uCharts.js X轴xAxis增加 opts.xAxis.lineHeight,X轴字体行高,默认20px
+- uCharts.js X轴xAxis增加 opts.xAxis.marginTop,X轴文字距离轴线的距离,默认0px
+- uCharts.js X轴xAxis增加 opts.xAxis.title,当前X轴标题
+- uCharts.js X轴xAxis增加 opts.xAxis.titleFontSize,标题字体大小,默认13px
+- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetY,标题纵向偏移距离,负数为向上偏移,正数向下偏移
+- uCharts.js X轴xAxis增加 opts.xAxis.titleOffsetX,标题横向偏移距离,负数为向左偏移,正数向右偏移
+- uCharts.js X轴xAxis增加 opts.xAxis.titleFontColor,标题字体颜色,默认#666666
+
+## 报错TypeError: Cannot read properties of undefined (reading 'length')
+- 如果是uni-modules版本组件,请先登录HBuilderX账号;
+- 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
+- 如果是cli项目请使用码云上的非uniCloud版本组件;
+- 或者添加uniCloud的依赖;
+- 或者使用原生uCharts;
+## 2.4.5-20221130(2022-11-30)
+- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
+- uCharts.js 折线图修复特殊情况下只有单点数据,并改变线宽后点变为圆形的bug
+- uCharts.js 修复Y轴disabled启用后无效并报错的bug
+- uCharts.js 修复仪表盘起始结束角度特殊情况下显示不正确的bug
+- uCharts.js 雷达图新增参数 opts.extra.radar.radius , 自定义雷达图半径
+- uCharts.js 折线图、区域图增加tooltip指示点,opts.extra.line.activeType/opts.extra.area.activeType,可选值"none"不启用激活指示点,"hollow"空心点模式,"solid"实心点模式
+## 2.4.4-20221102(2022-11-02)
+- 秋云图表组件 修复使用echarts时reload、reshow无法调用重新渲染的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/40)
+- 秋云图表组件 修复使用echarts时,初始化时宽高不正确的bug,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/42)
+- 秋云图表组件 修复uniapp的h5使用history模式时,无法加载echarts的bug
+- 秋云图表组件 小程序端@complete、@scrollLeft、@scrollRight、@getTouchStart、@getTouchMove、@getTouchEnd事件增加opts参数传出,方便一些特殊需求的交互获取数据。
+
+- uCharts.js 修复calTooltipYAxisData方法内formatter格式化方法未与y轴方法同步的问题,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/43)
+- uCharts.js 地图新增参数opts.series[i].fillOpacity,以透明度方式来设置颜色过度效果,[详见码云PR](https://gitee.com/uCharts/uCharts/pulls/38)
+- uCharts.js 地图新增参数opts.extra.map.active,是否启用点击激活变色
+- uCharts.js 地图新增参数opts.extra.map.activeTextColor,是否启用点击激活变色
+- uCharts.js 地图新增渲染完成事件renderComplete
+- uCharts.js 漏斗图修复当部分数据相同时tooltip提示窗点击错误的bug
+- uCharts.js 漏斗图新增参数series.data[i].centerText 居中标签文案
+- uCharts.js 漏斗图新增参数series.data[i].centerTextSize 居中标签文案字体大小,默认opts.fontSize
+- uCharts.js 漏斗图新增参数series.data[i].centerTextColor 居中标签文案字体颜色,默认#FFFFFF
+- uCharts.js 漏斗图新增参数opts.extra.funnel.minSize 最小值的最小宽度,默认0
+- uCharts.js 进度条新增参数opts.extra.arcbar.direction,动画方向,可选值为cw顺时针、ccw逆时针
+- uCharts.js 混合图新增参数opts.extra.mix.line.width,折线的宽度,默认2
+- uCharts.js 修复tooltip开启horizentalLine水平横线标注时,图表显示错位的bug
+- uCharts.js 优化tooltip当文字很多变为左侧显示时,如果画布仍显显示不下,提示框错位置变为以左侧0位置起画
+- uCharts.js 修复开启滚动条后X轴文字超出绘图区域后的隐藏逻辑
+- uCharts.js 柱状图、条状图修复堆叠模式不能通过{value,color}赋值单个柱子颜色的问题
+- uCharts.js 气泡图修复不识别series.textSize和series.textColor的bug
+
+## 报错TypeError: Cannot read properties of undefined (reading 'length')
+1. 如果是uni-modules版本组件,请先登录HBuilderX账号;
+2. 在HBuilderX中的manifest.json,点击重新获取uniapp的appid,或者删除appid重新粘贴,重新运行;
+3. 如果是cli项目请使用码云上的非uniCloud版本组件;
+4. 或者添加uniCloud的依赖;
+5. 或者使用原生uCharts;
+## 2.4.3-20220505(2022-05-05)
+- 秋云图表组件 修复开启canvas2d后将series赋值为空数组显示加载图标时,再次赋值后画布闪动的bug
+- 秋云图表组件 修复升级hbx最新版后ECharts的highlight方法报错的bug
+- uCharts.js 雷达图新增参数opts.extra.radar.gridEval,数据点位网格抽希,默认1
+- uCharts.js 雷达图新增参数opts.extra.radar.axisLabel,	是否显示刻度点值,默认false
+- uCharts.js 雷达图新增参数opts.extra.radar.axisLabelTofix,刻度点值小数位数,默认0
+- uCharts.js 雷达图新增参数opts.extra.radar.labelPointShow,是否显示末端刻度圆点,默认false
+- uCharts.js 雷达图新增参数opts.extra.radar.labelPointRadius,刻度圆点的半径,默认3
+- uCharts.js 雷达图新增参数opts.extra.radar.labelPointColor,刻度圆点的颜色,默认#cccccc
+- uCharts.js 雷达图新增参数opts.extra.radar.linearType,渐变色类型,可选值"none"关闭渐变,"custom"开启渐变
+- uCharts.js 雷达图新增参数opts.extra.radar.customColor,自定义渐变颜色,数组类型对应series的数组长度以匹配不同series颜色的不同配色方案,例如["#FA7D8D", "#EB88E2"]
+- uCharts.js 雷达图优化支持series.textColor、series.textSize属性
+- uCharts.js 柱状图中温度计式图标,优化支持全圆角类型,修复边框有缝隙的bug,详见官网【演示】中的温度计图表
+- uCharts.js 柱状图新增参数opts.extra.column.activeWidth,当前点击柱状图的背景宽度,默认一个单元格单位
+- uCharts.js 混合图增加opts.extra.mix.area.gradient 区域图是否开启渐变色
+- uCharts.js 混合图增加opts.extra.mix.area.opacity 区域图透明度,默认0.2
+- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelText,自定义标签文字,避免formatter格式化的繁琐,详见官网【演示】中的饼图
+- uCharts.js 饼图、圆环图、玫瑰图、漏斗图,增加opts.series[0].data[i].labelShow,自定义是否显示某一个指示标签,避免因饼图类别太多导致标签重复或者居多导致图形变形的问题,详见官网【演示】中的饼图
+- uCharts.js 增加opts.series[i].legendText/opts.series[0].data[i].legendText(与series.name同级)自定义图例显示文字的方法
+- uCharts.js 优化X轴、Y轴formatter格式化方法增加形参,统一为fromatter:function(value,index,opts){}
+- uCharts.js 修复横屏模式下无法使用双指缩放方法的bug
+- uCharts.js 修复当只有一条数据或者多条数据值相等的时候Y轴自动计算的最大值错误的bug
+- 【官网模板】增加外部自定义图例与图表交互的例子,[点击跳转](https://www.ucharts.cn/v2/#/layout/info?id=2)
+
+## 注意:非unimodules 版本如因更新 hbx 至 3.4.7 导致报错如下,请到码云更新非 unimodules 版本组件,[点击跳转](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6)
+> Error in callback for immediate watcher "uchartsOpts": "SyntaxError: Unexpected token u in JSON at position 0"
+## 2.4.2-20220421(2022-04-21)
+- 秋云图表组件 修复HBX升级3.4.6.20220420版本后echarts报错的问题
+## 2.4.2-20220420(2022-04-20)
+## 重要!此版本uCharts新增了很多功能,修复了诸多已知问题
+- 秋云图表组件 新增onzoom开启双指缩放功能(仅uCharts),前提需要直角坐标系类图表类型,并且ontouch为true、opts.enableScroll为true,详见实例项目K线图
+- 秋云图表组件 新增optsWatch是否监听opts变化,关闭optsWatch后,动态修改opts不会触发图表重绘
+- 秋云图表组件 修复开启canvas2d功能后,动态更新数据后画布闪动的bug
+- 秋云图表组件 去除directory属性,改为自动获取echarts.min.js路径(升级不受影响)
+- 秋云图表组件 增加getImage()方法及@getImage事件,通过ref调用getImage()方法获,触发@getImage事件获取当前画布的base64图片文件流。
+- 秋云图表组件 支付宝、字节跳动、飞书、快手小程序支持开启canvas2d同层渲染设置。
+- 秋云图表组件 新增加【非uniCloud】版本组件,避免有些不需要uniCloud的使用组件发布至小程序需要提交隐私声明问题,请到码云[【非uniCloud版本】](https://gitee.com/uCharts/uCharts/tree/master/uni-app/uCharts-%E7%BB%84%E4%BB%B6),或npm[【非uniCloud版本】](https://www.npmjs.com/package/@qiun/uni-ucharts)下载使用。
+- uCharts.js 新增dobuleZoom双指缩放功能
+- uCharts.js 新增山峰图type="mount",数据格式为饼图类格式,不需要传入categories,具体详见新版官网在线演示
+- uCharts.js 修复折线图当数据中存在null时tooltip报错的bug
+- uCharts.js 修复饼图类当画布比较小时自动计算的半径是负数报错的bug
+- uCharts.js 统一各图表类型的series.formatter格式化方法的形参为(val, index, series, opts),方便格式化时有更多参数可用
+- uCharts.js 标记线功能增加labelText自定义显示文字,增加labelAlign标签显示位置(左侧或右侧),增加标签显示位置微调labelOffsetX、labelOffsetY
+- uCharts.js 修复条状图当数值很小时开启圆角后样式错误的bug
+- uCharts.js 修复X轴开启disabled后,X轴仍占用空间的bug
+- uCharts.js 修复X轴开启滚动条并且开启rotateLabel后,X轴文字与滚动条重叠的bug
+- uCharts.js 增加X轴rotateAngle文字旋转自定义角度,取值范围(-90至90)
+- uCharts.js 修复地图文字标签层级显示不正确的bug
+- uCharts.js 修复饼图、圆环图、玫瑰图当数据全部为0的时候不显示数据标签的bug
+- uCharts.js 修复当opts.padding上边距为0时,Y轴顶部刻度标签位置不正确的bug
+
+## 另外我们还开发了各大原生小程序组件,已发布至码云和npm
+[https://gitee.com/uCharts/uCharts](https://gitee.com/uCharts/uCharts)
+[https://www.npmjs.com/~qiun](https://www.npmjs.com/~qiun)
+
+## 对于原生uCharts文档我们已上线新版官方网站,详情点击下面链接进入官网
+[https://www.uCharts.cn/v2/](https://www.ucharts.cn/v2/)
+## 2.3.7-20220122(2022-01-22)
+## 重要!使用vue3编译,请使用cli模式并升级至最新依赖,HbuilderX编译需要使用3.3.8以上版本
+- uCharts.js 修复uni-app平台组件模式使用vue3编译到小程序报错的bug。
+## 2.3.7-20220118(2022-01-18)
+## 注意,使用vue3的前提是需要3.3.8.20220114-alpha版本的HBuilder!
+## 2.3.67-20220118(2022-01-18)
+- 秋云图表组件 组件初步支持vue3,全端编译会有些问题,具体详见下面修改:
+1. 小程序端运行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new uni_modules_qiunDataCharts_js_sdk_uCharts_uCharts.uCharts,将.uCharts去掉。
+2. 小程序端发行时,在uni_modules文件夹的qiun-data-charts.js中搜索 new e.uCharts,将.uCharts去掉,变为 new e。
+3. 如果觉得上述步骤比较麻烦,如果您的项目只编译到小程序端,可以修改u-charts.js最后一行导出方式,将 export default uCharts;变更为 export default { uCharts: uCharts }; 这样变更后,H5和App端的renderjs会有问题,请开发者自行选择。(此问题非组件问题,请等待DC官方修复Vue3的小程序端)
+## 2.3.6-20220111(2022-01-11)
+- 秋云图表组件 修改组件 props 属性中的 background 默认值为 rgba(0,0,0,0)
+## 2.3.6-20211201(2021-12-01)
+- uCharts.js 修复bar条状图开启圆角模式时,值很小时圆角渲染错误的bug
+## 2.3.5-20211014(2021-10-15)
+- uCharts.js 增加vue3的编译支持(仅原生uCharts,qiun-data-charts组件后续会支持,请关注更新)
+## 2.3.4-20211012(2021-10-12)
+- 秋云图表组件 修复 mac os x 系统 mouseover 事件丢失的 bug
+## 2.3.3-20210706(2021-07-06)
+- uCharts.js 增加雷达图开启数据点值(opts.dataLabel)的显示
+## 2.3.2-20210627(2021-06-27)
+- 秋云图表组件 修复tooltipCustom个别情况下传值不正确报错TypeError: Cannot read property 'name' of undefined的bug
+## 2.3.1-20210616(2021-06-16)
+- uCharts.js 修复圆角柱状图使用4角圆角时,当数值过大时不正确的bug
+## 2.3.0-20210612(2021-06-12)
+- uCharts.js 【重要】uCharts增加nvue兼容,可在nvue项目中使用gcanvas组件渲染uCharts,[详见码云uCharts-demo-nvue](https://gitee.com/uCharts/uCharts)
+- 秋云图表组件 增加tapLegend属性,是否开启图例点击交互事件
+- 秋云图表组件 getIndex事件中增加返回uCharts实例中的opts参数,以便在页面中调用参数
+- 示例项目 pages/other/other.vue增加app端自定义tooltip的方法,详见showOptsTooltip方法
+## 2.2.1-20210603(2021-06-03)
+- uCharts.js 修复饼图、圆环图、玫瑰图,当起始角度不为0时,tooltip位置不准确的bug
+- uCharts.js 增加温度计式柱状图开启顶部半圆形的配置
+## 2.2.0-20210529(2021-05-29)
+- uCharts.js 增加条状图type="bar"
+- 示例项目 pages/ucharts/ucharts.vue增加条状图的demo
+## 2.1.7-20210524(2021-05-24)
+- uCharts.js 修复大数据量模式下曲线图不平滑的bug
+## 2.1.6-20210523(2021-05-23)
+- 秋云图表组件 修复小程序端开启滚动条更新数据后滚动条位置不符合预期的bug
+## 2.1.5-2021051702(2021-05-17)
+- uCharts.js 修复自定义Y轴min和max值为0时不能正确显示的bug
+## 2.1.5-20210517(2021-05-17)
+- uCharts.js 修复Y轴自定义min和max时,未按指定的最大值最小值显示坐标轴刻度的bug
+## 2.1.4-20210516(2021-05-16)
+- 秋云图表组件 优化onWindowResize防抖方法
+- 秋云图表组件 修复APP端uCharts更新数据时,清空series显示loading图标后再显示图表,图表抖动的bug
+- uCharts.js 修复开启canvas2d后,x轴、y轴、series自定义字体大小未按比例缩放的bug
+- 示例项目 修复format-e.vue拼写错误导致app端使用uCharts渲染图表
+## 2.1.3-20210513(2021-05-13)
+- 秋云图表组件 修改uCharts变更chartData数据为updateData方法,支持带滚动条的数据动态打点
+- 秋云图表组件 增加onWindowResize防抖方法 fix by ど誓言,如尘般染指流年づ 
+- 秋云图表组件 H5或者APP变更chartData数据显示loading图表时,原数据闪现的bug
+- 秋云图表组件 props增加errorReload禁用错误点击重新加载的方法
+- uCharts.js 增加tooltip显示category(x轴对应点位)标题的功能,opts.extra.tooltip.showCategory,默认为false
+- uCharts.js 修复mix混合图只有柱状图时,tooltip的分割线显示位置不正确的bug
+- uCharts.js 修复开启滚动条,图表在拖动中动态打点,滚动条位置不正确的bug
+- uCharts.js 修复饼图类数据格式为echarts数据格式,series为空数组报错的bug
+- 示例项目 修改uCharts.js更新到v2.1.2版本后,@getIndex方法获取索引值变更为e.currentIndex.index
+- 示例项目 pages/updata/updata.vue增加滚动条拖动更新(数据动态打点)的demo
+- 示例项目 pages/other/other.vue增加errorReload禁用错误点击重新加载的demo
+## 2.1.2-20210509(2021-05-09)
+秋云图表组件 修复APP端初始化时就传入chartData或lacaldata不显示图表的bug
+## 2.1.1-20210509(2021-05-09)
+- 秋云图表组件 变更ECharts的eopts配置在renderjs内执行,支持在config-echarts.js配置文件内写function配置。
+- 秋云图表组件 修复APP端报错Prop being mutated: "onmouse"错误的bug。
+- 秋云图表组件 修复APP端报错Error: Not Found:Page[6][-1,27] at view.umd.min.js:1的bug。
+## 2.1.0-20210507(2021-05-07)
+- 秋云图表组件 修复初始化时就有数据或者数据更新的时候loading加载动画闪动的bug
+- uCharts.js 修复x轴format方法categories为字符串类型时返回NaN的bug
+- uCharts.js 修复series.textColor、legend.fontColor未执行全局默认颜色的bug
+## 2.1.0-20210506(2021-05-06)
+- 秋云图表组件 修复极个别情况下报错item.properties undefined的bug
+- 秋云图表组件 修复极个别情况下关闭加载动画reshow不起作用,无法显示图表的bug
+- 示例项目 pages/ucharts/ucharts.vue 增加时间轴折线图(type="tline")、时间轴区域图(type="tarea")、散点图(type="scatter")、气泡图demo(type="bubble")、倒三角形漏斗图(opts.extra.funnel.type="triangle")、金字塔形漏斗图(opts.extra.funnel.type="pyramid")
+- 示例项目 pages/format-u/format-u.vue 增加X轴format格式化示例
+- uCharts.js 升级至v2.1.0版本
+- uCharts.js 修复 玫瑰图面积模式点击tooltip位置不正确的bug
+- uCharts.js 修复 玫瑰图点击图例,只剩一个类别显示空白的bug
+- uCharts.js 修复 饼图类图点击图例,其他图表tooltip位置某些情况下不准的bug
+- uCharts.js 修复 x轴为矢量轴(时间轴)情况下,点击tooltip位置不正确的bug
+- uCharts.js 修复 词云图获取点击索引偶尔不准的bug
+- uCharts.js 增加 直角坐标系图表X轴format格式化方法(原生uCharts.js用法请使用formatter)
+- uCharts.js 增加 漏斗图扩展配置,倒三角形(opts.extra.funnel.type="triangle"),金字塔形(opts.extra.funnel.type="pyramid")
+- uCharts.js 增加 散点图(opts.type="scatter")、气泡图(opts.type="bubble")
+- 后期计划 完善散点图、气泡图,增加markPoints标记点,增加横向条状图。
+## 2.0.0-20210502(2021-05-02)
+- uCharts.js 修复词云图获取点击索引不正确的bug
+## 2.0.0-20210501(2021-05-01)
+- 秋云图表组件 修复QQ小程序、百度小程序在关闭动画效果情况下,v-for循环使用图表,显示不正确的bug
+## 2.0.0-20210426(2021-04-26)
+- 秋云图表组件 修复QQ小程序不支持canvas2d的bug
+- 秋云图表组件 修复钉钉小程序某些情况点击坐标计算错误的bug
+- uCharts.js 增加 extra.column.categoryGap 参数,柱状图类每个category点位(X轴点)柱子组之间的间距
+- uCharts.js 增加 yAxis.data[i].titleOffsetY 参数,标题纵向偏移距离,负数为向上偏移,正数向下偏移
+- uCharts.js 增加 yAxis.data[i].titleOffsetX 参数,标题横向偏移距离,负数为向左偏移,正数向右偏移
+- uCharts.js 增加 extra.gauge.labelOffset 参数,仪表盘标签文字径向便宜距离,默认13px
+## 2.0.0-20210422-2(2021-04-22)
+秋云图表组件 修复 formatterAssign 未判断 args[key] == null 的情况导致栈溢出的 bug
+## 2.0.0-20210422(2021-04-22)
+- 秋云图表组件 修复H5、APP、支付宝小程序、微信小程序canvas2d模式下横屏模式的bug
+## 2.0.0-20210421(2021-04-21)
+- uCharts.js 修复多行图例的情况下,图例在上方或者下方时,图例float为左侧或者右侧时,第二行及以后的图例对齐方式不正确的bug
+## 2.0.0-20210420(2021-04-20)
+- 秋云图表组件 修复微信小程序开启canvas2d模式后,windows版微信小程序不支持canvas2d模式的bug
+- 秋云图表组件 修改非uni_modules版本为v2.0版本qiun-data-charts组件
+## 2.0.0-20210419(2021-04-19)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 修复混合图中柱状图单独设置颜色不生效的bug
+- uCharts.js 修复多Y轴单独设置fontSize时,开启canvas2d后,未对应放大字体的bug
+## 2.0.0-20210418(2021-04-18)
+- 秋云图表组件 增加directory配置,修复H5端history模式下如果发布到二级目录无法正确加载echarts.min.js的bug
+## 2.0.0-20210416(2021-04-16)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复APP端某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
+- 示例项目 修复APP端v-for循环某些情况下报错`Not Found Page`的bug,fix by 高级bug开发技术员
+- uCharts.js 修复非直角坐标系tooltip提示窗右侧超出未变换方向显示的bug
+## 2.0.0-20210415(2021-04-15)
+- 秋云图表组件 修复H5端发布到二级目录下echarts无法加载的bug
+- 秋云图表组件 修复某些情况下echarts.off('finished')移除监听事件报错的bug
+## 2.0.0-20210414(2021-04-14)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX,如仍不好用,请重启电脑;
+## 如果是cli项目,请尝试清理node_modules,重新install,还不行就删除项目,再重新install。
+## 此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## 其他图表不显示问题详见[常见问题选项卡](https://demo.ucharts.cn)
+## <font color=#FF0000> 新手请先完整阅读帮助文档及常见问题3遍,右侧蓝色按钮示例项目请看2遍! </font> 
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在项目中的应用参见 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复H5端在cli项目下ECharts引用地址错误的bug
+- 示例项目 增加ECharts的formatter用法的示例(详见示例项目format-e.vue)
+- uCharts.js 增加圆环图中心背景色的配置extra.ring.centerColor
+- uCharts.js 修复微信小程序安卓端柱状图开启透明色后显示不正确的bug
+## 2.0.0-20210413(2021-04-13)
+- 秋云图表组件 修复百度小程序多个图表真机未能正确获取根元素dom尺寸的bug
+- 秋云图表组件 修复百度小程序横屏模式方向不正确的bug
+- 秋云图表组件 修改ontouch时,@getTouchStart@getTouchMove@getTouchEnd的触发条件
+- uCharts.js 修复饼图类数据格式series属性不生效的bug
+- uCharts.js 增加时序区域图 详见示例项目中ucharts.vue
+## 2.0.0-20210412-2(2021-04-12)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册&lt;qiun-data-charts&gt;组件,请重启HBuilderX。如仍不好用,请重启电脑,此问题已于DCloud官方确认,HBuilderX下个版本会修复。
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- 秋云图表组件 修复uCharts在APP端横屏模式下不能正确渲染的bug
+- 示例项目 增加ECharts柱状图渐变色、圆角柱状图、横向柱状图(条状图)的示例
+## 2.0.0-20210412(2021-04-12)
+- 秋云图表组件 修复created中判断echarts导致APP端无法识别,改回mounted中判断echarts初始化
+- uCharts.js 修复2d模式下series.textOffset未乘像素比的bug
+## 2.0.0-20210411(2021-04-11)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧绿色【使用HBuilderX导入插件】即可使用,示例项目请点击右侧蓝色按钮【使用HBuilderX导入示例项目】。
+## 初次使用如果提示未注册<qiun-data-charts>组件,请重启HBuilderX,并清空小程序开发者工具缓存。
+## [DEMO演示及在线生成工具(v2.0文档)https://demo.ucharts.cn](https://demo.ucharts.cn)
+## [图表组件在uniCloudAdmin中的应用 UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 折线图区域图增加connectNulls断点续连的功能,详见示例项目中ucharts.vue
+- 秋云图表组件 变更初始化方法为created,变更type2d默认值为true,优化2d模式下组件初始化后dom获取不到的bug
+- 秋云图表组件 修复左右布局时,右侧图表点击坐标错误的bug,修复tooltip柱状图自定义颜色显示object的bug
+## 2.0.0-20210410(2021-04-10)
+- 修复左右布局时,右侧图表点击坐标错误的bug,修复柱状图自定义颜色tooltip显示object的bug
+- 增加标记线及柱状图自定义颜色的demo
+## 2.0.0-20210409(2021-04-08)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
+## 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+- uCharts.js 修复钉钉小程序百度小程序measureText不准确的bug,修复2d模式下饼图类activeRadius为按比例放大的bug
+- 修复组件在支付宝小程序端点击位置不准确的bug
+## 2.0.0-20210408(2021-04-07)
+- 修复组件在支付宝小程序端不能显示的bug(目前支付宝小程不能点击交互,后续修复)
+- uCharts.js 修复高分屏下柱状图类,圆弧进度条 自定义宽度不能按比例放大的bug
+## 2.0.0-20210407(2021-04-06)
+## v1.0版本已停更,建议转uni_modules版本组件方式调用,点击右侧【使用HBuilderX导入插件】即可体验,DEMO演示及在线生成工具(v2.0文档)[https://demo.ucharts.cn](https://demo.ucharts.cn)
+## 增加 通过tofix和unit快速格式化y轴的demo add by `howcode`
+## 增加 图表组件在uniCloudAdmin中的应用 [UReport数据报表](https://ext.dcloud.net.cn/plugin?id=4651) 
+## 2.0.0-20210406(2021-04-05)
+# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页
+## 2.0.0(2021-04-05)
+# 秋云图表组件+uCharts v2.0版本同步上线,使用方法详见https://demo.ucharts.cn帮助页

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 1618 - 0
uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 46 - 0
uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue


+ 162 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue

@@ -0,0 +1,162 @@
+<template>
+	 <view class="container loading1">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading1',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+.container.loading1 {
+  -webkit-transform: rotate(45deg);
+          transform: rotate(45deg);
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading1 .shape1 {
+  -webkit-animation: animation1shape1 0.5s ease 0s infinite alternate;
+          animation: animation1shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, 16px);
+            transform: translate(16px, 16px);
+  }
+}
+
+@keyframes animation1shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, 16px);
+            transform: translate(16px, 16px);
+  }
+}
+.loading1 .shape2 {
+  -webkit-animation: animation1shape2 0.5s ease 0s infinite alternate;
+          animation: animation1shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, 16px);
+            transform: translate(-16px, 16px);
+  }
+}
+
+@keyframes animation1shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, 16px);
+            transform: translate(-16px, 16px);
+  }
+}
+.loading1 .shape3 {
+  -webkit-animation: animation1shape3 0.5s ease 0s infinite alternate;
+          animation: animation1shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, -16px);
+            transform: translate(16px, -16px);
+  }
+}
+
+@keyframes animation1shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(16px, -16px);
+            transform: translate(16px, -16px);
+  }
+}
+.loading1 .shape4 {
+  -webkit-animation: animation1shape4 0.5s ease 0s infinite alternate;
+          animation: animation1shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation1shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, -16px);
+            transform: translate(-16px, -16px);
+  }
+}
+
+@keyframes animation1shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-16px, -16px);
+            transform: translate(-16px, -16px);
+  }
+}
+
+
+</style>

+ 170 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue

@@ -0,0 +1,170 @@
+<template>
+	 <view class="container loading2">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading2',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading2 {
+  -webkit-transform: rotate(10deg);
+          transform: rotate(10deg);
+}
+.container.loading2 .shape {
+  border-radius: 5px;
+}
+.container.loading2{
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+
+.loading2 .shape1 {
+  -webkit-animation: animation2shape1 0.5s ease 0s infinite alternate;
+          animation: animation2shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, 20px);
+            transform: translate(20px, 20px);
+  }
+}
+
+@keyframes animation2shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, 20px);
+            transform: translate(20px, 20px);
+  }
+}
+.loading2 .shape2 {
+  -webkit-animation: animation2shape2 0.5s ease 0s infinite alternate;
+          animation: animation2shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, 20px);
+            transform: translate(-20px, 20px);
+  }
+}
+
+@keyframes animation2shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, 20px);
+            transform: translate(-20px, 20px);
+  }
+}
+.loading2 .shape3 {
+  -webkit-animation: animation2shape3 0.5s ease 0s infinite alternate;
+          animation: animation2shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, -20px);
+            transform: translate(20px, -20px);
+  }
+}
+
+@keyframes animation2shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(20px, -20px);
+            transform: translate(20px, -20px);
+  }
+}
+.loading2 .shape4 {
+  -webkit-animation: animation2shape4 0.5s ease 0s infinite alternate;
+          animation: animation2shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation2shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, -20px);
+            transform: translate(-20px, -20px);
+  }
+}
+
+@keyframes animation2shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-20px, -20px);
+            transform: translate(-20px, -20px);
+  }
+}
+
+</style>

+ 173 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue

@@ -0,0 +1,173 @@
+<template>
+	 <view class="container loading3">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading3',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+ .container.loading3 {
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+.container.loading3 .shape1 {
+  border-top-left-radius: 10px;
+}
+.container.loading3 .shape2 {
+  border-top-right-radius: 10px;
+}
+.container.loading3 .shape3 {
+  border-bottom-left-radius: 10px;
+}
+.container.loading3 .shape4 {
+  border-bottom-right-radius: 10px;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading3 .shape1 {
+  -webkit-animation: animation3shape1 0.5s ease 0s infinite alternate;
+          animation: animation3shape1 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, 5px);
+            transform: translate(5px, 5px);
+  }
+}
+
+@keyframes animation3shape1 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, 5px);
+            transform: translate(5px, 5px);
+  }
+}
+.loading3 .shape2 {
+  -webkit-animation: animation3shape2 0.5s ease 0s infinite alternate;
+          animation: animation3shape2 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, 5px);
+            transform: translate(-5px, 5px);
+  }
+}
+
+@keyframes animation3shape2 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, 5px);
+            transform: translate(-5px, 5px);
+  }
+}
+.loading3 .shape3 {
+  -webkit-animation: animation3shape3 0.5s ease 0s infinite alternate;
+          animation: animation3shape3 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, -5px);
+            transform: translate(5px, -5px);
+  }
+}
+
+@keyframes animation3shape3 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(5px, -5px);
+            transform: translate(5px, -5px);
+  }
+}
+.loading3 .shape4 {
+  -webkit-animation: animation3shape4 0.5s ease 0s infinite alternate;
+          animation: animation3shape4 0.5s ease 0s infinite alternate;
+}
+
+@-webkit-keyframes animation3shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, -5px);
+            transform: translate(-5px, -5px);
+  }
+}
+
+@keyframes animation3shape4 {
+  from {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  to {
+    -webkit-transform: translate(-5px, -5px);
+            transform: translate(-5px, -5px);
+  }
+}
+</style>

+ 222 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue

@@ -0,0 +1,222 @@
+<template>
+	 <view class="container loading5">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading5',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading5 .shape {
+  width: 15px;
+  height: 15px;
+}
+
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+.loading5 .shape1 {
+  animation: animation5shape1 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+  50% {
+    -webkit-transform: translate(15px, 15px);
+            transform: translate(15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+}
+
+@keyframes animation5shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+  50% {
+    -webkit-transform: translate(15px, 15px);
+            transform: translate(15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+}
+.loading5 .shape2 {
+  animation: animation5shape2 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-15px, 15px);
+            transform: translate(-15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+}
+
+@keyframes animation5shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-15px, 15px);
+            transform: translate(-15px, 15px);
+  }
+  75% {
+    -webkit-transform: translate(0, 15px);
+            transform: translate(0, 15px);
+  }
+}
+.loading5 .shape3 {
+  animation: animation5shape3 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(15px, -15px);
+            transform: translate(15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+}
+
+@keyframes animation5shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(15px, 0);
+            transform: translate(15px, 0);
+  }
+  50% {
+    -webkit-transform: translate(15px, -15px);
+            transform: translate(15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+}
+.loading5 .shape4 {
+  animation: animation5shape4 2s ease 0s infinite reverse;
+}
+
+@-webkit-keyframes animation5shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+  50% {
+    -webkit-transform: translate(-15px, -15px);
+            transform: translate(-15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+}
+
+@keyframes animation5shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -15px);
+            transform: translate(0, -15px);
+  }
+  50% {
+    -webkit-transform: translate(-15px, -15px);
+            transform: translate(-15px, -15px);
+  }
+  75% {
+    -webkit-transform: translate(-15px, 0);
+            transform: translate(-15px, 0);
+  }
+}
+
+</style>

+ 229 - 0
uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue

@@ -0,0 +1,229 @@
+<template>
+	 <view class="container loading6">
+		<view class="shape shape1"></view>
+		<view class="shape shape2"></view>
+		<view class="shape shape3"></view>
+		<view class="shape shape4"></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: 'loading6',
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+<style scoped="true">
+.container {
+  width: 30px;
+  height: 30px;
+  position: relative;
+}
+
+.container.loading6 {
+  -webkit-animation: rotation 1s infinite;
+          animation: rotation 1s infinite;
+}
+.container.loading6 .shape {
+  width: 12px;
+  height: 12px;
+  border-radius: 2px;
+}
+.container .shape {
+  position: absolute;
+  width: 10px;
+  height: 10px;
+  border-radius: 1px;
+}
+.container .shape.shape1 {
+  left: 0;
+  background-color: #1890FF;
+}
+.container .shape.shape2 {
+  right: 0;
+  background-color: #91CB74;
+}
+.container .shape.shape3 {
+  bottom: 0;
+  background-color: #FAC858;
+}
+.container .shape.shape4 {
+  bottom: 0;
+  right: 0;
+  background-color: #EE6666;
+}
+
+
+.loading6 .shape1 {
+  -webkit-animation: animation6shape1 2s linear 0s infinite normal;
+          animation: animation6shape1 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+  50% {
+    -webkit-transform: translate(18px, 18px);
+            transform: translate(18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+}
+
+@keyframes animation6shape1 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+  50% {
+    -webkit-transform: translate(18px, 18px);
+            transform: translate(18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+}
+.loading6 .shape2 {
+  -webkit-animation: animation6shape2 2s linear 0s infinite normal;
+          animation: animation6shape2 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-18px, 18px);
+            transform: translate(-18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+}
+
+@keyframes animation6shape2 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(-18px, 18px);
+            transform: translate(-18px, 18px);
+  }
+  75% {
+    -webkit-transform: translate(0, 18px);
+            transform: translate(0, 18px);
+  }
+}
+.loading6 .shape3 {
+  -webkit-animation: animation6shape3 2s linear 0s infinite normal;
+          animation: animation6shape3 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(18px, -18px);
+            transform: translate(18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+}
+
+@keyframes animation6shape3 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(18px, 0);
+            transform: translate(18px, 0);
+  }
+  50% {
+    -webkit-transform: translate(18px, -18px);
+            transform: translate(18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+}
+.loading6 .shape4 {
+  -webkit-animation: animation6shape4 2s linear 0s infinite normal;
+          animation: animation6shape4 2s linear 0s infinite normal;
+}
+
+@-webkit-keyframes animation6shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+  50% {
+    -webkit-transform: translate(-18px, -18px);
+            transform: translate(-18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+}
+
+@keyframes animation6shape4 {
+  0% {
+    -webkit-transform: translate(0, 0);
+            transform: translate(0, 0);
+  }
+  25% {
+    -webkit-transform: translate(0, -18px);
+            transform: translate(0, -18px);
+  }
+  50% {
+    -webkit-transform: translate(-18px, -18px);
+            transform: translate(-18px, -18px);
+  }
+  75% {
+    -webkit-transform: translate(-18px, 0);
+            transform: translate(-18px, 0);
+  }
+}
+</style>

+ 36 - 0
uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue

@@ -0,0 +1,36 @@
+<template>
+	<view>
+	 <Loading1 v-if="loadingType==1"/>
+	 <Loading2 v-if="loadingType==2"/>
+	 <Loading3 v-if="loadingType==3"/>
+	 <Loading4 v-if="loadingType==4"/>
+	 <Loading5 v-if="loadingType==5"/>
+	</view>
+</template>
+
+<script>
+	import Loading1 from "./loading1.vue";
+	import Loading2 from "./loading2.vue";
+	import Loading3 from "./loading3.vue";
+	import Loading4 from "./loading4.vue";
+	import Loading5 from "./loading5.vue";
+	export default {
+		components:{Loading1,Loading2,Loading3,Loading4,Loading5},
+		name: 'qiun-loading',
+		props: {
+			loadingType: {
+				type: Number,
+				default: 2
+			},
+		},
+		data() {
+			return {
+				
+			};
+		},
+	}
+</script>
+
+<style>
+
+</style>

+ 422 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js

@@ -0,0 +1,422 @@
+/*
+ * uCharts®
+ * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
+ * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 复制使用请保留本段注释,感谢支持开源!
+ * 
+ * uCharts®官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ */
+
+// 通用配置项
+
+// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
+const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
+
+const cfe = {
+  //demotype为自定义图表类型
+	"type": ["pie", "ring", "rose", "funnel", "line", "column", "area", "radar", "gauge","candle","demotype"],
+  //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型例如最后的"demotype"
+	"categories": ["line", "column", "area", "radar", "gauge", "candle","demotype"],
+  //instance为实例变量承载属性,option为eopts承载属性,不要删除
+	"instance": {},
+	"option": {},
+  //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
+  "formatter":{
+    "tooltipDemo1":function(res){
+      let result = ''
+      for (let i in res) {
+      	if (i == 0) {
+      		result += res[i].axisValueLabel + '年销售额'
+      	}
+      	let value = '--'
+      	if (res[i].data !== null) {
+      		value = res[i].data
+      	}
+      	// #ifdef H5
+      	result += '\n' + res[i].seriesName + ':' + value + ' 万元'
+      	// #endif
+      	
+      	// #ifdef APP-PLUS
+      	result += '<br/>' + res[i].marker + res[i].seriesName + ':' + value + ' 万元'
+      	// #endif
+      }
+      return result;
+    },
+    legendFormat:function(name){
+      return "自定义图例+"+name;
+    },
+    yAxisFormatDemo:function (value, index) {
+      return value + '元';
+    },
+    seriesFormatDemo:function(res){
+      return res.name + '年' + res.value + '元';
+    }
+  },
+  //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在eopts参数,会将demotype与eopts中option合并后渲染图表。
+  "demotype":{
+    "color": color,
+    //在这里填写echarts的option即可
+    
+  },
+  //下面是自定义配置,请添加项目所需的通用配置
+	"column": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'bar',
+			"data": [],
+			"barwidth": 20,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"line": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'line',
+			"data": [],
+			"barwidth": 20,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"area": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'axis'
+		},
+		"grid": {
+			"top": 30,
+			"bottom": 50,
+			"right": 15,
+			"left": 40
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"toolbox": {
+			"show": false,
+		},
+		"xAxis": {
+			"type": 'category',
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+			"boundaryGap": true,
+			"data": []
+		},
+		"yAxis": {
+			"type": 'value',
+			"axisTick": {
+				"show": false,
+			},
+			"axisLabel": {
+				"color": '#666666'
+			},
+			"axisLine": {
+				"lineStyle": {
+					"color": '#CCCCCC'
+				}
+			},
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'line',
+			"data": [],
+			"areaStyle": {},
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"pie": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"grid": {
+			"top": 40,
+			"bottom": 30,
+			"right": 15,
+			"left": 15
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": '50%',
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+		},
+	},
+	"ring": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"grid": {
+			"top": 40,
+			"bottom": 30,
+			"right": 15,
+			"left": 15
+		},
+		"legend": {
+			"bottom": 'left',
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": ['40%', '70%'],
+			"avoidLabelOverlap": false,
+			"label": {
+				"show": true,
+        "color": "#666666",
+				"position": 'top',
+			},
+			"labelLine": {
+				"show": true
+			},
+		},
+	},
+	"rose": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item'
+		},
+		"legend": {
+			"top": 'bottom'
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'pie',
+			"data": [],
+			"radius": "55%",
+			"center": ['50%', '50%'],
+			"roseType": 'area',
+		},
+	},
+	"funnel": {
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"tooltip": {
+			"trigger": 'item',
+			"formatter": "{b} : {c}%"
+		},
+		"legend": {
+			"top": 'bottom'
+		},
+		"seriesTemplate": {
+			"name": '',
+			"type": 'funnel',
+			"left": '10%',
+			"top": 60,
+			"bottom": 60,
+			"width": '80%',
+			"min": 0,
+			"max": 100,
+			"minSize": '0%',
+			"maxSize": '100%',
+			"sort": 'descending',
+			"gap": 2,
+			"label": {
+				"show": true,
+				"position": 'inside'
+			},
+			"labelLine": {
+				"length": 10,
+				"lineStyle": {
+					"width": 1,
+					"type": 'solid'
+				}
+			},
+			"itemStyle": {
+				"bordercolor": '#fff',
+				"borderwidth": 1
+			},
+			"emphasis": {
+				"label": {
+					"fontSize": 20
+				}
+			},
+			"data": [],
+		},
+	},
+	"gauge": {
+		"color": color,
+		"tooltip": {
+        "formatter": '{a} <br/>{b} : {c}%'
+    },
+		"seriesTemplate": {
+			"name": '业务指标',
+      "type": 'gauge',
+      "detail": {"formatter": '{value}%'},
+      "data": [{"value": 50, "name": '完成率'}]
+		},
+	},
+	"candle": {
+		"xAxis": {
+			"data": []
+		},
+		"yAxis": {},
+		"color": color,
+		"title": {
+			"text": ''
+		},
+		"dataZoom": [{
+				"type": 'inside',
+				"xAxisIndex": [0, 1],
+				"start": 10,
+				"end": 100
+			},
+			{
+				"show": true,
+				"xAxisIndex": [0, 1],
+				"type": 'slider',
+				"bottom": 10,
+				"start": 10,
+				"end": 100
+			}
+		],
+		"seriesTemplate": {
+			"name": '',
+			"type": 'k',
+			"data": [],
+		},
+	}
+}
+
+export default cfe;

+ 606 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js

@@ -0,0 +1,606 @@
+/*
+ * uCharts®
+ * 高性能跨平台图表库,支持H5、APP、小程序(微信/支付宝/百度/头条/QQ/360)、Vue、Taro等支持canvas的框架平台
+ * Copyright (c) 2021 QIUN®秋云 https://www.ucharts.cn All rights reserved.
+ * Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
+ * 复制使用请保留本段注释,感谢支持开源!
+ * 
+ * uCharts®官方网站
+ * https://www.uCharts.cn
+ * 
+ * 开源地址:
+ * https://gitee.com/uCharts/uCharts
+ * 
+ * uni-app插件市场地址:
+ * http://ext.dcloud.net.cn/plugin?id=271
+ * 
+ */
+
+// 主题颜色配置:如每个图表类型需要不同主题,请在对应图表类型上更改color属性
+const color = ['#1890FF', '#91CB74', '#FAC858', '#EE6666', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'];
+
+//事件转换函数,主要用作格式化x轴为时间轴,根据需求自行修改
+const formatDateTime = (timeStamp, returnType)=>{
+  var date = new Date();
+  date.setTime(timeStamp * 1000);
+  var y = date.getFullYear();
+  var m = date.getMonth() + 1;
+  m = m < 10 ? ('0' + m) : m;
+  var d = date.getDate();
+  d = d < 10 ? ('0' + d) : d;
+  var h = date.getHours();
+  h = h < 10 ? ('0' + h) : h;
+  var minute = date.getMinutes();
+  var second = date.getSeconds();
+  minute = minute < 10 ? ('0' + minute) : minute;
+  second = second < 10 ? ('0' + second) : second;
+  if(returnType == 'full'){return y + '-' + m + '-' + d + ' '+ h +':' + minute + ':' + second;}
+  if(returnType == 'y-m-d'){return y + '-' + m + '-' + d;}
+  if(returnType == 'h:m'){return  h +':' + minute;}
+  if(returnType == 'h:m:s'){return  h +':' + minute +':' + second;}
+  return [y, m, d, h, minute, second];
+}
+
+const cfu = {
+  //demotype为自定义图表类型,一般不需要自定义图表类型,只需要改根节点上对应的类型即可
+	"type":["pie","ring","rose","word","funnel","map","arcbar","line","column","mount","bar","area","radar","gauge","candle","mix","tline","tarea","scatter","bubble","demotype"],
+	"range":["饼状图","圆环图","玫瑰图","词云图","漏斗图","地图","圆弧进度条","折线图","柱状图","山峰图","条状图","区域图","雷达图","仪表盘","K线图","混合图","时间轴折线","时间轴区域","散点图","气泡图","自定义类型"],
+  //增加自定义图表类型,如果需要categories,请在这里加入您的图表类型,例如最后的"demotype"
+  //自定义类型时需要注意"tline","tarea","scatter","bubble"等时间轴(矢量x轴)类图表,没有categories,不需要加入categories
+	"categories":["line","column","mount","bar","area","radar","gauge","candle","mix","demotype"],
+  //instance为实例变量承载属性,不要删除
+  "instance":{},
+  //option为opts及eopts承载属性,不要删除
+  "option":{},
+  //下面是自定义format配置,因除H5端外的其他端无法通过props传递函数,只能通过此属性对应下标的方式来替换
+  "formatter":{
+    "yAxisDemo1":function(val, index, opts){return val+'元'},
+    "yAxisDemo2":function(val, index, opts){return val.toFixed(2)},
+    "xAxisDemo1":function(val, index, opts){return val+'年';},
+    "xAxisDemo2":function(val, index, opts){return formatDateTime(val,'h:m')},
+    "seriesDemo1":function(val, index, series, opts){return val+'元'},
+    "tooltipDemo1":function(item, category, index, opts){
+      if(index==0){
+      	return '随便用'+item.data+'年'
+      }else{
+      	return '其他我没改'+item.data+'天'
+      }
+    },
+    "pieDemo":function(val, index, series, opts){
+      if(index !== undefined){
+        return series[index].name+':'+series[index].data+'元'
+      }
+    },
+  },
+  //这里演示了自定义您的图表类型的option,可以随意命名,之后在组件上 type="demotype" 后,组件会调用这个花括号里的option,如果组件上还存在opts参数,会将demotype与opts中option合并后渲染图表。
+  "demotype":{
+    //我这里把曲线图当做了自定义图表类型,您可以根据需要随意指定类型或配置
+    "type": "line",
+    "color": color,
+    "padding": [15,10,0,15],
+    "xAxis": {
+      "disableGrid": true,
+    },
+    "yAxis": {
+      "gridType": "dash",
+      "dashLength": 2,
+    },
+    "legend": {
+    },
+    "extra": {
+    	"line": {
+    		"type": "curve",
+    		"width": 2
+    	},
+    }
+  },
+  //下面是自定义配置,请添加项目所需的通用配置
+	"pie":{
+		"type": "pie",
+    "color": color,
+		"padding": [5,5,5,5],
+		"extra": {
+			"pie": {
+				"activeOpacity": 0.5,
+				"activeRadius": 10,
+				"offsetAngle": 0,
+				"labelWidth": 15,
+				"border": true,
+				"borderWidth": 3,
+				"borderColor": "#FFFFFF"
+			},
+		}
+	},
+	"ring":{
+		"type": "ring",
+    "color": color,
+		"padding": [5,5,5,5],
+		"rotate": false,
+		"dataLabel": true,
+		"legend": {
+			"show": true,
+			"position": "right",
+      "lineHeight": 25,
+		},
+		"title": {
+			"name": "收益率",
+			"fontSize": 15,
+			"color": "#666666"
+		},
+		"subtitle": {
+			"name": "70%",
+			"fontSize": 25,
+			"color": "#7cb5ec"
+		},
+		"extra": {
+			"ring": {
+				"ringWidth":30,
+				"activeOpacity": 0.5,
+				"activeRadius": 10,
+				"offsetAngle": 0,
+				"labelWidth": 15,
+				"border": true,
+				"borderWidth": 3,
+				"borderColor": "#FFFFFF"
+			},
+		},
+	},
+	"rose":{
+		"type": "rose",
+    "color": color,
+		"padding": [5,5,5,5],
+		"legend": {
+			"show": true,
+			"position": "left",
+      "lineHeight": 25,
+		},
+		"extra": {
+			"rose": {
+				"type": "area",
+				"minRadius": 50,
+				"activeOpacity": 0.5,
+				"activeRadius": 10,
+				"offsetAngle": 0,
+				"labelWidth": 15,
+				"border": false,
+				"borderWidth": 2,
+				"borderColor": "#FFFFFF"
+			},
+		}
+	},
+	"word":{
+		"type": "word",
+    "color": color,
+		"extra": {
+			"word": {
+				"type": "normal",
+				"autoColors": false
+			}
+		}
+	},
+	"funnel":{
+		"type": "funnel",
+    "color": color,
+		"padding": [15,15,0,15],
+		"extra": {
+			"funnel": {
+				"activeOpacity": 0.3,
+				"activeWidth": 10,
+				"border": true,
+				"borderWidth": 2,
+				"borderColor": "#FFFFFF",
+				"fillOpacity": 1,
+				"labelAlign": "right"
+			},
+		}
+	},
+	"map":{
+		"type": "map",
+    "color": color,
+		"padding": [0,0,0,0],
+    "dataLabel": true,
+		"extra": {
+			"map": {
+				"border": true,
+				"borderWidth": 1,
+				"borderColor": "#666666",
+				"fillOpacity": 0.6,
+				"activeBorderColor": "#F04864",
+				"activeFillColor": "#FACC14",
+				"activeFillOpacity": 1
+			},
+		}
+	},
+	"arcbar":{
+		"type": "arcbar",
+    "color": color,
+		"title": {
+			"name": "百分比",
+			"fontSize": 25,
+			"color": "#00FF00"
+		},
+		"subtitle": {
+			"name": "默认标题",
+			"fontSize": 15,
+			"color": "#666666"
+		},
+		"extra": {
+			"arcbar": {
+				"type": "default",
+				"width": 12,
+				"backgroundColor": "#E9E9E9",
+				"startAngle": 0.75,
+				"endAngle": 0.25,
+				"gap": 2
+			}
+		}
+	},
+	"line":{
+		"type": "line",
+    "color": color,
+		"padding": [15,10,0,15],
+		"xAxis": {
+      "disableGrid": true,
+		},
+		"yAxis": {
+      "gridType": "dash",
+      "dashLength": 2,
+		},
+		"legend": {
+		},
+		"extra": {
+			"line": {
+				"type": "straight",
+				"width": 2,
+        "activeType": "hollow"
+			},
+		}
+	},
+  "tline":{
+  	"type": "line",
+    "color": color,
+  	"padding": [15,10,0,15],
+  	"xAxis": {
+      "disableGrid": false,
+      "boundaryGap":"justify",
+  	},
+  	"yAxis": {
+      "gridType": "dash",
+      "dashLength": 2,
+      "data":[
+        {
+          "min":0,
+          "max":80
+        }
+      ]
+  	},
+  	"legend": {
+  	},
+  	"extra": {
+  		"line": {
+  			"type": "curve",
+  			"width": 2,
+        "activeType": "hollow"
+  		},
+  	}
+  },
+  "tarea":{
+  	"type": "area",
+    "color": color,
+  	"padding": [15,10,0,15],
+  	"xAxis": {
+      "disableGrid": true,
+      "boundaryGap":"justify",
+  	},
+  	"yAxis": {
+      "gridType": "dash",
+      "dashLength": 2,
+      "data":[
+        {
+          "min":0,
+          "max":80
+        }
+      ]
+  	},
+  	"legend": {
+  	},
+  	"extra": {
+  		"area": {
+  			"type": "curve",
+  			"opacity": 0.2,
+  			"addLine": true,
+  			"width": 2,
+  			"gradient": true,
+        "activeType": "hollow"
+  		},
+  	}
+  },
+	"column":{
+		"type": "column",
+    "color": color,
+		"padding": [15,15,0,5],
+		"xAxis": {
+      "disableGrid": true,
+		},
+		"yAxis": {
+      "data":[{"min":0}]
+		},
+		"legend": {
+		},
+		"extra": {
+			"column": {
+				"type": "group",
+				"width": 30,
+				"activeBgColor": "#000000",
+				"activeBgOpacity": 0.08
+			},
+		}
+	},
+  "mount":{
+  	"type": "mount",
+    "color": color,
+  	"padding": [15,15,0,5],
+  	"xAxis": {
+      "disableGrid": true,
+  	},
+  	"yAxis": {
+      "data":[{"min":0}]
+  	},
+  	"legend": {
+  	},
+  	"extra": {
+  		"mount": {
+  			"type": "mount",
+  			"widthRatio": 1.5,
+  		},
+  	}
+  },
+  "bar":{
+  	"type": "bar",
+    "color": color,
+  	"padding": [15,30,0,5],
+  	"xAxis": {
+      "boundaryGap":"justify",
+      "disableGrid":false,
+      "min":0,
+      "axisLine":false
+  	},
+  	"yAxis": {
+  	},
+  	"legend": {
+  	},
+  	"extra": {
+  		"bar": {
+  			"type": "group",
+  			"width": 30,
+  			"meterBorde": 1,
+  			"meterFillColor": "#FFFFFF",
+  			"activeBgColor": "#000000",
+  			"activeBgOpacity": 0.08
+  		},
+  	}
+  },
+	"area":{
+		"type": "area",
+		"color": color,
+		"padding": [15,15,0,15],
+		"xAxis": {
+      "disableGrid": true,
+		},
+		"yAxis": {
+      "gridType": "dash",
+      "dashLength": 2,
+		},
+		"legend": {
+		},
+		"extra": {
+			"area": {
+				"type": "straight",
+				"opacity": 0.2,
+				"addLine": true,
+				"width": 2,
+				"gradient": false,
+        "activeType": "hollow"
+			},
+		}
+	},
+	"radar":{
+		"type": "radar",
+		"color": color,
+		"padding": [5,5,5,5],
+    "dataLabel": false,
+		"legend": {
+			"show": true,
+			"position": "right",
+      "lineHeight": 25,
+		},
+		"extra": {
+			"radar": {
+				"gridType": "radar",
+				"gridColor": "#CCCCCC",
+				"gridCount": 3,
+				"opacity": 0.2,
+				"max": 200,
+				"labelShow": true
+			},
+		}
+	},
+	"gauge":{
+		"type": "gauge",
+		"color": color,
+		"title": {
+			"name": "66Km/H",
+			"fontSize": 25,
+			"color": "#2fc25b",
+			"offsetY": 50
+		},
+		"subtitle": {
+			"name": "实时速度",
+			"fontSize": 15,
+			"color": "#1890ff",
+			"offsetY": -50
+		},
+		"extra": {
+			"gauge": {
+				"type": "default",
+				"width": 30,
+				"labelColor": "#666666",
+				"startAngle": 0.75,
+				"endAngle": 0.25,
+				"startNumber": 0,
+				"endNumber": 100,
+				"labelFormat": "",
+				"splitLine": {
+					"fixRadius": 0,
+					"splitNumber": 10,
+					"width": 30,
+					"color": "#FFFFFF",
+					"childNumber": 5,
+					"childWidth": 12
+				},
+				"pointer": {
+					"width": 24,
+					"color": "auto"
+				}
+			}
+		}
+	},
+	"candle":{
+		"type": "candle",
+		"color": color,
+		"padding": [15,15,0,15],
+		"enableScroll": true,
+		"enableMarkLine": true,
+		"dataLabel": false,
+		"xAxis": {
+			"labelCount": 4,
+			"itemCount": 40,
+			"disableGrid": true,
+			"gridColor": "#CCCCCC",
+			"gridType": "solid",
+			"dashLength": 4,
+			"scrollShow": true,
+			"scrollAlign": "left",
+			"scrollColor": "#A6A6A6",
+			"scrollBackgroundColor": "#EFEBEF"
+		},
+		"yAxis": {
+		},
+		"legend": {
+		},
+		"extra": {
+			"candle": {
+				"color": {
+					"upLine": "#f04864",
+					"upFill": "#f04864",
+					"downLine": "#2fc25b",
+					"downFill": "#2fc25b"
+				},
+				"average": {
+					"show": true,
+					"name": ["MA5","MA10","MA30"],
+					"day": [5,10,20],
+					"color": ["#1890ff","#2fc25b","#facc14"]
+				}
+			},
+			"markLine": {
+				"type": "dash",
+				"dashLength": 5,
+				"data": [
+					{
+						"value": 2150,
+						"lineColor": "#f04864",
+						"showLabel": true
+					},
+					{
+						"value": 2350,
+						"lineColor": "#f04864",
+						"showLabel": true
+					}
+				]
+			}
+		}
+	},
+	"mix":{
+		"type": "mix",
+		"color": color,
+		"padding": [15,15,0,15],
+		"xAxis": {
+      "disableGrid": true,
+		},
+		"yAxis": {
+			"disabled": false,
+			"disableGrid": false,
+			"splitNumber": 5,
+			"gridType": "dash",
+			"dashLength": 4,
+			"gridColor": "#CCCCCC",
+			"padding": 10,
+			"showTitle": true,
+			"data": []
+		},
+		"legend": {
+		},
+		"extra": {
+			"mix": {
+				"column": {
+					"width": 20
+				}
+			},
+		}
+	},
+	"scatter":{
+		"type": "scatter",
+		"color":color,
+		"padding":[15,15,0,15],
+    "dataLabel":false,
+    "xAxis": {
+      "disableGrid": false,
+      "gridType":"dash",
+      "splitNumber":5,
+      "boundaryGap":"justify",
+      "min":0
+    },
+    "yAxis": {
+      "disableGrid": false,
+      "gridType":"dash",
+    },
+    "legend": {
+    },
+    "extra": {
+    	"scatter": {
+    	},
+    }
+	},
+	"bubble":{
+		"type": "bubble",
+		"color":color,
+		"padding":[15,15,0,15],
+    "xAxis": {
+      "disableGrid": false,
+      "gridType":"dash",
+      "splitNumber":5,
+      "boundaryGap":"justify",
+      "min":0,
+      "max":250
+    },
+    "yAxis": {
+      "disableGrid": false,
+      "gridType":"dash",
+      "data":[{
+        "min":0,
+        "max":150
+      }]
+    },
+    "legend": {
+    },
+    "extra": {
+    	"bubble": {
+        "border":2,
+        "opacity": 0.5,
+    	},
+    }
+	}
+}
+
+export default cfu;

+ 5 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md

@@ -0,0 +1,5 @@
+# uCharts JSSDK说明
+1、如不使用uCharts组件,可直接引用u-charts.js,打包编译后会`自动压缩`,压缩后体积约为`120kb`。
+2、如果120kb的体积仍需压缩,请手到uCharts官网通过在线定制选择您需要的图表。
+3、config-ucharts.js为uCharts组件的用户配置文件,升级前请`自行备份config-ucharts.js`文件,以免被强制覆盖。
+4、config-echarts.js为ECharts组件的用户配置文件,升级前请`自行备份config-echarts.js`文件,以免被强制覆盖。

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 7706 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 18 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js


+ 201 - 0
uni_modules/qiun-data-charts/license.md

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.

+ 81 - 0
uni_modules/qiun-data-charts/package.json

@@ -0,0 +1,81 @@
+{
+  "id": "qiun-data-charts",
+  "displayName": "秋云 ucharts echarts 高性能跨全端图表组件",
+  "version": "2.5.0-20230101",
+  "description": "uCharts 新增正负柱状图!支持H5及APP用 ucharts echarts 渲染图表,uniapp可视化首选组件",
+  "keywords": [
+    "ucharts",
+    "echarts",
+    "f2",
+    "图表",
+    "可视化"
+],
+  "repository": "https://gitee.com/uCharts/uCharts",
+  "engines": {
+    "HBuilderX": "^3.3.8"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": "474119"
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/~qiun",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "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"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        },
+        "Vue": {
+            "vue2": "y",
+            "vue3": "y"
+        }
+      }
+    }
+  }
+}

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 84 - 0
uni_modules/qiun-data-charts/readme.md


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 23 - 0
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 23 - 0
uni_modules/qiun-data-charts/static/h5/echarts.min.js


+ 34 - 0
uni_modules/uv-datetime-picker/changelog.md

@@ -0,0 +1,34 @@
+## 1.0.15(2024-06-14)
+1. 修复上次更改引出的BUG
+## 1.0.14(2024-05-31)
+1. 修复设置maxDate后存在选择不准确的BUG
+## 1.0.13(2024-03-22)
+1. 修复VUE3中出现的BUG
+## 1.0.12(2023-11-27)
+1. 增加round圆角属性
+## 1.0.11(2023-10-11)
+1. 修复设置minDate出现选择错乱的BUG
+## 1.0.10(2023-09-01)
+1. 增加clearDate参数,是否清除上次选择,默认false
+## 1.0.9(2023-08-31)
+1. 增加mode="year",方便只选择年
+## 1.0.8(2023-07-17)
+1. 优化文档
+2. 优化其他
+## 1.0.7(2023-07-13)
+1. 修复 uv-datetime-picker 设置value属性不生效的BUG 
+## 1.0.6(2023-07-05)
+修复vue3模式下,动态修改v-model绑定的值无效的BUG
+## 1.0.5(2023-07-02)
+uv-datetime-picker  由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/datetimePicker.html
+## 1.0.4(2023-06-29)
+1. 修复抖音小程序报错的BUG
+## 1.0.3(2023-06-07)
+1.  取消defaultIndex参数,传该值没实际意义,后续更新文档
+## 1.0.2(2023-06-02)
+1. 修复v-model重新赋值不更新的BUG
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+uv-datetime-picker 时间选择器

+ 130 - 0
uni_modules/uv-datetime-picker/components/uv-datetime-picker/props.js

@@ -0,0 +1,130 @@
+export default {
+	props: {
+		value: {
+			type: [String, Number],
+			default: ''
+		},
+		modelValue: {
+			type: [String, Number],
+			default: ''
+		},
+		// 是否打开组件
+		show: {
+			type: Boolean,
+			default: false
+		},
+		// 是否展示顶部的操作栏
+		showToolbar: {
+			type: Boolean,
+			default: true
+		},
+		// 顶部标题
+		title: {
+			type: String,
+			default: ''
+		},
+		// 展示格式,mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择
+		mode: {
+			type: String,
+			default: 'datetime'
+		},
+		// 可选的最大时间
+		maxDate: {
+			type: Number,
+			// 最大默认值为后10年
+			default: new Date(new Date().getFullYear() + 10, 0, 1).getTime()
+		},
+		// 可选的最小时间
+		minDate: {
+			type: Number,
+			// 最小默认值为前10年
+			default: new Date(new Date().getFullYear() - 10, 0, 1).getTime()
+		},
+		// 可选的最小小时,仅mode=time有效
+		minHour: {
+			type: Number,
+			default: 0
+		},
+		// 可选的最大小时,仅mode=time有效
+		maxHour: {
+			type: Number,
+			default: 23
+		},
+		// 可选的最小分钟,仅mode=time有效
+		minMinute: {
+			type: Number,
+			default: 0
+		},
+		// 可选的最大分钟,仅mode=time有效
+		maxMinute: {
+			type: Number,
+			default: 59
+		},
+		// 选项过滤函数
+		filter: {
+			type: [Function, null],
+			default: null
+		},
+		// 选项格式化函数
+		formatter: {
+			type: [Function, null],
+			default: null
+		},
+		// 是否显示加载中状态
+		loading: {
+			type: Boolean,
+			default: false
+		},
+		// 各列中,单个选项的高度
+		itemHeight: {
+			type: [String, Number],
+			default: 44
+		},
+		// 取消按钮的文字
+		cancelText: {
+			type: String,
+			default: '取消'
+		},
+		// 确认按钮的文字
+		confirmText: {
+			type: String,
+			default: '确认'
+		},
+		// 取消按钮的颜色
+		cancelColor: {
+			type: String,
+			default: '#909193'
+		},
+		// 确认按钮的颜色
+		confirmColor: {
+			type: String,
+			default: '#3c9cff'
+		},
+		// 每列中可见选项的数量
+		visibleItemCount: {
+			type: [String, Number],
+			default: 5
+		},
+		// 是否允许点击遮罩关闭选择器
+		closeOnClickOverlay: {
+			type: Boolean,
+			default: true
+		},
+		// 是否允许点击确认关闭选择器
+		closeOnClickConfirm: {
+			type: Boolean,
+			default: true
+		},
+		// 是否清空上次选择内容
+		clearDate: {
+			type: Boolean,
+			default: false
+		},
+		// 圆角
+		round: {
+			type: [String, Number],
+			default: 0
+		},
+		...uni.$uv?.props?.datetimePicker
+	}
+}

+ 360 - 0
uni_modules/uv-datetime-picker/components/uv-datetime-picker/uv-datetime-picker.vue

@@ -0,0 +1,360 @@
+<template>
+	<uv-picker
+		ref="picker"
+		:closeOnClickOverlay="closeOnClickOverlay"
+		:closeOnClickConfirm="closeOnClickConfirm"
+		:columns="columns"
+		:title="title"
+		:itemHeight="itemHeight"
+		:showToolbar="showToolbar"
+		:visibleItemCount="visibleItemCount"
+		:defaultIndex="innerDefaultIndex"
+		:cancelText="cancelText"
+		:confirmText="confirmText"
+		:cancelColor="cancelColor"
+		:confirmColor="confirmColor"
+		:round="round"
+		@close="close"
+		@cancel="cancel"
+		@confirm="confirm"
+		@change="change"
+	>
+	</uv-picker>
+</template>
+<script>
+	function times(n, iteratee) {
+		let index = -1
+		const result = Array(n < 0 ? 0 : n)
+		while (++index < n) {
+			result[index] = iteratee(index)
+		}
+		return result
+	}
+	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';
+	import dayjs from '@/uni_modules/uv-ui-tools/libs/util/dayjs.js'
+	/**
+	 * DatetimePicker 时间日期选择器
+	 * @description 此选择器用于时间日期
+	 * @tutorial https://www.uvui.cn/components/datetimePicker.html
+	 * @property {Boolean}			showToolbar			是否显示顶部的操作栏  ( 默认 true )
+	 * @property {String | Number}	value				绑定值
+	 * @property {String}			title				顶部标题
+	 * @property {String}			mode				展示格式 mode=date为日期选择,mode=time为时间选择,mode=year-month为年月选择,mode=datetime为日期时间选择  ( 默认 ‘datetime )
+	 * @property {Number}			maxDate				可选的最大时间  默认值为后10年
+	 * @property {Number}			minDate				可选的最小时间  默认值为前10年
+	 * @property {Number}			minHour				可选的最小小时,仅mode=time有效   ( 默认 0 )
+	 * @property {Number}			maxHour				可选的最大小时,仅mode=time有效	  ( 默认 23 )
+	 * @property {Number}			minMinute			可选的最小分钟,仅mode=time有效	  ( 默认 0 )
+	 * @property {Number}			maxMinute			可选的最大分钟,仅mode=time有效   ( 默认 59 )
+	 * @property {Function}			filter				选项过滤函数
+	 * @property {Function}			formatter			选项格式化函数
+	 * @property {Boolean}			loading				是否显示加载中状态   ( 默认 false )
+	 * @property {String | Number}	itemHeight			各列中,单个选项的高度   ( 默认 44 )
+	 * @property {String}			cancelText			取消按钮的文字  ( 默认 '取消' )
+	 * @property {String}			confirmText			确认按钮的文字  ( 默认 '确认' )
+	 * @property {String}			cancelColor			取消按钮的颜色  ( 默认 '#909193' )
+	 * @property {String}			confirmColor		确认按钮的颜色  ( 默认 '#3c9cff' )
+	 * @property {String | Number}	visibleItemCount	每列中可见选项的数量  ( 默认 5 )
+	 * @property {Boolean}			closeOnClickOverlay	是否允许点击遮罩关闭选择器  ( 默认 true )
+	 * @property {String | Number}	round	圆角  ( 默认 0 )
+	 * @event {Function} close 关闭选择器时触发
+	 * @event {Function} confirm 点击确定按钮,返回当前选择的值
+	 * @event {Function} change 当选择值变化时触发
+	 * @event {Function} cancel 点击取消按钮
+	 * @example  <uv-datetime-picker ref="datetimepicker" :value="value1"  mode="datetime" ></uv-datetime-picker>
+	 */
+	export default {
+		name: 'uv-datetime-picker',
+		emits: ['close', 'cancel', 'confirm', 'input', 'change', 'update:modelValue'],
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+				columns: [],
+				innerDefaultIndex: [],
+				innerFormatter: (type, value) => value
+			}
+		},
+		watch: {
+			propsChange() {
+				this.$uv.sleep(100).then(res=>{
+					this.init()
+				})
+			}
+		},
+		computed: {
+			// 如果以下这些变量发生了变化,意味着需要重新初始化各列的值
+			propsChange() {
+				const propsValue = this.value || this.modelValue;
+				return [this.mode, this.maxDate, this.minDate, this.minHour, this.maxHour, this.minMinute, this.maxMinute, this.filter, propsValue]
+			}
+		},
+		mounted() {
+			this.init()
+		},
+		methods: {
+			init() {
+				this.getValue();
+				this.updateColumnValue(this.innerValue)
+			},
+			getValue() {
+				const propsValue = this.value || this.modelValue;
+				this.innerValue = this.correctValue(propsValue)
+			},
+			// 在微信小程序中,不支持将函数当做props参数,故只能通过ref形式调用
+			setFormatter(e) {
+				this.innerFormatter = e
+			},
+			open() {
+				this.$refs.picker.open();
+				// 解决打开的前一次和当前日期错乱的BUG
+				setTimeout(()=>{
+					this.getValue();
+					this.updateColumnValue(this.innerValue);
+				},10)
+			},
+			close() {
+				this.$emit('close');
+			},
+			// 点击工具栏的取消按钮
+			cancel() {
+				this.$emit('cancel')
+			},
+			// 点击工具栏的确定按钮
+			confirm() {
+				this.$emit('confirm', {
+					value: this.innerValue,
+					mode: this.mode
+				})
+				if(!this.clearDate) {
+					this.$emit('input', this.innerValue)
+					this.$emit('update:modelValue', this.innerValue)
+				}
+			},
+			//用正则截取输出值,当出现多组数字时,抛出错误
+			intercept(e, type) {
+				let judge = e.match(/\d+/g)
+				//判断是否掺杂数字
+				if (judge.length > 1) {
+					this.$uv.error("请勿在过滤或格式化函数时添加数字")
+					return 0
+				} else if (type && judge[0].length == 4) { //判断是否是年份
+					return judge[0]
+				} else if (judge[0].length > 2) {
+					this.$uv.error("请勿在过滤或格式化函数时添加数字")
+					return 0
+				} else {
+					return judge[0]
+				}
+			},
+			// 列发生变化时触发
+			change(e) {
+				const { indexs, values } = e
+				let selectValue = ''
+				if (this.mode === 'time') {
+					// 根据value各列索引,从各列数组中,取出当前时间的选中值
+					selectValue = `${this.intercept(values[0][indexs[0]])}:${this.intercept(values[1][indexs[1]])}`
+				} else if (this.mode === 'year') {
+					const year = parseInt(this.intercept(values[0][indexs[0]], 'year'));
+					selectValue = Number(new Date(year, 0));
+				} else {
+					// 将选择的值转为数值,比如'03'转为数值的3,'2019'转为数值的2019
+					const year = parseInt(this.intercept(values[0][indexs[0]], 'year'))
+					const month = parseInt(this.intercept(values[1][indexs[1]]))
+					let date = parseInt(values[2] ? this.intercept(values[2][indexs[2]]) : 1)
+					let hour = 0,
+						minute = 0
+					// 此月份的最大天数
+					const maxDate = dayjs(`${year}-${month}`).daysInMonth()
+					// year-month模式下,date不会出现在列中,设置为1,为了符合后边需要减1的需求
+					if (this.mode === 'year-month') {
+						date = 1
+					}
+					// 不允许超过maxDate值
+					date = Math.min(maxDate, date)
+					if (this.mode === 'datetime') {
+						hour = parseInt(this.intercept(values[3][indexs[3]]))
+						minute = parseInt(this.intercept(values[4][indexs[4]]))
+					}
+					// 转为时间模式
+					selectValue = Number(new Date(year, month - 1, date, hour, minute))
+				}
+				// 取出准确的合法值,防止超越边界的情况
+				selectValue = this.correctValue(selectValue)
+				this.innerValue = selectValue
+				this.updateColumnValue(selectValue)
+				// 发出change时间,value为当前选中的时间戳
+				this.$emit('change', {
+					value: selectValue,
+					mode: this.mode
+				})
+			},
+			// 更新各列的值,进行补0、格式化等操作
+			updateColumnValue(value) {
+				this.innerValue = value
+				this.updateColumns()
+				this.updateIndexs(value)
+			},
+			// 更新索引
+			updateIndexs(value) {
+				let values = []
+				const formatter = this.formatter || this.innerFormatter;
+				if (this.mode === 'time') {
+					// 将time模式的时间用:分隔成数组
+					const timeArr = value.split(':')
+					// 使用formatter格式化方法进行管道处理
+					values = [formatter('hour', timeArr[0]), formatter('minute', timeArr[1])]
+				} else {
+					const date = new Date(value)
+					values = [
+						formatter('year', `${dayjs(value).year()}`),
+						// 月份补0
+						formatter('month', this.$uv.padZero(dayjs(value).month() + 1))
+					]
+					if (this.mode === 'date') {
+						// date模式,需要添加天列
+						values.push(formatter('day', this.$uv.padZero(dayjs(value).date())))
+					}
+					if (this.mode === 'datetime') {
+						// 数组的push方法,可以写入多个参数
+						values.push(formatter('day', this.$uv.padZero(dayjs(value).date())), formatter('hour', this.$uv.padZero(dayjs(value).hour())), formatter('minute', this.$uv.padZero(dayjs(value).minute())))
+					}
+				}
+				// 根据当前各列的所有值,从各列默认值中找到默认值在各列中的索引
+				const indexs = this.columns.map((column, index) => {
+					// 通过取大值,可以保证不会出现找不到索引的-1情况
+					return Math.max(0, column.findIndex(item => item === values[index]))
+				})
+				this.$nextTick(()=>{
+					this.$uv.sleep(100).then(res=>{
+						this.$refs.picker.setIndexs(indexs,true);
+					})
+				})
+			},
+			// 更新各列的值
+			updateColumns() {
+				const formatter = this.formatter || this.innerFormatter
+				// 获取各列的值,并且map后,对各列的具体值进行补0操作
+				const results = this.getOriginColumns().map((column) => column.values.map((value) => formatter(column.type, value)))
+				this.columns = results
+			},
+			getOriginColumns() {
+				// 生成各列的值
+				const results = this.getRanges().map(({ type, range }) => {
+					let values = times(range[1] - range[0] + 1, (index) => {
+						let value = range[0] + index
+						value = type === 'year' ? `${value}` : this.$uv.padZero(value)
+						return value
+					})
+					// 进行过滤
+					if (this.filter) {
+						values = this.filter(type, values)
+					}
+					return { type, values }
+				})
+				return results
+			},
+			// 通过最大值和最小值生成数组
+			generateArray(start, end) {
+				return Array.from(new Array(end + 1).keys()).slice(start)
+			},
+			// 得出合法的时间
+			correctValue(value) {
+				const isDateMode = this.mode !== 'time'
+				if (isDateMode && !this.$uv.test.date(value)) {
+					// 如果是日期类型,但是又没有设置合法的当前时间的话,使用最小时间为当前时间
+					value = this.minDate
+				} else if (!isDateMode && !value) {
+					// 如果是时间类型,而又没有默认值的话,就用最小时间
+					value = `${this.$uv.padZero(this.minHour)}:${this.$uv.padZero(this.minMinute)}`
+				}
+				// 时间类型
+				if (!isDateMode) {
+					if (String(value).indexOf(':') === -1) return this.$uv.error('时间错误,请传递如12:24的格式')
+					let [hour, minute] = value.split(':')
+					// 对时间补零,同时控制在最小值和最大值之间
+					hour = this.$uv.padZero(this.$uv.range(this.minHour, this.maxHour, Number(hour)))
+					minute = this.$uv.padZero(this.$uv.range(this.minMinute, this.maxMinute, Number(minute)))
+					return `${ hour }:${ minute }`
+				} else {
+					// 如果是日期格式,控制在最小日期和最大日期之间
+					value = dayjs(value).isBefore(dayjs(this.minDate)) ? this.minDate : value
+					value = dayjs(value).isAfter(dayjs(this.maxDate)) ? this.maxDate : value
+					return value
+				}
+			},
+			// 获取每列的最大和最小值
+			getRanges() {
+				if (this.mode === 'time') {
+					return [{
+						type: 'hour',
+						range: [this.minHour, this.maxHour],
+					}, {
+						type: 'minute',
+						range: [this.minMinute, this.maxMinute],
+					}, ];
+				}
+				const { maxYear, maxDate, maxMonth, maxHour, maxMinute, } = this.getBoundary('max', this.innerValue);
+				const { minYear, minDate, minMonth, minHour, minMinute, } = this.getBoundary('min', this.innerValue);
+				const result = [{
+					type: 'year',
+					range: [minYear, maxYear],
+				}, {
+					type: 'month',
+					range: [minMonth, maxMonth],
+				}, {
+					type: 'day',
+					range: [minDate, maxDate],
+				}, {
+					type: 'hour',
+					range: [minHour, maxHour],
+				}, {
+					type: 'minute',
+					range: [minMinute, maxMinute],
+				}, ];
+				if (this.mode === 'date') result.splice(3, 2);
+				if (this.mode === 'year-month') result.splice(2, 3);
+				if (this.mode === 'year') result.splice(1, 4);
+				return result;
+			},
+			// 根据minDate、maxDate、minHour、maxHour等边界值,判断各列的开始和结束边界值
+			getBoundary(type, innerValue) {
+				const value = new Date(innerValue)
+				const boundary = new Date(this[`${type}Date`])
+				const year = dayjs(boundary).year()
+				let month = 1
+				let date = 1
+				let hour = 0
+				let minute = 0
+				if (type === 'max') {
+					month = 12
+					// 月份的天数
+					date = dayjs(value).daysInMonth()
+					hour = 23
+					minute = 59
+				}
+				// 获取边界值,逻辑是:当年达到了边界值(最大或最小年),就检查月允许的最大和最小值,以此类推
+				if (dayjs(value).year() === year) {
+					month = dayjs(boundary).month() + 1
+					if (dayjs(value).month() + 1 === month) {
+						date = dayjs(boundary).date()
+						if (dayjs(value).date() === date) {
+							hour = dayjs(boundary).hour()
+							if (dayjs(value).hour() === hour) {
+								minute = dayjs(boundary).minute()
+							}
+						}
+					}
+				}
+				return {
+					[`${type}Year`]: year,
+					[`${type}Month`]: month,
+					[`${type}Date`]: date,
+					[`${type}Hour`]: hour,
+					[`${type}Minute`]: minute
+				}
+			},
+		},
+	}
+</script>

+ 89 - 0
uni_modules/uv-datetime-picker/package.json

@@ -0,0 +1,89 @@
+{
+  "id": "uv-datetime-picker",
+  "displayName": "uv-datetime-picker 时间选择器 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.15",
+  "description": "时间选择器组件用于时间日期,主要用于年月日时分的选择,具体选择的精确度由参数控制。",
+  "keywords": [
+    "datetime-picker",
+    "uvui",
+    "uv-ui",
+    "datetime",
+    "时间选择"
+],
+  "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",
+			"uv-picker"
+		],
+    "encrypt": [],
+    "platforms": {
+			"cloud": {
+				"tcb": "y",
+                "aliyun": "y",
+                "alipay": "n"
+			},
+			"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"
+				}
+			}
+		}
+  }
+}

+ 19 - 0
uni_modules/uv-datetime-picker/readme.md

@@ -0,0 +1,19 @@
+## DatetimePicker 时间选择器
+
+> **组件名:uv-datetime-picker**
+
+此选择器用于时间日期,主要用于年月日时分的选择,具体选择的精确度由参数控制。
+
+# <a href="https://www.uvui.cn/components/datetimePicker.html" target="_blank">查看文档</a>
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+</a>
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 9 - 0
uni_modules/uv-loading-icon/changelog.md

@@ -0,0 +1,9 @@
+## 1.0.3(2023-08-14)
+1. 新增参数textStyle,自定义文本样式
+## 1.0.2(2023-06-27)
+优化
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+1. 新增uv-loading-icon组件

+ 67 - 0
uni_modules/uv-loading-icon/components/uv-loading-icon/props.js

@@ -0,0 +1,67 @@
+export default {
+	props: {
+		// 是否显示组件
+		show: {
+			type: Boolean,
+			default: true
+		},
+		// 颜色
+		color: {
+			type: String,
+			default: '#909193'
+		},
+		// 提示文字颜色
+		textColor: {
+			type: String,
+			default: '#909193'
+		},
+		// 文字和图标是否垂直排列
+		vertical: {
+			type: Boolean,
+			default: false
+		},
+		// 模式选择,circle-圆形,spinner-花朵形,semicircle-半圆形
+		mode: {
+			type: String,
+			default: 'spinner'
+		},
+		// 图标大小,单位默认px
+		size: {
+			type: [String, Number],
+			default: 24
+		},
+		// 文字大小
+		textSize: {
+			type: [String, Number],
+			default: 15
+		},
+		// 文字样式
+		textStyle: {
+			type: Object,
+			default () {
+				return {}
+			}
+		},
+		// 文字内容
+		text: {
+			type: [String, Number],
+			default: ''
+		},
+		// 动画模式 https://www.runoob.com/cssref/css3-pr-animation-timing-function.html
+		timingFunction: {
+			type: String,
+			default: 'linear'
+		},
+		// 动画执行周期时间
+		duration: {
+			type: [String, Number],
+			default: 1200
+		},
+		// mode=circle时的暗边颜色
+		inactiveColor: {
+			type: String,
+			default: ''
+		},
+		...uni.$uv?.props?.loadingIcon
+	}
+}

+ 347 - 0
uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue

@@ -0,0 +1,347 @@
+<template>
+	<view
+		class="uv-loading-icon"
+		:style="[$uv.addStyle(customStyle)]"
+		:class="[vertical && 'uv-loading-icon--vertical']"
+		v-if="show"
+	>
+		<view
+			v-if="!webviewHide"
+			class="uv-loading-icon__spinner"
+			:class="[`uv-loading-icon__spinner--${mode}`]"
+			ref="ani"
+			:style="{
+				color: color,
+				width: $uv.addUnit(size),
+				height: $uv.addUnit(size),
+				borderTopColor: color,
+				borderBottomColor: otherBorderColor,
+				borderLeftColor: otherBorderColor,
+				borderRightColor: otherBorderColor,
+				'animation-duration': `${duration}ms`,
+				'animation-timing-function': mode === 'semicircle' || mode === 'circle' ? timingFunction : ''
+			}"
+		>
+			<block v-if="mode === 'spinner'">
+				<!-- #ifndef APP-NVUE -->
+				<view
+					v-for="(item, index) in array12"
+					:key="index"
+					class="uv-loading-icon__dot"
+				>
+				</view>
+				<!-- #endif -->
+				<!-- #ifdef APP-NVUE -->
+				<!-- 此组件内部图标部分无法设置宽高,即使通过width和height配置了也无效 -->
+				<loading-indicator
+					v-if="!webviewHide"
+					class="uv-loading-indicator"
+					:animating="true"
+					:style="{
+						color: color,
+						width: $uv.addUnit(size),
+						height: $uv.addUnit(size)
+					}"
+				/>
+				<!-- #endif -->
+			</block>
+		</view>
+		<text
+			v-if="text"
+			class="uv-loading-icon__text"
+			:style="[{
+				fontSize: $uv.addUnit(textSize),
+				color: textColor,
+			},$uv.addStyle(textStyle)]"
+		>{{text}}</text>
+	</view>
+</template>
+
+<script>
+	import { colorGradient } from '@/uni_modules/uv-ui-tools/libs/function/colorGradient.js'
+	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';
+	// #ifdef APP-NVUE
+	const animation = weex.requireModule('animation');
+	// #endif
+	/**
+	 * loading 加载动画
+	 * @description 警此组件为一个小动画,目前用在uvui的loadmore加载更多和switch开关等组件的正在加载状态场景。
+	 * @tutorial https://www.uvui.cn/components/loading.html
+	 * @property {Boolean}			show			是否显示组件  (默认 true)
+	 * @property {String}			color			动画活动区域的颜色,只对 mode = flower 模式有效(默认#909193)
+	 * @property {String}			textColor		提示文本的颜色(默认#909193)
+	 * @property {Boolean}			vertical		文字和图标是否垂直排列 (默认 false )
+	 * @property {String}			mode			模式选择,见官网说明(默认 'circle' )
+	 * @property {String | Number}	size			加载图标的大小,单位px (默认 24 )
+	 * @property {String | Number}	textSize		文字大小(默认 15 )
+	 * @property {String | Number}	text			文字内容 
+	 * @property {Object}	textStyle 文字样式
+	 * @property {String}			timingFunction	动画模式 (默认 'ease-in-out' )
+	 * @property {String | Number}	duration		动画执行周期时间(默认 1200)
+	 * @property {String}			inactiveColor	mode=circle时的暗边颜色 
+	 * @property {Object}			customStyle		定义需要用到的外部样式
+	 * @example <uv-loading mode="circle"></uv-loading>
+	 */
+	export default {
+		name: 'uv-loading-icon',
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+				// Array.form可以通过一个伪数组对象创建指定长度的数组
+				// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/from
+				array12: Array.from({
+					length: 12
+				}),
+				// 这里需要设置默认值为360,否则在安卓nvue上,会延迟一个duration周期后才执行
+				// 在iOS nvue上,则会一开始默认执行两个周期的动画
+				aniAngel: 360, // 动画旋转角度
+				webviewHide: false, // 监听webview的状态,如果隐藏了页面,则停止动画,以免性能消耗
+				loading: false, // 是否运行中,针对nvue使用
+			}
+		},
+		computed: {
+			// 当为circle类型时,给其另外三边设置一个更轻一些的颜色
+			// 之所以需要这么做的原因是,比如父组件传了color为红色,那么需要另外的三个边为浅红色
+			// 而不能是固定的某一个其他颜色(因为这个固定的颜色可能浅蓝,导致效果没有那么细腻良好)
+			otherBorderColor() {
+				const lightColor = colorGradient(this.color, '#ffffff', 100)[80]
+				if (this.mode === 'circle') {
+					return this.inactiveColor ? this.inactiveColor : lightColor
+				} else {
+					return 'transparent'
+				}
+			}
+		},
+		watch: {
+			show(n) {
+				// nvue中,show为true,且为非loading状态,就重新执行动画模块
+				// #ifdef APP-NVUE
+				if (n && !this.loading) {
+					setTimeout(() => {
+						this.startAnimate()
+					}, 30)
+				}
+				// #endif
+			}
+		},
+		mounted() {
+			this.init()
+		},
+		methods: {
+			init() {
+				setTimeout(() => {
+					// #ifdef APP-NVUE
+					this.show && this.nvueAnimate()
+					// #endif
+					// #ifdef APP-PLUS 
+					this.show && this.addEventListenerToWebview()
+					// #endif
+				}, 20)
+			},
+			// 监听webview的显示与隐藏
+			addEventListenerToWebview() {
+				// webview的堆栈
+				const pages = getCurrentPages()
+				// 当前页面
+				const page = pages[pages.length - 1]
+				// 当前页面的webview实例
+				const currentWebview = page.$getAppWebview()
+				// 监听webview的显示与隐藏,从而停止或者开始动画(为了性能)
+				currentWebview.addEventListener('hide', () => {
+					this.webviewHide = true
+				})
+				currentWebview.addEventListener('show', () => {
+					this.webviewHide = false
+				})
+			},
+			// #ifdef APP-NVUE
+			nvueAnimate() {
+				// nvue下,非spinner类型时才需要旋转,因为nvue的spinner类型,使用了weex的
+				// loading-indicator组件,自带旋转功能
+				this.mode !== 'spinner' && this.startAnimate()
+			},
+			// 执行nvue的animate模块动画
+			startAnimate() {
+				this.loading = true
+				const ani = this.$refs.ani
+				if (!ani) return
+				animation.transition(ani, {
+					// 进行角度旋转
+					styles: {
+						transform: `rotate(${this.aniAngel}deg)`,
+						transformOrigin: 'center center'
+					},
+					duration: this.duration,
+					timingFunction: this.timingFunction,
+					// delay: 10
+				}, () => {
+					// 每次增加360deg,为了让其重新旋转一周
+					this.aniAngel += 360
+					// 动画结束后,继续循环执行动画,需要同时判断webviewHide变量
+					// nvue安卓,页面隐藏后依然会继续执行startAnimate方法
+					this.show && !this.webviewHide ? this.startAnimate() : this.loading = false
+				})
+			}
+			// #endif
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
+	@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
+	$uv-loading-icon-color: #c8c9cc !default;
+	$uv-loading-icon-text-margin-left:4px !default;
+	$uv-loading-icon-text-color:$uv-content-color !default;
+	$uv-loading-icon-text-font-size:14px !default;
+	$uv-loading-icon-text-line-height:20px !default;
+	$uv-loading-width:30px !default;
+	$uv-loading-height:30px !default;
+	$uv-loading-max-width:100% !default;
+	$uv-loading-max-height:100% !default;
+	$uv-loading-semicircle-border-width: 2px !default;
+	$uv-loading-semicircle-border-color:transparent !default;
+	$uv-loading-semicircle-border-top-right-radius: 100px !default;
+	$uv-loading-semicircle-border-top-left-radius: 100px !default;
+	$uv-loading-semicircle-border-bottom-left-radius: 100px !default;
+	$uv-loading-semicircle-border-bottom-right-radiu: 100px !default;
+	$uv-loading-semicircle-border-style: solid !default;
+	$uv-loading-circle-border-top-right-radius: 100px !default;
+	$uv-loading-circle-border-top-left-radius: 100px !default;
+	$uv-loading-circle-border-bottom-left-radius: 100px !default;
+	$uv-loading-circle-border-bottom-right-radiu: 100px !default;
+	$uv-loading-circle-border-width:2px !default;
+	$uv-loading-circle-border-top-color:#e5e5e5 !default;
+	$uv-loading-circle-border-right-color:$uv-loading-circle-border-top-color !default;
+	$uv-loading-circle-border-bottom-color:$uv-loading-circle-border-top-color !default;
+	$uv-loading-circle-border-left-color:$uv-loading-circle-border-top-color !default;
+	$uv-loading-circle-border-style:solid !default;
+	$uv-loading-icon-host-font-size:0px !default;
+	$uv-loading-icon-host-line-height:1 !default;
+	$uv-loading-icon-vertical-margin:6px 0 0 !default;
+	$uv-loading-icon-dot-top:0 !default;
+	$uv-loading-icon-dot-left:0 !default;
+	$uv-loading-icon-dot-width:100% !default;
+	$uv-loading-icon-dot-height:100% !default;
+	$uv-loading-icon-dot-before-width:2px !default;
+	$uv-loading-icon-dot-before-height:25% !default;
+	$uv-loading-icon-dot-before-margin:0 auto !default;
+	$uv-loading-icon-dot-before-background-color:currentColor !default;
+	$uv-loading-icon-dot-before-border-radius:40% !default;
+
+	.uv-loading-icon {
+		/* #ifndef APP-NVUE */
+		// display: inline-flex;
+		/* #endif */
+		flex-direction: row;
+		align-items: center;
+		justify-content: center;
+		color: $uv-loading-icon-color;
+
+		&__text {
+			margin-left: $uv-loading-icon-text-margin-left;
+			color: $uv-loading-icon-text-color;
+			font-size: $uv-loading-icon-text-font-size;
+			line-height: $uv-loading-icon-text-line-height;
+		}
+
+		&__spinner {
+			width: $uv-loading-width;
+			height: $uv-loading-height;
+			position: relative;
+			/* #ifndef APP-NVUE */
+			box-sizing: border-box;
+			max-width: $uv-loading-max-width;
+			max-height: $uv-loading-max-height;
+			animation: uv-rotate 1s linear infinite;
+			/* #endif */
+		}
+
+		&__spinner--semicircle {
+			border-width: $uv-loading-semicircle-border-width;
+			border-color: $uv-loading-semicircle-border-color;
+			border-top-right-radius: $uv-loading-semicircle-border-top-right-radius;
+			border-top-left-radius: $uv-loading-semicircle-border-top-left-radius;
+			border-bottom-left-radius: $uv-loading-semicircle-border-bottom-left-radius;
+			border-bottom-right-radius: $uv-loading-semicircle-border-bottom-right-radiu;
+			border-style: $uv-loading-semicircle-border-style;
+		}
+
+		&__spinner--circle {
+			border-top-right-radius: $uv-loading-circle-border-top-right-radius;
+			border-top-left-radius: $uv-loading-circle-border-top-left-radius;
+			border-bottom-left-radius: $uv-loading-circle-border-bottom-left-radius;
+			border-bottom-right-radius: $uv-loading-circle-border-bottom-right-radiu;
+			border-width: $uv-loading-circle-border-width;
+			border-top-color: $uv-loading-circle-border-top-color;
+			border-right-color: $uv-loading-circle-border-right-color;
+			border-bottom-color: $uv-loading-circle-border-bottom-color;
+			border-left-color: $uv-loading-circle-border-left-color;
+			border-style: $uv-loading-circle-border-style;
+		}
+
+		&--vertical {
+			flex-direction: column
+		}
+	}
+
+	/* #ifndef APP-NVUE */
+	:host {
+		font-size: $uv-loading-icon-host-font-size;
+		line-height: $uv-loading-icon-host-line-height;
+	}
+
+	.uv-loading-icon {
+		&__spinner--spinner {
+			animation-timing-function: steps(12)
+		}
+
+		&__text:empty {
+			display: none
+		}
+
+		&--vertical &__text {
+			margin: $uv-loading-icon-vertical-margin;
+			color: $uv-content-color;
+		}
+
+		&__dot {
+			position: absolute;
+			top: $uv-loading-icon-dot-top;
+			left: $uv-loading-icon-dot-left;
+			width: $uv-loading-icon-dot-width;
+			height: $uv-loading-icon-dot-height;
+
+			&:before {
+				display: block;
+				width: $uv-loading-icon-dot-before-width;
+				height: $uv-loading-icon-dot-before-height;
+				margin: $uv-loading-icon-dot-before-margin;
+				background-color: $uv-loading-icon-dot-before-background-color;
+				border-radius: $uv-loading-icon-dot-before-border-radius;
+				content: " "
+			}
+		}
+	}
+
+	@for $i from 1 through 12 {
+		.uv-loading-icon__dot:nth-of-type(#{$i}) {
+			transform: rotate($i * 30deg);
+			opacity: 1 - 0.0625 * ($i - 1);
+		}
+	}
+
+	@keyframes uv-rotate {
+		0% {
+			transform: rotate(0deg)
+		}
+
+		to {
+			transform: rotate(1turn)
+		}
+	}
+
+	/* #endif */
+</style>

+ 87 - 0
uni_modules/uv-loading-icon/package.json

@@ -0,0 +1,87 @@
+{
+  "id": "uv-loading-icon",
+  "displayName": "uv-loading-icon 加载动画 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.3",
+  "description": "此组件为一个小动画,目前用在uv-ui的uv-load-more加载更多等组件,还可以运用在项目中正在加载状态场景。",
+  "keywords": [
+    "uv-loading-icon",
+    "uvui",
+    "uv-ui",
+    "loading",
+    "加载动画"
+],
+  "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"
+				}
+			}
+		}
+  }
+}

+ 19 - 0
uni_modules/uv-loading-icon/readme.md

@@ -0,0 +1,19 @@
+## LoadingIcon 加载动画
+
+> **组件名:uv-loading-icon**
+
+此组件为一个小动画,目前用在 `uv-ui` 的 `uv-load-more` 加载更多等组件,还可以运用在项目中正在加载状态场景。
+
+# <a href="https://www.uvui.cn/components/loadingIcon.html" target="_blank">查看文档</a>
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+</a>
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

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

@@ -0,0 +1,9 @@
+## 1.0.3(2023-07-02)
+uv-overlay  由于弹出层uv-transition的修改,组件内部做了相应的修改,参数不变。
+## 1.0.2(2023-06-29)
+1. 优化,H5端禁止穿透滚动
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+1. 新增uv-overlay组件

+ 25 - 0
uni_modules/uv-overlay/components/uv-overlay/props.js

@@ -0,0 +1,25 @@
+export default {
+	props: {
+		// 是否显示遮罩
+		show: {
+			type: Boolean,
+			default: false
+		},
+		// 层级z-index
+		zIndex: {
+			type: [String, Number],
+			default: 10070
+		},
+		// 遮罩的过渡时间,单位为ms
+		duration: {
+			type: [String, Number],
+			default: 300
+		},
+		// 不透明度值,当做rgba的第四个参数
+		opacity: {
+			type: [String, Number],
+			default: 0.5
+		},
+		...uni.$uv?.props?.overlay
+	}
+}

+ 85 - 0
uni_modules/uv-overlay/components/uv-overlay/uv-overlay.vue

@@ -0,0 +1,85 @@
+<template>
+	<uv-transition
+	  :show="show"
+		mode="fade"
+	  custom-class="uv-overlay"
+	  :duration="duration"
+	  :custom-style="overlayStyle"
+	  @click="clickHandler"
+		@touchmove.stop.prevent="clear"
+	>
+		<slot />
+	</uv-transition>
+</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';
+
+	/**
+	 * overlay 遮罩
+	 * @description 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景
+	 * @tutorial https://www.uvui.cn/components/overlay.html
+	 * @property {Boolean}			show		是否显示遮罩(默认 false )
+	 * @property {String | Number}	zIndex		zIndex 层级(默认 10070 )
+	 * @property {String | Number}	duration	动画时长,单位毫秒(默认 300 )
+	 * @property {String | Number}	opacity		不透明度值,当做rgba的第四个参数 (默认 0.5 )
+	 * @property {Object}			customStyle	定义需要用到的外部样式
+	 * @event {Function} click 点击遮罩发送事件
+	 * @example <uv-overlay :show="show" @click="show = false"></uv-overlay>
+	 */
+	export default {
+		name: "uv-overlay",
+		emits: ['click'],
+		mixins: [mpMixin, mixin, props],
+		watch: {
+			show(newVal){
+				// #ifdef H5
+				if(newVal){
+					document.querySelector('body').style.overflow = 'hidden';
+				}else{
+					document.querySelector('body').style.overflow = '';
+				}
+				// #endif
+			}
+		},
+		computed: {
+			overlayStyle() {
+				const style = {
+					position: 'fixed',
+					top: 0,
+					left: 0,
+					right: 0,
+					zIndex: this.zIndex,
+					bottom: 0,
+					'background-color': `rgba(0, 0, 0, ${this.opacity})`
+				}
+				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
+			}
+		},
+		methods: {
+			clickHandler() {
+				this.$emit('click')
+			},
+			clear() {}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+/* #ifndef APP-NVUE */
+$uv-overlay-top:0 !default;
+$uv-overlay-left:0 !default;
+$uv-overlay-width:100% !default;
+$uv-overlay-height:100% !default;
+$uv-overlay-background-color:rgba(0, 0, 0, .7) !default;
+.uv-overlay {
+	position: fixed;
+	top:$uv-overlay-top;
+	left:$uv-overlay-left;
+	width: $uv-overlay-width;
+	height:$uv-overlay-height;
+	background-color:$uv-overlay-background-color;
+}
+/* #endif */
+</style>

+ 88 - 0
uni_modules/uv-overlay/package.json

@@ -0,0 +1,88 @@
+{
+  "id": "uv-overlay",
+  "displayName": "uv-overlay 遮罩层  全面兼容小程序、nvue、vue2、vue3等多端",
+  "version": "1.0.3",
+  "description": "uv-overlay 创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。",
+  "keywords": [
+    "uv-overlay",
+    "uvui",
+    "uv-ui",
+    "overlay",
+    "遮罩层"
+],
+  "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",
+			"uv-transition"
+		],
+    "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-overlay/readme.md

@@ -0,0 +1,11 @@
+## Overlay 遮罩层
+
+> **组件名:uv-overlay**
+
+创建一个遮罩层,用于强调特定的页面元素,并阻止用户对遮罩下层的内容进行操作,一般用于弹窗场景,uv-popup、uv-toast、uv-tooltip等组件就是用了该组件。
+
+### <a href="https://www.uvui.cn/components/overlay.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>

+ 33 - 0
uni_modules/uv-picker/changelog.md

@@ -0,0 +1,33 @@
+## 1.0.14(2023-12-29)
+1. 修复上个版本引出的BUG
+## 1.0.13(2023-12-26)
+1. 修复抖音小程序滚到底不触发change的BUG
+## 1.0.12(2023-11-20)
+1. 修复issues反馈的问题uv-picker在组合式API的自定义组件中,columns动态赋值无法显示选项:https://gitee.com/climblee/uv-ui/issues/I8H0GQ
+## 1.0.11(2023-10-11)
+1. 将immediate-change默认值改为true,该值在于change回调的及时性,微信小程序生效
+## 1.0.10(2023-08-25)
+1. 增加round属性设置弹窗圆角,默认为0
+## 1.0.9(2023-08-24)
+1. 修复cli项目不返回值的问题
+## 1.0.8(2023-08-04)
+1. 优化
+## 1.0.7(2023-08-02)
+1. 改组件中删除uv-toolbar组件,请单独下载uv-toolbar组件
+## 1.0.6(2023-07-02)
+uv-picker  由于弹出层uv-popup的修改,打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/picker.html
+## 1.0.5(2023-06-26)
+1. 增加color参数
+2. 增加activeColor参数
+## 1.0.4(2023-06-15)
+1. 修改支付宝报错的BUG
+## 1.0.3(2023-06-12)
+1. setColumnValues的使用统一化,避免某些平台报错
+2. 取消change回调回传的组件实例,直接统一通过ref的方式调取setColumnValues方法
+## 1.0.2(2023-05-23)
+1. uv-toolbar组件新增下边框属性 
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+uv-picker 选择器

+ 95 - 0
uni_modules/uv-picker/components/uv-picker/props.js

@@ -0,0 +1,95 @@
+export default {
+	props: {
+		// 是否展示顶部的操作栏
+		showToolbar: {
+			type: Boolean,
+			default: true
+		},
+		// 顶部标题
+		title: {
+			type: String,
+			default: ''
+		},
+		// 弹窗圆角
+		round: {
+			type: [String, Number],
+			default: 0
+		},
+		// 对象数组,设置每一列的数据
+		columns: {
+			type: Array,
+			default: () => []
+		},
+		// 是否显示加载中状态
+		loading: {
+			type: Boolean,
+			default: false
+		},
+		// 各列中,单个选项的高度
+		itemHeight: {
+			type: [String, Number],
+			default: 44
+		},
+		// 取消按钮的文字
+		cancelText: {
+			type: String,
+			default: '取消'
+		},
+		// 确认按钮的文字
+		confirmText: {
+			type: String,
+			default: '确定'
+		},
+		// 取消按钮的颜色
+		cancelColor: {
+			type: String,
+			default: '#909193'
+		},
+		// 确认按钮的颜色
+		confirmColor: {
+			type: String,
+			default: '#3c9cff'
+		},
+		// 文字颜色
+		color: {
+			type: String,
+			default: ''
+		},
+		// 选中文字的颜色
+		activeColor: {
+			type: String,
+			default: ''
+		},
+		// 每列中可见选项的数量
+		visibleItemCount: {
+			type: [String, Number],
+			default: 5
+		},
+		// 选项对象中,需要展示的属性键名
+		keyName: {
+			type: String,
+			default: 'text'
+		},
+		// 是否允许点击遮罩关闭选择器
+		closeOnClickOverlay: {
+			type: Boolean,
+			default: true
+		},
+		// 是否允许点击确认关闭选择器
+		closeOnClickConfirm: {
+			type: Boolean,
+			default: true
+		},
+		// 各列的默认索引
+		defaultIndex: {
+			type: Array,
+			default: () => [],
+		},
+		// 是否在手指松开时立即触发 change 事件。若不开启则会在滚动动画结束后触发 change 事件,只在微信2.21.1及以上有效
+		immediateChange: {
+			type: Boolean,
+			default: true
+		},
+		...uni.$uv?.props?.picker
+	}
+}

+ 330 - 0
uni_modules/uv-picker/components/uv-picker/uv-picker.vue

@@ -0,0 +1,330 @@
+<template>
+	<uv-popup
+		ref="pickerPopup"
+		mode="bottom"
+		:round="round"
+		:close-on-click-overlay="closeOnClickOverlay"
+		@change="popupChange"
+	>
+		<view class="uv-picker">
+			<uv-toolbar
+				v-if="showToolbar"
+				:cancelColor="cancelColor"
+				:confirmColor="confirmColor"
+				:cancelText="cancelText"
+				:confirmText="confirmText"
+				:title="title"
+				@cancel="cancel"
+				@confirm="confirm"
+			></uv-toolbar>
+			<!-- #ifdef MP-TOUTIAO -->
+			<picker-view
+				class="uv-picker__view"
+				:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
+				:value="innerIndex"
+				:immediateChange="immediateChange"
+				:style="{
+					height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
+				}"
+				@pickend="changeHandler"
+			>
+			<!-- #endif -->
+			<!-- #ifndef MP-TOUTIAO -->
+			<picker-view
+				class="uv-picker__view"
+				:indicatorStyle="`height: ${$uv.addUnit(itemHeight)}`"
+				:value="innerIndex"
+				:immediateChange="immediateChange"
+				:style="{
+					height: `${$uv.addUnit(visibleItemCount * itemHeight)}`
+				}"
+				@change="changeHandler"
+			>
+			<!-- #endif -->
+			<!-- @pickend在这里为了解决抖音等滚到底不触发change兼容性问题 -->
+				<picker-view-column
+					v-for="(item, index) in innerColumns"
+					:key="index"
+					class="uv-picker__view__column"
+				>
+					<text
+						v-if="$uv.test.array(item)"
+						class="uv-picker__view__column__item uv-line-1"
+						v-for="(item1, index1) in item"
+						:key="index1"
+						:style="[{
+								height: $uv.addUnit(itemHeight),
+								lineHeight: $uv.addUnit(itemHeight),
+								fontWeight: index1 === innerIndex[index] ? 'bold' : 'normal'
+							},textStyle(index,index1)]"
+					>{{ getItemText(item1) }}</text>
+				</picker-view-column>
+			</picker-view>
+			<view
+				v-if="loading"
+				class="uv-picker--loading"
+			>
+				<uv-loading-icon mode="circle"></uv-loading-icon>
+			</view>
+		</view>
+	</uv-popup>
+</template>
+
+<script>
+/**
+ * uv-picker
+ * @description 选择器
+ * @property {Boolean}			showToolbar			是否显示顶部的操作栏(默认 true )
+ * @property {String}			title				顶部标题
+ * @property {Array}			columns				对象数组,设置每一列的数据
+ * @property {Boolean}			loading				是否显示加载中状态(默认 false )
+ * @property {String | Number}	itemHeight			各列中,单个选项的高度(默认 44 )
+ * @property {String}			cancelText			取消按钮的文字(默认 '取消' )
+ * @property {String}			confirmText			确认按钮的文字(默认 '确定' )
+ * @property {String}			cancelColor			取消按钮的颜色(默认 '#909193' )
+ * @property {String}			confirmColor		确认按钮的颜色(默认 '#3c9cff' )
+ * @property {String}			color		文字颜色(默认 '' )
+ * @property {String}			activeColor		选中文字的颜色(默认 '' )
+ * @property {String | Number}	visibleItemCount	每列中可见选项的数量(默认 5 )
+ * @property {String}			keyName				选项对象中,需要展示的属性键名(默认 'text' )
+ * @property {Boolean}			closeOnClickOverlay	是否允许点击遮罩关闭选择器(默认 false )
+ * @property {Array}			defaultIndex		各列的默认索引
+ * @property {Boolean}			immediateChange		是否在手指松开时立即触发change事件(默认 false )
+ * @event {Function} close		关闭选择器时触发
+ * @event {Function} cancel		点击取消按钮触发
+ * @event {Function} change		当选择值变化时触发
+ * @event {Function} confirm	点击确定按钮,返回当前选择的值
+ */
+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';
+export default {
+	name: 'uv-picker',
+	emits: ['confirm','cancel','close','change'],
+	mixins: [mpMixin, mixin, props],
+	computed: {
+		// 为了解决支付宝不生效
+		textStyle(){
+			return (index,index1) => {
+				const style = {};
+				// #ifndef APP-NVUE 
+				style.display = 'block';
+				// #endif
+				if(this.color) {
+					style.color = this.color;
+				}
+				if(this.activeColor && index1 === this.innerIndex[index]) {
+					style.color = this.activeColor;
+				}
+				return style;
+			}
+		}
+	},
+	data() {
+		return {
+			// 上一次选择的列索引
+			lastIndex: [],
+			// 索引值 ,对应picker-view的value
+			innerIndex: [],
+			// 各列的值
+			innerColumns: [],
+			// 上一次的变化列索引
+			columnIndex: 0,
+		}
+	},
+	watch: {
+		// 监听默认索引的变化,重新设置对应的值
+		defaultIndex: {
+			immediate: true,
+			handler(n) {
+				this.setIndexs(n, true)
+			}
+		},
+		// 监听columns参数的变化
+		columns: {
+			deep: true,
+			immediate: true,
+			handler(n) {
+				this.setColumns(n)
+			}
+		},
+	},
+	methods: {
+		open() {
+			this.$refs.pickerPopup.open();
+		},
+		close() {
+			this.$refs.pickerPopup.close();
+		},
+		popupChange(e) {
+			if(!e.show) this.$emit('close');
+		},
+		// 获取item需要显示的文字,判别为对象还是文本
+		getItemText(item) {
+			if (this.$uv.test.object(item)) {
+				return item[this.keyName]
+			} else {
+				return item
+			}
+		},
+		// 点击工具栏的取消按钮
+		cancel() {
+			this.$emit('cancel');
+			this.close();
+		},
+		// 点击工具栏的确定按钮
+		confirm() {
+			// 在这里使用deepClone拷贝后,vue3会自动转换成原始对象,这样处理是因为cli项目可能出现不返回值的情况
+			this.$emit('confirm', this.$uv.deepClone({
+				indexs: this.innerIndex,
+				value: this.innerColumns.map((item, index) => item[this.innerIndex[index]]),
+				values: this.innerColumns
+			}));
+			if(this.closeOnClickConfirm) {
+				this.close();
+			}
+		},
+		// 选择器某一列的数据发生变化时触发
+		changeHandler(e) {
+			const {
+				value
+			} = e.detail
+			let index = 0,
+				columnIndex = 0
+			// 通过对比前后两次的列索引,得出当前变化的是哪一列
+			for (let i = 0; i < value.length; i++) {
+				let item = value[i]
+				if (item !== (this.lastIndex[i] || 0)) { // 把undefined转为合法假值0
+					// 设置columnIndex为当前变化列的索引
+					columnIndex = i
+					// index则为变化列中的变化项的索引
+					index = item
+					break // 终止循环,即使少一次循环,也是性能的提升
+				}
+			}
+			this.columnIndex = columnIndex
+			const values = this.innerColumns
+			// 将当前的各项变化索引,设置为"上一次"的索引变化值
+			this.setLastIndex(value)
+			this.setIndexs(value)
+
+			this.$emit('change', {
+				value: this.innerColumns.map((item, index) => item[value[index]]),
+				index,
+				indexs: value,
+				// values为当前变化列的数组内容
+				values,
+				columnIndex
+			})
+		},
+		// 设置index索引,此方法可被外部调用设置
+		setIndexs(index, setLastIndex) {
+			this.innerIndex = this.$uv.deepClone(index)
+			if (setLastIndex) {
+				this.setLastIndex(index)
+			}
+		},
+		// 记录上一次的各列索引位置
+		setLastIndex(index) {
+			// 当能进入此方法,意味着当前设置的各列默认索引,即为“上一次”的选中值,需要记录,是因为changeHandler中
+			// 需要拿前后的变化值进行对比,得出当前发生改变的是哪一列
+			this.lastIndex = this.$uv.deepClone(index)
+		},
+		// 设置对应列选项的所有值
+		setColumnValues(columnIndex, values) {
+			// 替换innerColumns数组中columnIndex索引的值为values,使用的是数组的splice方法
+			this.innerColumns.splice(columnIndex, 1, values)
+			// 拷贝一份原有的innerIndex做临时变量,将大于当前变化列的所有的列的默认索引设置为0
+			let tmpIndex = this.$uv.deepClone(this.innerIndex)
+			for (let i = 0; i < this.innerColumns.length; i++) {
+				if (i > this.columnIndex) {
+					tmpIndex[i] = 0
+				}
+			}
+			// 一次性赋值,不能单个修改,否则无效
+			this.setIndexs(tmpIndex)
+		},
+		// 获取对应列的所有选项
+		getColumnValues(columnIndex) {
+			// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
+			// 索引如果在外部change的回调中调用getColumnValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
+			(async () => {
+				await this.$uv.sleep()
+			})()
+			return this.innerColumns[columnIndex]
+		},
+		// 设置整体各列的columns的值
+		setColumns(columns) {
+			this.innerColumns = this.$uv.deepClone(columns)
+			// 如果在设置各列数据时,没有被设置默认的各列索引defaultIndex,那么用0去填充它,数组长度为列的数量
+			if (this.innerIndex.length === 0) {
+				this.innerIndex = new Array(columns.length).fill(0)
+			}
+		},
+		// 获取各列选中值对应的索引
+		getIndexs() {
+			return this.innerIndex
+		},
+		// 获取各列选中的值
+		getValues() {
+			// 进行同步阻塞,因为外部得到change事件之后,可能需要执行setColumnValues更新列的值
+			// 索引如果在外部change的回调中调用getValues的话,可能无法得到变更后的列值,这里进行一定延时,保证值的准确性
+			(async () => {
+				await this.$uv.sleep()
+			})()
+			return this.innerColumns.map((item, index) => item[this.innerIndex[index]])
+		}
+	},
+}
+</script>
+
+<style lang="scss" scoped>
+	$show-lines: 1;
+	@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
+	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
+	@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
+	.uv-picker {
+		position: relative;
+
+		&__view {
+
+			&__column {
+				@include flex;
+				flex: 1;
+				justify-content: center;
+
+				&__item {
+					@include flex;
+					justify-content: center;
+					align-items: center;
+					font-size: 16px;
+					text-align: center;
+					/* #ifndef APP-NVUE */
+					display: block;
+					/* #endif */
+					color: $uv-main-color;
+
+					&--disabled {
+						/* #ifndef APP-NVUE */
+						cursor: not-allowed;
+						/* #endif */
+						opacity: 0.35;
+					}
+				}
+			}
+		}
+
+		&--loading {
+			position: absolute;
+			top: 0;
+			right: 0;
+			left: 0;
+			bottom: 0;
+			@include flex;
+			justify-content: center;
+			align-items: center;
+			background-color: rgba(255, 255, 255, 0.87);
+			z-index: 1000;
+		}
+	}
+</style>

+ 90 - 0
uni_modules/uv-picker/package.json

@@ -0,0 +1,90 @@
+{
+  "id": "uv-picker",
+  "displayName": "uv-picker 选择器 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.14",
+  "description": "uv-picker 此选择器用于单列,多列,多列联动的选择场景...",
+  "keywords": [
+    "uv-picker",
+    "uvui",
+    "uv-ui",
+    "picker",
+    "联动选择"
+],
+  "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",
+			"uv-popup",
+			"uv-loading-icon",
+			"uv-toolbar"
+		],
+    "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"
+				}
+			}
+		}
+  }
+}

+ 21 - 0
uni_modules/uv-picker/readme.md

@@ -0,0 +1,21 @@
+## Picker 选择器
+
+> **组件名:uv-picker**
+
+此选择器用于单列,多列,多列联动的选择场景。
+
+`uv-datetime-picker`等组件也用到了该组件,功能完善,需要特别注意的是`columns`参数的形式是数组嵌套。
+
+# <a href="https://www.uvui.cn/components/picker.html" target="_blank">查看文档</a>
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+</a>
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 18 - 0
uni_modules/uv-popup/changelog.md

@@ -0,0 +1,18 @@
+## 1.0.7(2023-11-20)
+修复issues问题:https://gitee.com/climblee/uv-ui/issues/I8HDLO
+## 1.0.6(2023-10-13)
+1. 优化vue,内容有背景色,设置圆角被遮挡的情况
+## 1.0.5(2023-09-10)
+1. 修复H5默认层级过高的问题
+2. 修复全局设置prop无效的问题
+## 1.0.4(2023-08-08)
+1. 修复修改zIndex不生效的BUG
+## 1.0.3(2023-07-02)
+uv-popup  弹出层,代码重构优化,性能翻倍,小程序体验性能更加,避免卡顿。打开和关闭方法更改,详情参考文档:https://www.uvui.cn/components/popup.html
+## 1.0.2(2023-06-11)
+1. 修复zIndex层级问题
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+1. 新增uv-popup组件

+ 45 - 0
uni_modules/uv-popup/components/uv-popup/keypress.js

@@ -0,0 +1,45 @@
+// #ifdef H5
+export default {
+  name: 'Keypress',
+  props: {
+    disable: {
+      type: Boolean,
+      default: false
+    }
+  },
+  mounted () {
+    const keyNames = {
+      esc: ['Esc', 'Escape'],
+      tab: 'Tab',
+      enter: 'Enter',
+      space: [' ', 'Spacebar'],
+      up: ['Up', 'ArrowUp'],
+      left: ['Left', 'ArrowLeft'],
+      right: ['Right', 'ArrowRight'],
+      down: ['Down', 'ArrowDown'],
+      delete: ['Backspace', 'Delete', 'Del']
+    }
+    const listener = ($event) => {
+      if (this.disable) {
+        return
+      }
+      const keyName = Object.keys(keyNames).find(key => {
+        const keyName = $event.key
+        const value = keyNames[key]
+        return value === keyName || (Array.isArray(value) && value.includes(keyName))
+      })
+      if (keyName) {
+        // 避免和其他按键事件冲突
+        setTimeout(() => {
+          this.$emit(keyName, {})
+        }, 0)
+      }
+    }
+    document.addEventListener('keyup', listener)
+    // this.$once('hook:beforeDestroy', () => {
+    //   document.removeEventListener('keyup', listener)
+    // })
+  },
+	render: () => {}
+}
+// #endif

+ 539 - 0
uni_modules/uv-popup/components/uv-popup/uv-popup.vue

@@ -0,0 +1,539 @@
+<template>
+	<view 
+		v-if="showPopup" 
+		class="uv-popup" 
+		:class="[popupClass, isDesktop ? 'fixforpc-z-index' : '']"
+		:style="[{zIndex: zIndex}]"
+	>
+		<view @touchstart="touchstart">
+			<!-- 遮罩层 -->
+			<uv-overlay
+				key="1"
+				v-if="maskShow && overlay"
+				:show="showTrans"
+				:duration="duration"
+				:custom-style="overlayStyle"
+				:opacity="overlayOpacity"
+			  :zIndex="zIndex"
+				@click="onTap"
+			></uv-overlay>
+			<uv-transition 
+				key="2" 
+				:mode="ani" 
+				name="content" 
+				:custom-style="transitionStyle" 
+				:duration="duration"
+				:show="showTrans" 
+				@click="onTap"
+			>
+				<view 
+					class="uv-popup__content" 
+					:style="[contentStyle]" 
+					:class="[popupClass]" 
+					@click="clear"
+				>
+					<uv-status-bar v-if="safeAreaInsetTop"></uv-status-bar>
+					<slot />
+					<uv-safe-bottom v-if="safeAreaInsetBottom"></uv-safe-bottom>
+					<view
+						v-if="closeable"
+						@tap.stop="close"
+						class="uv-popup__content__close"
+						:class="['uv-popup__content__close--' + closeIconPos]"
+						hover-class="uv-popup__content__close--hover"
+						hover-stay-time="150"
+					>
+						<uv-icon
+							name="close"
+							color="#909399"
+							size="18"
+							bold
+						></uv-icon>
+					</view>
+				</view>
+			</uv-transition>
+		</view>
+		<!-- #ifdef H5 -->
+		<keypress v-if="maskShow" @esc="onTap" />
+		<!-- #endif -->
+	</view>
+</template>
+
+<script>
+	// #ifdef H5
+	import keypress from './keypress.js'
+	// #endif
+	import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
+	import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
+	/**
+	* PopUp 弹出层
+	* @description 弹出层组件,为了解决遮罩弹层的问题
+	* @tutorial https://www.uvui.cn/components/popup.html
+	* @property {String} mode = [top|center|bottom|left|right] 弹出方式
+	* 	@value top 顶部弹出
+	* 	@value center 中间弹出
+	* 	@value bottom 底部弹出
+	* 	@value left		左侧弹出
+	* 	@value right  右侧弹出
+	* @property {Number} duration 动画时长,默认300
+	* @property {Boolean} overlay 是否显示遮罩,默认true
+	* @property {Boolean} overlayOpacity 遮罩透明度,默认0.5 
+	* @property {Object} overlayStyle 遮罩自定义样式
+	* @property {Boolean} closeOnClickOverlay = [true|false] 蒙版点击是否关闭弹窗,默认true
+	* @property {Number | String} zIndex 弹出层的层级
+	* @property {Boolean} safeAreaInsetTop 是否留出顶部安全区(状态栏高度),默认false
+	* @property {Boolean} safeAreaInsetBottom 是否为留出底部安全区适配,默认true
+	* @property {Boolean} closeable 是否显示关闭图标,默认false
+	* @property {Boolean} closeIconPos 自定义关闭图标位置,`top-left`-左上角,`top-right`-右上角,`bottom-left`-左下角,`bottom-right`-右下角,默认top-right
+	* @property {String}  bgColor 主窗口背景色
+	* @property {String}  maskBackgroundColor 蒙版颜色
+	* @property {Boolean} customStyle 自定义样式
+	* @event {Function} change 打开关闭弹窗触发,e={show: false}
+	* @event {Function} maskClick 点击遮罩触发
+	*/
+	export default {
+		name: 'uv-popup',
+		components: {
+			// #ifdef H5
+			keypress
+			// #endif
+		},
+		mixins: [mpMixin, mixin],
+		emits: ['change', 'maskClick'],
+		props: {
+			// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
+			// message: 消息提示 ; dialog : 对话框
+			mode: {
+				type: String,
+				default: 'center'
+			},
+			// 动画时长,单位ms
+			duration: {
+				type: [String, Number],
+				default: 300
+			},
+			// 层级
+			zIndex: {
+				type: [String, Number],
+				// #ifdef H5
+				default: 997
+				// #endif
+				// #ifndef H5
+				default: 10075
+				// #endif
+			},
+			bgColor: {
+				type: String,
+				default: '#ffffff'
+			},
+			safeArea: {
+				type: Boolean,
+				default: true
+			},
+			// 是否显示遮罩
+			overlay: {
+				type: Boolean,
+				default: true
+			},
+			// 点击遮罩是否关闭弹窗
+			closeOnClickOverlay: {
+				type: Boolean,
+				default: true
+			},
+			// 遮罩的透明度,0-1之间
+			overlayOpacity: {
+				type: [Number, String],
+				default: 0.4
+			},
+			// 自定义遮罩的样式
+			overlayStyle: {
+				type: [Object, String],
+				default: ''
+			},
+			// 是否为iPhoneX留出底部安全距离
+			safeAreaInsetBottom: {
+				type: Boolean,
+				default: true
+			},
+			// 是否留出顶部安全距离(状态栏高度)
+			safeAreaInsetTop: {
+				type: Boolean,
+				default: false
+			},
+			// 是否显示关闭图标
+			closeable: {
+				type: Boolean,
+				default: false
+			},
+			// 自定义关闭图标位置,top-left为左上角,top-right为右上角,bottom-left为左下角,bottom-right为右下角
+			closeIconPos: {
+				type: String,
+				default: 'top-right'
+			},
+			// mode=center,也即中部弹出时,是否使用缩放模式
+			zoom: {
+				type: Boolean,
+				default: true
+			},
+			round: {
+				type: [Number, String],
+				default: 0
+			},
+			...uni.$uv?.props?.popup
+		},
+		watch: {
+			/**
+			 * 监听type类型
+			 */
+			type: {
+				handler: function(type) {
+					if (!this.config[type]) return
+					this[this.config[type]](true)
+				},
+				immediate: true
+			},
+			isDesktop: {
+				handler: function(newVal) {
+					if (!this.config[newVal]) return
+					this[this.config[this.mode]](true)
+				},
+				immediate: true
+			},
+			// H5 下禁止底部滚动
+			showPopup(show) {
+				// #ifdef H5
+				// fix by mehaotian 处理 h5 滚动穿透的问题
+				document.getElementsByTagName('body')[0].style.overflow = show ? 'hidden' : 'visible'
+				// #endif
+			}
+		},
+		data() {
+			return {
+				ani: [],
+				showPopup: false,
+				showTrans: false,
+				popupWidth: 0,
+				popupHeight: 0,
+				config: {
+					top: 'top',
+					bottom: 'bottom',
+					center: 'center',
+					left: 'left',
+					right: 'right',
+					message: 'top',
+					dialog: 'center',
+					share: 'bottom'
+				},
+				transitionStyle: {
+					position: 'fixed',
+					left: 0,
+					right: 0
+				},
+				maskShow: true,
+				mkclick: true,
+				popupClass: this.isDesktop ? 'fixforpc-top' : 'top',
+				direction: ''
+			}
+		},
+		computed: {
+			isDesktop() {
+				return this.popupWidth >= 500 && this.popupHeight >= 500
+			},
+			bg() {
+				if (this.bgColor === '' || this.bgColor === 'none' || this.$uv.getPx(this.round)>0) {
+					return 'transparent'
+				}
+				return this.bgColor
+			},
+			contentStyle() {
+				const style = {};
+				if (this.bgColor) {
+					style.backgroundColor = this.bg
+				}
+				if(this.round) {
+					const value = this.$uv.addUnit(this.round)
+					const mode = this.direction?this.direction:this.mode
+					style.backgroundColor = this.bgColor
+					if(mode === 'top') {
+						style.borderBottomLeftRadius = value
+						style.borderBottomRightRadius = value
+					} else if(mode === 'bottom') {
+						style.borderTopLeftRadius = value
+						style.borderTopRightRadius = value
+					} else if(mode === 'center') {
+						style.borderRadius = value
+					} 
+				}
+				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
+			}
+		},
+		// #ifndef VUE3
+		// TODO vue2
+		destroyed() {
+			this.setH5Visible()
+		},
+		// #endif
+		// #ifdef VUE3
+		// TODO vue3
+		unmounted() {
+			this.setH5Visible()
+		},
+		// #endif
+		created() {
+			// TODO 处理 message 组件生命周期异常的问题
+			this.messageChild = null
+			// TODO 解决头条冒泡的问题
+			this.clearPropagation = false
+		},
+		methods: {
+			setH5Visible() {
+				// #ifdef H5
+				// fix by mehaotian 处理 h5 滚动穿透的问题
+				document.getElementsByTagName('body')[0].style.overflow = 'visible'
+				// #endif
+			},
+			/**
+			 * 公用方法,不显示遮罩层
+			 */
+			closeMask() {
+				this.maskShow = false
+			},
+			// TODO nvue 取消冒泡
+			clear(e) {
+				// #ifndef APP-NVUE
+				e.stopPropagation()
+				// #endif
+				this.clearPropagation = true
+			},
+
+			open(direction) {
+				// fix by mehaotian 处理快速打开关闭的情况
+				if (this.showPopup) {
+					return
+				}
+				let innerType = ['top', 'center', 'bottom', 'left', 'right', 'message', 'dialog', 'share']
+				if (!(direction && innerType.indexOf(direction) !== -1)) {
+					direction = this.mode
+				}else {
+					this.direction = direction;
+				}
+				if (!this.config[direction]) {
+					return this.$uv.error(`缺少类型:${direction}`);
+				}
+				this[this.config[direction]]()
+				this.$emit('change', {
+					show: true,
+					type: direction
+				})
+			},
+			close(type) {
+				this.showTrans = false
+				this.$emit('change', {
+					show: false,
+					type: this.mode
+				})
+				clearTimeout(this.timer)
+				// // 自定义关闭事件
+				this.timer = setTimeout(() => {
+					this.showPopup = false
+				}, 300)
+			},
+			// TODO 处理冒泡事件,头条的冒泡事件有问题 ,先这样兼容
+			touchstart() {
+				this.clearPropagation = false
+			},
+			onTap() {
+				if (this.clearPropagation) {
+					// fix by mehaotian 兼容 nvue
+					this.clearPropagation = false
+					return
+				}
+				this.$emit('maskClick')
+				if (!this.closeOnClickOverlay) return
+				this.close()
+			},
+			/**
+			 * 顶部弹出样式处理
+			 */
+			top(type) {
+				this.popupClass = this.isDesktop ? 'fixforpc-top' : 'top'
+				this.ani = ['slide-top']
+				this.transitionStyle = {
+					position: 'fixed',
+					zIndex: this.zIndex,
+					left: 0,
+					right: 0,
+					backgroundColor: this.bg
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+				this.$nextTick(() => {
+					if (this.messageChild && this.mode === 'message') {
+						this.messageChild.timerClose()
+					}
+				})
+			},
+			/**
+			 * 底部弹出样式处理
+			 */
+			bottom(type) {
+				this.popupClass = 'bottom'
+				this.ani = ['slide-bottom']
+				this.transitionStyle = {
+					position: 'fixed',
+					zIndex: this.zIndex,
+					left: 0,
+					right: 0,
+					bottom: 0,
+					backgroundColor: this.bg
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			/**
+			 * 中间弹出样式处理
+			 */
+			center(type) {
+				this.popupClass = 'center'
+				this.ani = this.zoom?['zoom-in', 'fade']:['fade'];
+				this.transitionStyle = {
+					position: 'fixed',
+					zIndex: this.zIndex,
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column',
+					/* #endif */
+					bottom: 0,
+					left: 0,
+					right: 0,
+					top: 0,
+					justifyContent: 'center',
+					alignItems: 'center'
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			left(type) {
+				this.popupClass = 'left'
+				this.ani = ['slide-left']
+				this.transitionStyle = {
+					position: 'fixed',
+					zIndex: this.zIndex,
+					left: 0,
+					bottom: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			},
+			right(type) {
+				this.popupClass = 'right'
+				this.ani = ['slide-right']
+				this.transitionStyle = {
+					position: 'fixed',
+					zIndex: this.zIndex,
+					bottom: 0,
+					right: 0,
+					top: 0,
+					backgroundColor: this.bg,
+					/* #ifndef APP-NVUE */
+					display: 'flex',
+					flexDirection: 'column'
+					/* #endif */
+				}
+				// TODO 兼容 type 属性 ,后续会废弃
+				if (type) return
+				this.showPopup = true
+				this.showTrans = true
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.uv-popup {
+		position: fixed;
+		/* #ifndef APP-NVUE */
+		z-index: 99;
+
+		/* #endif */
+		&.top,
+		&.left,
+		&.right {
+			/* #ifdef H5 */
+			top: var(--window-top);
+			/* #endif */
+			/* #ifndef H5 */
+			top: 0;
+			/* #endif */
+		}
+
+		.uv-popup__content {
+			/* #ifndef APP-NVUE */
+			display: block;
+			overflow: hidden;
+			/* #endif */
+			position: relative;
+
+			&.left,
+			&.right {
+				/* #ifdef H5 */
+				padding-top: var(--window-top);
+				/* #endif */
+				/* #ifndef H5 */
+				padding-top: 0;
+				/* #endif */
+				flex: 1;
+			}
+			&__close {
+				position: absolute;
+
+				&--hover {
+					opacity: 0.4;
+				}
+			}
+			
+			&__close--top-left {
+				top: 15px;
+				left: 15px;
+			}
+			
+			&__close--top-right {
+				top: 15px;
+				right: 15px;
+			}
+			
+			&__close--bottom-left {
+				bottom: 15px;
+				left: 15px;
+			}
+			
+			&__close--bottom-right {
+				right: 15px;
+				bottom: 15px;
+			}
+		}
+	}
+
+	.fixforpc-z-index {
+		/* #ifndef APP-NVUE */
+		z-index: 999;
+		/* #endif */
+	}
+
+	.fixforpc-top {
+		top: 0;
+	}
+</style>

+ 92 - 0
uni_modules/uv-popup/package.json

@@ -0,0 +1,92 @@
+{
+  "id": "uv-popup",
+  "displayName": "uv-popup 弹出层 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.7",
+  "description": "uv-popup 弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。",
+  "keywords": [
+    "uv-popup",
+    "uvui",
+    "uv-ui",
+    "popup",
+    "弹出层"
+],
+  "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",
+			"uv-overlay",
+			"uv-transition",
+			"uv-icon",
+			"uv-status-bar",
+			"uv-safe-bottom"
+		],
+    "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"
+				}
+			}
+		}
+  }
+}

+ 21 - 0
uni_modules/uv-popup/readme.md

@@ -0,0 +1,21 @@
+## Popup 弹出层
+
+> **组件名:uv-popup**
+
+弹出层容器,用于展示弹窗、信息提示等内容,支持上、下、左、右和中部弹出。组件只提供容器,内部内容由用户自定义。
+
+该组件已经放弃原来`uview2.x`的写法,参照了官方`uni-popup`的写法进行重构。在小程序端的性能大大提升,打开和关闭避免延迟,调用方法与之前相比也有所差异,具体请查看文档。
+
+# <a href="https://www.uvui.cn/components/popup.html" target="_blank">查看文档</a>
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+</a>
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 7 - 0
uni_modules/uv-status-bar/changelog.md

@@ -0,0 +1,7 @@
+## 1.0.2(2023-06-05)
+1. 兼容渐变背景色
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+1. 新增uv-status-bar组件

+ 8 - 0
uni_modules/uv-status-bar/components/uv-status-bar/props.js

@@ -0,0 +1,8 @@
+export default {
+    props: {
+        bgColor: {
+            type: String,
+            default: 'transparent'
+        }
+    }
+}

+ 54 - 0
uni_modules/uv-status-bar/components/uv-status-bar/uv-status-bar.vue

@@ -0,0 +1,54 @@
+<template>
+	<view
+	    :style="[style]"
+	    class="uv-status-bar"
+	>
+		<slot />
+	</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';
+	/**
+	 * StatbusBar 状态栏占位
+	 * @description 本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
+	 * @tutorial https://www.uvui.cn/components/statusBar.html
+	 * @property {String}			bgColor			背景色 (默认 'transparent' )
+	 * @property {String | Object}	customStyle		自定义样式 
+	 * @example <uv-status-bar></uv-status-bar>
+	 */
+	export default {
+		name: 'uv-status-bar',
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+			}
+		},
+		computed: {
+			style() {
+				const style = {}
+				// 状态栏高度,由于某些安卓和微信开发工具无法识别css的顶部状态栏变量,所以使用js获取的方式
+				style.height = this.$uv.addUnit(this.$uv.sys().statusBarHeight, 'px')
+				if(this.bgColor){
+					if (this.bgColor.indexOf("gradient") > -1) {// 渐变色
+						style.backgroundImage = this.bgColor;
+					}else{
+						style.background = this.bgColor;
+					}
+				}
+				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.uv-status-bar {
+		// nvue会默认100%,如果nvue下,显式写100%的话,会导致宽度不为100%而异常
+		/* #ifndef APP-NVUE */
+		width: 100%;
+		/* #endif */
+	}
+</style>

+ 87 - 0
uni_modules/uv-status-bar/package.json

@@ -0,0 +1,87 @@
+{
+  "id": "uv-status-bar",
+  "displayName": "uv-status-bar 状态栏占位",
+  "version": "1.0.2",
+  "description": "状态栏占位组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。",
+  "keywords": [
+    "uv-status-bar",
+    "uvui",
+    "uv-ui",
+    "status-bar",
+    "状态栏"
+],
+  "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"
+				}
+			}
+		}
+  }
+}

+ 10 - 0
uni_modules/uv-status-bar/readme.md

@@ -0,0 +1,10 @@
+## StatbusBar 状态栏占位
+
+> **组件名:uv-status-bar**
+
+本组件主要用于状态填充,比如在自定导航栏的时候,它会自动适配一个恰当的状态栏高度。
+
+### [完整示例项目下载 | 关注更多组件](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>
+

+ 2 - 0
uni_modules/uv-toolbar/changelog.md

@@ -0,0 +1,2 @@
+## 1.0.0(2023-08-02)
+1. 新增工具条组件

+ 40 - 0
uni_modules/uv-toolbar/components/uv-toolbar/props.js

@@ -0,0 +1,40 @@
+export default {
+	props: {
+		// 是否展示工具条
+		show: {
+			type: Boolean,
+			default: true
+		},
+		// 是否显示下边框
+		showBorder: {
+			type: Boolean,
+			default: false
+		},
+		// 取消按钮的文字
+		cancelText: {
+			type: String,
+			default: '取消'
+		},
+		// 确认按钮的文字
+		confirmText: {
+			type: String,
+			default: '确认'
+		},
+		// 取消按钮的颜色
+		cancelColor: {
+			type: String,
+			default: '#909193'
+		},
+		// 确认按钮的颜色
+		confirmColor: {
+			type: String,
+			default: '#3c9cff'
+		},
+		// 标题文字
+		title: {
+			type: String,
+			default: ''
+		},
+		...uni.$uv?.props?.toolbar
+	}
+}

+ 109 - 0
uni_modules/uv-toolbar/components/uv-toolbar/uv-toolbar.vue

@@ -0,0 +1,109 @@
+<template>
+	<view
+		:class="['uv-toolbar',{'uv-border-bottom':showBorder}]"
+		@touchmove.stop.prevent="noop"
+		v-if="show"
+	>
+		<view
+			class="uv-toolbar__cancel__wrapper"
+			hover-class="uv-hover-class"
+		>
+			<text
+				class="uv-toolbar__wrapper__cancel"
+				@tap="cancel"
+				:style="{
+					color: cancelColor
+				}"
+			>{{ cancelText }}</text>
+		</view>
+		<text
+			class="uv-toolbar__title uv-line-1"
+			v-if="title"
+		>{{ title }}</text>
+		<view
+			class="uv-toolbar__confirm__wrapper"
+			hover-class="uv-hover-class"
+		>
+			<text
+				class="uv-toolbar__wrapper__confirm"
+				@tap="confirm"
+				:style="{
+				color: confirmColor
+			}"
+			>{{ confirmText }}</text>
+		</view>
+	</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';
+	/**
+	 * Toolbar 工具条
+	 * @description 
+	 * @tutorial https://www.uvui.cn/components/toolbar.html
+	 * @property {Boolean}	show			是否展示工具条(默认 true )
+	 * @property {Boolean}	showBorder			是否展示工具条下方边框(默认 false )
+	 * @property {String}	cancelText		取消按钮的文字(默认 '取消' )
+	 * @property {String}	confirmText		确认按钮的文字(默认 '确认' )
+	 * @property {String}	cancelColor		取消按钮的颜色(默认 '#909193' )
+	 * @property {String}	confirmColor	确认按钮的颜色(默认 '#3c9cff' )
+	 * @property {String}	title	标题文字
+	 * @event {Function} 
+	 * @example 
+	 */
+	export default {
+		name: 'uv-toolbar',
+		emits: ['confirm', 'cancel'],
+		mixins: [mpMixin, mixin, props],
+		methods: {
+			// 点击取消按钮
+			cancel() {
+				this.$emit('cancel')
+			},
+			// 点击确定按钮
+			confirm() {
+				this.$emit('confirm')
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	$show-lines: 1;
+	$show-hover: 1;
+	$show-border: 1;
+	$show-border-bottom: 1;
+	@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
+	@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
+	$uv-tips-color: #909193 !default;
+	$uv-main-color: #303133 !default;
+	$uv-primary: #3c9cff !default;
+	.uv-toolbar {
+		height: 42px;
+		@include flex;
+		justify-content: space-between;
+		align-items: center;
+		&__wrapper {
+			&__cancel {
+				color: $uv-tips-color;
+				font-size: 15px;
+				padding: 0 15px;
+			}
+		}
+		&__title {
+			color: $uv-main-color;
+			padding: 0 60rpx;
+			font-size: 16px;
+			flex: 1;
+			text-align: center;
+		}
+		&__wrapper {
+			&__confirm {
+				color: $uv-primary;
+				font-size: 15px;
+				padding: 0 15px;
+			}
+		}
+	}
+</style>

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

@@ -0,0 +1,87 @@
+{
+  "id": "uv-toolbar",
+  "displayName": "uv-toolbar 工具条",
+  "version": "1.0.0",
+  "description": "该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条",
+  "keywords": [
+    "uv-toolbar",
+    "uvui",
+    "uv-ui",
+    "工具条",
+    "工具"
+],
+  "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"
+				}
+			}
+		}
+  }
+}

+ 31 - 0
uni_modules/uv-toolbar/readme.md

@@ -0,0 +1,31 @@
+## Toolbar 工具条
+
+> **组件名:uv-toolbar**
+
+该组价是仅用于uv-ui中一个公共小工具,提供一个取消和确定的样式,可以设置标题,主要用于弹窗顶部的选择确定工具条。
+
+### 基本使用
+
+```vue
+<uv-toolbar title="标题文字"></uv-toolbar>
+```
+
+### Toolbar Props
+
+| 属性名 | 类型 | 默认值 | 说明 |
+|:-|:-|:-|:-|
+| show | Boolean | true | 是否展示工具条 |
+| showBorder | Boolean | false | 是否显示下边框 |
+| cancelText | String | '取消' | 取消按钮的文字 |
+| confirmText | String | '确定' | 确定按钮的文字 |
+| cancelColor | String | '#909193' | 取消按钮的颜色 |
+| confirmColor | String | '#3c9cff' | 确认按钮的颜色 |
+| title | String | - | 标题文字 |
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

+ 19 - 0
uni_modules/uv-transition/changelog.md

@@ -0,0 +1,19 @@
+## 1.0.8(2023-10-18)
+1. 修复在APP上不能正常显示的BUG
+## 1.0.7(2023-10-12)
+1. 修复部分情况,修改某属性自动关闭的BUG
+## 1.0.6(2023-07-24)
+1. 优化  nvue模式下增加cellChild参数,是否在list中cell节点下,nvue中cell下建议设置成true
+## 1.0.5(2023-07-02)
+修改VUE3模式下可能存在的BUG
+## 1.0.4(2023-07-02)
+uv-transition  动画组件,代码重构优化,性能更加友好,增加自定义动画功能。详情参考文档:https://www.uvui.cn/components/transition.html
+## 1.0.3(2023-06-12)
+1. 恢复this.$nextTick的使用,经过测试百度等平台无问题
+## 1.0.2(2023-05-23)
+1. 百度小程序等平台不支持this.$nextick,修改成延时
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+1. 新增动画组件

+ 131 - 0
uni_modules/uv-transition/components/uv-transition/createAnimation.js

@@ -0,0 +1,131 @@
+// const defaultOption = {
+// 	duration: 300,
+// 	timingFunction: 'linear',
+// 	delay: 0,
+// 	transformOrigin: '50% 50% 0'
+// }
+// #ifdef APP-NVUE
+const nvueAnimation = uni.requireNativePlugin('animation')
+// #endif
+class MPAnimation {
+	constructor(options, _this) {
+		this.options = options
+		// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
+		this.animation = uni.createAnimation({
+			...options
+		})
+		this.currentStepAnimates = {}
+		this.next = 0
+		this.$ = _this
+
+	}
+
+	_nvuePushAnimates(type, args) {
+		let aniObj = this.currentStepAnimates[this.next]
+		let styles = {}
+		if (!aniObj) {
+			styles = {
+				styles: {},
+				config: {}
+			}
+		} else {
+			styles = aniObj
+		}
+		if (animateTypes1.includes(type)) {
+			if (!styles.styles.transform) {
+				styles.styles.transform = ''
+			}
+			let unit = ''
+			if(type === 'rotate'){
+				unit = 'deg'
+			}
+			styles.styles.transform += `${type}(${args+unit}) `
+		} else {
+			styles.styles[type] = `${args}`
+		}
+		this.currentStepAnimates[this.next] = styles
+	}
+	_animateRun(styles = {}, config = {}) {
+		let ref = this.$.$refs['ani'].ref
+		if (!ref) return
+		return new Promise((resolve, reject) => {
+			nvueAnimation.transition(ref, {
+				styles,
+				...config
+			}, res => {
+				resolve()
+			})
+		})
+	}
+
+	_nvueNextAnimate(animates, step = 0, fn) {
+		let obj = animates[step]
+		if (obj) {
+			let {
+				styles,
+				config
+			} = obj
+			this._animateRun(styles, config).then(() => {
+				step += 1
+				this._nvueNextAnimate(animates, step, fn)
+			})
+		} else {
+			this.currentStepAnimates = {}
+			typeof fn === 'function' && fn()
+			this.isEnd = true
+		}
+	}
+
+	step(config = {}) {
+		// #ifndef APP-NVUE
+		this.animation.step(config)
+		// #endif
+		// #ifdef APP-NVUE
+		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
+		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
+		this.next++
+		// #endif
+		return this
+	}
+
+	run(fn) {
+		// #ifndef APP-NVUE
+		this.$.animationData = this.animation.export()
+		this.$.timer = setTimeout(() => {
+			typeof fn === 'function' && fn()
+		}, this.$.durationTime)
+		// #endif
+		// #ifdef APP-NVUE
+		this.isEnd = false
+		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
+		if(!ref) return
+		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
+		this.next = 0
+		// #endif
+	}
+}
+
+
+const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
+	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
+	'translateZ'
+]
+const animateTypes2 = ['opacity', 'backgroundColor']
+const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
+animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
+	MPAnimation.prototype[type] = function(...args) {
+		// #ifndef APP-NVUE
+		this.animation[type](...args)
+		// #endif
+		// #ifdef APP-NVUE
+		this._nvuePushAnimates(type, args)
+		// #endif
+		return this
+	}
+})
+
+export function createAnimation(option, _this) {
+	if(!_this) return
+	clearTimeout(_this.timer)
+	return new MPAnimation(option, _this)
+}

+ 31 - 0
uni_modules/uv-transition/components/uv-transition/props.js

@@ -0,0 +1,31 @@
+export default {
+	props: {
+		// 是否展示组件
+		show: {
+			type: Boolean,
+			default: false
+		},
+		// 使用的动画模式
+		mode: {
+			type: [Array, String, null],
+			default() {
+				return 'fade'
+			}
+		},
+		// 动画的执行时间,单位ms
+		duration: {
+			type: [String, Number],
+			default: 300
+		},
+		// 使用的动画过渡函数
+		timingFunction: {
+			type: String,
+			default: 'ease-out'
+		},
+		customClass: {
+			type: String,
+			default: ''
+		},
+		...uni.$uv?.props?.transition
+	}
+}

+ 320 - 0
uni_modules/uv-transition/components/uv-transition/uv-transition.vue

@@ -0,0 +1,320 @@
+<template>
+  <!-- #ifndef APP-NVUE -->
+  <view 
+		v-if="isShow" 
+		ref="ani" 
+		:animation="animationData" 
+		:class="customClass" 
+		:style="transformStyles" 
+		@click="onClick">
+		<slot></slot>
+	</view>
+  <!-- #endif -->
+  <!-- #ifdef APP-NVUE -->
+  <view 
+		v-if="isShow" 
+		ref="ani" 
+		:animation="animationData" 
+		:class="customClass" 
+		:style="transformStyles" 
+		@click="onClick">
+		<slot></slot>
+	</view>
+  <!-- #endif -->
+</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 { createAnimation } from './createAnimation'
+	/**
+	* transition  动画组件
+	* @description
+	* @tutorial
+	* @property {Boolean}	show	控制组件显示或关闭 (默认 false )
+	* @property {Array | String	}	mode	内置过渡动画类型 (默认 'fade' )
+	* @value fade 渐隐渐出过渡
+	* @value slide-top 由上至下过渡
+	* @value slide-bottom 由下至上过渡
+	* @value slide-left 由左至右过渡
+	* @value slide-right 由右至左过渡
+	* @value zoom-in 由小到大过渡
+	* @value zoom-out 由大到小过渡
+	* @property {String | Number}	duration	动画的执行时间,单位ms (默认 300 )
+	* @property {String} timingFunction	使用的动画过渡函数 (默认 'ease-out' )
+	* @property {Object} customStyle	自定义样式
+	* @property {String} customClass	自定义类名
+	* @event {Function} click 点击组件触发	
+	* @event {Function} change	过渡动画结束时触发	
+	* @example 
+	*/
+	export default {
+		name: 'uv-transition',
+		mixins: [mpMixin,mixin],
+		emits:['click','change'],
+		props: {
+			// 是否展示组件
+			show: {
+				type: Boolean,
+				default: false
+			},
+			// 使用的动画模式
+			mode: {
+				type: [Array, String, null],
+				default() {
+					return 'fade'
+				}
+			},
+			// 动画的执行时间,单位ms
+			duration: {
+				type: [String, Number],
+				default: 300
+			},
+			// 使用的动画过渡函数
+			timingFunction: {
+				type: String,
+				default: 'ease-out'
+			},
+			customClass: {
+				type: String,
+				default: ''
+			},
+			// nvue模式下 是否直接显示,在uv-list等cell下面使用就需要设置
+			cellChild: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data(){
+			return {
+				isShow: false,
+				transform: '',
+				opacity: 1,
+				animationData: {},
+				durationTime: 300,
+				config: {}
+			}
+		},
+		watch: {
+			show: {
+				handler(newVal) {
+					if (newVal) {
+						this.open();
+					} else {
+						// 避免上来就执行 close,导致动画错乱
+						if (this.isShow) {
+							this.close();
+						}
+					}
+				},
+				immediate: true
+			}
+		},
+		computed: {
+			// 初始化动画条件
+			transformStyles() {
+				const style = {
+					transform: this.transform,
+					opacity: this.opacity,
+					...this.$uv.addStyle(this.customStyle),
+					'transition-duration': `${this.duration / 1000}s`
+				};
+				return this.$uv.addStyle(style,'string');
+			}
+		},
+		created() {
+			// 动画默认配置
+			this.config = {
+				duration: this.duration,
+				timingFunction: this.timingFunction,
+				transformOrigin: '50% 50%',
+				delay: 0
+			};
+			this.durationTime = this.duration;
+		},
+		methods: {
+			/**
+			 *  ref 触发 初始化动画
+			 */
+			init(obj = {}) {
+				if (obj.duration) {
+					this.durationTime = obj.duration;
+				}
+				this.animation = createAnimation(Object.assign(this.config, obj),this);
+			},
+			/**
+			 * 点击组件触发回调
+			 */
+			onClick() {
+				this.$emit('click', {
+					detail: this.isShow
+				})
+			},
+			/**
+			 * ref 触发 动画分组
+			 * @param {Object} obj
+			 */
+			step(obj, config = {}) {
+				if (!this.animation) return;
+				for (let i in obj) {
+					try {
+						if(typeof obj[i] === 'object'){
+							this.animation[i](...obj[i]);
+						}else{
+							this.animation[i](obj[i]);
+						}
+					} catch (e) {
+						console.error(`方法 ${i} 不存在`);
+					}
+				}
+				this.animation.step(config);
+				return this;
+			},
+			/**
+			 *  ref 触发 执行动画
+			 */
+			run(fn) {
+				if (!this.animation) return;
+				this.animation.run(fn);
+			},
+			// 开始过度动画
+			open() {
+				clearTimeout(this.timer);
+				this.transform = '';
+				this.isShow = true;
+				let { opacity, transform } = this.styleInit(false);
+				if (typeof opacity !== 'undefined') {
+					this.opacity = opacity;
+				}
+				this.transform = transform;
+				// 确保动态样式已经生效后,执行动画,如果不加 nextTick ,会导致 wx 动画执行异常
+				this.$nextTick(() => {
+					// TODO 定时器保证动画完全执行,目前有些问题,后面会取消定时器
+					this.timer = setTimeout(() => {
+						this.animation = createAnimation(this.config, this);
+						this.tranfromInit(false).step();
+						// #ifdef APP-NVUE
+						if(this.cellChild) {
+							this.opacity = 1;
+						} else{
+							this.animation.run();
+						}
+						// #endif
+						// #ifndef APP-NVUE
+						this.animation.run();
+						// #endif
+						// #ifdef VUE3
+						// #ifdef H5
+						this.opacity = 1;
+						// #endif
+						// #endif
+						this.$emit('change', {
+							detail: this.isShow
+						})
+						// #ifdef H5
+						// #ifdef VUE3
+						this.transform = '';
+						// #endif
+						// #endif
+					}, 20);
+				})
+			},
+			// 关闭过渡动画
+			close(type) {
+				if (!this.animation) return;
+				this.tranfromInit(true)
+					.step()
+					.run(() => {
+						this.isShow = false;
+						this.animationData = null;
+						this.animation = null;
+						let { opacity, transform } = this.styleInit(false);
+						this.opacity = opacity || 1;
+						this.transform = transform;
+						this.$emit('change', {
+							detail: this.isShow
+						});
+					})
+			},
+			// 处理动画开始前的默认样式
+			styleInit(type) {
+				let styles = {
+					transform: ''
+				};
+				let buildStyle = (type, mode) => {
+					if (mode === 'fade') {
+						styles.opacity = this.animationType(type)[mode];
+					} else {
+						styles.transform += this.animationType(type)[mode] + ' ';
+					}
+				}
+				if (typeof this.mode === 'string') {
+					buildStyle(type, this.mode);
+				} else {
+					this.mode.forEach(mode => {
+						buildStyle(type, mode)
+					})
+				}
+				return styles
+			},
+			// 处理内置组合动画
+			tranfromInit(type) {
+				let buildTranfrom = (type, mode) => {
+					let aniNum = null;
+					if (mode === 'fade') {
+						aniNum = type ? 0 : 1;
+					} else {
+						aniNum = type ? '-100%' : '0';
+						if (mode === 'zoom-in') {
+							aniNum = type ? 0.8 : 1
+						}
+						if (mode === 'zoom-out') {
+							aniNum = type ? 1.2 : 1
+						}
+						if (mode === 'slide-right') {
+							aniNum = type ? '100%' : '0'
+						}
+						if (mode === 'slide-bottom') {
+							aniNum = type ? '100%' : '0'
+						}
+					}
+					this.animation[this.animationMode()[mode]](aniNum)
+				}
+				if (typeof this.mode === 'string') {
+					buildTranfrom(type, this.mode)
+				} else {
+					this.mode.forEach(mode => {
+						buildTranfrom(type, mode)
+					})
+				}
+				return this.animation;
+			},
+			animationType(type) {
+				return {
+					fade: type ? 1 : 0,
+					'slide-top': `translateY(${type ? '0' : '-100%'})`,
+					'slide-right': `translateX(${type ? '0' : '100%'})`,
+					'slide-bottom': `translateY(${type ? '0' : '100%'})`,
+					'slide-left': `translateX(${type ? '0' : '-100%'})`,
+					'zoom-in': `scaleX(${type ? 1 : 0.8}) scaleY(${type ? 1 : 0.8})`,
+					'zoom-out': `scaleX(${type ? 1 : 1.2}) scaleY(${type ? 1 : 1.2})`
+				}
+			},
+			// 内置动画类型与实际动画对应字典
+			animationMode() {
+				return {
+					fade: 'opacity',
+					'slide-top': 'translateY',
+					'slide-right': 'translateX',
+					'slide-bottom': 'translateY',
+					'slide-left': 'translateX',
+					'zoom-in': 'scale',
+					'zoom-out': 'scale'
+				}
+			},
+			// 驼峰转中横线
+			toLine(name) {
+				return name.replace(/([A-Z])/g, '-$1').toLowerCase()
+			}
+		}
+	}
+</script>

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

@@ -0,0 +1,87 @@
+{
+  "id": "uv-transition",
+  "displayName": "uv-transition 动画 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.8",
+  "description": "transition 该组件用于组件的动画过渡效果。",
+  "keywords": [
+    "uv-transition",
+    "uvui",
+    "uv-ui",
+    "transition",
+    "动画"
+],
+  "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"
+				}
+			}
+		}
+  }
+}

+ 15 - 0
uni_modules/uv-transition/readme.md

@@ -0,0 +1,15 @@
+## Transition 动画
+
+> **组件名:uv-transition**
+
+该组件用于组件的动画过渡效果,支持自定义动画,开箱即用。
+
+# <a href="https://www.uvui.cn/components/transition.html" target="_blank">查看文档</a>
+
+## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
+
+![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
+
+#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

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

@@ -1,3 +1,5 @@
+## 1.1.25(2024-01-20)
+1.1.20版本更新
 ## 1.1.24(2023-12-21)
 1. luch-request更新
 ## 1.1.23(2023-12-12)

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

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

+ 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.24",
+  "version": "1.1.25",
   "description": "uv-ui-tools,集成工具库,强大的Http请求封装,清晰的文档说明,开箱即用。方便使用,可以全局使用",
   "keywords": [
     "uv-ui-tools,uv-ui组件库,工具集,uvui,uView2.x"

+ 21 - 0
utils/getSystemInfo.js

@@ -0,0 +1,21 @@
+// 获取系统状态栏高度和胶囊按钮高度
+export const getSystemInfo = () => {
+	let {
+		statusBarHeight
+	} = uni.getWindowInfo()
+
+	let {
+		top,
+		height
+	} = uni.getMenuButtonBoundingClientRect()
+
+	let menuButtonHeight = (top - statusBarHeight) * 2 + height
+
+
+	return {
+		statusBarHeight,
+		menuButtonHeight,
+		top,
+		height
+	}
+}