shang 1 year ago
parent
commit
419e8c2417
100 changed files with 18000 additions and 377 deletions
  1. 108 13
      chuanCheng_fenbao/search.vue
  2. 0 50
      chuanCheng_fenbao/search/search.vue
  3. 160 96
      chuanCheng_fenbao/touGao.vue
  4. 24 23
      config/api.js
  5. 4 8
      config/config.js
  6. 7 6
      index_fenbao/jianzhu/jianZhuXQ.vue
  7. 252 11
      index_fenbao/jianzhu/jianZhu_index.vue
  8. 2 2
      index_fenbao/jianzhu/jianzhu.vue
  9. 0 1
      index_fenbao/jianzhu/map_page.vue
  10. 143 0
      index_fenbao/mn_jingshen/PageSpirit.vue
  11. 7 1
      index_fenbao/mn_jingshen/xiang_qing.vue
  12. 2 2
      index_fenbao/mn_wenhua/mn_wenhua.vue
  13. 147 0
      jiyi_fenbao/recommendedDetails.vue
  14. 1 1
      mixins/auth.js
  15. 20 2
      pages.json
  16. 132 87
      pages/chuanCheng/chuanCheng.vue
  17. 3 2
      pages/course/detail.vue
  18. 19 7
      pages/index/index.vue
  19. 9 57
      pages/jiyi/jiyi.vue
  20. 10 8
      pages/user/index.vue
  21. BIN
      static/image/2019-07-03000000000018.png
  22. BIN
      static/image/BSV.png
  23. BIN
      static/image/flower.png
  24. BIN
      static/image/jz_titbg.png
  25. BIN
      static/image/kctp.png
  26. BIN
      static/image/传统吉祥纹样17.png
  27. BIN
      static/image/余额.png
  28. BIN
      static/image/椭圆 839.png
  29. BIN
      static/image/账期 拷贝.png
  30. BIN
      static/image/账期(1).png
  31. BIN
      static/image/账期(3).png
  32. BIN
      static/image/账期.png
  33. 320 0
      uni_modules/qiun-data-charts/changelog.md
  34. 1618 0
      uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue
  35. 46 0
      uni_modules/qiun-data-charts/components/qiun-error/qiun-error.vue
  36. 162 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading1.vue
  37. 170 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading2.vue
  38. 173 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading3.vue
  39. 222 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading4.vue
  40. 229 0
      uni_modules/qiun-data-charts/components/qiun-loading/loading5.vue
  41. 36 0
      uni_modules/qiun-data-charts/components/qiun-loading/qiun-loading.vue
  42. 422 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-echarts.js
  43. 606 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/config-ucharts.js
  44. 5 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/readme.md
  45. 7706 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js
  46. 18 0
      uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.min.js
  47. 201 0
      uni_modules/qiun-data-charts/license.md
  48. 80 0
      uni_modules/qiun-data-charts/package.json
  49. 84 0
      uni_modules/qiun-data-charts/readme.md
  50. 23 0
      uni_modules/qiun-data-charts/static/app-plus/echarts.min.js
  51. 23 0
      uni_modules/qiun-data-charts/static/h5/echarts.min.js
  52. 31 0
      uni_modules/uv-icon/changelog.md
  53. 160 0
      uni_modules/uv-icon/components/uv-icon/icons.js
  54. 90 0
      uni_modules/uv-icon/components/uv-icon/props.js
  55. 226 0
      uni_modules/uv-icon/components/uv-icon/uv-icon.vue
  56. BIN
      uni_modules/uv-icon/components/uv-icon/uvicons.ttf
  57. 83 0
      uni_modules/uv-icon/package.json
  58. 15 0
      uni_modules/uv-icon/readme.md
  59. 36 0
      uni_modules/uv-image/changelog.md
  60. 95 0
      uni_modules/uv-image/components/uv-image/props.js
  61. 287 0
      uni_modules/uv-image/components/uv-image/uv-image.vue
  62. 89 0
      uni_modules/uv-image/package.json
  63. 15 0
      uni_modules/uv-image/readme.md
  64. 9 0
      uni_modules/uv-loading-icon/changelog.md
  65. 67 0
      uni_modules/uv-loading-icon/components/uv-loading-icon/props.js
  66. 347 0
      uni_modules/uv-loading-icon/components/uv-loading-icon/uv-loading-icon.vue
  67. 87 0
      uni_modules/uv-loading-icon/package.json
  68. 19 0
      uni_modules/uv-loading-icon/readme.md
  69. 19 0
      uni_modules/uv-transition/changelog.md
  70. 131 0
      uni_modules/uv-transition/components/uv-transition/createAnimation.js
  71. 31 0
      uni_modules/uv-transition/components/uv-transition/props.js
  72. 320 0
      uni_modules/uv-transition/components/uv-transition/uv-transition.vue
  73. 87 0
      uni_modules/uv-transition/package.json
  74. 15 0
      uni_modules/uv-transition/readme.md
  75. 74 0
      uni_modules/uv-ui-tools/changelog.md
  76. 6 0
      uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue
  77. 79 0
      uni_modules/uv-ui-tools/index.js
  78. 7 0
      uni_modules/uv-ui-tools/index.scss
  79. 34 0
      uni_modules/uv-ui-tools/libs/config/config.js
  80. 32 0
      uni_modules/uv-ui-tools/libs/css/color.scss
  81. 100 0
      uni_modules/uv-ui-tools/libs/css/common.scss
  82. 23 0
      uni_modules/uv-ui-tools/libs/css/components.scss
  83. 111 0
      uni_modules/uv-ui-tools/libs/css/variable.scss
  84. 40 0
      uni_modules/uv-ui-tools/libs/css/vue.scss
  85. 134 0
      uni_modules/uv-ui-tools/libs/function/colorGradient.js
  86. 29 0
      uni_modules/uv-ui-tools/libs/function/debounce.js
  87. 167 0
      uni_modules/uv-ui-tools/libs/function/digit.js
  88. 734 0
      uni_modules/uv-ui-tools/libs/function/index.js
  89. 75 0
      uni_modules/uv-ui-tools/libs/function/platform.js
  90. 287 0
      uni_modules/uv-ui-tools/libs/function/test.js
  91. 30 0
      uni_modules/uv-ui-tools/libs/function/throttle.js
  92. 132 0
      uni_modules/uv-ui-tools/libs/luch-request/adapters/index.js
  93. 51 0
      uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js
  94. 201 0
      uni_modules/uv-ui-tools/libs/luch-request/core/Request.js
  95. 20 0
      uni_modules/uv-ui-tools/libs/luch-request/core/buildFullPath.js
  96. 33 0
      uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js
  97. 6 0
      uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js
  98. 126 0
      uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js
  99. 16 0
      uni_modules/uv-ui-tools/libs/luch-request/core/settle.js
  100. 0 0
      uni_modules/uv-ui-tools/libs/luch-request/helpers/buildURL.js

+ 108 - 13
chuanCheng_fenbao/search.vue

@@ -1,39 +1,79 @@
 <template>
 	<view class="box">
-		<u-navbar title="搜索" :autoBack="true" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
-		<view class="box_search" @click="searchBtn">
-			<u-search :shape="square" v-model="val" bgColor="#efefef" :showAction="false" height="70rpx"></u-search>
-			<view class="sousuo">搜索</view>
+		<u-navbar title="搜索" :placeholder="true" :autoBack="true" bgColor="rgba(255,255,255,0)" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+		<view class="box_search">
+			<u-search :shape="square" v-model="val" bgColor="#efefef" borderColor="#cccccc" :showAction="false" height="70rpx"></u-search>
+			<view @click="searchBtn" class="sousuo">搜索</view>
+		</view>
+
+		<view class="box_22" @click="recommendBtn(index)" v-for="(item, index) in list" :key="item.id">
+			<view class="block_5">
+				<image style="width: 100%; height: 100%; border-radius: 0 50rpx 0 20rpx" :src="item.thumbnail"></image>
+
+				<view class="tag_1">
+					<text lines="1" class="text_9">{{ item.type_text }}</text>
+				</view>
+
+				<view class="tag_2">
+					<text lines="1" class="text_10">{{ item.title }}</text>
+				</view>
+			</view>
 		</view>
 	</view>
 </template>
 
 <script>
+let that;
 export default {
 	data() {
 		return {
-			val: ''
+			val: '',
+			main_body_id: '',
+			model_id: '',
+			list: []
 		};
 	},
+	onLoad(o) {
+		that = this;
+		this.main_body_id = this.$db.get('main_body_id');
+		this.model_id = o.id;
+	},
 	methods: {
-		searchBtn() {}
+		searchBtn() {
+			this.$api.getContentList(
+				{
+					model_id: this.model_id,
+					main_body_id: this.main_body_id,
+					keywords: this.val,
+					page: 1,
+					pageSize: '10'
+				},
+				function (res) {
+					that.list = res.data;
+				}
+			);
+		},
+		//精彩推荐内容
+		recommendBtn(i) {
+			this.$common.navigateTo(this.list[i].page);
+		}
 	}
 };
 </script>
 
 <style>
 .box {
-	height: auto;
 	width: 100%;
-	background-color: #f8f8f8;
+	background-image: url('https://huli-app.wenlvti.net/app_static/wuyuan/static/shouhu/wyj-feiyi3-001.png');
+	background-size: 100% 100%;
 	background-attachment: fixed;
-	position: relative;
-	display: flex;
-	flex-direction: column;
+	background-repeat: repeat-y;
+	height: 100%;
+	padding-bottom: 50rpx;
 }
 .box_search {
 	display: flex;
-	margin: 20rpx 32rpx 0 46rpx;
+	margin: 40rpx 32rpx 0 46rpx;
 	width: 650rpx;
 	height: 80rpx;
 }
@@ -45,6 +85,61 @@ export default {
 	color: #ffffff;
 	line-height: 80rpx;
 	background: #ca5642;
-	border-radius: 20rpx;
+	border-radius: 10rpx;
+}
+.box_22 {
+	height: 345rpx;
+	display: flex;
+	flex-direction: column;
+	width: 686rpx;
+	margin: 40rpx 0 0 47rpx;
+}
+.block_5 {
+	position: relative;
+	height: 345rpx;
+	width: 645rpx;
+	display: flex;
+	flex-direction: column;
+	margin-left: 9rpx;
+}
+.tag_1 {
+	position: absolute;
+	background-color: rgba(77, 113, 153, 1);
+	border-radius: 9rpx 9rpx 32rpx 0rpx;
+	height: 48rpx;
+	display: flex;
+	flex-direction: column;
+	width: 86rpx;
+}
+.tag_2 {
+	position: absolute;
+	bottom: 36rpx;
+	right: 20rpx;
+}
+.text_9 {
+	width: 47rpx;
+	height: 23rpx;
+	overflow-wrap: break-word;
+	color: rgba(255, 255, 255, 1);
+	font-size: 24rpx;
+	font-family: SourceHanSansCN-Bold;
+	font-weight: 700;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 24rpx;
+	margin: 12rpx 0 0 19rpx;
+}
+
+.text_10 {
+	width: 147rpx;
+	height: 29rpx;
+	overflow-wrap: break-word;
+	color: #ffffff;
+	font-size: 34rpx;
+	font-family: Adobe Heiti Std R;
+	font-weight: normal;
+	text-align: left;
+	white-space: nowrap;
+	line-height: 30rpx;
 }
 </style>

+ 0 - 50
chuanCheng_fenbao/search/search.vue

@@ -1,50 +0,0 @@
-<template>
-	<view class="box">
-		<u-navbar title="搜索" :autoBack="true" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
-		<view class="box_search" @click="searchBtn">
-			<u-search :shape="square" v-model="val" bgColor="#efefef" :showAction="false" height="70rpx"></u-search>
-			<view class="sousuo">搜索</view>
-		</view>
-	</view>
-</template>
-
-<script>
-export default {
-	data() {
-		return {
-			val: ''
-		};
-	},
-	methods: {
-		searchBtn() {}
-	}
-};
-</script>
-
-<style>
-.box {
-	height: auto;
-	width: 100%;
-	background-color: #f8f8f8;
-	background-attachment: fixed;
-	position: relative;
-	display: flex;
-	flex-direction: column;
-}
-.box_search {
-	display: flex;
-	margin: 20rpx 32rpx 0 46rpx;
-	width: 650rpx;
-	height: 80rpx;
-}
-
-.sousuo {
-	width: 118rpx;
-	height: 80rpx;
-	text-align: center;
-	color: #ffffff;
-	line-height: 80rpx;
-	background: #ca5642;
-	border-radius: 20rpx;
-}
-</style>

+ 160 - 96
chuanCheng_fenbao/touGao.vue

@@ -2,26 +2,28 @@
 	<view class="body" style="background-color: #efefef">
 		<u-navbar :autoBack="true" title="发布" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
 		<view class="nav_fabu">
-			<view class="nav_left">
+			<view class="nav_left" @click="releaseBtn(0)">
 				<view class="left_icon"><uni-icons type="compose" size="20" color=" #ffffff"></uni-icons></view>
 				<text>发文章</text>
 			</view>
-			<view class="nav_right">
-				<view class="left_icon"><uni-icons type="compose" size="20" color=" #ffffff"></uni-icons></view>
-				<text>发照片</text>
+			<view class="nav_right" @click="releaseBtn(1)">
+				<view class="left_icon" style="background-color: #4e7198"><uni-icons type="videocam" size="20" color=" #ffffff"></uni-icons></view>
+				<text>发视频</text>
 			</view>
+			<view class="uptriangle" :class="{ uptriangle_active: releaseTab == 1, uptriangle: releaseTab == 0 }"></view>
 		</view>
 		<!-- 上传发布组件 -->
-		<view class="" style="margin-bottom: 20rpx">
-			<u--input v-model="titleVal" customStyle="background-color: #ffffff;height: 105rpx;" placeholder="请填写标题" border="surround" clearable></u--input>
+		<view style="margin: 20rpx 0 20rpx 0">
+			<u--input v-model.trim="titleVal" customStyle="background-color: #ffffff;height: 105rpx;" placeholder="请填写标题" border="surround" clearable></u--input>
 		</view>
 
 		<view class="box">
-			<view class="sc_box">
-				<text class="sc_tp">请上传图片</text>
-				<text class="sc_tp">{{ uploadNumber + '/' + 9 }}</text>
-			</view>
-			<view style="margin-left: 56rpx">
+			<!-- 上传照片 -->
+			<view style="margin-left: 56rpx" v-if="releaseTab == 0">
+				<view class="sc_box">
+					<text class="sc_tp">请上传图片</text>
+					<text class="sc_tp">{{ uploadNumber + '/' + 9 }}</text>
+				</view>
 				<u-upload
 					width="200rpx"
 					height="200rpx"
@@ -34,53 +36,61 @@
 					multiple
 				></u-upload>
 			</view>
+			<!-- 上传视频 -->
+			<view style="margin-left: 56rpx" v-if="releaseTab == 1">
+				<view class="sc_box">
+					<text class="sc_tp">请上传视频</text>
+				</view>
+				<u-upload
+					width="200rpx"
+					height="200rpx"
+					:fileList="fileList2"
+					@afterRead="afterRead"
+					@delete="deletePic"
+					name="2"
+					multiple
+					:maxCount="10"
+					accept="video"
+				></u-upload>
+			</view>
 			<view class="" style="background-color: #efefef; height: 20rpx; width: 100%"><!-- 分割背景 --></view>
 			<view class="banxin" style="background-color: #ffffff; margin-top: 20rpx">
-				<u--textarea v-model="textVal" placeholder="请输入内容"></u--textarea>
+				<u--textarea v-model.trim="textVal" placeholder="请输入内容"></u--textarea>
 			</view>
 			<!-- 分区 -->
 			<u-popup :show="showTanCeng" mode="bottom" @close="close" bgColor="#efefef">
 				<view class="show_box">
 					<view class="" style="display: flex; justify-content: space-between">
 						<text @click="showTanCeng = false">取消</text>
-						<text class="box_ok">确认</text>
+						<text @click="showTanCeng = false" class="box_ok">确认</text>
 					</view>
 					<view class="box_fenqu" @click="show = true">
-						<text>分区</text>
-						<view class="">
-							<text style="color: #999999; font-size: 28rpx">生活 - 日常</text>
+						<text>选择投稿类型</text>
+						<view style="display: flex">
+							<text style="color: #999999; font-size: 28rpx">{{ typeName }}</text>
 							<uni-icons color="#999999" type="forward" size="20"></uni-icons>
 						</view>
 					</view>
 					<!-- 添加标签 -->
 					<view class="box_tj">
-						<!-- <text style="color: #999999; font-size: 28rpx">还可以添加 2 个标签</text> -->
+						<text style="color: #999999; font-size: 28rpx">选择内容类型</text>
 						<view class="tag_box">
 							<view class="" v-for="(item, index) in radios" :key="index">
-								<u-tag size="mini" :text="`选项${index + 1}`" :plain="!item.checked" shape="circle" type="warning" :name="index" @click="radioClick"></u-tag>
+								<u-tag size="mini" :text="item.name" :plain="!item.checked" shape="circle" type="warning" :name="index" @click="radioClick"></u-tag>
 							</view>
 						</view>
-						<!-- 推荐标签 -->
-						<!-- 	<view class="" style="margin-top: 20rpx">
-							<view style="color: #000000; font-size: 30rpx">推荐标签</view>
-							<view class="" style="display: flex; margin-top: 20rpx">
-								<u-tag size="mini" shape="circle" text="标签" type="warning"></u-tag>
-								<u-tag size="mini" shape="circle" text="标签" type="success"></u-tag>
-							</view>
-						</view> -->
 					</view>
 
 					<u-picker
-						title="选择分区"
+						title="选择投稿类型"
 						:show="show"
 						@close="show = false"
 						ref="uPicker"
 						@cancel="show = false"
-						keyName="label"
+						keyName="name"
 						:closeOnClickOverlay="true"
 						:columns="columns"
 						@confirm="confirm"
-						@change="changeHandler"
 					></u-picker>
 				</view>
 			</u-popup>
@@ -97,10 +107,7 @@
 
 			<!-- 评论 -->
 			<view class="" style="background-color: #efefef; height: 20rpx; width: 100%"></view>
-			<!-- 		<view class="pl_box">
-				<text>开启评论</text>
-				<u-switch activeColor="#5ac725" v-model="switchval" @change="change"></u-switch>
-			</view> -->
+
 			<view class="queren" @click="isOk">确认发布</view>
 		</view>
 	</view>
@@ -111,52 +118,57 @@ let that;
 export default {
 	data() {
 		return {
+			releaseTab: 0,
 			radios: [
 				{
+					name: '文章',
+					id: 1,
 					checked: true
 				},
 				{
+					name: '视频',
+					id: 2,
+					checked: false
+				},
+				{
+					name: '音频',
+					id: 3,
 					checked: false
 				},
 				{
+					name: '相册',
+					id: 4,
 					checked: false
 				}
 			],
+			model_id: '' /* 投稿模型id */,
+			typeId: 1 /* 投稿内容类型id */,
+			main_body_column_id: '' /* 投稿栏目id */,
+			typeName: '' /* 选中的类型 */,
 			closeTag: true,
-			tags: [
-				{ label: '标签1', type: 'primary', closable: true },
-				{ label: '标签2', type: 'warning ', closable: true },
-				{ label: '标签3', type: 'success', closable: true }
-			],
 			showTanCeng: false,
 			show: false,
-			columns: [
-				[
-					{ label: '中国', id: 1 },
-					{ label: '美国', id: 2 }
-				],
-				['深圳', '厦门', '上海', '拉萨']
-			],
-			columnData: [
-				['深圳', '厦门', '上海', '拉萨'],
-				['得州', '华盛顿', '纽约', '阿拉斯加']
-			],
+			columns: [],
 			titleVal: '',
 			textVal: '',
 			// switchval: '',
+			// 上传的图片
 			fileList1: [
-				{
-					url: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/shouyeTJ.png'
-				},
-				{
-					url: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/cs_shouye_tp.png'
-				}
-			]
+				// {
+				// 	url: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/shouyeTJ.png'
+				// },
+				// {
+				// 	url: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/cs_shouye_tp.png'
+				// }
+			],
+			// 上传的视频
+			fileList2: []
 		};
 	},
 	onLoad() {
 		that = this;
 		this.main_body_id = this.$db.get('main_body_id');
+		this.getColumnList();
 	},
 	computed: {
 		uploadNumber() {
@@ -164,39 +176,38 @@ export default {
 		}
 	},
 	methods: {
+		getColumnList() {
+			this.$api.getColumnList(
+				{
+					main_body_id: this.main_body_id,
+					// 暂时传2
+					model_id: '2'
+				},
+				function (res) {
+					// console.log(res, 565656);
+					let aa = [];
+					aa.push(res.data);
+					// console.log(aa, 13131313);
+					that.columns = aa;
+				}
+			);
+		},
+		releaseBtn(i) {
+			this.releaseTab = i;
+		},
 		fenquBtn() {
 			// this.show = true;
 			this.showTanCeng = true;
 		},
-		// 关闭标签
-		closeBtn(item) {
-			console.log(item);
-			this.tags.splice(this.tags.indexOf(item), 1);
-		},
-		// 分区组件方法
-		changeHandler(e) {
-			const {
-				columnIndex,
-				value,
-				values, // values为当前变化列的数组内容
-				index,
-				// 微信小程序无法将picker实例传出来,只能通过ref操作
-				picker = this.$refs.uPicker
-			} = e;
-			// 当第一列值发生变化时,变化第二列(后一列)对应的选项
-			if (columnIndex === 0) {
-				// picker为选择器this实例,变化第二列对应的选项
-				picker.setColumnValues(1, this.columnData[index]);
-			}
-		},
-		//// 分区组件方法 回调参数为包含columnIndex、value、values
+
 		confirm(e) {
-			console.log('confirm', e.value[0]);
+			console.log('confirm', e.value);
+			this.model_id = e.value[0].model_id;
+			this.main_body_column_id = e.value[0].id;
+			this.typeName = e.value[0].name;
 			this.show = false;
 		},
-		// change(e) {
-		// 	console.log('change', e);
-		// },
+
 		// 删除图片
 		deletePic(event) {
 			console.log(event, 'event');
@@ -232,7 +243,7 @@ export default {
 		uploadFilePromise(url) {
 			return new Promise((resolve, reject) => {
 				let a = uni.uploadFile({
-					url: 'http://192.168.2.21:7001/upload', // 仅为示例,非真实的接口地址
+					url: 'https://mnhcdn.wenlvti.net/api/minnansoul/content/contribute', // 仅为示例,非真实的接口地址
 					filePath: url,
 					name: 'file',
 					formData: {
@@ -250,17 +261,53 @@ export default {
 			this.radios.map((item, index) => {
 				item.checked = index === name ? true : false;
 			});
+			this.typeId = this.radios[name].id;
 		},
+		// 投稿
 		isOk() {
-			if (this.titleVal == '' || this.titleVal == undefined) {
-				that.$common.errorToShow('请填写标题');
+			let titleIsEmpty = this.titleVal === '';
+			let textIsEmpty = this.textVal === '';
+
+			// 先检查标题和内容是否为空
+			if (titleIsEmpty) {
+				that.$common.errorToShow('请填写投稿标题');
+				return false; // 遇到错误时提前返回,避免后续条件的判断
 			}
-			if (this.textVal == '' || this.textVal == undefined) {
-				that.$common.errorToShow('请输入内容');
+
+			if (textIsEmpty) {
+				that.$common.errorToShow('请输入投稿内容');
+				return false;
+			}
+
+			// 再检查模型ID、类型ID和栏目ID
+			if (this.model_id === '' || this.main_body_column_id === '') {
+				that.$common.errorToShow('请选择投稿类型');
+				return false;
+			}
+
+			// 如果typeId是必须选择的,这里也要进行验证
+			if (this.typeId === '') {
+				that.$common.errorToShow('请选择内容类型');
+				return false;
 			} else {
-				// this.$api.contribute({}, function (res) {
-				// 	console.log(res, 6666);
-				// });
+				this.$api.contribute(
+					{
+						main_body_id: this.main_body_id,
+						model_id: this.model_id,
+						main_body_column_id: this.main_body_column_id,
+						title: this.titleVal,
+						type: this.typeId,
+						content: this.titleVal
+					},
+					function (res) {
+						if (res.code == 1) {
+							that.$common.successToShow('投稿成功');
+						} else {
+							that.$common.errorToShow('投稿失败请稍后在试');
+							console.log(that.fileList1, 6666);
+						}
+					}
+				);
 			}
 		},
 		close() {
@@ -272,6 +319,24 @@ export default {
 </script>
 
 <style>
+.uptriangle {
+	position: absolute;
+	top: 120rpx;
+	left: 170rpx;
+	width: 0px;
+	height: 0px;
+	border: 30rpx solid transparent;
+	border-top-color: #ca5642;
+}
+.uptriangle_active {
+	position: absolute;
+	top: 120rpx;
+	left: 510rpx;
+	width: 0px;
+	height: 0px;
+	border: 30rpx solid transparent;
+	border-top-color: #ca5642;
+}
 .banxin {
 	margin: 0 32rpx 0 32rpx;
 }
@@ -287,12 +352,11 @@ export default {
 }
 .tag_box {
 	display: flex;
+	margin-top: 20rpx;
 }
-/* .u-icon__icon.data-v-2ee87dc9 {
-	font-size: 25rpx !important;
-	line-height: 26rpx !important;
-} */
+
 .nav_fabu {
+	position: relative;
 	display: flex;
 	justify-content: space-evenly;
 	background-color: #ca5642;
@@ -339,7 +403,7 @@ export default {
 .sc_box {
 	display: flex;
 	justify-content: space-between;
-	margin: 0 55rpx 40rpx 55rpx;
+	margin: 0 55rpx 40rpx 10rpx;
 	border-bottom: 1px #dedede solid;
 	height: 60rpx;
 }
@@ -412,4 +476,4 @@ export default {
 	margin-top: 20rpx;
 	padding: 20rpx;
 }
-</style>
+</style>

+ 24 - 23
config/api.js

@@ -7,7 +7,7 @@ import * as db from './db.js' //引入common
 // 需要登陆的,都写到这里,否则就是不需要登陆的接口
 let methodsToken = ['profile', 'refreshUser', 'wxLogin', 'changeMobile', 'getContentDetail',
 	'addCart', 'previewOrder', 'editMainBodyUser', 'like', 'unLike', 'getUserLike', 'getUserCollect', 'collect',
-	'uncollect'
+	'uncollect', 'contribute'
 ];
 const post = (method, data, callback, type, orgurl) => {
 	let userToken = '';
@@ -244,7 +244,7 @@ const syncpost = (f, m, d) => {
 
 }
 // 登录
-export const third = (data, callback) => post('third', data, callback, 'minnansoul/main_body_user');
+export const third = (data, callback) => post('third', data, callback, 'content/main_body_user');
 // 用户绑定手机
 export const bindphone = (data, callback) => post('bind', data, callback, 'discover/User');
 // 修改用户信息
@@ -252,7 +252,7 @@ export const profile = (data, callback) => post('profile', data, callback, 'disc
 // 发送验证码
 export const sendSmsVerify = (data, callback) => post('sendSmsVerify', data, callback, 'discover/User');
 // 刷新用户
-export const refreshUser = (data, callback) => post('refreshUser', data, callback, 'minnansoul/main_body_user');
+export const refreshUser = (data, callback) => post('refreshUser', data, callback, 'content/main_body_user');
 // 注册
 // export const register = (data, callback) => post('register', data, callback, 'discover/User');
 // 登录
@@ -332,7 +332,7 @@ function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
 }
 
 //取轮播图
-export const getIndexBanner = (data, callback) => get('api/minnansoul/banner_function/getIndexBanner' + queryParams(
+export const getIndexBanner = (data, callback) => get('api/content/banner_function/getIndexBanner' + queryParams(
 	data,
 	true), callback);
 // export const getWuyuanUser = (data, callback) => post('getWuyuanUser', data, callback, 'wuyuan/user');
@@ -386,60 +386,61 @@ export const scheduleStartLearn = (data, callback) => post('startLearn', data, c
 export const getMineCourseList = (data, callback) => post('getMineCourseList', data, callback, '',
 	'addons/yuneducation/course/getMineCourseList');
 // 城市主体列表
-export const getCity = (data, callback) => get('api/minnansoul/main_body/getCity' + queryParams(data, true),
+export const getCity = (data, callback) => get('api/content/main_body/getCity' + queryParams(data, true),
 	callback);
 //获取主体用户信息
 export const getMainBodyUser = (data, callback) => post('getMainBodyUser', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //修改主体用户信息
 export const editMainBodyUser = (data, callback) => post('editMainBodyUser', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 // 首页功能集
-export const getIndexFunction = (data, callback) => get('api/minnansoul/banner_function/getIndexFunction' + queryParams(
+export const getIndexFunction = (data, callback) => get('api/content/banner_function/getIndexFunction' + queryParams(
 	data,
 	true), callback);
 // 获取带标志的内容列表
 export const getFlagList = (data, callback) => post('getFlagList', data, callback,
-	'minnansoul/content');
+	'content/content');
 // 模型的主体栏目列表
 export const getColumnList = (data, callback) => post('getColumnList', data, callback,
-	'minnansoul/main_body_column');
+	'content/main_body_column');
 // 模型内容列表
 export const getContentList = (data, callback) => post('getContentList', data, callback,
-	'minnansoul/content');
+	'content/content');
 // 模型主体栏目内容列表
 export const getMainBodyColumnContentList = (data, callback) => post('getMainBodyColumnContentList', data, callback,
-	'minnansoul/content');
+	'content/content');
 // 内容详情
 export const getContentDetails = (data, callback) => post('getContentDetail', data, callback,
-	'minnansoul/content');
+	'content/content');
 //史馆列表
 export const getHistoryMuseum = (data, callback) => post('getHistoryMuseum', data, callback,
-	'minnansoul/main_body');
+	'content/main_body');
 //史馆详情
 export const getDetail = (data, callback) => post('getDetail', data, callback,
-	'minnansoul/main_body');
+	'content/main_body');
 //史馆列表分类列表
 export const getCategoryLists = (data, callback) => post('getCategoryList', data, callback,
-	'minnansoul/category');
+	'content/category');
 //点赞
 export const like = (data, callback) => post('like', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //取消点赞
 export const unLike = (data, callback) => post('unLike', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //点赞内容列表
 export const getUserLike = (data, callback) => post('getUserLike', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //收藏
 export const collect = (data, callback) => post('collect', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //取消收藏
 export const uncollect = (data, callback) => post('uncollect', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //收藏内容列表
 export const getUserCollect = (data, callback) => post('getUserCollect', data, callback,
-	'minnansoul/main_body_user');
+	'content/main_body_user');
 //投稿
 export const contribute = (data, callback) => post('contribute', data, callback,
-	'minnansoul/content');
+	'content/content');
+// content

File diff suppressed because it is too large
+ 4 - 8
config/config.js


+ 7 - 6
index_fenbao/jianzhu/jianZhuXQ.vue

@@ -107,7 +107,7 @@
 				<view style="font-weight: 700; font-size: 18px">文物责任人</view>
 			</view>
 			<view class="text">
-				<u-parse :content="list.director"></u-parse>
+				<u-parse :content="list.director ? list.director : '暂无责任人'"></u-parse>
 			</view>
 		</view>
 	</view>
@@ -121,11 +121,11 @@ export default {
 			main_body_id: '',
 			list: [],
 			imageList: [
-				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt2.png',
-				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt1.png',
-				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt3.jpg',
-				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt4.jpg',
-				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt5.png'
+				// 'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt2.png',
+				// 'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt1.png',
+				// 'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt3.jpg',
+				// 'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt4.jpg',
+				// 'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt5.png'
 			]
 		};
 	},
@@ -146,6 +146,7 @@ export default {
 				},
 				function (res) {
 					that.list = res.data;
+					that.imageList = res.data.images;
 				}
 			);
 		},

+ 252 - 11
index_fenbao/jianzhu/jianZhu_index.vue

@@ -16,12 +16,19 @@
 		</view>
 		<view class="tit">建筑地图</view>
 		<view class="map_box" @click="navMap">
-			<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/map2.jpg"></image>
+			<view style="width: 1700rpx; height: 1400rpx; position: absolute; left: -61%; top: -140%">
+				<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/map3.jpg"></image>
+			</view>
 		</view>
-		<view class="tit">建筑简介</view>
+		<view class="tit">建筑文化</view>
 		<view class="jj_box">
 			<view class="jj_left">
-				闽南建筑风格独特。闽南建筑风格以红墙、红瓦、燕尾脊为特征,给人以鲜明、热烈的视觉感受。建筑中大量使用装饰性构件,如砖雕、石雕、木雕等,这些雕刻工艺精湛,图案丰富,具有很高的艺术价值。同时,建筑内部的布局和装饰也充满了闽南文化的特色,如“出砖入石”的墙体、精细的石雕和木雕、富有地方特色的彩绘等。
+				<view class="jj_bg">建筑文化简介</view>
+				<view class="jj_left_js">
+					闽南建筑风格独特。闽南建筑风格以红墙、红瓦、燕尾脊为特征,给人以鲜明、热烈的视觉感受。建筑中大量使用装饰性构件,如砖雕、石雕、木雕等,这些雕刻工艺精湛,图案丰富,具有很高的艺术价值。同时,建筑内部的布局和装饰也充满了闽南文化的特色,如“出砖入石”的墙体、精细的石雕和木雕、富有地方特色的彩绘等。
+					闽南建筑融合了多元文化。闽南地区历史上是中原移民的重要聚居地,同时又与东南亚地区交往密切,因此闽南建筑文化中融合了中原文化、东南亚文化等多元文化因素。例如,闽南建筑的屋顶形式、装饰风格等受到中原文化的影响;而建筑中的雕刻艺术、建筑材料等则体现了东南亚文化的特色。这种多元文化的融合使得闽南建筑具有更加丰富的文化内涵
+					通过了解这些闽南建筑文物的特点,人们能够更好地认识和了解闽南文化。同时,这些文物也是传承和弘扬闽南文化的重要载体。在今天的社会中,随着城市化进程的加速和传统文化的逐渐消失,保护和传承这些宝贵的文化遗产显得尤为重要。
+				</view>
 			</view>
 			<view class="jj_right">
 				<view class="right_top">
@@ -30,6 +37,67 @@
 				<view class="right_btm"><image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/tv7.jpg"></image></view>
 			</view>
 		</view>
+		<!-- 饼图 -->
+		<view class="tit">文物统计</view>
+		<view class="bt_box">
+			<view style="position: absolute; left: 80rpx; top: 10rpx; color: #873b3f">厦门</view>
+			<view style="position: absolute; left: 312rpx; top: 8rpx; color: #873b3f">漳州</view>
+			<view style="position: absolute; left: 540rpx; top: 10rpx; color: #873b3f">泉州</view>
+			<!-- 图例 -->
+			<view class="" style="position: absolute; top: 312rpx">
+				<view style="display: flex; width: 320rpx; justify-content: space-around">
+					<view style="display: flex; align-items: center">
+						<view style="width: 20rpx; height: 20rpx; border-radius: 50%; background-color: #ee6666"></view>
+						<view style="font-size: 24rpx; color: #873b3f">国家级</view>
+					</view>
+					<view style="display: flex; align-items: center">
+						<view style="width: 20rpx; height: 20rpx; border-radius: 50%; background-color: #fac858"></view>
+						<view style="font-size: 24rpx; color: #873b3f">省级</view>
+					</view>
+					<view style="display: flex; align-items: center">
+						<view style="width: 20rpx; height: 20rpx; border-radius: 50%; background-color: #873b3f"></view>
+						<view style="font-size: 24rpx; color: #873b3f">市级</view>
+					</view>
+				</view>
+				<view style="display: flex; width: 320rpx; justify-content: space-around">
+					<view style="display: flex; align-items: center">
+						<view style="width: 20rpx; height: 20rpx; border-radius: 50%; background-color: #91cb74"></view>
+						<view style="font-size: 24rpx; color: #873b3f">县级</view>
+					</view>
+					<view style="display: flex; align-items: center">
+						<view style="width: 20rpx; height: 20rpx; border-radius: 50%; background-color: #73c0de"></view>
+						<view style="font-size: 24rpx; color: #873b3f">区级</view>
+					</view>
+				</view>
+			</view>
+			<view class="charts-box1">
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 80rpx; top: 30rpx; z-index: 9">12.41%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 135rpx; top: 70rpx; z-index: 9">19.15%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 135rpx; top: 135rpx; z-index: 9">17.02%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 72rpx; top: 160rpx; z-index: 9">20.21%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 50rpx; top: 100rpx; z-index: 9">21%</view>
+				<qiun-data-charts type="pie" :opts="opts" :chartData="chartData" />
+			</view>
+			<view class="charts-box">
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 30rpx; top: 110rpx; z-index: 9">34.42%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 170rpx; top: 116rpx; z-index: 9">2.29%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 150rpx; top: 150rpx; z-index: 9">12.29%</view>
+				<qiun-data-charts type="pie" :opts="opts2" :chartData="chartData2" />
+			</view>
+			<view class="charts-box1">
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 30rpx; top: 110rpx; z-index: 9">34.27%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 150rpx; top: 110rpx; z-index: 9">4.68%</view>
+				<view style="position: absolute; color: #ffffff; font-size: 18rpx; left: 136rpx; top: 140rpx; z-index: 9">11.05%</view>
+				<qiun-data-charts type="pie" :opts="opts3" :chartData="chartData3" />
+			</view>
+		</view>
+		<view class="tit">文物推荐</view>
+		<view class="btm_box" @click="recommendBtn">
+			<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/tv5.jpg"></image>
+		</view>
+		<view class="btm_box" @click="recommendBtn">
+			<image style="width: 100%; height: 100%" src="https://huli-app.wenlvti.net/app_static/minnanhun/image/tv8.jpg"></image>
+		</view>
 	</view>
 </template>
 
@@ -41,7 +109,114 @@ export default {
 			isLoading: false, // 节流阀 默认为关闭状态
 			main_body_id: '',
 			model_id: '',
+			chartData: {
+				series: [
+					{
+						data: [
+							{ name: '国家级', value: 48 },
+							{ name: '省级', value: 57 },
+							{ name: '市级', value: 88 },
+							{ name: '县级', value: 35 },
+							{ name: '区级', value: 54 }
+							// { name: '未定级', value: 1743 }
+						],
+						textOffset: 50
+					}
+				]
+			},
+			opts: {
+				color: ['#EE6666', '#fac858', '#873b3f', '#91CB74', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
+				padding: [0, 0, 0, 0],
+				enableScroll: false,
+				fontSize: 8, // 字体大小
+				fontColor: '#1890FF',
+				dataLabel: false,
+				legend: {
+					show: false
+				},
 
+				extra: {
+					pie: {
+						activeOpacity: 0.5,
+						activeRadius: 8,
+						offsetAngle: 0,
+						labelWidth: 2,
+						border: false,
+						borderWidth: 3,
+						borderColor: '#FFFFFF'
+					}
+				}
+			},
+			// 漳州图
+			chartData2: {
+				series: [
+					{
+						data: [
+							{ name: '国家级', value: 26 },
+							{ name: '省级', value: 151 },
+							{ name: '市区县级', value: 959 }
+						]
+					}
+				]
+			},
+			opts2: {
+				color: ['#EE6666', '#fac858', '#873b3f', '#91CB74', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
+				padding: [0, 0, 0, 0],
+				enableScroll: false,
+				fontSize: 8, // 字体大小
+				fontColor: '#1890FF',
+				dataLabel: false,
+				legend: {
+					show: false
+				},
+
+				extra: {
+					pie: {
+						activeOpacity: 0.5,
+						activeRadius: 8,
+						offsetAngle: 0,
+						labelWidth: 2,
+						border: false,
+						borderWidth: 3,
+						borderColor: '#FFFFFF'
+					}
+				}
+			},
+			// 泉州图
+			chartData3: {
+				series: [
+					{
+						data: [
+							{ name: '国家级', value: 44 },
+							{ name: '省级', value: 104 },
+							{ name: '市区县级', value: 793 }
+						]
+					}
+				]
+			},
+			opts3: {
+				color: ['#EE6666', '#fac858', '#873b3f', '#91CB74', '#73C0DE', '#3CA272', '#FC8452', '#9A60B4', '#ea7ccc'],
+				padding: [0, 0, 0, 0],
+				enableScroll: false,
+				fontSize: 8, // 字体大小
+				fontColor: '#1890FF',
+				dataLabel: false,
+				legend: {
+					show: false
+				},
+
+				extra: {
+					pie: {
+						activeOpacity: 0.5,
+						activeRadius: 8,
+						offsetAngle: 0,
+						labelWidth: 2,
+						border: false,
+						borderWidth: 3,
+						borderColor: '#FFFFFF'
+					}
+				}
+			},
 			list1: [
 				'https://img1.baidu.com/it/u=3551075903,1493549593&fm=253&fmt=auto&app=138&f=JPEG?w=667&h=500',
 				'https://img0.baidu.com/it/u=1667631211,245764236&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=357',
@@ -49,7 +224,7 @@ export default {
 			]
 		};
 	},
-	onLoad(o) {
+	onLoad() {
 		that = this;
 		this.main_body_id = this.$db.get('main_body_id');
 	},
@@ -66,6 +241,12 @@ export default {
 			uni.navigateTo({
 				url: this.jianZhuList[i].page
 			});
+		},
+		// 文物推荐
+		recommendBtn() {
+			uni.navigateTo({
+				url: '/index_fenbao/jianzhu/jianzhu?id=' + 21
+			});
 		}
 	}
 };
@@ -94,10 +275,10 @@ export default {
 	margin: auto;
 	text-align: center;
 	line-height: 60rpx;
-	margin-top: 20rpx;
+	margin-top: 80rpx;
 	margin-bottom: 20rpx;
 	font-size: 28rpx;
-	color: #f8eddf;
+	color: #f1e8d7;
 	background-image: url('/static/image/jz_bg.png');
 	background-size: 100% 100%;
 }
@@ -106,10 +287,11 @@ export default {
 	height: 400rpx;
 	border: #873b3f 8rpx solid;
 	margin: auto;
+	position: relative;
+	overflow: hidden;
 }
 .jj_box {
 	width: 700rpx;
-	height: 600rpx;
 	display: flex;
 	text-indent: 2em;
 	line-height: 40rpx;
@@ -119,8 +301,33 @@ export default {
 }
 .jj_left {
 	width: 50%;
+	height: 500rpx;
+	background-image: url('https://huli-app.wenlvti.net/app_static/minnanhun/image/jz_titbg.png');
+	background-size: 100% 100%;
 	background-color: #873b3f;
 }
+.jj_left_js {
+	width: 270rpx;
+	height: 360rpx;
+	margin: auto;
+	margin-top: 10rpx;
+	border-radius: 10rpx;
+	overflow: scroll;
+	background-color: rgba(255, 255, 255, 0.3);
+}
+.jj_bg {
+	width: 300rpx;
+	height: 70rpx;
+	line-height: 72rpx;
+	padding-left: 20rpx;
+	color: #8e3e3d;
+	font-size: 28rpx;
+	margin: auto;
+	margin-top: 20rpx;
+
+	background-image: url('/static/image/jz_tit.png');
+	background-size: 100% 100%;
+}
 .jj_right {
 	width: 50%;
 	height: 100%;
@@ -129,14 +336,48 @@ export default {
 .right_top {
 	display: flex;
 	width: 350rpx;
-	height: 290rpx;
-	background-color: #873b3f;
+	height: 240rpx;
+	border: #873b3f 4rpx solid;
 }
 .right_btm {
 	display: flex;
 	width: 350rpx;
-	height: 290rpx;
+	height: 240rpx;
 	margin-top: 20rpx;
-	background-color: #873b3f;
+	border: #873b3f 4rpx solid;
+}
+
+.btm_box {
+	width: 90%;
+	height: 340rpx;
+	margin: auto;
+	margin-top: 20rpx;
+	border: #873b3f 4rpx solid;
+}
+.charts-box {
+	position: relative;
+	width: 240rpx;
+	height: 240rpx;
+}
+.charts-box1 {
+	position: relative;
+	width: 220rpx;
+	height: 220rpx;
+}
+.csbt {
+	position: absolute;
+	bottom: -4%;
+	left: 40%;
+	font-size: 12px;
+}
+.bt_box {
+	position: relative;
+	width: 90%;
+	height: 400rpx;
+	padding-top: 55rpx;
+	margin: auto;
+	display: flex;
+	justify-content: space-around;
+	border: #873b3f 8rpx solid;
 }
 </style>

+ 2 - 2
index_fenbao/jianzhu/jianzhu.vue

@@ -110,7 +110,7 @@ export default {
 		getColumnList(id) {
 			this.$api.getColumnList(
 				{
-					model_id: id,
+					model_id: 1,
 					main_body_id: this.main_body_id
 				},
 				function (res) {
@@ -131,7 +131,7 @@ export default {
 			this.isLoading = true;
 			this.$api.getContentList(
 				{
-					model_id: this.model_id,
+					model_id: 1,
 					main_body_id: this.main_body_id,
 					page: this.page,
 					pageSize: '10'

+ 0 - 1
index_fenbao/jianzhu/map_page.vue

@@ -60,7 +60,6 @@ export default {
 							height: 35, //高
 							joinCluster: true,
 							title: item.title, //标注点名
-
 							label: {
 								//自定义标记点上方的文本
 								content: item.title, //文本

+ 143 - 0
index_fenbao/mn_jingshen/PageSpirit.vue

@@ -0,0 +1,143 @@
+<template>
+	<view>
+		<u-navbar :autoBack="true" :title="list.title" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+
+		<view class="block_3">
+			<view class="text_3">
+				<text class="text_10">
+					<!-- <u-parse :content="list.content"></u-parse> -->
+					{{ (list.content || '').replace(/<\/?[^>]*>/g, '') | removeHTMLTag }}
+				</text>
+			</view>
+			<view class="box_3">
+				<image style="width: 100%; height: 100%" :src="list.image"></image>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+let that;
+export default {
+	data() {
+		return {
+			main_body_id: '',
+			list: {}
+		};
+	},
+	filters: {
+		removeHTMLTag(str) {
+			str = str.replace(/<\/?[^>]*>/g, ''); // 去除HTML tag
+			str = str.replace(/[ | ]*\n/g, '\n'); // 去除行尾空白
+			str = str.replace(/\n[\s| | ]*\r/g, '\n'); //去除多余空行
+			// str = str.replace(/ /gi, ''); // 去掉
+			const arrEntities = {
+				lt: '<',
+				gt: '>',
+				nbsp: ' ',
+				amp: '&',
+				quot: '"'
+			}; // 转义符换成普通字符
+			str = str.replace(/&(lt|gt|nbsp|amp|quot);/gi, function (all, t) {
+				return arrEntities[t];
+			});
+			return str;
+		}
+	},
+	onLoad(o) {
+		that = this;
+		this.main_body_id = this.$db.get('main_body_id');
+		this.getContentDetails(o.id);
+	},
+	mounted() {},
+	methods: {
+		// 详情
+		getContentDetails(id) {
+			this.$api.getContentDetails(
+				{
+					main_body_id: this.main_body_id,
+					id: id
+				},
+				function (res) {
+					that.list = res.data;
+					// console.log(that.list, '99999999');
+				}
+			);
+		}
+	}
+};
+</script>
+
+<style>
+.box_r {
+	display: flex;
+	align-items: center;
+	margin-right: 15rpx;
+}
+.sh_xs {
+	margin: 32rpx;
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+}
+
+.block_3 {
+	background-color: rgba(255, 255, 255, 1);
+	width: 749rpx;
+	margin-top: 60rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_3 {
+	width: 685rpx;
+	height: 400rpx;
+	text-indent: 2rem;
+	font-size: 0rpx;
+	overflow: scroll;
+	line-height: 48rpx;
+	margin: 38rpx 0 0 42rpx;
+}
+.text_10 {
+	width: 685rpx;
+	height: 300rpx;
+	/* overflow-wrap: break-word; */
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	line-height: 48rpx;
+}
+
+.box_3 {
+	background-color: rgba(232, 242, 217, 1);
+	height: 422rpx;
+	margin-top: 46rpx;
+	display: flex;
+	flex-direction: column;
+	width: 750rpx;
+}
+.box_4 {
+	background-color: rgba(0, 0, 0, 0.15);
+	width: 750rpx;
+	height: 422rpx;
+	display: flex;
+	flex-direction: column;
+}
+
+.paragraph_5 {
+	width: 684rpx;
+	height: 378rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	line-height: 14rpx;
+}
+
+.box_35 {
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 50rpx 0 32rpx 380rpx;
+}
+</style>

+ 7 - 1
index_fenbao/mn_jingshen/xiang_qing.vue

@@ -2,7 +2,7 @@
 	<view>
 		<u-navbar :autoBack="true" :title="title" bgColor="rgba(255,255,255,255)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
 		<view class="ad">
-			<view class="box_22" v-for="(item, index) in projectList" :key="item.id">
+			<view @click="projectListBtn(index)" class="box_22" v-for="(item, index) in projectList" :key="item.id">
 				<view class="block_5">
 					<image style="width: 100%; height: 100%; border-radius: 0 50rpx 0 20rpx" :src="item.thumbnail"></image>
 
@@ -48,6 +48,12 @@ export default {
 					that.projectList = res.data;
 				}
 			);
+		},
+		// 详情
+		projectListBtn(i) {
+			uni.navigateTo({
+				url: '/index_fenbao/mn_jingshen/PageSpirit?id=' + this.projectList[i].id
+			});
 		}
 	}
 };

+ 2 - 2
index_fenbao/mn_wenhua/mn_wenhua.vue

@@ -21,7 +21,7 @@
 				</view>
 				<view class="group_3" v-for="item in 2" :key="item">
 					<view class="section_3">
-						<image src="../../../static/image/kctp.png"></image>
+						<image src="https://huli-app.wenlvti.net/app_static/minnanhun/image/kctp.png"></image>
 					</view>
 					<view class="section_16">
 						<view class="text-group_36">
@@ -611,4 +611,4 @@ export default {
 	line-height: 24rpx;
 	margin: 10rpx 0 0 18rpx;
 }
-</style>
+</style>

+ 147 - 0
jiyi_fenbao/recommendedDetails.vue

@@ -0,0 +1,147 @@
+<template>
+	<view class="box">
+		<u-navbar :autoBack="true" :title="list.title" bgColor="rgba(255,255,255,0)" :placeholder="true" titleStyle="font-weight:bold;color:#121212"></u-navbar>
+
+		<view class="block_3">
+			<view class="text_3">
+				<text class="text_10">
+					<!-- <u-parse :content="list.content"></u-parse> -->
+					{{ (list.content || '').replace(/<\/?[^>]*>/g, '') | removeHTMLTag }}
+				</text>
+			</view>
+			<view class="box_3">
+				<image style="width: 100%; height: 100%" :src="list.image"></image>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+let that;
+export default {
+	data() {
+		return {
+			main_body_id: '',
+			list: {}
+		};
+	},
+	filters: {
+		removeHTMLTag(str) {
+			str = str.replace(/<\/?[^>]*>/g, ''); // 去除HTML tag
+			str = str.replace(/[ | ]*\n/g, '\n'); // 去除行尾空白
+			str = str.replace(/\n[\s| | ]*\r/g, '\n'); //去除多余空行
+			// str = str.replace(/ /gi, ''); // 去掉
+			const arrEntities = {
+				lt: '<',
+				gt: '>',
+				nbsp: ' ',
+				amp: '&',
+				quot: '"'
+			}; // 转义符换成普通字符
+			str = str.replace(/&(lt|gt|nbsp|amp|quot);/gi, function (all, t) {
+				return arrEntities[t];
+			});
+			return str;
+		}
+	},
+	onLoad(o) {
+		that = this;
+		this.main_body_id = this.$db.get('main_body_id');
+		this.getContentDetails(o.id);
+	},
+	mounted() {},
+	methods: {
+		// 详情
+		getContentDetails(id) {
+			this.$api.getContentDetails(
+				{
+					main_body_id: this.main_body_id,
+					id: id
+				},
+				function (res) {
+					that.list = res.data;
+					// console.log(that.list, '99999999');
+				}
+			);
+		}
+	}
+};
+</script>
+
+<style>
+.box {
+	height: 100%;
+	background-color: #fff9e9;
+}
+.box_r {
+	display: flex;
+	align-items: center;
+	margin-right: 15rpx;
+}
+.sh_xs {
+	margin: 32rpx;
+	display: flex;
+	flex-flow: wrap;
+	justify-content: space-between;
+}
+
+.block_3 {
+	/* background-color: rgba(255, 255, 255, 1); */
+	width: 749rpx;
+	margin-top: 60rpx;
+	display: flex;
+	flex-direction: column;
+}
+.text_3 {
+	width: 685rpx;
+	height: 400rpx;
+	text-indent: 2rem;
+	font-size: 0rpx;
+	overflow: scroll;
+	line-height: 48rpx;
+	margin: 38rpx 0 0 42rpx;
+}
+.text_10 {
+	width: 685rpx;
+	height: 300rpx;
+	/* overflow-wrap: break-word; */
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	line-height: 48rpx;
+}
+
+.box_3 {
+	background-color: rgba(232, 242, 217, 1);
+	height: 422rpx;
+	margin-top: 46rpx;
+	display: flex;
+	flex-direction: column;
+	width: 750rpx;
+}
+.box_4 {
+	background-color: rgba(0, 0, 0, 0.15);
+	width: 750rpx;
+	height: 422rpx;
+	display: flex;
+	flex-direction: column;
+}
+
+.paragraph_5 {
+	width: 684rpx;
+	height: 378rpx;
+	overflow-wrap: break-word;
+	color: rgba(49, 37, 32, 1);
+	font-size: 30rpx;
+	font-family: SourceHanSansCN-Regular;
+	font-weight: normal;
+
+	line-height: 14rpx;
+}
+
+.box_35 {
+	height: 32rpx;
+	flex-direction: row;
+	display: flex;
+	margin: 50rpx 0 32rpx 380rpx;
+}
+</style>

+ 1 - 1
mixins/auth.js

@@ -11,4 +11,4 @@ export default {
 			silentReload()
 		}
 	}
-}
+}

+ 20 - 2
pages.json

@@ -253,7 +253,16 @@
 					"enablePullDownRefresh": false
 				}
 
-			}]
+			}    ,{
+                    "path" : "PageSpirit",
+                    "style" :                                                                                    
+                {
+                    "navigationBarTitleText": "",
+                    "enablePullDownRefresh": false
+                }
+                
+                }
+            ]
 		},
 		{
 			"root": "index_fenbao/mn_wenhua",
@@ -288,7 +297,16 @@
 					"enablePullDownRefresh": false
 				}
 
-			}]
+			}    ,{
+                    "path" : "recommendedDetails",
+                    "style" :                                                                                    
+                {
+                    "navigationBarTitleText": "",
+                    "enablePullDownRefresh": false
+                }
+                
+                }
+            ]
 		},
 
 		// llllllllllll

+ 132 - 87
pages/chuanCheng/chuanCheng.vue

@@ -16,6 +16,7 @@
 			</view>
 			<view class="box_tab">
 				<u-tabs
+					@click="tabsBtn"
 					:duration="200"
 					:list="listTab"
 					:lineWidth="25"
@@ -28,16 +29,38 @@
 					}"
 				></u-tabs>
 			</view>
-			<!-- 瀑布流 -->
 
-			<custom-waterfalls-flow :value="list" style="width: 90%; margin: auto">
-				<view class="item" style="position: relative" v-for="(item, index) in list" :key="index" slot="slot{{index}}">
-					<view class="title_pubu">
-						{{ item.title }}
+			<uv-waterfall ref="waterfall" v-model="list" :add-time="10" left-gap="10" right-gap="10" :column-gap="columnGap" @changeList="changeList">
+				<template v-slot:list1>
+					<view>
+						<view @click="detailsBtn(index)" v-for="(item, index) in list1" :key="item.id" class="waterfall-item">
+							<view class="waterfall-item__image" :style="[imageStyle(item)]">
+								<image :src="item.image" mode="widthFix" style="border-radius: 25rpx 60rpx 0rpx 30rpx" :style="{ width: item.width + 'px' }"></image>
+							</view>
+							<view class="waterfall-item__ft">
+								<view class="waterfall-item__ft__title">
+									<text class="value">{{ item.title }}</text>
+								</view>
+							</view>
+						</view>
 					</view>
-					<!-- <view class="desc">{{ item.desc }}</view> -->
-				</view>
-			</custom-waterfalls-flow>
+				</template>
+
+				<template v-slot:list2>
+					<view>
+						<view @click="detailsBtn2(index)" v-for="(item, index) in list2" :key="item.id" class="waterfall-item">
+							<view class="waterfall-item__image" :style="[imageStyle(item)]">
+								<image :src="item.image" mode="widthFix" style="border-radius: 25rpx 60rpx 0rpx 30rpx" :style="{ width: item.width + 'px' }"></image>
+							</view>
+							<view class="waterfall-item__ft">
+								<view class="waterfall-item__ft__title">
+									<text class="value">{{ item.title }}</text>
+								</view>
+							</view>
+						</view>
+					</view>
+				</template>
+			</uv-waterfall>
 		</view>
 		<mntabBar footerTab="2" :messageCount="0"></mntabBar>
 	</view>
@@ -51,88 +74,102 @@ export default {
 	components: {},
 	data() {
 		return {
+			main_body_id: '',
 			tabImg: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/tab.png',
-			list: [
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy1.png',
-					title: '传统捏泥人',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy2.png',
-					title: '青龙宫',
-					desc: '描述描述描述描述描述描述描述描述1'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy3.png',
-					title: '火把节',
-					desc: '11'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy9.png',
-					title: '老物件',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy4.png',
-					title: '林后青龙宫',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy10.png',
-					title: '书籍',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy7.png',
-					title: '建筑',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy8.png',
-					title: '老钟表',
-					desc: '描述描述描述描述描述描述描述描述2'
-				},
-
-				{
-					image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy14.png',
-					title: '老物件',
-					desc: '描述描述描述描述描述描述描述描述2'
-				}
-			],
+			model_id: '',
+			list: [],
+			list1: [], // 瀑布流第一列数据
+			list2: [], // 瀑布流第二列数据
+			columnGap: 10,
 			listTab: [
 				{
-					name: '书法',
-					tabid: 1
-				},
-				{
-					name: '戏曲',
-					tabid: 2
-				},
-				{
 					name: '非遗',
-					tabid: 3
-				},
-				{
-					name: '文化',
-					tabid: 4
+					tabid: 2
 				},
 				{
-					name: '创作',
-					tabid: 5
+					name: '建筑',
+					tabid: 1
 				}
+				// {
+				// 	name: '书法',
+				// 	tabid: 1
+				// },
+				// {
+				// 	name: '戏曲',
+				// 	tabid: 2
+				// },
+
+				// {
+				// 	name: '文化',
+				// 	tabid: 4
+				// },
+				// {
+				// 	name: '创作',
+				// 	tabid: 5
+				// }
 			]
 		};
 	},
 	onLoad(option) {
 		that = this;
+		this.main_body_id = this.$db.get('main_body_id');
+		this.getContentList();
+	},
+	computed: {
+		imageStyle(item) {
+			return (item) => {
+				const v = uni.upx2px(750) - this.leftGap - this.rightGap - this.columnGap;
+				const w = v / 2;
+				const rate = w / item.w;
+				const h = rate * item.h;
+				return {
+					width: w + 'px',
+					height: h + 'px'
+				};
+			};
+		}
 	},
-	computed: {},
 	methods: {
+		// 栏目内容列表
+		getContentList(id) {
+			this.$api.getContentList(
+				{
+					model_id: id ? id : 2,
+					main_body_id: this.main_body_id,
+					page: 1,
+					pageSize: '10'
+				},
+				function (res) {
+					that.list = res.data;
+					that.model_id = res.data[0].model_id;
+					// console.log(that.model_id, 'that.model_id');
+				}
+			);
+		},
+		detailsBtn(i) {
+			uni.navigateTo({
+				url: this.list1[i].page
+			});
+		},
+		detailsBtn2(i) {
+			uni.navigateTo({
+				url: this.list2[i].page
+			});
+		},
+		tabsBtn(i) {
+			that.list = [];
+			that.$refs.waterfall.clear();
+			that.list1 = [];
+			that.list2 = [];
+			// this.id1 = index.id;
+			this.getContentList(this.listTab[i.index].tabid);
+		},
+		changeList(e) {
+			this[e.name].push(e.value);
+		},
 		searchBtn() {
 			uni.navigateTo({
-				url: '/chuanCheng_fenbao/search/search'
+				url: '/chuanCheng_fenbao/search?id=' + this.model_id
 			});
 		},
 		tougaoBtn() {
@@ -191,20 +228,9 @@ export default {
 	margin: -90rpx 32rpx 0 34rpx;
 }
 .box_tab {
-	margin: 45rpx 32rpx 0 32rpx;
-}
-.title_pubu {
-	width: 100%;
-	height: 65rpx;
-	line-height: 65rpx;
-	background-color: #ca5642;
-	font-size: 30rpx;
-	color: #ffffff;
-	text-align: center;
-	position: absolute;
-	bottom: 0;
-	left: 0;
+	margin: 45rpx 32rpx 20rpx 32rpx;
 }
+
 .gy_box {
 	width: 160rpx;
 	height: 60rpx;
@@ -224,4 +250,23 @@ export default {
 	border-radius: 20rpx 0rpx 0rpx 20rpx;
 	background-color: #ca5642;
 }
+.waterfall-item__ft__title {
+	width: 100%;
+	height: 65rpx;
+	position: absolute;
+	bottom: 0;
+	left: 0;
+	line-height: 65rpx;
+	background-color: #ca5642;
+	font-size: 30rpx;
+	text-align: center;
+	color: #ffffff;
+	border-radius: 0 0 10rpx 10rpx;
+}
+.waterfall-item__ft {
+	position: relative;
+}
+.waterfall-item {
+	margin-bottom: 30rpx;
+}
 </style>

+ 3 - 2
pages/course/detail.vue

@@ -199,7 +199,7 @@ export default {
 	data() {
 		return {
 			state: null,
-
+			courseId: '',
 			examineList: [],
 			chapterIndex: -1,
 			contentIndex: -1,
@@ -569,7 +569,8 @@ export default {
 			// if (!this.checkLogin()) {
 			// 	return;
 			// }
-			this.$api.addCart({ id: this.courseId }, function (res) {
+			console.log(this.courseId, ' this.courseId this.courseId this.courseId');
+			this.$api.addCart({ id: that.courseId }, function (res) {
 				console.log('加入购物车', res);
 				if (res.code == 1) {
 					this.$store.commit('addCartItem', {

+ 19 - 7
pages/index/index.vue

@@ -40,7 +40,7 @@
 				</view>
 			</view>
 			<view class="block_8">
-				<view @click="moreBtn" class="an" style="width: 650rpx; margin-top: 25rpx">
+				<view @click="moreBtn" class="an" style="width: 650rpx; margin: auto; margin-top: 25rpx">
 					<u-notice-bar bgColor="#efd9ba" text="欢迎进入闽南魂"></u-notice-bar>
 				</view>
 
@@ -124,6 +124,7 @@ let that;
 export default {
 	data() {
 		return {
+			loadTriggered: false,
 			isLoading: false,
 			page: '1',
 			main_body_id: '' /* 主体id */,
@@ -151,12 +152,14 @@ export default {
 	},
 	onLoad(option) {
 		that = this;
-		this.main_body_id = this.$db.get('main_body_id');
 		this.getCity();
-		this.getIndexBanner();
-		this.getIndexFunction();
-		this.getFlagList();
-		this.getHistoryMuseum();
+		this.main_body_id = this.$db.get('main_body_id');
+		if (this.main_body_id) {
+			this.getIndexBanner();
+			this.getIndexFunction();
+			this.getFlagList();
+			this.getHistoryMuseum();
+		}
 	},
 
 	methods: {
@@ -189,6 +192,15 @@ export default {
 				that.cityList.forEach((item) => {
 					if (item.isChecked) {
 						that.$db.set('main_body_id', item.main_body_id);
+						that.main_body_id = item.main_body_id; // 设置 main_body_id
+						// 增加这一部分以触发后续请求
+						if (!that.loadTriggered) {
+							that.loadTriggered = true;
+							that.getIndexBanner();
+							that.getIndexFunction();
+							that.getFlagList();
+							that.getHistoryMuseum();
+						}
 					}
 				});
 			});
@@ -249,7 +261,7 @@ export default {
 				// 取前三个和后三个元素
 				that.bannerlist1 = valuesArray.slice(0, 3);
 				that.bannerlist2 = valuesArray.slice(-3);
-				console.log(that.bannerlist2);
+				// console.log(that.bannerlist2);
 			});
 		},
 		//精彩推荐内容

+ 9 - 57
pages/jiyi/jiyi.vue

@@ -103,53 +103,7 @@ export default {
 				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt4.jpg',
 				'https://huli-app.wenlvti.net/app_static/minnanhun/image/sy_lbt5.png'
 			],
-			list: [
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy1.png',
-				// 	title: '传统捏泥人',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy2.png',
-				// 	title: '青龙宫',
-				// 	desc: '描述描述描述描述描述描述描述描述1'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy3.png',
-				// 	title: '火把节',
-				// 	desc: '11'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy9.png',
-				// 	title: '老物件',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy4.png',
-				// 	title: '林后青龙宫',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy10.png',
-				// 	title: '书籍',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy7.png',
-				// 	title: '建筑',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy8.png',
-				// 	title: '老钟表',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// },
-				// {
-				// 	image: 'https://huli-app.wenlvti.net/app_static/minnanhun/image/mn_jy14.png',
-				// 	title: '老物件',
-				// 	desc: '描述描述描述描述描述描述描述描述2'
-				// }
-			],
+			list: [],
 			list1: [], // 瀑布流第一列数据
 			list2: [], // 瀑布流第二列数据
 			columnGap: 10
@@ -194,26 +148,24 @@ export default {
 				that.list = res.data;
 			});
 		},
-		// // 内容详情
-		// getContentDetail(id) {
-		// 	console.log(id, '瀑布流');
-		// 	this.$api.getContentDetail({ main_body_id: '2', id: '245' }, function (res) {
-		// 		console.log(res, '详情');
-		// 	});
-		// },
+
 		changeList(e) {
 			// console.log(e, '瀑布流');
 			this[e.name].push(e.value);
 		},
 		// 第一列详情
 		waterfallDetails(i) {
+			uni.navigateTo({
+				url: '/jiyi_fenbao/recommendedDetails?id=' + this.list1[i].id
+			});
 			// console.log(this.list1[i].id, 888888888);
-			// this.getContentDetail(this.list1[i].id);
 		},
 		// 第二列详情
 		waterfallDetails2(i) {
-			// console.log(this.list2[i].id, 888888888);
-			// this.getContentDetail(this.list2[i].id);
+			// console.log(this.list2[i].id, 999999);
+			uni.navigateTo({
+				url: '/jiyi_fenbao/recommendedDetails?id=' + this.list2[i].id
+			});
 		},
 		// 点赞
 		likeBtn(i) {

+ 10 - 8
pages/user/index.vue

@@ -43,7 +43,7 @@
 								</view>
 							</view>
 							<view class="juli">
-								<view style="margin-bottom: 10rpx">待收</view>
+								<view style="margin-bottom: 10rpx">待收</view>
 								<view class="">
 									<uni-icons type="wallet-filled" color="#ca5642" size="25"></uni-icons>
 								</view>
@@ -242,7 +242,6 @@ export default {
 		this.mainBodyUserInfo = this.$db.get('mainBodyUserInfo');
 		this.id = this.mainBodyUserInfo.id;
 		this.body_id = this.$db.get('main_body_id');
-
 		this.refreshUser();
 		/* 调用userInfo()从本地获取用户信息 */
 		this.user = this.$common.userInfo();
@@ -250,6 +249,7 @@ export default {
 			this.getFace = true;
 		}
 	},
+
 	onLoad(option) {
 		/* 来到我的页面判断用户是否登录 */
 		_this = this;
@@ -267,7 +267,7 @@ export default {
 	},
 	computed: {
 		userAvatar() {
-			return this.mainBodyUserInfo.avatar ? this.mainBodyUserInfo.avatar : this.user.avatar;
+			return this.user.avatar || 'https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQP6yfMxBgJ0F3YRqJCJ1aPAK2dQagdusBZg/0';
 		},
 		userNickname() {
 			return this.mainBodyUserInfo.nickname ? this.mainBodyUserInfo.nickname : this.user.nickname;
@@ -278,11 +278,11 @@ export default {
 		refreshUser() {
 			this.$api.refreshUser(
 				{
-					main_body_id: this.body_id,
-					main_body_user_id: this.id
+					main_body_id: this.body_id
+					// main_body_user_id: this.id
 				},
 				(val) => {
-					console.log(val, 333333);
+					console.log(val, '刷新成功');
 					if (val.code == 401) {
 						this.$common.navigateTo('/pages/user/login');
 						return;
@@ -298,7 +298,8 @@ export default {
 		},
 		// 获取头像
 		onChooseAvatar(e) {
-			this.mainBodyUserInfo.avatar = e.detail.avatarUrl;
+			this.user.avatar = e.detail.avatarUrl;
+			_this.$db.set('user', _this.user);
 		},
 		// 获取昵称
 		blurname(e) {
@@ -313,11 +314,12 @@ export default {
 					main_body_id: this.body_id,
 					main_body_user_id: this.id,
 					nickname: this.mainBodyUserInfo.nickname,
-					avatar: this.mainBodyUserInfo.avatar
+					avatar: this.user.avatar
 				},
 				function (res) {
 					if (res.code == 1) {
 						_this.$common.successToShow('修改成功');
+						_this.$db.set('user', _this.user);
 						_this.$db.set('mainBodyUserInfo', _this.mainBodyUserInfo);
 					}
 				}

BIN
static/image/2019-07-03000000000018.png


BIN
static/image/BSV.png


BIN
static/image/flower.png


BIN
static/image/jz_titbg.png


BIN
static/image/kctp.png


BIN
static/image/传统吉祥纹样17.png


BIN
static/image/余额.png


BIN
static/image/椭圆 839.png


BIN
static/image/账期 拷贝.png


BIN
static/image/账期(1).png


BIN
static/image/账期(3).png


BIN
static/image/账期.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帮助页

File diff suppressed because it is too large
+ 1618 - 0
uni_modules/qiun-data-charts/components/qiun-data-charts/qiun-data-charts.vue


File diff suppressed because it is too large
+ 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`文件,以免被强制覆盖。

File diff suppressed because it is too large
+ 7706 - 0
uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts.js


File diff suppressed because it is too large
+ 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.

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

@@ -0,0 +1,80 @@
+{
+  "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": {
+  },
+"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"
+        }
+      }
+    }
+  }
+}

File diff suppressed because it is too large
+ 84 - 0
uni_modules/qiun-data-charts/readme.md


File diff suppressed because it is too large
+ 23 - 0
uni_modules/qiun-data-charts/static/app-plus/echarts.min.js


File diff suppressed because it is too large
+ 23 - 0
uni_modules/qiun-data-charts/static/h5/echarts.min.js


+ 31 - 0
uni_modules/uv-icon/changelog.md

@@ -0,0 +1,31 @@
+## 1.0.13(2023-12-06)
+1. 优化
+## 1.0.12(2023-12-06)
+1. 阻止事件冒泡处理
+## 1.0.11(2023-10-29)
+1. imgMode默认值改成aspectFit
+## 1.0.10(2023-08-13)
+1. 优化nvue,方便自定义图标
+## 1.0.9(2023-07-28)
+1. 修改几个对应错误图标的BUG
+## 1.0.8(2023-07-24)
+1. 优化 支持base64图片
+## 1.0.7(2023-07-17)
+1. 修复  uv-icon 恢复uv-empty相关的图标
+## 1.0.6(2023-07-13)
+1. 修复icon设置name属性对应图标错误的BUG
+## 1.0.5(2023-07-04)
+1. 更新图标,删除一些不常用的图标
+2. 删除base64,修改成ttf文件引入读取图标
+3. 自定义图标文档说明:https://www.uvui.cn/guide/customIcon.html
+## 1.0.4(2023-07-03)
+1. 修复主题颜色在APP不生效的BUG
+## 1.0.3(2023-05-24)
+1. 将线上ttf字体包替换成base64,避免加载时或者网络差时候显示白色方块
+## 1.0.2(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.1(2023-05-10)
+1. 修复小程序中异常显示
+## 1.0.0(2023-05-04)
+新发版

+ 160 - 0
uni_modules/uv-icon/components/uv-icon/icons.js

@@ -0,0 +1,160 @@
+export default {
+	'uvicon-level': 'e68f',
+	'uvicon-checkbox-mark': 'e659',
+	'uvicon-folder': 'e694',
+	'uvicon-movie': 'e67c',
+	'uvicon-star-fill': 'e61e',
+	'uvicon-star': 'e618',
+	'uvicon-phone-fill': 'e6ac',
+	'uvicon-phone': 'e6ba',
+	'uvicon-apple-fill': 'e635',
+	'uvicon-backspace': 'e64d',
+	'uvicon-attach': 'e640',
+	'uvicon-empty-data': 'e671',
+	'uvicon-empty-address': 'e68a',
+	'uvicon-empty-favor': 'e662',
+	'uvicon-empty-car': 'e657',
+	'uvicon-empty-order': 'e66b',
+	'uvicon-empty-list': 'e672',
+	'uvicon-empty-search': 'e677',
+	'uvicon-empty-permission': 'e67d',
+	'uvicon-empty-news': 'e67e',
+	'uvicon-empty-history': 'e685',
+	'uvicon-empty-coupon': 'e69b',
+	'uvicon-empty-page': 'e60e',
+	'uvicon-empty-wifi-off': 'e6cc',
+	'uvicon-reload': 'e627',
+	'uvicon-order': 'e695',
+	'uvicon-server-man': 'e601',
+	'uvicon-search': 'e632',
+	'uvicon-more-dot-fill': 'e66f',
+	'uvicon-scan': 'e631',
+	'uvicon-map': 'e665',
+	'uvicon-map-fill': 'e6a8',
+	'uvicon-tags': 'e621',
+	'uvicon-tags-fill': 'e613',
+	'uvicon-eye': 'e664',
+	'uvicon-eye-fill': 'e697',
+	'uvicon-eye-off': 'e69c',
+	'uvicon-eye-off-outline': 'e688',
+	'uvicon-mic': 'e66d',
+	'uvicon-mic-off': 'e691',
+	'uvicon-calendar': 'e65c',
+	'uvicon-trash': 'e623',
+	'uvicon-trash-fill': 'e6ce',
+	'uvicon-play-left': 'e6bf',
+	'uvicon-play-right': 'e6b3',
+	'uvicon-minus': 'e614',
+	'uvicon-plus': 'e625',
+	'uvicon-info-circle': 'e69f',
+	'uvicon-info-circle-fill': 'e6a7',
+	'uvicon-question-circle': 'e622',
+	'uvicon-question-circle-fill': 'e6bc',
+	'uvicon-close': 'e65a',
+	'uvicon-checkmark': 'e64a',
+	'uvicon-checkmark-circle': 'e643',
+	'uvicon-checkmark-circle-fill': 'e668',
+	'uvicon-setting': 'e602',
+	'uvicon-setting-fill': 'e6d0',
+	'uvicon-heart': 'e6a2',
+	'uvicon-heart-fill': 'e68b',
+	'uvicon-camera': 'e642',
+	'uvicon-camera-fill': 'e650',
+	'uvicon-more-circle': 'e69e',
+	'uvicon-more-circle-fill': 'e684',
+	'uvicon-chat': 'e656',
+	'uvicon-chat-fill': 'e63f',
+	'uvicon-bag': 'e647',
+	'uvicon-error-circle': 'e66e',
+	'uvicon-error-circle-fill': 'e655',
+	'uvicon-close-circle': 'e64e',
+	'uvicon-close-circle-fill': 'e666',
+	'uvicon-share': 'e629',
+	'uvicon-share-fill': 'e6bb',
+	'uvicon-share-square': 'e6c4',
+	'uvicon-shopping-cart': 'e6cb',
+	'uvicon-shopping-cart-fill': 'e630',
+	'uvicon-bell': 'e651',
+	'uvicon-bell-fill': 'e604',
+	'uvicon-list': 'e690',
+	'uvicon-list-dot': 'e6a9',
+	'uvicon-zhifubao-circle-fill': 'e617',
+	'uvicon-weixin-circle-fill': 'e6cd',
+	'uvicon-weixin-fill': 'e620',
+	'uvicon-qq-fill': 'e608',
+	'uvicon-qq-circle-fill': 'e6b9',
+	'uvicon-moments-circel-fill': 'e6c2',
+	'uvicon-moments': 'e6a0',
+	'uvicon-car': 'e64f',
+	'uvicon-car-fill': 'e648',
+	'uvicon-warning-fill': 'e6c7',
+	'uvicon-warning': 'e6c1',
+	'uvicon-clock-fill': 'e64b',
+	'uvicon-clock': 'e66c',
+	'uvicon-edit-pen': 'e65d',
+	'uvicon-edit-pen-fill': 'e679',
+	'uvicon-email': 'e673',
+	'uvicon-email-fill': 'e683',
+	'uvicon-minus-circle': 'e6a5',
+	'uvicon-plus-circle': 'e603',
+	'uvicon-plus-circle-fill': 'e611',
+	'uvicon-file-text': 'e687',
+	'uvicon-file-text-fill': 'e67f',
+	'uvicon-pushpin': 'e6d1',
+	'uvicon-pushpin-fill': 'e6b6',
+	'uvicon-grid': 'e68c',
+	'uvicon-grid-fill': 'e698',
+	'uvicon-play-circle': 'e6af',
+	'uvicon-play-circle-fill': 'e62a',
+	'uvicon-pause-circle-fill': 'e60c',
+	'uvicon-pause': 'e61c',
+	'uvicon-pause-circle': 'e696',
+	'uvicon-gift-fill': 'e6b0',
+	'uvicon-gift': 'e680',
+	'uvicon-kefu-ermai': 'e660',
+	'uvicon-server-fill': 'e610',
+	'uvicon-coupon-fill': 'e64c',
+	'uvicon-coupon': 'e65f',
+	'uvicon-integral': 'e693',
+	'uvicon-integral-fill': 'e6b1',
+	'uvicon-home-fill': 'e68e',
+	'uvicon-home': 'e67b',
+	'uvicon-account': 'e63a',
+	'uvicon-account-fill': 'e653',
+	'uvicon-thumb-down-fill': 'e628',
+	'uvicon-thumb-down': 'e60a',
+	'uvicon-thumb-up': 'e612',
+	'uvicon-thumb-up-fill': 'e62c',
+	'uvicon-lock-fill': 'e6a6',
+	'uvicon-lock-open': 'e68d',
+	'uvicon-lock-opened-fill': 'e6a1',
+	'uvicon-lock': 'e69d',
+	'uvicon-red-packet': 'e6c3',
+	'uvicon-photo-fill': 'e6b4',
+	'uvicon-photo': 'e60d',
+	'uvicon-volume-off-fill': 'e6c8',
+	'uvicon-volume-off': 'e6bd',
+	'uvicon-volume-fill': 'e624',
+	'uvicon-volume': 'e605',
+	'uvicon-download': 'e670',
+	'uvicon-arrow-up-fill': 'e636',
+	'uvicon-arrow-down-fill': 'e638',
+	'uvicon-play-left-fill': 'e6ae',
+	'uvicon-play-right-fill': 'e6ad',
+	'uvicon-arrow-downward': 'e634',
+	'uvicon-arrow-leftward': 'e63b',
+	'uvicon-arrow-rightward': 'e644',
+	'uvicon-arrow-upward': 'e641',
+	'uvicon-arrow-down': 'e63e',
+	'uvicon-arrow-right': 'e63c',
+	'uvicon-arrow-left': 'e646',
+	'uvicon-arrow-up': 'e633',
+	'uvicon-skip-back-left': 'e6c5',
+	'uvicon-skip-forward-right': 'e61f',
+	'uvicon-arrow-left-double': 'e637',
+	'uvicon-man': 'e675',
+	'uvicon-woman': 'e626',
+	'uvicon-en': 'e6b8',
+	'uvicon-twitte': 'e607',
+	'uvicon-twitter-circle-fill': 'e6cf'
+}

+ 90 - 0
uni_modules/uv-icon/components/uv-icon/props.js

@@ -0,0 +1,90 @@
+export default {
+	props: {
+		// 图标类名
+		name: {
+			type: String,
+			default: ''
+		},
+		// 图标颜色,可接受主题色
+		color: {
+			type: String,
+			default: '#606266'
+		},
+		// 字体大小,单位px
+		size: {
+			type: [String, Number],
+			default: '16px'
+		},
+		// 是否显示粗体
+		bold: {
+			type: Boolean,
+			default: false
+		},
+		// 点击图标的时候传递事件出去的index(用于区分点击了哪一个)
+		index: {
+			type: [String, Number],
+			default: null
+		},
+		// 触摸图标时的类名
+		hoverClass: {
+			type: String,
+			default: ''
+		},
+		// 自定义扩展前缀,方便用户扩展自己的图标库
+		customPrefix: {
+			type: String,
+			default: 'uvicon'
+		},
+		// 图标右边或者下面的文字
+		label: {
+			type: [String, Number],
+			default: ''
+		},
+		// label的位置,只能右边或者下边
+		labelPos: {
+			type: String,
+			default: 'right'
+		},
+		// label的大小
+		labelSize: {
+			type: [String, Number],
+			default: '15px'
+		},
+		// label的颜色
+		labelColor: {
+			type: String,
+			default: '#606266'
+		},
+		// label与图标的距离
+		space: {
+			type: [String, Number],
+			default: '3px'
+		},
+		// 图片的mode
+		imgMode: {
+			type: String,
+			default: 'aspectFit'
+		},
+		// 用于显示图片小图标时,图片的宽度
+		width: {
+			type: [String, Number],
+			default: ''
+		},
+		// 用于显示图片小图标时,图片的高度
+		height: {
+			type: [String, Number],
+			default: ''
+		},
+		// 用于解决某些情况下,让图标垂直居中的用途
+		top: {
+			type: [String, Number],
+			default: 0
+		},
+		// 是否阻止事件传播
+		stop: {
+			type: Boolean,
+			default: false
+		},
+		...uni.$uv?.props?.icon
+	}
+}

+ 226 - 0
uni_modules/uv-icon/components/uv-icon/uv-icon.vue

@@ -0,0 +1,226 @@
+<template>
+	<view
+	  class="uv-icon"
+	  @tap="clickHandler"
+	  :class="['uv-icon--' + labelPos]"
+	>
+		<image
+		  class="uv-icon__img"
+		  v-if="isImg"
+		  :src="name"
+		  :mode="imgMode"
+		  :style="[imgStyle, $uv.addStyle(customStyle)]"
+		></image>
+		<text
+		  v-else
+		  class="uv-icon__icon"
+		  :class="uClasses"
+		  :style="[iconStyle, $uv.addStyle(customStyle)]"
+		  :hover-class="hoverClass"
+		>{{icon}}</text>
+		<!-- 这里进行空字符串判断,如果仅仅是v-if="label",可能会出现传递0的时候,结果也无法显示 -->
+		<text
+		  v-if="label !== ''" 
+		  class="uv-icon__label"
+		  :style="{
+			color: labelColor,
+			fontSize: $uv.addUnit(labelSize),
+			marginLeft: labelPos == 'right' ? $uv.addUnit(space) : 0,
+			marginTop: labelPos == 'bottom' ? $uv.addUnit(space) : 0,
+			marginRight: labelPos == 'left' ? $uv.addUnit(space) : 0,
+			marginBottom: labelPos == 'top' ? $uv.addUnit(space) : 0
+		}"
+		>{{ label }}</text>
+	</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'
+	// #ifdef APP-NVUE
+	// nvue通过weex的dom模块引入字体,相关文档地址如下:
+	// https://weex.apache.org/zh/docs/modules/dom.html#addrule
+	import iconUrl from './uvicons.ttf';
+	const domModule = weex.requireModule('dom')
+	domModule.addRule('fontFace', {
+		'fontFamily': "uvicon-iconfont",
+		'src': "url('" + iconUrl + "')"
+	})
+	// #endif
+	// 引入图标名称,已经对应的unicode
+	import icons from './icons';
+	import props from './props.js';
+	/**
+	 * icon 图标
+	 * @description 基于字体的图标集,包含了大多数常见场景的图标。
+	 * @tutorial https://www.uvui.cn/components/icon.html
+	 * @property {String}			name			图标名称,见示例图标集
+	 * @property {String}			color			图标颜色,可接受主题色 (默认 color['uv-content-color'] )
+	 * @property {String | Number}	size			图标字体大小,单位px (默认 '16px' )
+	 * @property {Boolean}			bold			是否显示粗体 (默认 false )
+	 * @property {String | Number}	index			点击图标的时候传递事件出去的index(用于区分点击了哪一个)
+	 * @property {String}			hoverClass		图标按下去的样式类,用法同uni的view组件的hoverClass参数,详情见官网
+	 * @property {String}			customPrefix	自定义扩展前缀,方便用户扩展自己的图标库 (默认 'uicon' )
+	 * @property {String | Number}	label			图标右侧的label文字
+	 * @property {String}			labelPos		label相对于图标的位置,只能right或bottom (默认 'right' )
+	 * @property {String | Number}	labelSize		label字体大小,单位px (默认 '15px' )
+	 * @property {String}			labelColor		图标右侧的label文字颜色 ( 默认 color['uv-content-color'] )
+	 * @property {String | Number}	space			label与图标的距离,单位px (默认 '3px' )
+	 * @property {String}			imgMode			图片的mode
+	 * @property {String | Number}	width			显示图片小图标时的宽度
+	 * @property {String | Number}	height			显示图片小图标时的高度
+	 * @property {String | Number}	top				图标在垂直方向上的定位 用于解决某些情况下,让图标垂直居中的用途  (默认 0 )
+	 * @property {Boolean}			stop			是否阻止事件传播 (默认 false )
+	 * @property {Object}			customStyle		icon的样式,对象形式
+	 * @event {Function} click 点击图标时触发
+	 * @event {Function} touchstart 事件触摸时触发
+	 * @example <uv-icon name="photo" color="#2979ff" size="28"></uv-icon>
+	 */
+	export default {
+		name: 'uv-icon',
+		emits: ['click'],
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+				colorType: [
+					'primary',
+					'success',
+					'info',
+					'error',
+					'warning'
+				]
+			}
+		},
+		computed: {
+			uClasses() {
+				let classes = []
+				classes.push(this.customPrefix)
+				classes.push(this.customPrefix + '-' + this.name)
+				// 主题色,通过类配置
+				if (this.color && this.colorType.includes(this.color)) classes.push('uv-icon__icon--' + this.color)
+				// 阿里,头条,百度小程序通过数组绑定类名时,无法直接使用[a, b, c]的形式,否则无法识别
+				// 故需将其拆成一个字符串的形式,通过空格隔开各个类名
+				//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
+				classes = classes.join(' ')
+				//#endif
+				return classes
+			},
+			iconStyle() {
+				let style = {}
+				style = {
+					fontSize: this.$uv.addUnit(this.size),
+					lineHeight: this.$uv.addUnit(this.size),
+					fontWeight: this.bold ? 'bold' : 'normal',
+					// 某些特殊情况需要设置一个到顶部的距离,才能更好的垂直居中
+					top: this.$uv.addUnit(this.top)
+				}
+				// 非主题色值时,才当作颜色值
+				if (this.color && !this.colorType.includes(this.color)) style.color = this.color
+				return style
+			},
+			// 判断传入的name属性,是否图片路径,只要带有"/"均认为是图片形式
+			isImg() {
+				const isBase64 = this.name.indexOf('data:') > -1 && this.name.indexOf('base64') > -1;
+				return this.name.indexOf('/') !== -1 || isBase64;
+			},
+			imgStyle() {
+				let style = {}
+				// 如果设置width和height属性,则优先使用,否则使用size属性
+				style.width = this.width ? this.$uv.addUnit(this.width) : this.$uv.addUnit(this.size)
+				style.height = this.height ? this.$uv.addUnit(this.height) : this.$uv.addUnit(this.size)
+				return style
+			},
+			// 通过图标名,查找对应的图标
+			icon() {
+				// 如果内置的图标中找不到对应的图标,就直接返回name值,因为用户可能传入的是unicode代码
+				const code = icons['uvicon-' + this.name];
+				// #ifdef APP-NVUE
+				if(!code) {
+					return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? unescape(`%u${this.name}`) : '';
+				}
+				// #endif
+				return code ? unescape(`%u${code}`) : ['uvicon'].indexOf(this.customPrefix) > -1 ? this.name : '';
+			}
+		},
+		methods: {
+			clickHandler(e) {
+				this.$emit('click', this.index)
+				// 是否阻止事件冒泡
+				this.stop && this.preventEvent(e)
+			}
+		}
+	}
+</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-icon-primary: $uv-primary !default;
+	$uv-icon-success: $uv-success !default;
+	$uv-icon-info: $uv-info !default;
+	$uv-icon-warning: $uv-warning !default;
+	$uv-icon-error: $uv-error !default;
+	$uv-icon-label-line-height: 1 !default;
+	/* #ifndef APP-NVUE */
+	// 非nvue下加载字体
+	@font-face {
+		font-family: 'uvicon-iconfont';
+		src: url('./uvicons.ttf') format('truetype');
+	}
+	/* #endif */
+	.uv-icon {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		align-items: center;
+		&--left {
+			flex-direction: row-reverse;
+			align-items: center;
+		}
+		&--right {
+			flex-direction: row;
+			align-items: center;
+		}
+		&--top {
+			flex-direction: column-reverse;
+			justify-content: center;
+		}
+		&--bottom {
+			flex-direction: column;
+			justify-content: center;
+		}
+		&__icon {
+			font-family: uvicon-iconfont;
+			position: relative;
+			@include flex;
+			align-items: center;
+			&--primary {
+				color: $uv-icon-primary;
+			}
+			&--success {
+				color: $uv-icon-success;
+			}
+			&--error {
+				color: $uv-icon-error;
+			}
+			&--warning {
+				color: $uv-icon-warning;
+			}
+			&--info {
+				color: $uv-icon-info;
+			}
+		}
+		&__img {
+			/* #ifndef APP-NVUE */
+			height: auto;
+			will-change: transform;
+			/* #endif */
+		}
+		&__label {
+			/* #ifndef APP-NVUE */
+			line-height: $uv-icon-label-line-height;
+			/* #endif */
+		}
+	}
+</style>

BIN
uni_modules/uv-icon/components/uv-icon/uvicons.ttf


+ 83 - 0
uni_modules/uv-icon/package.json

@@ -0,0 +1,83 @@
+{
+  "id": "uv-icon",
+  "displayName": "uv-icon 图标 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.13",
+  "description": "基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。可自定义颜色、大小。",
+  "keywords": [
+    "uv-ui,uvui,uv-icon,icon,图标,字体图标"
+],
+  "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-icon/readme.md

@@ -0,0 +1,15 @@
+## uv-icon 图标库
+
+> **组件名:uv-icon**
+
+基于字体的图标集,包含了大多数常见场景的图标,支持自定义,支持自定义图片图标等。
+
+# <a href="https://www.uvui.cn/components/icon.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>

+ 36 - 0
uni_modules/uv-image/changelog.md

@@ -0,0 +1,36 @@
+## 1.0.16(2023-12-21)
+1. 修复设置show-menu-by-longpress不生效的BUG
+## 1.0.15(2023-12-06)
+1. 优化
+## 1.0.14(2023-12-06)
+1. 阻止事件冒泡问题
+## 1.0.13(2023-11-15)
+1. 修复webp之前未使用的BUG
+## 1.0.12(2023-10-11)
+1. 修复懒加载报错:https://gitee.com/climblee/uv-ui/issues/I869JS
+## 1.0.11(2023-08-31)
+1. 修复设置widthFix时出现显示不全的BUG
+2. 修复抖音等平台在width和height属性改变时出现不显示的BUG
+## 1.0.10(2023-08-29)
+1. 修复异步修改宽高不生效的问题,问题来源:https://gitee.com/climblee/uv-ui/issues/I7WUQ3
+## 1.0.9(2023-08-21)
+1. 修复设置宽高为百分比不生效的BUG
+## 1.0.8(2023-07-24)
+1. 优化 nvue模式下增加cellChild参数,是否在list中cell节点下,nvue中cell下建议设置成true
+## 1.0.7(2023-07-02)
+修复VUE3模式下可能不显示的BUG
+## 1.0.6(2023-07-02)
+优化修改
+## 1.0.5(2023-06-28)
+修复duration属性不生效的BUG
+## 1.0.4(2023-05-27)
+1. 修复可能报错的问题
+## 1.0.3(2023-05-24)
+1. 去掉template中存在的this.导致头条小程序编译警告
+## 1.0.2(2023-05-23)
+1. 优化
+## 1.0.1(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.0(2023-05-10)
+uv-image 图片

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

@@ -0,0 +1,95 @@
+export default {
+	props: {
+		// 图片地址
+		src: {
+			type: String,
+			default: ''
+		},
+		// 裁剪模式
+		mode: {
+			type: String,
+			default: 'aspectFill'
+		},
+		// 宽度,单位任意
+		width: {
+			type: [String, Number],
+			default: '300'
+		},
+		// 高度,单位任意
+		height: {
+			type: [String, Number],
+			default: '225'
+		},
+		// 图片形状,circle-圆形,square-方形
+		shape: {
+			type: String,
+			default: 'square'
+		},
+		// 圆角,单位任意
+		radius: {
+			type: [String, Number],
+			default: 0
+		},
+		// 是否懒加载,微信小程序、App、百度小程序、字节跳动小程序
+		lazyLoad: {
+			type: Boolean,
+			default: true
+		},
+		// 是否开启observer懒加载,nvue不生效
+		observeLazyLoad: {
+			type: Boolean,
+			default: false
+		},
+		// 开启长按图片显示识别微信小程序码菜单
+		showMenuByLongpress: {
+			type: Boolean,
+			default: true
+		},
+		// 加载中的图标,或者小图片
+		loadingIcon: {
+			type: String,
+			default: 'photo'
+		},
+		// 加载失败的图标,或者小图片
+		errorIcon: {
+			type: String,
+			default: 'error-circle'
+		},
+		// 是否显示加载中的图标或者自定义的slot
+		showLoading: {
+			type: Boolean,
+			default: true
+		},
+		// 是否显示加载错误的图标或者自定义的slot
+		showError: {
+			type: Boolean,
+			default: true
+		},
+		// 是否需要淡入效果
+		fade: {
+			type: Boolean,
+			default: true
+		},
+		// 只支持网络资源,只对微信小程序有效
+		webp: {
+			type: Boolean,
+			default: false
+		},
+		// 过渡时间,单位ms
+		duration: {
+			type: [String, Number],
+			default: 500
+		},
+		// 背景颜色,用于深色页面加载图片时,为了和背景色融合
+		bgColor: {
+			type: String,
+			default: '#f3f4f6'
+		},
+		// nvue模式下 是否直接显示,在uv-list等cell下面使用就需要设置
+		cellChild: {
+			type: Boolean,
+			default: false
+		},
+		...uni.$uv?.props?.image
+	}
+}

+ 287 - 0
uni_modules/uv-image/components/uv-image/uv-image.vue

@@ -0,0 +1,287 @@
+<template>
+	<uv-transition
+		v-if="show"
+		:show="show"
+		mode="fade"
+		:duration="fade ? duration : 0"
+		:cell-child="cellChild"
+		:custom-style="wrapStyle"
+	>
+		<view
+			class="uv-image"
+			:class="[`uv-image--${elIndex}`]"
+			@tap="onClick"
+			:style="[wrapStyle, backgroundStyle]"
+		>
+			<image
+				v-if="!isError && observeShow"
+				:src="src"
+				:mode="mode"
+				@error="onErrorHandler"
+				@load="onLoadHandler"
+				:show-menu-by-longpress="showMenuByLongpress"
+				:lazy-load="lazyLoad"
+				class="uv-image__image"
+				:style="[imageStyle]"
+				:webp="webp"
+			></image>
+			<view
+				v-if="showLoading && loading"
+				class="uv-image__loading"
+				:style="{
+					borderRadius: shape == 'circle' ? '50%' : $uv.addUnit(radius),
+					backgroundColor: bgColor,
+					width: $uv.addUnit(width),
+					height: $uv.addUnit(height)
+				}"
+			>
+				<slot name="loading">
+					<uv-icon
+						:name="loadingIcon"
+						:width="width"
+						:height="height"
+					></uv-icon>
+				</slot>
+			</view>
+			<view
+				v-if="showError && isError && !loading"
+				class="uv-image__error"
+				:style="{
+					borderRadius: shape == 'circle' ? '50%' : $uv.addUnit(radius),
+					width: $uv.addUnit(width),
+					height: $uv.addUnit(height)
+				}"
+			>
+				<slot name="error">
+					<uv-icon
+						:name="errorIcon"
+						:width="width"
+						:height="height"
+					></uv-icon>
+				</slot>
+			</view>
+		</view>
+	</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';
+	/**
+	 * Image 图片
+	 * @description 此组件为uni-app的image组件的加强版,在继承了原有功能外,还支持淡入动画、加载中、加载失败提示、圆角值和形状等。
+	 * @tutorial https://www.uvui.cn/components/image.html
+	 * @property {String}			src 				图片地址
+	 * @property {String}			mode 				裁剪模式,见官网说明 (默认 'aspectFill' )
+	 * @property {String | Number}	width 				宽度,单位任意,如果为数值,则为px单位 (默认 '300' )
+	 * @property {String | Number}	height 				高度,单位任意,如果为数值,则为px单位 (默认 '225' )
+	 * @property {String}			shape 				图片形状,circle-圆形,square-方形 (默认 'square' )
+	 * @property {String | Number}	radius		 		圆角值,单位任意,如果为数值,则为px单位 (默认 0 )
+	 * @property {Boolean}			lazyLoad			是否懒加载,仅微信小程序、App、百度小程序、字节跳动小程序有效 (默认 true )
+	 * @property {Boolean}			showMenuByLongpress	是否开启长按图片显示识别小程序码菜单,仅微信小程序有效 (默认 true )
+	 * @property {String}			loadingIcon 		加载中的图标,或者小图片 (默认 'photo' )
+	 * @property {String}			errorIcon 			加载失败的图标,或者小图片 (默认 'error-circle' )
+	 * @property {Boolean}			showLoading 		是否显示加载中的图标或者自定义的slot (默认 true )
+	 * @property {Boolean}			showError 			是否显示加载错误的图标或者自定义的slot (默认 true )
+	 * @property {Boolean}			fade 				是否需要淡入效果 (默认 true )
+	 * @property {Boolean}			webp 				只支持网络资源,只对微信小程序有效 (默认 false )
+	 * @property {String | Number}	duration 			搭配fade参数的过渡时间,单位ms (默认 500 )
+	 * @property {String}			bgColor 			背景颜色,用于深色页面加载图片时,为了和背景色融合  (默认 '#f3f4f6' )
+	 * @property {Object}			customStyle  		定义需要用到的外部样式
+	 * @event {Function}	click	点击图片时触发
+	 * @event {Function}	error	图片加载失败时触发
+	 * @event {Function} load 图片加载成功时触发
+	 * @example <uv-image width="100%" height="300px" :src="src"></uv-image>
+	 */
+	export default {
+		name: 'uv-image',
+		emits: ['click','load','error'],
+		mixins: [mpMixin, mixin, props],
+		data() {
+			return {
+				// 图片是否加载错误,如果是,则显示错误占位图
+				isError: false,
+				// 初始化组件时,默认为加载中状态
+				loading: true,
+				// 图片加载完成时,去掉背景颜色,因为如果是png图片,就会显示灰色的背景
+				backgroundStyle: {},
+				// 用于fade模式的控制组件显示与否
+				show: false,
+				// 是否开启图片出现在可视范围进行加载(另一种懒加载)
+				observeShow: !this.observeLazyLoad,
+				elIndex: '',
+				// 因为props的值无法修改,故需要一个中间值
+				imgWidth: this.width,
+				// 因为props的值无法修改,故需要一个中间值
+				imgHeight: this.height,
+				thresholdValue: 50
+			};
+		},
+		watch: {
+			src: {
+				immediate: true,
+				handler(n) {
+					if (!n) {
+						// 如果传入null或者'',或者false,或者undefined,标记为错误状态
+						this.isError = true
+					} else {
+						this.isError = false;
+						this.loading = true;
+					}
+				}
+			},
+			width(newVal){
+				// 这样做的目的是避免在更新时候,某些平台动画会恢复关闭状态
+				this.show = false;
+				this.$uv.sleep(2).then(res=>{
+					this.show = true;
+				});
+				this.imgWidth = newVal;
+			},
+			height(newVal){
+				// 这样做的目的是避免在更新时候,某些平台动画会恢复关闭状态
+				this.show = false;
+				this.$uv.sleep(2).then(res=>{
+					this.show = true;
+				});
+				this.imgHeight = newVal;
+			}
+		},
+		computed: {
+			wrapStyle() {
+				let style = {};
+				// 通过调用addUnit()方法,如果有单位,如百分比,px单位等,直接返回,如果是纯粹的数值,则加上rpx单位
+				if(this.mode !== 'heightFix') {
+					style.width = this.$uv.addUnit(this.imgWidth);
+				}
+				if(this.mode !== 'widthFix') {
+					style.height = this.$uv.addUnit(this.imgHeight);
+				}
+				// 如果是显示圆形,设置一个很多的半径值即可
+				style.borderRadius = this.shape == 'circle' ? '10000px' : this.$uv.addUnit(this.radius)
+				// 如果设置圆角,必须要有hidden,否则可能圆角无效
+				style.overflow = this.radius > 0 ? 'hidden' : 'visible'
+				return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle));
+			},
+			imageStyle() {
+				let style = {};
+				style.borderRadius = this.shape == 'circle' ? '10000px' : this.$uv.addUnit(this.radius);
+				// #ifdef APP-NVUE
+				style.width = this.$uv.addUnit(this.imgWidth);
+				style.height = this.$uv.addUnit(this.imgHeight);
+				// #endif
+				return style;
+			}
+		},
+		created() {
+			this.elIndex = this.$uv.guid();
+			this.observer = {}
+			this.observerName = 'lazyLoadContentObserver'
+		},
+		mounted() {
+			this.show = true;
+			this.$nextTick(()=>{
+				if(this.observeLazyLoad) this.observerFn();
+			})
+		},
+		methods: {
+			// 点击图片
+			onClick() {
+				this.$emit('click')
+			},
+			// 图片加载失败
+			onErrorHandler(err) {
+				this.loading = false
+				this.isError = true
+				this.$emit('error', err)
+			},
+			// 图片加载完成,标记loading结束
+			onLoadHandler(event) {
+				if(this.mode == 'widthFix') this.imgHeight = 'auto'
+				if(this.mode == 'heightFix') this.imgWidth = 'auto'
+				this.loading = false
+				this.isError = false
+				this.$emit('load', event)
+				this.removeBgColor()
+			},
+			// 移除图片的背景色
+			removeBgColor() {
+				// 淡入动画过渡完成后,将背景设置为透明色,否则png图片会看到灰色的背景
+				this.backgroundStyle = {
+					backgroundColor: 'transparent'
+				};
+			},
+			// 观察图片是否在可见视口
+			observerFn(){
+				// 在需要用到懒加载的页面,在触发底部的时候触发tOnLazyLoadReachBottom事件,保证所有图片进行加载
+				this.$nextTick(() => {
+					uni.$once('onLazyLoadReachBottom', () => {
+						if (!this.observeShow) this.observeShow = true
+					})
+				})
+				setTimeout(() => {
+					// #ifndef APP-NVUE
+					this.disconnectObserver(this.observerName)
+					const contentObserver = uni.createIntersectionObserver(this)
+					contentObserver.relativeToViewport({
+						bottom: this.thresholdValue
+					}).observe(`.uv-image--${this.elIndex}`, (res) => {
+						if (res.intersectionRatio > 0) {
+							// 懒加载状态改变
+							this.observeShow = true
+							// 如果图片已经加载,去掉监听,减少性能消耗
+							this.disconnectObserver(this.observerName)
+						}
+					})
+					this[this.observerName] = contentObserver
+					// #endif
+					// #ifdef APP-NVUE
+					this.observeShow = true;
+					// #endif
+				}, 50)
+			},
+			disconnectObserver(observerName) {
+				const observer = this[observerName]
+				observer && observer.disconnect()
+			}
+		}
+	};
+</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-image-error-top:0px !default;
+	$uv-image-error-left:0px !default;
+	$uv-image-error-width:100% !default;
+	$uv-image-error-hight:100% !default;
+	$uv-image-error-background-color:$uv-bg-color !default;
+	$uv-image-error-color:$uv-tips-color !default;
+	$uv-image-error-font-size: 46rpx !default;
+
+	.uv-image {
+		position: relative;
+		transition: opacity 0.5s ease-in-out;
+
+		&__image {
+			width: 100%;
+			height: 100%;
+		}
+
+		&__loading,
+		&__error {
+			position: absolute;
+			top: $uv-image-error-top;
+			left: $uv-image-error-left;
+			width: $uv-image-error-width;
+			height: $uv-image-error-hight;
+			@include flex;
+			align-items: center;
+			justify-content: center;
+			background-color: $uv-image-error-background-color;
+			color: $uv-image-error-color;
+			font-size: $uv-image-error-font-size;
+		}
+	}
+</style>

+ 89 - 0
uni_modules/uv-image/package.json

@@ -0,0 +1,89 @@
+{
+  "id": "uv-image",
+  "displayName": "uv-image 图片 全面兼容vue3+2、app、h5、小程序等多端",
+  "version": "1.0.16",
+  "description": "uv-image 此组件为uni-app的image组件的加强版,在继承了原有功能外,增加observer懒加载功能,还支持淡入动画、加载中、加载失败提示、圆角值和形状等。",
+  "keywords": [
+    "uv-image",
+    "uvui",
+    "uv-ui",
+    "image",
+    "图片"
+],
+  "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",
+			"uv-icon"
+		],
+    "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-image/readme.md

@@ -0,0 +1,15 @@
+## Image 图片
+
+> **组件名:uv-image**
+
+此组件为`uni-app`的`image`组件的加强版,在继承了原有功能外,增加`observer`懒加载功能,还支持淡入动画、加载中、加载失败提示、圆角值和形状等。
+
+# <a href="https://www.uvui.cn/components/image.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>

+ 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>

+ 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>

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

@@ -0,0 +1,74 @@
+## 1.1.24(2023-12-21)
+1. luch-request更新
+## 1.1.23(2023-12-12)
+1. 1.1.19版本
+## 1.1.22(2023-11-28)
+1. 优化
+## 1.1.21(2023-11-10)
+1. 1.1.17版本
+## 1.1.20(2023-10-30)
+1. 1.1.16版本
+## 1.1.19(2023-10-13)
+1. 兼容vue3
+## 1.1.18(2023-10-12)
+1. 1.1.15版本
+## 1.1.17(2023-09-27)
+1. 1.1.14版本发布
+## 1.1.16(2023-09-15)
+1. 1.1.13版本发布
+## 1.1.15(2023-09-15)
+1. 更新button.js相关按钮支持open-type="agreePrivacyAuthorization"
+## 1.1.14(2023-09-14)
+1. 优化dayjs
+## 1.1.13(2023-09-13)
+1. 优化,$uv中增加unit参数,方便组件中使用
+## 1.1.12(2023-09-10)
+1. 升级版本
+## 1.1.11(2023-09-04)
+1. 1.1.11版本
+## 1.1.10(2023-08-31)
+1. 修复customStyle和customClass存在冲突的问题
+## 1.1.9(2023-08-27)
+1. 版本升级
+2. 优化
+## 1.1.8(2023-08-24)
+1. 版本升级
+## 1.1.7(2023-08-22)
+1. 版本升级
+## 1.1.6(2023-08-18)
+uvui版本:1.1.6
+## 1.0.15(2023-08-14)
+1. 更新uvui版本号
+## 1.0.13(2023-08-06)
+1. 优化
+## 1.0.12(2023-08-06)
+1. 修改版本号
+## 1.0.11(2023-08-06)
+1. 路由增加events参数
+2. 路由拦截修复
+## 1.0.10(2023-08-01)
+1. 优化
+## 1.0.9(2023-06-28)
+优化openType.js
+## 1.0.8(2023-06-15)
+1. 修改支付宝报错的BUG
+## 1.0.7(2023-06-07)
+1. 解决微信小程序使用uvui提示 Some selectors are not allowed in component wxss, including tag name selectors, ID selectors, and attribute selectors
+2. 解决上述提示,需要在uni.scss配置$uvui-nvue-style: false; 然后在APP.vue下面引入uvui内置的基础样式:@import '@/uni_modules/uv-ui-tools/index.scss';
+## 1.0.6(2023-06-04)
+1.  uv-ui-tools 优化工具组件,兼容更多功能
+2.  小程序分享功能优化等
+## 1.0.5(2023-06-02)
+1. 修改扩展使用mixin中方法的问题
+## 1.0.4(2023-05-23)
+1. 兼容百度小程序修改bem函数
+## 1.0.3(2023-05-16)
+1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
+2. 优化部分功能
+## 1.0.2(2023-05-10)
+1. 增加Http请求封装
+2. 优化
+## 1.0.1(2023-05-04)
+1. 修改名称及备注
+## 1.0.0(2023-05-04)
+1. uv-ui工具集首次发布

+ 6 - 0
uni_modules/uv-ui-tools/components/uv-ui-tools/uv-ui-tools.vue

@@ -0,0 +1,6 @@
+<template>
+</template>
+<script>
+</script>
+<style>
+</style>

+ 79 - 0
uni_modules/uv-ui-tools/index.js

@@ -0,0 +1,79 @@
+// 全局挂载引入http相关请求拦截插件
+import Request from './libs/luch-request'
+
+// 引入全局mixin
+import mixin from './libs/mixin/mixin.js'
+// 小程序特有的mixin
+import mpMixin from './libs/mixin/mpMixin.js'
+// #ifdef MP
+import mpShare from './libs/mixin/mpShare.js'
+// #endif
+
+// 路由封装
+import route from './libs/util/route.js'
+// 公共工具函数
+import * as index from './libs/function/index.js'
+// 防抖方法
+import debounce from './libs/function/debounce.js'
+// 节流方法
+import throttle from './libs/function/throttle.js'
+// 规则检验
+import * as test from './libs/function/test.js'
+
+// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
+import * as colorGradient from './libs/function/colorGradient.js'
+
+// 配置信息
+import config from './libs/config/config.js'
+// 平台
+import platform from './libs/function/platform'
+
+const $uv = {
+	route,
+	config,
+	test,
+	date: index.timeFormat, // 另名date
+	...index,
+	colorGradient: colorGradient.colorGradient,
+	hexToRgb: colorGradient.hexToRgb,
+	rgbToHex: colorGradient.rgbToHex,
+	colorToRgba: colorGradient.colorToRgba,
+	http: new Request(),
+	debounce,
+	throttle,
+	platform,
+	mixin,
+	mpMixin
+}
+uni.$uv = $uv;
+const install = (Vue,options={}) => {
+		// #ifndef APP-NVUE
+		const cloneMixin = index.deepClone(mixin);
+		delete cloneMixin?.props?.customClass;
+		delete cloneMixin?.props?.customStyle;
+		Vue.mixin(cloneMixin);
+		// #ifdef MP
+		if(options.mpShare){
+			Vue.mixin(mpShare);
+		}
+		// #endif
+		// #endif
+		// #ifdef VUE2
+		// 时间格式化,同时两个名称,date和timeFormat
+		Vue.filter('timeFormat', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
+		Vue.filter('date', (timestamp, format) => uni.$uv.timeFormat(timestamp, format));
+		// 将多久以前的方法,注入到全局过滤器
+		Vue.filter('timeFrom', (timestamp, format) => uni.$uv.timeFrom(timestamp, format));
+		// 同时挂载到uni和Vue.prototype中
+		// #ifndef APP-NVUE
+		// 只有vue,挂载到Vue.prototype才有意义,因为nvue中全局Vue.prototype和Vue.mixin是无效的
+		Vue.prototype.$uv = $uv;
+		// #endif
+		// #endif
+		// #ifdef VUE3
+		Vue.config.globalProperties.$uv = $uv;
+		// #endif
+}
+export default {
+	install
+}

+ 7 - 0
uni_modules/uv-ui-tools/index.scss

@@ -0,0 +1,7 @@
+// 引入公共基础类
+@import "./libs/css/common.scss";
+
+// 非nvue的样式
+/* #ifndef APP-NVUE */
+@import "./libs/css/vue.scss";
+/* #endif */

+ 34 - 0
uni_modules/uv-ui-tools/libs/config/config.js

@@ -0,0 +1,34 @@
+// 此版本发布于2023-12-12
+const version = '1.1.19'
+
+// 开发环境才提示,生产环境不会提示
+if (process.env.NODE_ENV === 'development') {
+	console.log(`\n %c uvui V${version} https://www.uvui.cn/ \n\n`, 'color: #ffffff; background: #3c9cff; padding:5px 0; border-radius: 5px;');
+}
+
+export default {
+    v: version,
+    version,
+    // 主题名称
+    type: [
+        'primary',
+        'success',
+        'info',
+        'error',
+        'warning'
+    ],
+    // 颜色部分,本来可以通过scss的:export导出供js使用,但是奈何nvue不支持
+    color: {
+        'uv-primary': '#2979ff',
+        'uv-warning': '#ff9900',
+        'uv-success': '#19be6b',
+        'uv-error': '#fa3534',
+        'uv-info': '#909399',
+        'uv-main-color': '#303133',
+        'uv-content-color': '#606266',
+        'uv-tips-color': '#909399',
+        'uv-light-color': '#c0c4cc'
+    },
+	// 默认单位,可以通过配置为rpx,那么在用于传入组件大小参数为数值时,就默认为rpx
+	unit: 'px'
+}

+ 32 - 0
uni_modules/uv-ui-tools/libs/css/color.scss

@@ -0,0 +1,32 @@
+$uv-main-color: #303133 !default;
+$uv-content-color: #606266 !default;
+$uv-tips-color: #909193 !default;
+$uv-light-color: #c0c4cc !default;
+$uv-border-color: #dadbde !default;
+$uv-bg-color: #f3f4f6 !default;
+$uv-disabled-color: #c8c9cc !default;
+
+$uv-primary: #3c9cff !default;
+$uv-primary-dark: #398ade !default;
+$uv-primary-disabled: #9acafc !default;
+$uv-primary-light: #ecf5ff !default;
+
+$uv-warning: #f9ae3d !default;
+$uv-warning-dark: #f1a532 !default;
+$uv-warning-disabled: #f9d39b !default;
+$uv-warning-light: #fdf6ec !default;
+
+$uv-success: #5ac725 !default;
+$uv-success-dark: #53c21d !default;
+$uv-success-disabled: #a9e08f !default;
+$uv-success-light: #f5fff0;
+
+$uv-error: #f56c6c !default;
+$uv-error-dark: #e45656 !default;
+$uv-error-disabled: #f7b2b2 !default;
+$uv-error-light: #fef0f0 !default;
+
+$uv-info: #909399 !default;
+$uv-info-dark: #767a82 !default;
+$uv-info-disabled: #c4c6c9 !default;
+$uv-info-light: #f4f4f5 !default;

+ 100 - 0
uni_modules/uv-ui-tools/libs/css/common.scss

@@ -0,0 +1,100 @@
+// 超出行数,自动显示行尾省略号,最多5行
+// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
+@for $i from 1 through 5 {
+	.uv-line-#{$i} {
+		/* #ifdef APP-NVUE */
+		// nvue下,可以直接使用lines属性,这是weex特有样式
+		lines: $i;
+		text-overflow: ellipsis;
+		overflow: hidden;
+		flex: 1;
+		/* #endif */
+
+		/* #ifndef APP-NVUE */
+		// vue下,单行和多行显示省略号需要单独处理
+		@if $i == '1' {
+			overflow: hidden;
+			white-space: nowrap;
+			text-overflow: ellipsis;
+		} @else {
+			display: -webkit-box!important;
+			overflow: hidden;
+			text-overflow: ellipsis;
+			word-break: break-all;
+			-webkit-line-clamp: $i;
+			-webkit-box-orient: vertical!important;
+		}
+		/* #endif */
+	}
+}
+$uv-bordercolor: #dadbde;
+@if variable-exists(uv-border-color) {
+	$uv-bordercolor: $uv-border-color;
+}
+
+// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
+// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
+// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
+// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
+.uv-border {
+	border-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-style: solid;
+}
+
+.uv-border-top {
+	border-top-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-top-style: solid;
+}
+
+.uv-border-left {
+	border-left-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-left-style: solid;
+}
+
+.uv-border-right {
+	border-right-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-right-style: solid;
+}
+
+.uv-border-bottom {
+	border-bottom-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-bottom-style: solid;
+}
+
+.uv-border-top-bottom {
+	border-top-width: 0.5px!important;
+	border-bottom-width: 0.5px!important;
+	border-color: $uv-bordercolor!important;
+    border-top-style: solid;
+    border-bottom-style: solid;
+}
+
+// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
+.uv-reset-button {
+	padding: 0;
+	background-color: transparent;
+	/* #ifndef APP-PLUS */
+	font-size: inherit;
+	line-height: inherit;
+	color: inherit;
+	/* #endif */
+	/* #ifdef APP-NVUE */
+	border-width: 0;
+	/* #endif */
+}
+
+/* #ifndef APP-NVUE */
+.uv-reset-button::after {
+   border: none;
+}
+/* #endif */
+
+.uv-hover-class {
+	opacity: 0.7;
+}
+

+ 23 - 0
uni_modules/uv-ui-tools/libs/css/components.scss

@@ -0,0 +1,23 @@
+@mixin flex($direction: row) {
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: $direction;
+}
+
+/* #ifndef APP-NVUE */
+// 由于uvui是基于nvue环境进行开发的,此环境中普通元素默认为flex-direction: column;
+// 所以在非nvue中,需要对元素进行重置为flex-direction: column; 否则可能会表现异常
+$uvui-nvue-style: true !default;
+@if $uvui-nvue-style == true {
+	view, scroll-view, swiper-item {
+		display: flex;
+		flex-direction: column;
+		flex-shrink: 0;
+		flex-grow: 0;
+		flex-basis: auto;
+		align-items: stretch;
+		align-content: flex-start;
+	}
+}
+/* #endif */

+ 111 - 0
uni_modules/uv-ui-tools/libs/css/variable.scss

@@ -0,0 +1,111 @@
+// 超出行数,自动显示行尾省略号,最多5行
+// 来自uvui的温馨提示:当您在控制台看到此报错,说明需要在App.vue的style标签加上【lang="scss"】
+@if variable-exists(show-lines) {
+	@for $i from 1 through 5 {
+		.uv-line-#{$i} {
+			/* #ifdef APP-NVUE */
+			// nvue下,可以直接使用lines属性,这是weex特有样式
+			lines: $i;
+			text-overflow: ellipsis;
+			overflow: hidden;
+			flex: 1;
+			/* #endif */
+
+			/* #ifndef APP-NVUE */
+			// vue下,单行和多行显示省略号需要单独处理
+			@if $i == '1' {
+				overflow: hidden;
+				white-space: nowrap;
+				text-overflow: ellipsis;
+			} @else {
+				display: -webkit-box!important;
+				overflow: hidden;
+				text-overflow: ellipsis;
+				word-break: break-all;
+				-webkit-line-clamp: $i;
+				-webkit-box-orient: vertical!important;
+			}
+			/* #endif */
+		}
+	}
+}
+@if variable-exists(show-border) {
+	$uv-bordercolor: #dadbde;
+	@if variable-exists(uv-border-color) {
+		$uv-bordercolor: $uv-border-color;
+	}
+	// 此处加上!important并非随意乱用,而是因为目前*.nvue页面编译到H5时,
+	// App.vue的样式会被uni-app的view元素的自带border属性覆盖,导致无效
+	// 综上,这是uni-app的缺陷导致我们为了多端兼容,而必须要加上!important
+	// 移动端兼容性较好,直接使用0.5px去实现细边框,不使用伪元素形式实现
+	@if variable-exists(show-border-surround) {
+		.uv-border {
+			border-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+			border-style: solid;
+		}
+	}
+	@if variable-exists(show-border-top) {
+		.uv-border-top {
+			border-top-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+			border-top-style: solid;
+		}
+	}
+	@if variable-exists(show-border-left) {
+		.uv-border-left {
+			border-left-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+			border-left-style: solid;
+		}
+	}
+	@if variable-exists(show-border-right) {
+		.uv-border-right {
+			border-right-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+			border-right-style: solid;
+		}
+	}
+	@if variable-exists(show-border-bottom) {
+		.uv-border-bottom {
+			border-bottom-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+				border-bottom-style: solid;
+		}
+	}
+	@if variable-exists(show-border-top-bottom) {
+		.uv-border-top-bottom {
+			border-top-width: 0.5px!important;
+			border-bottom-width: 0.5px!important;
+			border-color: $uv-bordercolor!important;
+			border-top-style: solid;
+			border-bottom-style: solid;
+		}
+	}
+}
+@if variable-exists(show-reset-button) {
+	// 去除button的所有默认样式,让其表现跟普通的view、text元素一样
+	.uv-reset-button {
+		padding: 0;
+		background-color: transparent;
+		/* #ifndef APP-PLUS */
+		font-size: inherit;
+		line-height: inherit;
+		color: inherit;
+		/* #endif */
+		/* #ifdef APP-NVUE */
+		border-width: 0;
+		/* #endif */
+	}
+
+	/* #ifndef APP-NVUE */
+	.uv-reset-button::after {
+		 border: none;
+	}
+	/* #endif */
+}
+@if variable-exists(show-hover) {
+	.uv-hover-class {
+		opacity: 0.7;
+	}
+}

+ 40 - 0
uni_modules/uv-ui-tools/libs/css/vue.scss

@@ -0,0 +1,40 @@
+// 历遍生成4个方向的底部安全区
+@each $d in top, right, bottom, left {
+	.uv-safe-area-inset-#{$d} {
+		padding-#{$d}: 0;
+		padding-#{$d}: constant(safe-area-inset-#{$d});  
+		padding-#{$d}: env(safe-area-inset-#{$d});  
+	}
+}
+
+//提升H5端uni.toast()的层级,避免被uvui的modal等遮盖
+/* #ifdef H5 */
+uni-toast {
+    z-index: 10090;
+}
+uni-toast .uni-toast {
+   z-index: 10090;
+}
+/* #endif */
+
+// 隐藏scroll-view的滚动条
+::-webkit-scrollbar {
+    display: none;  
+    width: 0 !important;  
+    height: 0 !important;  
+    -webkit-appearance: none;  
+    background: transparent;  
+}
+
+$uvui-nvue-style: true !default;
+@if $uvui-nvue-style == false {
+	view, scroll-view, swiper-item {
+		display: flex;
+		flex-direction: column;
+		flex-shrink: 0;
+		flex-grow: 0;
+		flex-basis: auto;
+		align-items: stretch;
+		align-content: flex-start;
+	}
+}

+ 134 - 0
uni_modules/uv-ui-tools/libs/function/colorGradient.js

@@ -0,0 +1,134 @@
+/**
+ * 求两个颜色之间的渐变值
+ * @param {string} startColor 开始的颜色
+ * @param {string} endColor 结束的颜色
+ * @param {number} step 颜色等分的份额
+ * */
+function colorGradient(startColor = 'rgb(0, 0, 0)', endColor = 'rgb(255, 255, 255)', step = 10) {
+    const startRGB = hexToRgb(startColor, false) // 转换为rgb数组模式
+    const startR = startRGB[0]
+    const startG = startRGB[1]
+    const startB = startRGB[2]
+
+    const endRGB = hexToRgb(endColor, false)
+    const endR = endRGB[0]
+    const endG = endRGB[1]
+    const endB = endRGB[2]
+
+    const sR = (endR - startR) / step // 总差值
+    const sG = (endG - startG) / step
+    const sB = (endB - startB) / step
+    const colorArr = []
+    for (let i = 0; i < step; i++) {
+        // 计算每一步的hex值
+        let hex = rgbToHex(`rgb(${Math.round((sR * i + startR))},${Math.round((sG * i + startG))},${Math.round((sB
+			* i + startB))})`)
+        // 确保第一个颜色值为startColor的值
+        if (i === 0) hex = rgbToHex(startColor)
+        // 确保最后一个颜色值为endColor的值
+        if (i === step - 1) hex = rgbToHex(endColor)
+        colorArr.push(hex)
+    }
+    return colorArr
+}
+
+// 将hex表示方式转换为rgb表示方式(这里返回rgb数组模式)
+function hexToRgb(sColor, str = true) {
+    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+    sColor = String(sColor).toLowerCase()
+    if (sColor && reg.test(sColor)) {
+        if (sColor.length === 4) {
+            let sColorNew = '#'
+            for (let i = 1; i < 4; i += 1) {
+                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
+            }
+            sColor = sColorNew
+        }
+        // 处理六位的颜色值
+        const sColorChange = []
+        for (let i = 1; i < 7; i += 2) {
+            sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
+        }
+        if (!str) {
+            return sColorChange
+        }
+        return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`
+    } if (/^(rgb|RGB)/.test(sColor)) {
+        const arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
+        return arr.map((val) => Number(val))
+    }
+    return sColor
+}
+
+// 将rgb表示方式转换为hex表示方式
+function rgbToHex(rgb) {
+    const _this = rgb
+    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+    if (/^(rgb|RGB)/.test(_this)) {
+        const aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
+        let strHex = '#'
+        for (let i = 0; i < aColor.length; i++) {
+            let hex = Number(aColor[i]).toString(16)
+            hex = String(hex).length == 1 ? `${0}${hex}` : hex // 保证每个rgb的值为2位
+            if (hex === '0') {
+                hex += hex
+            }
+            strHex += hex
+        }
+        if (strHex.length !== 7) {
+            strHex = _this
+        }
+        return strHex
+    } if (reg.test(_this)) {
+        const aNum = _this.replace(/#/, '').split('')
+        if (aNum.length === 6) {
+            return _this
+        } if (aNum.length === 3) {
+            let numHex = '#'
+            for (let i = 0; i < aNum.length; i += 1) {
+                numHex += (aNum[i] + aNum[i])
+            }
+            return numHex
+        }
+    } else {
+        return _this
+    }
+}
+
+/**
+* JS颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
+* sHex为传入的十六进制的色值
+* alpha为rgba的透明度
+*/
+function colorToRgba(color, alpha) {
+    color = rgbToHex(color)
+    // 十六进制颜色值的正则表达式
+    const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
+    /* 16进制颜色转为RGB格式 */
+    let sColor = String(color).toLowerCase()
+    if (sColor && reg.test(sColor)) {
+        if (sColor.length === 4) {
+            let sColorNew = '#'
+            for (let i = 1; i < 4; i += 1) {
+                sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1))
+            }
+            sColor = sColorNew
+        }
+        // 处理六位的颜色值
+        const sColorChange = []
+        for (let i = 1; i < 7; i += 2) {
+            sColorChange.push(parseInt(`0x${sColor.slice(i, i + 2)}`))
+        }
+        // return sColorChange.join(',')
+        return `rgba(${sColorChange.join(',')},${alpha})`
+    }
+
+    return sColor
+}
+
+export {
+    colorGradient,
+    hexToRgb,
+    rgbToHex,
+    colorToRgba
+}

+ 29 - 0
uni_modules/uv-ui-tools/libs/function/debounce.js

@@ -0,0 +1,29 @@
+let timeout = null
+
+/**
+ * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
+ *
+ * @param {Function} func 要执行的回调函数
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行
+ * @return null
+ */
+function debounce(func, wait = 500, immediate = false) {
+    // 清除定时器
+    if (timeout !== null) clearTimeout(timeout)
+    // 立即执行,此类情况一般用不到
+    if (immediate) {
+        const callNow = !timeout
+        timeout = setTimeout(() => {
+            timeout = null
+        }, wait)
+        if (callNow) typeof func === 'function' && func()
+    } else {
+        // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
+        timeout = setTimeout(() => {
+            typeof func === 'function' && func()
+        }, wait)
+    }
+}
+
+export default debounce

+ 167 - 0
uni_modules/uv-ui-tools/libs/function/digit.js

@@ -0,0 +1,167 @@
+let _boundaryCheckingState = true; // 是否进行越界检查的全局开关
+
+/**
+ * 把错误的数据转正
+ * @private
+ * @example strip(0.09999999999999998)=0.1
+ */
+function strip(num, precision = 15) {
+  return +parseFloat(Number(num).toPrecision(precision));
+}
+
+/**
+ * Return digits length of a number
+ * @private
+ * @param {*number} num Input number
+ */
+function digitLength(num) {
+  // Get digit length of e
+  const eSplit = num.toString().split(/[eE]/);
+  const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
+  return len > 0 ? len : 0;
+}
+
+/**
+ * 把小数转成整数,如果是小数则放大成整数
+ * @private
+ * @param {*number} num 输入数
+ */
+function float2Fixed(num) {
+  if (num.toString().indexOf('e') === -1) {
+    return Number(num.toString().replace('.', ''));
+  }
+  const dLen = digitLength(num);
+  return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
+}
+
+/**
+ * 检测数字是否越界,如果越界给出提示
+ * @private
+ * @param {*number} num 输入数
+ */
+function checkBoundary(num) {
+  if (_boundaryCheckingState) {
+    if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
+      console.warn(`${num} 超出了精度限制,结果可能不正确`);
+    }
+  }
+}
+
+/**
+ * 把递归操作扁平迭代化
+ * @param {number[]} arr 要操作的数字数组
+ * @param {function} operation 迭代操作
+ * @private
+ */
+function iteratorOperation(arr, operation) {
+  const [num1, num2, ...others] = arr;
+  let res = operation(num1, num2);
+
+  others.forEach((num) => {
+    res = operation(res, num);
+  });
+
+  return res;
+}
+
+/**
+ * 高精度乘法
+ * @export
+ */
+export function times(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, times);
+  }
+
+  const [num1, num2] = nums;
+  const num1Changed = float2Fixed(num1);
+  const num2Changed = float2Fixed(num2);
+  const baseNum = digitLength(num1) + digitLength(num2);
+  const leftValue = num1Changed * num2Changed;
+
+  checkBoundary(leftValue);
+
+  return leftValue / Math.pow(10, baseNum);
+}
+
+/**
+ * 高精度加法
+ * @export
+ */
+export function plus(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, plus);
+  }
+
+  const [num1, num2] = nums;
+  // 取最大的小数位
+  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+  // 把小数都转为整数然后再计算
+  return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度减法
+ * @export
+ */
+export function minus(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, minus);
+  }
+
+  const [num1, num2] = nums;
+  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
+  return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
+}
+
+/**
+ * 高精度除法
+ * @export
+ */
+export function divide(...nums) {
+  if (nums.length > 2) {
+    return iteratorOperation(nums, divide);
+  }
+
+  const [num1, num2] = nums;
+  const num1Changed = float2Fixed(num1);
+  const num2Changed = float2Fixed(num2);
+  checkBoundary(num1Changed);
+  checkBoundary(num2Changed);
+  // 重要,这里必须用strip进行修正
+  return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
+}
+
+/**
+ * 四舍五入
+ * @export
+ */
+export function round(num, ratio) {
+  const base = Math.pow(10, ratio);
+  let result = divide(Math.round(Math.abs(times(num, base))), base);
+  if (num < 0 && result !== 0) {
+    result = times(result, -1);
+  }
+  // 位数不足则补0
+  return result;
+}
+
+/**
+ * 是否进行边界检查,默认开启
+ * @param flag 标记开关,true 为开启,false 为关闭,默认为 true
+ * @export
+ */
+export function enableBoundaryChecking(flag = true) {
+  _boundaryCheckingState = flag;
+}
+
+
+export default {
+  times,
+  plus,
+  minus,
+  divide,
+  round,
+  enableBoundaryChecking,
+};
+

+ 734 - 0
uni_modules/uv-ui-tools/libs/function/index.js

@@ -0,0 +1,734 @@
+import { number, empty } from './test.js'
+import { round } from './digit.js'
+/**
+ * @description 如果value小于min,取min;如果value大于max,取max
+ * @param {number} min
+ * @param {number} max
+ * @param {number} value
+ */
+function range(min = 0, max = 0, value = 0) {
+	return Math.max(min, Math.min(max, Number(value)))
+}
+
+/**
+ * @description 用于获取用户传递值的px值  如果用户传递了"xxpx"或者"xxrpx",取出其数值部分,如果是"xxxrpx"还需要用过uni.upx2px进行转换
+ * @param {number|string} value 用户传递值的px值
+ * @param {boolean} unit
+ * @returns {number|string}
+ */
+function getPx(value, unit = false) {
+	if (number(value)) {
+		return unit ? `${value}px` : Number(value)
+	}
+	// 如果带有rpx,先取出其数值部分,再转为px值
+	if (/(rpx|upx)$/.test(value)) {
+		return unit ? `${uni.upx2px(parseInt(value))}px` : Number(uni.upx2px(parseInt(value)))
+	}
+	return unit ? `${parseInt(value)}px` : parseInt(value)
+}
+
+/**
+ * @description 进行延时,以达到可以简写代码的目的 比如: await uni.$uv.sleep(20)将会阻塞20ms
+ * @param {number} value 堵塞时间 单位ms 毫秒
+ * @returns {Promise} 返回promise
+ */
+function sleep(value = 30) {
+	return new Promise((resolve) => {
+		setTimeout(() => {
+			resolve()
+		}, value)
+	})
+}
+/**
+ * @description 运行期判断平台
+ * @returns {string} 返回所在平台(小写)
+ * @link 运行期判断平台 https://uniapp.dcloud.io/frame?id=判断平台
+ */
+function os() {
+	return uni.getSystemInfoSync().platform.toLowerCase()
+}
+/**
+ * @description 获取系统信息同步接口
+ * @link 获取系统信息同步接口 https://uniapp.dcloud.io/api/system/info?id=getsysteminfosync
+ */
+function sys() {
+	return uni.getSystemInfoSync()
+}
+
+/**
+ * @description 取一个区间数
+ * @param {Number} min 最小值
+ * @param {Number} max 最大值
+ */
+function random(min, max) {
+	if (min >= 0 && max > 0 && max >= min) {
+		const gab = max - min + 1
+		return Math.floor(Math.random() * gab + min)
+	}
+	return 0
+}
+
+/**
+ * @param {Number} len uuid的长度
+ * @param {Boolean} firstU 将返回的首字母置为"u"
+ * @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
+ */
+function guid(len = 32, firstU = true, radix = null) {
+	const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
+	const uuid = []
+	radix = radix || chars.length
+
+	if (len) {
+		// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
+		for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
+	} else {
+		let r
+		// rfc4122标准要求返回的uuid中,某些位为固定的字符
+		uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
+		uuid[14] = '4'
+
+		for (let i = 0; i < 36; i++) {
+			if (!uuid[i]) {
+				r = 0 | Math.random() * 16
+				uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r]
+			}
+		}
+	}
+	// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
+	if (firstU) {
+		uuid.shift()
+		return `u${uuid.join('')}`
+	}
+	return uuid.join('')
+}
+
+/**
+* @description 获取父组件的参数,因为支付宝小程序不支持provide/inject的写法
+   this.$parent在非H5中,可以准确获取到父组件,但是在H5中,需要多次this.$parent.$parent.xxx
+   这里默认值等于undefined有它的含义,因为最顶层元素(组件)的$parent就是undefined,意味着不传name
+   值(默认为undefined),就是查找最顶层的$parent
+*  @param {string|undefined} name 父组件的参数名
+*/
+function $parent(name = undefined) {
+	let parent = this.$parent
+	// 通过while历遍,这里主要是为了H5需要多层解析的问题
+	while (parent) {
+		// 父组件
+		if (parent.$options && parent.$options.name !== name) {
+			// 如果组件的name不相等,继续上一级寻找
+			parent = parent.$parent
+		} else {
+			return parent
+		}
+	}
+	return false
+}
+
+/**
+ * @description 样式转换
+ * 对象转字符串,或者字符串转对象
+ * @param {object | string} customStyle 需要转换的目标
+ * @param {String} target 转换的目的,object-转为对象,string-转为字符串
+ * @returns {object|string}
+ */
+function addStyle(customStyle, target = 'object') {
+	// 字符串转字符串,对象转对象情形,直接返回
+	if (empty(customStyle) || typeof(customStyle) === 'object' && target === 'object' || target === 'string' &&
+		typeof(customStyle) === 'string') {
+		return customStyle
+	}
+	// 字符串转对象
+	if (target === 'object') {
+		// 去除字符串样式中的两端空格(中间的空格不能去掉,比如padding: 20px 0如果去掉了就错了),空格是无用的
+		customStyle = trim(customStyle)
+		// 根据";"将字符串转为数组形式
+		const styleArray = customStyle.split(';')
+		const style = {}
+		// 历遍数组,拼接成对象
+		for (let i = 0; i < styleArray.length; i++) {
+			// 'font-size:20px;color:red;',如此最后字符串有";"的话,会导致styleArray最后一个元素为空字符串,这里需要过滤
+			if (styleArray[i]) {
+				const item = styleArray[i].split(':')
+				style[trim(item[0])] = trim(item[1])
+			}
+		}
+		return style
+	}
+	// 这里为对象转字符串形式
+	let string = ''
+	for (const i in customStyle) {
+		// 驼峰转为中划线的形式,否则css内联样式,无法识别驼峰样式属性名
+		const key = i.replace(/([A-Z])/g, '-$1').toLowerCase()
+		string += `${key}:${customStyle[i]};`
+	}
+	// 去除两端空格
+	return trim(string)
+}
+
+/**
+ * @description 添加单位,如果有rpx,upx,%,px等单位结尾或者值为auto,直接返回,否则加上px单位结尾
+ * @param {string|number} value 需要添加单位的值
+ * @param {string} unit 添加的单位名 比如px
+ */
+function addUnit(value = 'auto', unit = uni?.$uv?.config?.unit ? uni?.$uv?.config?.unit : 'px') {
+	value = String(value)
+	// 用uvui内置验证规则中的number判断是否为数值
+	return number(value) ? `${value}${unit}` : value
+}
+
+/**
+ * @description 深度克隆
+ * @param {object} obj 需要深度克隆的对象
+ * @param cache 缓存
+ * @returns {*} 克隆后的对象或者原值(不是对象)
+ */
+function deepClone(obj, cache = new WeakMap()) {
+	if (obj === null || typeof obj !== 'object') return obj;
+	if (cache.has(obj)) return cache.get(obj);
+	let clone;
+	if (obj instanceof Date) {
+		clone = new Date(obj.getTime());
+	} else if (obj instanceof RegExp) {
+		clone = new RegExp(obj);
+	} else if (obj instanceof Map) {
+		clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
+	} else if (obj instanceof Set) {
+		clone = new Set(Array.from(obj, value => deepClone(value, cache)));
+	} else if (Array.isArray(obj)) {
+		clone = obj.map(value => deepClone(value, cache));
+	} else if (Object.prototype.toString.call(obj) === '[object Object]') {
+		clone = Object.create(Object.getPrototypeOf(obj));
+		cache.set(obj, clone);
+		for (const [key, value] of Object.entries(obj)) {
+			clone[key] = deepClone(value, cache);
+		}
+	} else {
+		clone = Object.assign({}, obj);
+	}
+	cache.set(obj, clone);
+	return clone;
+}
+
+/**
+ * @description JS对象深度合并
+ * @param {object} target 需要拷贝的对象
+ * @param {object} source 拷贝的来源对象
+ * @returns {object|boolean} 深度合并后的对象或者false(入参有不是对象)
+ */
+function deepMerge(target = {}, source = {}) {
+	target = deepClone(target)
+	if (typeof target !== 'object' || target === null || typeof source !== 'object' || source === null) return target;
+	const merged = Array.isArray(target) ? target.slice() : Object.assign({}, target);
+	for (const prop in source) {
+		if (!source.hasOwnProperty(prop)) continue;
+		const sourceValue = source[prop];
+		const targetValue = merged[prop];
+		if (sourceValue instanceof Date) {
+			merged[prop] = new Date(sourceValue);
+		} else if (sourceValue instanceof RegExp) {
+			merged[prop] = new RegExp(sourceValue);
+		} else if (sourceValue instanceof Map) {
+			merged[prop] = new Map(sourceValue);
+		} else if (sourceValue instanceof Set) {
+			merged[prop] = new Set(sourceValue);
+		} else if (typeof sourceValue === 'object' && sourceValue !== null) {
+			merged[prop] = deepMerge(targetValue, sourceValue);
+		} else {
+			merged[prop] = sourceValue;
+		}
+	}
+	return merged;
+}
+
+/**
+ * @description error提示
+ * @param {*} err 错误内容
+ */
+function error(err) {
+	// 开发环境才提示,生产环境不会提示
+	if (process.env.NODE_ENV === 'development') {
+		console.error(`uvui提示:${err}`)
+	}
+}
+
+/**
+ * @description 打乱数组
+ * @param {array} array 需要打乱的数组
+ * @returns {array} 打乱后的数组
+ */
+function randomArray(array = []) {
+	// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
+	return array.sort(() => Math.random() - 0.5)
+}
+
+// padStart 的 polyfill,因为某些机型或情况,还无法支持es7的padStart,比如电脑版的微信小程序
+// 所以这里做一个兼容polyfill的兼容处理
+if (!String.prototype.padStart) {
+	// 为了方便表示这里 fillString 用了ES6 的默认参数,不影响理解
+	String.prototype.padStart = function(maxLength, fillString = ' ') {
+		if (Object.prototype.toString.call(fillString) !== '[object String]') {
+			throw new TypeError(
+				'fillString must be String'
+			)
+		}
+		const str = this
+		// 返回 String(str) 这里是为了使返回的值是字符串字面量,在控制台中更符合直觉
+		if (str.length >= maxLength) return String(str)
+
+		const fillLength = maxLength - str.length
+		let times = Math.ceil(fillLength / fillString.length)
+		while (times >>= 1) {
+			fillString += fillString
+			if (times === 1) {
+				fillString += fillString
+			}
+		}
+		return fillString.slice(0, fillLength) + str
+	}
+}
+
+/**
+ * @description 格式化时间
+ * @param {String|Number} dateTime 需要格式化的时间戳
+ * @param {String} fmt 格式化规则 yyyy:mm:dd|yyyy:mm|yyyy年mm月dd日|yyyy年mm月dd日 hh时MM分等,可自定义组合 默认yyyy-mm-dd
+ * @returns {string} 返回格式化后的字符串
+ */
+function timeFormat(dateTime = null, formatStr = 'yyyy-mm-dd') {
+	let date
+	// 若传入时间为假值,则取当前时间
+	if (!dateTime) {
+		date = new Date()
+	}
+	// 若为unix秒时间戳,则转为毫秒时间戳(逻辑有点奇怪,但不敢改,以保证历史兼容)
+	else if (/^\d{10}$/.test(dateTime?.toString().trim())) {
+		date = new Date(dateTime * 1000)
+	}
+	// 若用户传入字符串格式时间戳,new Date无法解析,需做兼容
+	else if (typeof dateTime === 'string' && /^\d+$/.test(dateTime.trim())) {
+		date = new Date(Number(dateTime))
+	}
+	// 处理平台性差异,在Safari/Webkit中,new Date仅支持/作为分割符的字符串时间
+	// 处理 '2022-07-10 01:02:03',跳过 '2022-07-10T01:02:03'
+	else if (typeof dateTime === 'string' && dateTime.includes('-') && !dateTime.includes('T')) {
+		date = new Date(dateTime.replace(/-/g, '/'))
+	}
+	// 其他都认为符合 RFC 2822 规范
+	else {
+		date = new Date(dateTime)
+	}
+
+	const timeSource = {
+		'y': date.getFullYear().toString(), // 年
+		'm': (date.getMonth() + 1).toString().padStart(2, '0'), // 月
+		'd': date.getDate().toString().padStart(2, '0'), // 日
+		'h': date.getHours().toString().padStart(2, '0'), // 时
+		'M': date.getMinutes().toString().padStart(2, '0'), // 分
+		's': date.getSeconds().toString().padStart(2, '0') // 秒
+		// 有其他格式化字符需求可以继续添加,必须转化成字符串
+	}
+
+	for (const key in timeSource) {
+		const [ret] = new RegExp(`${key}+`).exec(formatStr) || []
+		if (ret) {
+			// 年可能只需展示两位
+			const beginIndex = key === 'y' && ret.length === 2 ? 2 : 0
+			formatStr = formatStr.replace(ret, timeSource[key].slice(beginIndex))
+		}
+	}
+
+	return formatStr
+}
+
+/**
+ * @description 时间戳转为多久之前
+ * @param {String|Number} timestamp 时间戳
+ * @param {String|Boolean} format
+ * 格式化规则如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
+ * 如果为布尔值false,无论什么时间,都返回多久以前的格式
+ * @returns {string} 转化后的内容
+ */
+function timeFrom(timestamp = null, format = 'yyyy-mm-dd') {
+	if (timestamp == null) timestamp = Number(new Date())
+	timestamp = parseInt(timestamp)
+	// 判断用户输入的时间戳是秒还是毫秒,一般前端js获取的时间戳是毫秒(13位),后端传过来的为秒(10位)
+	if (timestamp.toString().length == 10) timestamp *= 1000
+	let timer = (new Date()).getTime() - timestamp
+	timer = parseInt(timer / 1000)
+	// 如果小于5分钟,则返回"刚刚",其他以此类推
+	let tips = ''
+	switch (true) {
+		case timer < 300:
+			tips = '刚刚'
+			break
+		case timer >= 300 && timer < 3600:
+			tips = `${parseInt(timer / 60)}分钟前`
+			break
+		case timer >= 3600 && timer < 86400:
+			tips = `${parseInt(timer / 3600)}小时前`
+			break
+		case timer >= 86400 && timer < 2592000:
+			tips = `${parseInt(timer / 86400)}天前`
+			break
+		default:
+			// 如果format为false,则无论什么时间戳,都显示xx之前
+			if (format === false) {
+				if (timer >= 2592000 && timer < 365 * 86400) {
+					tips = `${parseInt(timer / (86400 * 30))}个月前`
+				} else {
+					tips = `${parseInt(timer / (86400 * 365))}年前`
+				}
+			} else {
+				tips = timeFormat(timestamp, format)
+			}
+	}
+	return tips
+}
+
+/**
+ * @description 去除空格
+ * @param String str 需要去除空格的字符串
+ * @param String pos both(左右)|left|right|all 默认both
+ */
+function trim(str, pos = 'both') {
+	str = String(str)
+	if (pos == 'both') {
+		return str.replace(/^\s+|\s+$/g, '')
+	}
+	if (pos == 'left') {
+		return str.replace(/^\s*/, '')
+	}
+	if (pos == 'right') {
+		return str.replace(/(\s*$)/g, '')
+	}
+	if (pos == 'all') {
+		return str.replace(/\s+/g, '')
+	}
+	return str
+}
+
+/**
+ * @description 对象转url参数
+ * @param {object} data,对象
+ * @param {Boolean} isPrefix,是否自动加上"?"
+ * @param {string} arrayFormat 规则 indices|brackets|repeat|comma
+ */
+function queryParams(data = {}, isPrefix = true, arrayFormat = 'brackets') {
+	const prefix = isPrefix ? '?' : ''
+	const _result = []
+	if (['indices', 'brackets', 'repeat', 'comma'].indexOf(arrayFormat) == -1) arrayFormat = 'brackets'
+	for (const key in data) {
+		const value = data[key]
+		// 去掉为空的参数
+		if (['', undefined, null].indexOf(value) >= 0) {
+			continue
+		}
+		// 如果值为数组,另行处理
+		if (value.constructor === Array) {
+			// e.g. {ids: [1, 2, 3]}
+			switch (arrayFormat) {
+				case 'indices':
+					// 结果: ids[0]=1&ids[1]=2&ids[2]=3
+					for (let i = 0; i < value.length; i++) {
+						_result.push(`${key}[${i}]=${value[i]}`)
+					}
+					break
+				case 'brackets':
+					// 结果: ids[]=1&ids[]=2&ids[]=3
+					value.forEach((_value) => {
+						_result.push(`${key}[]=${_value}`)
+					})
+					break
+				case 'repeat':
+					// 结果: ids=1&ids=2&ids=3
+					value.forEach((_value) => {
+						_result.push(`${key}=${_value}`)
+					})
+					break
+				case 'comma':
+					// 结果: ids=1,2,3
+					let commaStr = ''
+					value.forEach((_value) => {
+						commaStr += (commaStr ? ',' : '') + _value
+					})
+					_result.push(`${key}=${commaStr}`)
+					break
+				default:
+					value.forEach((_value) => {
+						_result.push(`${key}[]=${_value}`)
+					})
+			}
+		} else {
+			_result.push(`${key}=${value}`)
+		}
+	}
+	return _result.length ? prefix + _result.join('&') : ''
+}
+
+/**
+ * 显示消息提示框
+ * @param {String} title 提示的内容,长度与 icon 取值有关。
+ * @param {Number} duration 提示的延迟时间,单位毫秒,默认:2000
+ */
+function toast(title, duration = 2000) {
+	uni.showToast({
+		title: String(title),
+		icon: 'none',
+		duration
+	})
+}
+
+/**
+ * @description 根据主题type值,获取对应的图标
+ * @param {String} type 主题名称,primary|info|error|warning|success
+ * @param {boolean} fill 是否使用fill填充实体的图标
+ */
+function type2icon(type = 'success', fill = false) {
+	// 如果非预置值,默认为success
+	if (['primary', 'info', 'error', 'warning', 'success'].indexOf(type) == -1) type = 'success'
+	let iconName = ''
+	// 目前(2019-12-12),info和primary使用同一个图标
+	switch (type) {
+		case 'primary':
+			iconName = 'info-circle'
+			break
+		case 'info':
+			iconName = 'info-circle'
+			break
+		case 'error':
+			iconName = 'close-circle'
+			break
+		case 'warning':
+			iconName = 'error-circle'
+			break
+		case 'success':
+			iconName = 'checkmark-circle'
+			break
+		default:
+			iconName = 'checkmark-circle'
+	}
+	// 是否是实体类型,加上-fill,在icon组件库中,实体的类名是后面加-fill的
+	if (fill) iconName += '-fill'
+	return iconName
+}
+
+/**
+ * @description 数字格式化
+ * @param {number|string} number 要格式化的数字
+ * @param {number} decimals 保留几位小数
+ * @param {string} decimalPoint 小数点符号
+ * @param {string} thousandsSeparator 千分位符号
+ * @returns {string} 格式化后的数字
+ */
+function priceFormat(number, decimals = 0, decimalPoint = '.', thousandsSeparator = ',') {
+	number = (`${number}`).replace(/[^0-9+-Ee.]/g, '')
+	const n = !isFinite(+number) ? 0 : +number
+	const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
+	const sep = (typeof thousandsSeparator === 'undefined') ? ',' : thousandsSeparator
+	const dec = (typeof decimalPoint === 'undefined') ? '.' : decimalPoint
+	let s = ''
+
+	s = (prec ? round(n, prec) + '' : `${Math.round(n)}`).split('.')
+	const re = /(-?\d+)(\d{3})/
+	while (re.test(s[0])) {
+		s[0] = s[0].replace(re, `$1${sep}$2`)
+	}
+
+	if ((s[1] || '').length < prec) {
+		s[1] = s[1] || ''
+		s[1] += new Array(prec - s[1].length + 1).join('0')
+	}
+	return s.join(dec)
+}
+
+/**
+ * @description 获取duration值
+ * 如果带有ms或者s直接返回,如果大于一定值,认为是ms单位,小于一定值,认为是s单位
+ * 比如以30位阈值,那么300大于30,可以理解为用户想要的是300ms,而不是想花300s去执行一个动画
+ * @param {String|number} value 比如: "1s"|"100ms"|1|100
+ * @param {boolean} unit  提示: 如果是false 默认返回number
+ * @return {string|number}
+ */
+function getDuration(value, unit = true) {
+	const valueNum = parseInt(value)
+	if (unit) {
+		if (/s$/.test(value)) return value
+		return value > 30 ? `${value}ms` : `${value}s`
+	}
+	if (/ms$/.test(value)) return valueNum
+	if (/s$/.test(value)) return valueNum > 30 ? valueNum : valueNum * 1000
+	return valueNum
+}
+
+/**
+ * @description 日期的月或日补零操作
+ * @param {String} value 需要补零的值
+ */
+function padZero(value) {
+	return `00${value}`.slice(-2)
+}
+
+/**
+ * @description 在uv-form的子组件内容发生变化,或者失去焦点时,尝试通知uv-form执行校验方法
+ * @param {*} instance
+ * @param {*} event
+ */
+function formValidate(instance, event) {
+	const formItem = $parent.call(instance, 'uv-form-item')
+	const form = $parent.call(instance, 'uv-form')
+	// 如果发生变化的input或者textarea等,其父组件中有uv-form-item或者uv-form等,就执行form的validate方法
+	// 同时将form-item的pros传递给form,让其进行精确对象验证
+	if (formItem && form) {
+		form.validateField(formItem.prop, () => {}, event)
+	}
+}
+
+/**
+ * @description 获取某个对象下的属性,用于通过类似'a.b.c'的形式去获取一个对象的的属性的形式
+ * @param {object} obj 对象
+ * @param {string} key 需要获取的属性字段
+ * @returns {*}
+ */
+function getProperty(obj, key) {
+	if (!obj) {
+		return
+	}
+	if (typeof key !== 'string' || key === '') {
+		return ''
+	}
+	if (key.indexOf('.') !== -1) {
+		const keys = key.split('.')
+		let firstObj = obj[keys[0]] || {}
+
+		for (let i = 1; i < keys.length; i++) {
+			if (firstObj) {
+				firstObj = firstObj[keys[i]]
+			}
+		}
+		return firstObj
+	}
+	return obj[key]
+}
+
+/**
+ * @description 设置对象的属性值,如果'a.b.c'的形式进行设置
+ * @param {object} obj 对象
+ * @param {string} key 需要设置的属性
+ * @param {string} value 设置的值
+ */
+function setProperty(obj, key, value) {
+	if (!obj) {
+		return
+	}
+	// 递归赋值
+	const inFn = function(_obj, keys, v) {
+		// 最后一个属性key
+		if (keys.length === 1) {
+			_obj[keys[0]] = v
+			return
+		}
+		// 0~length-1个key
+		while (keys.length > 1) {
+			const k = keys[0]
+			if (!_obj[k] || (typeof _obj[k] !== 'object')) {
+				_obj[k] = {}
+			}
+			const key = keys.shift()
+			// 自调用判断是否存在属性,不存在则自动创建对象
+			inFn(_obj[k], keys, v)
+		}
+	}
+
+	if (typeof key !== 'string' || key === '') {
+
+	} else if (key.indexOf('.') !== -1) { // 支持多层级赋值操作
+		const keys = key.split('.')
+		inFn(obj, keys, value)
+	} else {
+		obj[key] = value
+	}
+}
+
+/**
+ * @description 获取当前页面路径
+ */
+function page() {
+	const pages = getCurrentPages();
+	const route = pages[pages.length - 1]?.route;
+	// 某些特殊情况下(比如页面进行redirectTo时的一些时机),pages可能为空数组
+	return `/${route ? route : ''}`
+}
+
+/**
+ * @description 获取当前路由栈实例数组
+ */
+function pages() {
+	const pages = getCurrentPages()
+	return pages
+}
+
+/**
+ * 获取页面历史栈指定层实例
+ * @param back {number} [0] - 0或者负数,表示获取历史栈的哪一层,0表示获取当前页面实例,-1 表示获取上一个页面实例。默认0。
+ */
+function getHistoryPage(back = 0) {
+	const pages = getCurrentPages()
+	const len = pages.length
+	return pages[len - 1 + back]
+}
+
+
+
+/**
+ * @description 修改uvui内置属性值
+ * @param {object} props 修改内置props属性
+ * @param {object} config 修改内置config属性
+ * @param {object} color 修改内置color属性
+ * @param {object} zIndex 修改内置zIndex属性
+ */
+function setConfig({
+	props = {},
+	config = {},
+	color = {},
+	zIndex = {}
+}) {
+	const {
+		deepMerge,
+	} = uni.$uv
+	uni.$uv.config = deepMerge(uni.$uv.config, config)
+	uni.$uv.props = deepMerge(uni.$uv.props, props)
+	uni.$uv.color = deepMerge(uni.$uv.color, color)
+	uni.$uv.zIndex = deepMerge(uni.$uv.zIndex, zIndex)
+}
+
+export {
+	range,
+	getPx,
+	sleep,
+	os,
+	sys,
+	random,
+	guid,
+	$parent,
+	addStyle,
+	addUnit,
+	deepClone,
+	deepMerge,
+	error,
+	randomArray,
+	timeFormat,
+	timeFrom,
+	trim,
+	queryParams,
+	toast,
+	type2icon,
+	priceFormat,
+	getDuration,
+	padZero,
+	formValidate,
+	getProperty,
+	setProperty,
+	page,
+	pages,
+	getHistoryPage,
+	setConfig
+}

+ 75 - 0
uni_modules/uv-ui-tools/libs/function/platform.js

@@ -0,0 +1,75 @@
+/**
+ * 注意:
+ * 此部分内容,在vue-cli模式下,需要在vue.config.js加入如下内容才有效:
+ * module.exports = {
+ *     transpileDependencies: ['uview-v2']
+ * }
+ */
+
+let platform = 'none'
+
+// #ifdef VUE3
+platform = 'vue3'
+// #endif
+
+// #ifdef VUE2
+platform = 'vue2'
+// #endif
+
+// #ifdef APP-PLUS
+platform = 'plus'
+// #endif
+
+// #ifdef APP-NVUE
+platform = 'nvue'
+// #endif
+
+// #ifdef H5
+platform = 'h5'
+// #endif
+
+// #ifdef MP-WEIXIN
+platform = 'weixin'
+// #endif
+
+// #ifdef MP-ALIPAY
+platform = 'alipay'
+// #endif
+
+// #ifdef MP-BAIDU
+platform = 'baidu'
+// #endif
+
+// #ifdef MP-TOUTIAO
+platform = 'toutiao'
+// #endif
+
+// #ifdef MP-QQ
+platform = 'qq'
+// #endif
+
+// #ifdef MP-KUAISHOU
+platform = 'kuaishou'
+// #endif
+
+// #ifdef MP-360
+platform = '360'
+// #endif
+
+// #ifdef MP
+platform = 'mp'
+// #endif
+
+// #ifdef QUICKAPP-WEBVIEW
+platform = 'quickapp-webview'
+// #endif
+
+// #ifdef QUICKAPP-WEBVIEW-HUAWEI
+platform = 'quickapp-webview-huawei'
+// #endif
+
+// #ifdef QUICKAPP-WEBVIEW-UNION
+platform = 'quckapp-webview-union'
+// #endif
+
+export default platform

+ 287 - 0
uni_modules/uv-ui-tools/libs/function/test.js

@@ -0,0 +1,287 @@
+/**
+ * 验证电子邮箱格式
+ */
+function email(value) {
+    return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value)
+}
+
+/**
+ * 验证手机格式
+ */
+function mobile(value) {
+    return /^1([3589]\d|4[5-9]|6[1-2,4-7]|7[0-8])\d{8}$/.test(value)
+}
+
+/**
+ * 验证URL格式
+ */
+function url(value) {
+    return /^((https|http|ftp|rtsp|mms):\/\/)(([0-9a-zA-Z_!~*'().&=+$%-]+: )?[0-9a-zA-Z_!~*'().&=+$%-]+@)?(([0-9]{1,3}.){3}[0-9]{1,3}|([0-9a-zA-Z_!~*'()-]+.)*([0-9a-zA-Z][0-9a-zA-Z-]{0,61})?[0-9a-zA-Z].[a-zA-Z]{2,6})(:[0-9]{1,4})?((\/?)|(\/[0-9a-zA-Z_!~*'().;?:@&=+$,%#-]+)+\/?)$/
+        .test(value)
+}
+
+/**
+ * 验证日期格式
+ */
+function date(value) {
+    if (!value) return false
+    // 判断是否数值或者字符串数值(意味着为时间戳),转为数值,否则new Date无法识别字符串时间戳
+    if (number(value)) value = +value
+    return !/Invalid|NaN/.test(new Date(value).toString())
+}
+
+/**
+ * 验证ISO类型的日期格式
+ */
+function dateISO(value) {
+    return /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value)
+}
+
+/**
+ * 验证十进制数字
+ */
+function number(value) {
+    return /^[\+-]?(\d+\.?\d*|\.\d+|\d\.\d+e\+\d+)$/.test(value)
+}
+
+/**
+ * 验证字符串
+ */
+function string(value) {
+    return typeof value === 'string'
+}
+
+/**
+ * 验证整数
+ */
+function digits(value) {
+    return /^\d+$/.test(value)
+}
+
+/**
+ * 验证身份证号码
+ */
+function idCard(value) {
+    return /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(
+        value
+    )
+}
+
+/**
+ * 是否车牌号
+ */
+function carNo(value) {
+    // 新能源车牌
+    const xreg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DF]$)|([DF][A-HJ-NP-Z0-9][0-9]{4}$))/
+    // 旧车牌
+    const creg = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/
+    if (value.length === 7) {
+        return creg.test(value)
+    } if (value.length === 8) {
+        return xreg.test(value)
+    }
+    return false
+}
+
+/**
+ * 金额,只允许2位小数
+ */
+function amount(value) {
+    // 金额,只允许保留两位小数
+    return /^[1-9]\d*(,\d{3})*(\.\d{1,2})?$|^0\.\d{1,2}$/.test(value)
+}
+
+/**
+ * 中文
+ */
+function chinese(value) {
+    const reg = /^[\u4e00-\u9fa5]+$/gi
+    return reg.test(value)
+}
+
+/**
+ * 只能输入字母
+ */
+function letter(value) {
+    return /^[a-zA-Z]*$/.test(value)
+}
+
+/**
+ * 只能是字母或者数字
+ */
+function enOrNum(value) {
+    // 英文或者数字
+    const reg = /^[0-9a-zA-Z]*$/g
+    return reg.test(value)
+}
+
+/**
+ * 验证是否包含某个值
+ */
+function contains(value, param) {
+    return value.indexOf(param) >= 0
+}
+
+/**
+ * 验证一个值范围[min, max]
+ */
+function range(value, param) {
+    return value >= param[0] && value <= param[1]
+}
+
+/**
+ * 验证一个长度范围[min, max]
+ */
+function rangeLength(value, param) {
+    return value.length >= param[0] && value.length <= param[1]
+}
+
+/**
+ * 是否固定电话
+ */
+function landline(value) {
+    const reg = /^\d{3,4}-\d{7,8}(-\d{3,4})?$/
+    return reg.test(value)
+}
+
+/**
+ * 判断是否为空
+ */
+function empty(value) {
+    switch (typeof value) {
+    case 'undefined':
+        return true
+    case 'string':
+        if (value.replace(/(^[ \t\n\r]*)|([ \t\n\r]*$)/g, '').length == 0) return true
+        break
+    case 'boolean':
+        if (!value) return true
+        break
+    case 'number':
+        if (value === 0 || isNaN(value)) return true
+        break
+    case 'object':
+        if (value === null || value.length === 0) return true
+        for (const i in value) {
+            return false
+        }
+        return true
+    }
+    return false
+}
+
+/**
+ * 是否json字符串
+ */
+function jsonString(value) {
+    if (typeof value === 'string') {
+        try {
+            const obj = JSON.parse(value)
+            if (typeof obj === 'object' && obj) {
+                return true
+            }
+            return false
+        } catch (e) {
+            return false
+        }
+    }
+    return false
+}
+
+/**
+ * 是否数组
+ */
+function array(value) {
+    if (typeof Array.isArray === 'function') {
+        return Array.isArray(value)
+    }
+    return Object.prototype.toString.call(value) === '[object Array]'
+}
+
+/**
+ * 是否对象
+ */
+function object(value) {
+    return Object.prototype.toString.call(value) === '[object Object]'
+}
+
+/**
+ * 是否短信验证码
+ */
+function code(value, len = 6) {
+    return new RegExp(`^\\d{${len}}$`).test(value)
+}
+
+/**
+ * 是否函数方法
+ * @param {Object} value
+ */
+function func(value) {
+    return typeof value === 'function'
+}
+
+/**
+ * 是否promise对象
+ * @param {Object} value
+ */
+function promise(value) {
+    return object(value) && func(value.then) && func(value.catch)
+}
+
+/** 是否图片格式
+ * @param {Object} value
+ */
+function image(value) {
+    const newValue = value.split('?')[0]
+    const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i
+    return IMAGE_REGEXP.test(newValue)
+}
+
+/**
+ * 是否视频格式
+ * @param {Object} value
+ */
+function video(value) {
+    const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv|m3u8)/i
+    return VIDEO_REGEXP.test(value)
+}
+
+/**
+ * 是否为正则对象
+ * @param {Object}
+ * @return {Boolean}
+ */
+function regExp(o) {
+    return o && Object.prototype.toString.call(o) === '[object RegExp]'
+}
+
+export {
+    email,
+    mobile,
+    url,
+    date,
+    dateISO,
+    number,
+    digits,
+    idCard,
+    carNo,
+    amount,
+    chinese,
+    letter,
+    enOrNum,
+    contains,
+    range,
+    rangeLength,
+    empty,
+    jsonString,
+    landline,
+    object,
+    array,
+    code,
+    func,
+    promise,
+    video,
+    image,
+    regExp,
+    string
+}

+ 30 - 0
uni_modules/uv-ui-tools/libs/function/throttle.js

@@ -0,0 +1,30 @@
+let timer; let
+    flag
+/**
+ * 节流原理:在一定时间内,只能触发一次
+ *
+ * @param {Function} func 要执行的回调函数
+ * @param {Number} wait 延时的时间
+ * @param {Boolean} immediate 是否立即执行
+ * @return null
+ */
+function throttle(func, wait = 500, immediate = true) {
+    if (immediate) {
+        if (!flag) {
+            flag = true
+            // 如果是立即执行,则在wait毫秒内开始时执行
+            typeof func === 'function' && func()
+            timer = setTimeout(() => {
+                flag = false
+            }, wait)
+        }
+    } else if (!flag) {
+        flag = true
+        // 如果是非立即执行,则在wait毫秒内的结束处执行
+        timer = setTimeout(() => {
+            flag = false
+            typeof func === 'function' && func()
+        }, wait)
+    }
+}
+export default throttle

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

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

+ 51 - 0
uni_modules/uv-ui-tools/libs/luch-request/core/InterceptorManager.js

@@ -0,0 +1,51 @@
+'use strict'
+
+
+function InterceptorManager() {
+  this.handlers = []
+}
+
+/**
+ * Add a new interceptor to the stack
+ *
+ * @param {Function} fulfilled The function to handle `then` for a `Promise`
+ * @param {Function} rejected The function to handle `reject` for a `Promise`
+ *
+ * @return {Number} An ID used to remove interceptor later
+ */
+InterceptorManager.prototype.use = function use(fulfilled, rejected) {
+  this.handlers.push({
+    fulfilled: fulfilled,
+    rejected: rejected
+  })
+  return this.handlers.length - 1
+}
+
+/**
+ * Remove an interceptor from the stack
+ *
+ * @param {Number} id The ID that was returned by `use`
+ */
+InterceptorManager.prototype.eject = function eject(id) {
+  if (this.handlers[id]) {
+    this.handlers[id] = null
+  }
+}
+
+/**
+ * Iterate over all the registered interceptors
+ *
+ * This method is particularly useful for skipping over any
+ * interceptors that may have become `null` calling `eject`.
+ *
+ * @param {Function} fn The function to call for each interceptor
+ */
+InterceptorManager.prototype.forEach = function forEach(fn) {
+  this.handlers.forEach(h => {
+    if (h !== null) {
+      fn(h)
+    }
+  })
+}
+
+export default InterceptorManager

+ 201 - 0
uni_modules/uv-ui-tools/libs/luch-request/core/Request.js

@@ -0,0 +1,201 @@
+/**
+ * @Class Request
+ * @description luch-request http请求插件
+ * @Author lu-ch
+ * @Email webwork.s@qq.com
+ * 文档: https://www.quanzhan.co/luch-request/
+ * github: https://github.com/lei-mu/luch-request
+ * DCloud: http://ext.dcloud.net.cn/plugin?id=392
+ */
+
+
+import dispatchRequest from './dispatchRequest'
+import InterceptorManager from './InterceptorManager'
+import mergeConfig from './mergeConfig'
+import defaults from './defaults'
+import { isPlainObject } from '../utils'
+import clone from '../utils/clone'
+
+export default class Request {
+  /**
+   * @param {Object} arg - 全局配置
+   * @param {String} arg.baseURL - 全局根路径
+   * @param {Object} arg.header - 全局header
+   * @param {String} arg.method = [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE] - 全局默认请求方式
+   * @param {String} arg.dataType = [json] - 全局默认的dataType
+   * @param {String} arg.responseType = [text|arraybuffer] - 全局默认的responseType。支付宝小程序不支持
+   * @param {Object} arg.custom - 全局默认的自定义参数
+   * @param {Number} arg.timeout - 全局默认的超时时间,单位 ms。默认60000。H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)、微信小程序(2.10.0)、支付宝小程序
+   * @param {Boolean} arg.sslVerify - 全局默认的是否验证 ssl 证书。默认true.仅App安卓端支持(HBuilderX 2.3.3+)
+   * @param {Boolean} arg.withCredentials - 全局默认的跨域请求时是否携带凭证(cookies)。默认false。仅H5支持(HBuilderX 2.6.15+)
+   * @param {Boolean} arg.firstIpv4 - 全DNS解析时优先使用ipv4。默认false。仅 App-Android 支持 (HBuilderX 2.8.0+)
+   * @param {Function(statusCode):Boolean} arg.validateStatus - 全局默认的自定义验证器。默认statusCode >= 200 && statusCode < 300
+   */
+  constructor(arg = {}) {
+    if (!isPlainObject(arg)) {
+      arg = {}
+      console.warn('设置全局参数必须接收一个Object')
+    }
+    this.config = clone({...defaults, ...arg})
+    this.interceptors = {
+      request: new InterceptorManager(),
+      response: new InterceptorManager()
+    }
+  }
+
+  /**
+   * @Function
+   * @param {Request~setConfigCallback} f - 设置全局默认配置
+   */
+  setConfig(f) {
+    this.config = f(this.config)
+  }
+
+  middleware(config) {
+    config = mergeConfig(this.config, config)
+    let chain = [dispatchRequest, undefined]
+    let promise = Promise.resolve(config)
+
+    this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {
+      chain.unshift(interceptor.fulfilled, interceptor.rejected)
+    })
+
+    this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) {
+      chain.push(interceptor.fulfilled, interceptor.rejected)
+    })
+
+    while (chain.length) {
+      promise = promise.then(chain.shift(), chain.shift())
+    }
+
+    return promise
+  }
+
+  /**
+   * @Function
+   * @param {Object} config - 请求配置项
+   * @prop {String} options.url - 请求路径
+   * @prop {Object} options.data - 请求参数
+   * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
+   * @prop {Object} [options.dataType = config.dataType] - 如果设为 json,会尝试对返回的数据做一次 JSON.parse
+   * @prop {Object} [options.header = config.header] - 请求header
+   * @prop {Object} [options.method = config.method] - 请求方法
+   * @returns {Promise<unknown>}
+   */
+  request(config = {}) {
+    return this.middleware(config)
+  }
+
+  get(url, options = {}) {
+    return this.middleware({
+      url,
+      method: 'GET',
+      ...options
+    })
+  }
+
+  post(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'POST',
+      ...options
+    })
+  }
+
+  // #ifndef MP-ALIPAY || MP-KUAISHOU || MP-JD
+  put(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'PUT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  delete(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'DELETE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  connect(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'CONNECT',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef  H5 || MP-WEIXIN || MP-BAIDU
+  head(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'HEAD',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef APP-PLUS || H5 || MP-WEIXIN || MP-BAIDU
+  options(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'OPTIONS',
+      ...options
+    })
+  }
+
+  // #endif
+
+  // #ifdef H5 || MP-WEIXIN
+  trace(url, data, options = {}) {
+    return this.middleware({
+      url,
+      data,
+      method: 'TRACE',
+      ...options
+    })
+  }
+
+  // #endif
+
+  upload(url, config = {}) {
+    config.url = url
+    config.method = 'UPLOAD'
+    return this.middleware(config)
+  }
+
+  download(url, config = {}) {
+    config.url = url
+    config.method = 'DOWNLOAD'
+    return this.middleware(config)
+  }
+
+  get version () {
+    return '3.1.0'
+  }
+}
+
+
+/**
+ * setConfig回调
+ * @return {Object} - 返回操作后的config
+ * @callback Request~setConfigCallback
+ * @param {Object} config - 全局默认config
+ */

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

@@ -0,0 +1,20 @@
+'use strict'
+
+import isAbsoluteURL from '../helpers/isAbsoluteURL'
+import combineURLs from '../helpers/combineURLs'
+
+/**
+ * Creates a new URL by combining the baseURL with the requestedURL,
+ * only when the requestedURL is not already an absolute URL.
+ * If the requestURL is absolute, this function returns the requestedURL untouched.
+ *
+ * @param {string} baseURL The base URL
+ * @param {string} requestedURL Absolute or relative URL to combine
+ * @returns {string} The combined full path
+ */
+export default function buildFullPath(baseURL, requestedURL) {
+  if (baseURL && !isAbsoluteURL(requestedURL)) {
+    return combineURLs(baseURL, requestedURL)
+  }
+  return requestedURL
+}

+ 33 - 0
uni_modules/uv-ui-tools/libs/luch-request/core/defaults.js

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

+ 6 - 0
uni_modules/uv-ui-tools/libs/luch-request/core/dispatchRequest.js

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

+ 126 - 0
uni_modules/uv-ui-tools/libs/luch-request/core/mergeConfig.js

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

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

@@ -0,0 +1,16 @@
+/**
+ * Resolve or reject a Promise based on response status.
+ *
+ * @param {Function} resolve A function that resolves the promise.
+ * @param {Function} reject A function that rejects the promise.
+ * @param {object} response The response.
+ */
+export default function settle(resolve, reject, response) {
+  const validateStatus = response.config.validateStatus
+  const status = response.statusCode
+  if (status && (!validateStatus || validateStatus(status))) {
+    resolve(response)
+  } else {
+    reject(response)
+  }
+}

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


Some files were not shown because too many files changed in this diff