瀏覽代碼

style:修改统计页面样式

443166679@qq.com 1 年之前
父節點
當前提交
ef03d907ea

+ 50 - 49
common/chart/mixture_chart.vue

@@ -1,6 +1,7 @@
 <template>
 	<view class="charts-box">
-		<qiun-data-charts type="mix" :opts="opts" :canvas2d='isCanvas2d' :canvasId='canvasId' :chartData="chartData" />
+		<qiun-data-charts type="mix" :opts="opts" :canvas2d='isCanvas2d' :ontouch="true" :canvasId='canvasId'
+			:chartData="chartData" />
 	</view>
 </template>
 
@@ -29,7 +30,7 @@
 					dataPointShape: false,
 					dataPointShapeType: "solid",
 					touchMoveLimit: 60,
-					enableScroll: false,
+					enableScroll: true,
 					enableMarkLine: false,
 					legend: {
 						show: false,
@@ -58,7 +59,7 @@
 						marginTop: 20,
 						rotateLabel: false,
 						rotateAngle: 45,
-						itemCount: 5,
+						itemCount: 3,
 						boundaryGap: "center",
 						splitNumber: 5,
 						gridColor: "#CCCCCC",
@@ -190,14 +191,14 @@
 									"value": 90,
 								}, 100, 150, 90]
 							},
-              {
-                name: "柱2",
-                index: 1,
-                type: "column",
-                data: [160, {
-                  "value": 90,
-                }, 100, 150, 90]
-              },
+							{
+								name: "柱2",
+								index: 1,
+								type: "column",
+								data: [160, {
+									"value": 90,
+								}, 100, 150, 90]
+							},
 							{
 								name: "曲线",
 								type: "line",
@@ -219,44 +220,44 @@
 					this.chartData = JSON.parse(JSON.stringify(res));
 				}, 500);
 			},
-      setServerData(data){
-        setTimeout(() => {
-          //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
-          let res = {
-            categories: data.titles,
-            series: [{
-              name: "金额(男)",
-              index: 1,
-              type: "column",
-              data: data.oneMoney
-            },
-              {
-                name: "金额(女)",
-                index: 2,
-                type: "column",
-                data: data.twoMoney
-              },
-              {
-                name:  "数量(男)",
-                type: "line",
-                style: "curve",
-                color: "#FFD023",
-                disableLegend: true,
-                data:  data.oneNum
-              },
-              {
-                name:  "数量(女)",
-                type: "line",
-                style: "curve",
-                color: "#0CAF60",
-                disableLegend: true,
-                data:  data.twoNum
-              }
-            ]
-          };
-          this.chartData = JSON.parse(JSON.stringify(res));
-        }, 50);
-      }
+			setServerData(data) {
+				setTimeout(() => {
+					//模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
+					let res = {
+						categories: data.titles,
+						series: [{
+								name: "金额(男)",
+								index: 1,
+								type: "column",
+								data: data.oneMoney
+							},
+							{
+								name: "金额(女)",
+								index: 2,
+								type: "column",
+								data: data.twoMoney
+							},
+							{
+								name: "数量(男)",
+								type: "line",
+								style: "curve",
+								color: "#FFD023",
+								disableLegend: true,
+								data: data.oneNum
+							},
+							{
+								name: "数量(女)",
+								type: "line",
+								style: "curve",
+								color: "#0CAF60",
+								disableLegend: true,
+								data: data.twoNum
+							}
+						]
+					};
+					this.chartData = JSON.parse(JSON.stringify(res));
+				}, 50);
+			}
 		}
 	};
 </script>

+ 192 - 186
common/chart/peak_chart.vue

@@ -1,194 +1,200 @@
 <template>
-  <view class="charts-box">
-    <qiun-data-charts
-	  :canvas2d='isCanvas2d'
-	  :canvasId='canvasId'
-      type="mount"
-      :opts="opts"
-      :chartData="chartData"
-    />
-  </view>
+	<view class="charts-box">
+		<qiun-data-charts :canvas2d='isCanvas2d' :canvasId='canvasId' type="mount" :ontouch="true" :opts="opts"
+			:chartData="chartData" />
+	</view>
 </template>
 
 <script>
-export default {
-  props:{
-	 canvasId:{
-		 type:String,
-		 default:''
-	 } 
-  },	
-  data() {
-    return {
-      isCanvas2d:process.uniEnv.isCanvas2d,
-      chartData: {},
-      //这里的 opts 是图表类型 type="mount" 的全部配置参数,您可以将此配置复制到 config-ucharts.js 文件中下标为 ['mount'] 的节点中来覆盖全局默认参数。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
-      opts: {
-        timing: "easeIn",
-        duration: 1000,
-        rotate: false,
-        rotateLock: false,
-        color: ["#1890FF","#91CB74","#FAC858","#EE6666","#73C0DE","#3CA272","#FC8452","#9A60B4","#ea7ccc"],
-        padding: [15,15,0,5],
-        fontSize: 15,
-        fontColor: "#000000",
-        dataLabel: true,
-        dataPointShape: true,
-        dataPointShapeType: "solid",
-        touchMoveLimit: 60,
-        enableScroll: false,
-        enableMarkLine: false,
-        legend: {
-          show: false,
-          position: "bottom",
-          float: "center",
-          padding: 5,
-          margin: 5,
-          backgroundColor: "rgba(0,0,0,0)",
-          borderColor: "rgba(0,0,0,0)",
-          borderWidth: 0,
-          fontSize: 13,
-          fontColor: "#666666",
-          lineHeight: 11,
-          hiddenColor: "#CECECE",
-          itemGap: 10
-        },
-        xAxis: {
-          disableGrid: true,
-          disabled: false,
-          axisLine: true,
-          axisLineColor: "#CCCCCC",
-          calibration: false,
-          fontColor: "#717A89",
-          fontSize: 12,
-          lineHeight: 20,
-          marginTop: 12,
-          rotateLabel: true,
-          rotateAngle: 45,
-          itemCount: 5,
-          boundaryGap: "center",
-          splitNumber: 5,
-          gridColor: "#CCCCCC",
-          gridType: "solid",
-          dashLength: 4,
-          gridEval: 1,
-          scrollShow: false,
-          scrollAlign: "left",
-          scrollColor: "#A6A6A6",
-          scrollBackgroundColor: "#EFEBEF",
-          title: "",
-          titleFontSize: 13,
-          titleOffsetY: 0,
-          titleOffsetX: 0,
-          titleFontColor: "#717A89",
-          format: ""
-        },
-        yAxis: {
-          data: [
-            {
-              min: 0
-            }
-          ],
-          disabled: true,
-          disableGrid: false,
-          splitNumber: 3,
-          gridType: "dash",
-          dashLength: 8,
-          gridColor: "#CCCCCC",
-          padding: 10,
-          showTitle: false
-        },
-        extra: {
-          mount: {
-            type: "bar",
-            widthRatio: 0.3,
-            borderWidth: 1,
-            barBorderCircle: false,
-            barBorderRadius: [
-              12,
-              12,
-              0,
-              0
-            ],
-            linearType: "none",
-            linearOpacity: 1,
-            colorStop: 0
-          },
-          tooltip: {
-            showBox: true,
-            showArrow: true,
-            showCategory: false,
-            borderWidth: 0,
-            borderRadius: 5,
-            borderColor: "#000000",
-            borderOpacity: 0.7,
-            bgColor: "#000000",
-            bgOpacity: 0.7,
-            gridType: "dash",
-            dashLength: 4,
-            gridColor: "#cccccc",
-            boxPadding: 3,
-            fontSize: 13,
-            lineHeight: 20,
-            fontColor: "#FFFFFF",
-            legendShow: true,
-            legendShape: "diamond",
-            splitLine: true,
-            horizentalLine: true,
-            xAxisLabel: false,
-            yAxisLabel: false,
-            labelBgColor: "#FFFFFF",
-            labelBgOpacity: 0.7,
-            labelFontColor: "#666666"
-          },
-          markLine: {
-            type: "solid",
-            dashLength: 4,
-            data: []
-          }
-        }
-      }
-    };
-  },
-  onReady() {
-    // this.getServerData();
-  },
-  methods: {
-    getServerData() {
-      //模拟从服务器获取数据时的延时
-      setTimeout(() => {
-        //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
-        let res = {
-            series: [
-              {
-                data: [{"name":"综合业务二部门","value":82},{"name":"综合业务二部门","value":63},{"name":"综合业务二部门","value":86},{"name":"综合业务二部门","value":65},{"name":"综合业务二部门","value":79}]
-              }
-            ]
-          };
-        this.chartData = JSON.parse(JSON.stringify(res));
-      }, 500);
-    },
-    setServerData(data){
-      setTimeout(() => {
-        //模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
-        let res = {
-          series: [
-            {
-              data:data
-            }
-          ]
-        };
-        this.chartData = JSON.parse(JSON.stringify(res));
-      }, 100);
-    }
-  }
-};
+	export default {
+		props: {
+			canvasId: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				isCanvas2d: process.uniEnv.isCanvas2d,
+				chartData: {},
+				//这里的 opts 是图表类型 type="mount" 的全部配置参数,您可以将此配置复制到 config-ucharts.js 文件中下标为 ['mount'] 的节点中来覆盖全局默认参数。实际应用过程中 opts 只需传入与全局默认参数中不一致的【某一个属性】即可实现同类型的图表显示不同的样式,达到页面简洁的需求。
+				opts: {
+					timing: "easeIn",
+					duration: 1000,
+					rotate: false,
+					rotateLock: false,
+					color: ["#1890FF", "#91CB74", "#FAC858", "#EE6666", "#73C0DE", "#3CA272", "#FC8452", "#9A60B4",
+						"#ea7ccc"
+					],
+					padding: [15, 15, 0, 5],
+					fontSize: 15,
+					fontColor: "#000000",
+					dataLabel: true,
+					dataPointShape: true,
+					dataPointShapeType: "solid",
+					touchMoveLimit: 60,
+					enableScroll: true,
+					enableMarkLine: false,
+					legend: {
+						show: false,
+						position: "bottom",
+						float: "center",
+						padding: 5,
+						margin: 5,
+						backgroundColor: "rgba(0,0,0,0)",
+						borderColor: "rgba(0,0,0,0)",
+						borderWidth: 0,
+						fontSize: 13,
+						fontColor: "#666666",
+						lineHeight: 11,
+						hiddenColor: "#CECECE",
+						itemGap: 10
+					},
+					xAxis: {
+						disableGrid: true,
+						disabled: false,
+						axisLine: true,
+						axisLineColor: "#CCCCCC",
+						calibration: false,
+						fontColor: "#717A89",
+						fontSize: 12,
+						lineHeight: 20,
+						marginTop: 12,
+						rotateLabel: true,
+						rotateAngle: 45,
+						itemCount: 5,
+						boundaryGap: "center",
+						splitNumber: 5,
+						gridColor: "#CCCCCC",
+						gridType: "solid",
+						dashLength: 4,
+						gridEval: 1,
+						scrollShow: false,
+						scrollAlign: "left",
+						scrollColor: "#A6A6A6",
+						scrollBackgroundColor: "#EFEBEF",
+						title: "",
+						titleFontSize: 13,
+						titleOffsetY: 0,
+						titleOffsetX: 0,
+						titleFontColor: "#717A89",
+						format: ""
+					},
+					yAxis: {
+						data: [{
+							min: 0
+						}],
+						disabled: true,
+						disableGrid: false,
+						splitNumber: 3,
+						gridType: "dash",
+						dashLength: 8,
+						gridColor: "#CCCCCC",
+						padding: 10,
+						showTitle: false
+					},
+					extra: {
+						mount: {
+							type: "bar",
+							widthRatio: 0.3,
+							borderWidth: 1,
+							barBorderCircle: false,
+							barBorderRadius: [
+								12,
+								12,
+								0,
+								0
+							],
+							linearType: "none",
+							linearOpacity: 1,
+							colorStop: 0
+						},
+						tooltip: {
+							showBox: true,
+							showArrow: true,
+							showCategory: false,
+							borderWidth: 0,
+							borderRadius: 5,
+							borderColor: "#000000",
+							borderOpacity: 0.7,
+							bgColor: "#000000",
+							bgOpacity: 0.7,
+							gridType: "dash",
+							dashLength: 4,
+							gridColor: "#cccccc",
+							boxPadding: 3,
+							fontSize: 13,
+							lineHeight: 20,
+							fontColor: "#FFFFFF",
+							legendShow: true,
+							legendShape: "diamond",
+							splitLine: true,
+							horizentalLine: true,
+							xAxisLabel: false,
+							yAxisLabel: false,
+							labelBgColor: "#FFFFFF",
+							labelBgOpacity: 0.7,
+							labelFontColor: "#666666"
+						},
+						markLine: {
+							type: "solid",
+							dashLength: 4,
+							data: []
+						}
+					}
+				}
+			};
+		},
+		onReady() {
+			// this.getServerData();
+		},
+		methods: {
+			getServerData() {
+				//模拟从服务器获取数据时的延时
+				setTimeout(() => {
+					//模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
+					let res = {
+						series: [{
+							data: [{
+								"name": "综合业务二部门",
+								"value": 82
+							}, {
+								"name": "综合业务二部门",
+								"value": 63
+							}, {
+								"name": "综合业务二部门",
+								"value": 86
+							}, {
+								"name": "综合业务二部门",
+								"value": 65
+							}, {
+								"name": "综合业务二部门",
+								"value": 79
+							}]
+						}]
+					};
+					this.chartData = JSON.parse(JSON.stringify(res));
+				}, 500);
+			},
+			setServerData(data) {
+				setTimeout(() => {
+					//模拟服务器返回数据,如果数据格式和标准格式不同,需自行按下面的格式拼接
+					let res = {
+						series: [{
+							data: data
+						}]
+					};
+					this.chartData = JSON.parse(JSON.stringify(res));
+				}, 100);
+			}
+		}
+	};
 </script>
 
 <style scoped>
-  /* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
-  .charts-box {
-    width: 100%;
-    height: 300px;
-  }
+	/* 请根据实际需求修改父元素尺寸,组件自动识别宽高 */
+	.charts-box {
+		width: 100%;
+		height: 300px;
+	}
 </style>

+ 28 - 25
common/task/task-item.vue

@@ -28,7 +28,8 @@
 							</image>
 							<button class="button-background en_button sys-weight-500 text-color-fff size-28 r-100"
 								style="width: 200rpx;height: 70rpx;line-height: 70rpx;" type="default"
-								hover-class="is-hover" v-else-if="type === 2" @click.stop="takeTask(index)">领取任务</button>
+								hover-class="is-hover" v-else-if="type === 2"
+								@click.stop="takeTask(index)">领取任务</button>
 							<button class="button-background en_button sys-weight-500 text-color-fff size-28 r-100"
 								style="width: 200rpx;height: 70rpx;line-height: 70rpx;" type="default"
 								hover-class="is-hover" v-else-if="type === 4">去处理</button>
@@ -46,19 +47,21 @@
 			</view>
 			<view class="placeholder sys-list-background-color" v-if="is_bottom"></view>
 		</view>
-    <en-blank v-if="taskList.length<=0"></en-blank>
+		<en-blank v-if="taskList.length<=0"></en-blank>
 	</view>
 </template>
 
 <script>
 	import EnButton from "@/components/en-utils/en-button/en-button.vue";
-  import {takeTask} from "@/api/task";
-  import tools from "@/service/tools";
-  import EnBlank from "@/components/en-utils/en-blank/en-blank.vue";
+	import {
+		takeTask
+	} from "@/api/task";
+	import tools from "@/service/tools";
+	import EnBlank from "@/components/en-utils/en-blank/en-blank.vue";
 
 	export default {
 		components: {
-      EnBlank,
+			EnBlank,
 			EnButton
 		},
 		props: {
@@ -97,28 +100,28 @@
 				leftImg: ['task-house', 'task-business', 'task-repayment'],
 				iconList: ['task-audit', 'task-do', 'task-stay'],
 				lineColor: ['#DE5847', '#EF8F27', '#0FB160'],
-        isAjax:false
+				isAjax: false
 			}
 		},
 		methods: {
-      takeTask(index) {
-        if (this.isAjax) {
-          return;
-        }
-        this.isAjax = true;
-        takeTask({
-          'id': this.taskList[index].id
-        }).then((res) => {
-          this.isAjax = false
-          if (res.code === 1) {
-            tools.success(res.msg)
-            // this.taskList.splice(index, 1)
-            this.$emit('takeTask',index)
-          } else {
-            tools.error(res.msg)
-          }
-        })
-      },
+			takeTask(index) {
+				if (this.isAjax) {
+					return;
+				}
+				this.isAjax = true;
+				takeTask({
+					'id': this.taskList[index].id
+				}).then((res) => {
+					this.isAjax = false
+					if (res.code === 1) {
+						tools.success(res.msg)
+						// this.taskList.splice(index, 1)
+						this.$emit('takeTask', index)
+					} else {
+						tools.error(res.msg)
+					}
+				})
+			},
 			getIconStatus() {
 				return `/static/img/task/${this.iconList[this.iconStatus]}.png`
 			},

+ 2 - 2
components/en-utils/en-nav/en-nav.vue

@@ -43,8 +43,8 @@
 					bg_path: 'https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/index/index-bg.png?imageMogr2/quality/20',
 					nav_path: '/static/img/index/top-nav.png '
 				}, {
-					bg_path: 'https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/task/task-nav-bg.png',
-					nav_path: '/static/img/enNav/tab.png'
+					bg_path: '',
+					nav_path: ''
 				}, {
 					bg_path: '',
 					nav_path: ''

+ 94 - 47
page_task/gain_task/gain_task.vue

@@ -1,10 +1,14 @@
 <template>
-	<view class="total-page page-box">
-		<Nav :title="'领取任务'" :genre="1" :fixedHeight="110"></Nav>
-		<view class="task-tabs m-t30">
-			<TaskImgTab @setProductId="setProductId"></TaskImgTab>
+	<view class="total-page page-box gain-task">
+		<Nav :title="'领取任务'" :genre="1"></Nav>
+		<view class="m-lr20 r-20">
+			<!-- <TaskImgTab @setProductId="setProductId"></TaskImgTab> -->
+			<k-tabs-swiper class="r-20" v-model="current" :tabs="tabs" :field="'name'" bgColor="#fff" color="#444444"
+				activeColor="#10B261" fontSize="28rpx" :bold="true" :scroll="true" height="100rpx" lineHeight="10rpx"
+				@change="changeTab" paddingItem="0 50rpx">
+				<!-- <image class="wh-30" src="/static/img/task/vector.png" mode="scaleToFill" /> -->
+			</k-tabs-swiper>
 		</view>
-		<!-- <EnButton is_both></EnButton> -->
 		<EnScroll ref="scroll" :navHeight="110" class="main" @onRefresh="onRefresh" @onScrollBottom="onScrollBottom">
 			<TaskItem :type="2" :task-list="taskList" is_bottom @takeTask="setTakeTask"></TaskItem>
 		</EnScroll>
@@ -14,8 +18,11 @@
 <script>
 	import TaskItem from "@/common/task/task-item.vue"
 	import TaskImgTab from "@/page_task/module/task_ima_tab.vue"
-  import {getTaskReceiving, takeTask} from "@/api/task";
-  import tools from "@/service/tools";
+	import {
+		getTaskReceiving,
+		takeTask
+	} from "@/api/task";
+	import tools from "@/service/tools";
 
 	export default {
 		components: {
@@ -24,45 +31,77 @@
 		},
 		data() {
 			return {
-        taskList: [],
-        page: 1,
-        totalNum: 9999,
-        isAjax: false,
-        productId:0
+				current: 0,
+				tabs: [{
+					name: '新闻',
+					icon: '/static/img/statistics/task-four.png'
+				}, {
+					name: '新闻新闻',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻新',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻新闻',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻新闻',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻新闻',
+					icon: '/static/img/logo.png'
+				}, {
+					name: '新闻',
+					icon: '/static/img/logo.png'
+				}, ],
+				taskList: [],
+				page: 1,
+				totalNum: 9999,
+				isAjax: false,
+				productId: 0
 			}
 		},
-    mounted() {
-      this.getTaskReceiving()
-    },
-    methods: {
-      setProductId(productId){
-        console.log('productId:'+productId)
-        this.productId=productId
-        this.startList()
-      },
+		mounted() {
+			this.getTaskReceiving()
+		},
+		methods: {
+			changeTab(index) {
+				this.current = index
+			},
+			setProductId(productId) {
+				console.log('productId:' + productId)
+				this.productId = productId
+				this.startList()
+			},
 			// 下拉刷新
-      startList() {
-        this.taskList = [];
-        this.page = 1
-        this.totalNum = 99999
-        this.getTaskReceiving()
-      },
-      async getTaskReceiving() {
-        if (this.totalNum <= this.taskList.length) {
-          return;
-        }
-        const res = await getTaskReceiving({'page':this.page,'productId':this.productId})
-        if (res.code === 1) {
-          this.totalNum=res.data.totalNum
-          this.taskList.push(...res.data.items)
-          ++this.page
-        }
-      },
-      setTakeTask(index){
-        console.log('index:'+index)
-        this.taskList.splice(index, 1)
-        uni.$emit('updateMemberInfo')
-      },
+			startList() {
+				this.taskList = [];
+				this.page = 1
+				this.totalNum = 99999
+				this.getTaskReceiving()
+			},
+			async getTaskReceiving() {
+				if (this.totalNum <= this.taskList.length) {
+					return;
+				}
+				const res = await getTaskReceiving({
+					'page': this.page,
+					'productId': this.productId
+				})
+				if (res.code === 1) {
+					this.totalNum = res.data.totalNum
+					this.taskList.push(...res.data.items)
+						++this.page
+				}
+			},
+			setTakeTask(index) {
+				console.log('index:' + index)
+				this.taskList.splice(index, 1)
+				uni.$emit('updateMemberInfo')
+			},
 
 			onRefresh() {
 				uni.showLoading({
@@ -74,7 +113,7 @@
 						icon: 'none'
 					})
 					this.$refs.scroll.onEndPulling()
-          this.startList()
+					this.startList()
 				}, 1000)
 				console.log("下拉刷新");
 			},
@@ -83,7 +122,7 @@
 				uni.showLoading({
 					title: '数据加载中'
 				})
-        this.getTaskReceiving()
+				this.getTaskReceiving()
 				setTimeout(() => {
 					uni.showToast({
 						title: '加载完成',
@@ -96,6 +135,14 @@
 	}
 </script>
 
-<style>
-
+<style lang="scss" scoped>
+	.gain-task {
+		display: flex;
+		flex-direction: column;
+		min-height: 100%;
+		/* 高度占满整个屏幕 */
+		background-image: url('https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/task/task-nav-bg.png');
+		background-repeat: no-repeat;
+		background-size: 100% auto;
+	}
 </style>

+ 30 - 31
page_task/module/task_ima_tab.vue

@@ -2,16 +2,14 @@
 	<view class="task-tab">
 		<scroll-view class="scroll-Y row" scroll-x="true">
 			<view class="z-tabs-scroll-view row-justify-sb center" style="position: relative;">
-				<view class="column-c tab-item p-lr30 p-t30 p-b20" v-for="(item,index) in navList" :key="index"
+				<view class="column-c p-lr30 p-t30 p-b20" v-for="(item,index) in navList" :key="index"
 					@click="setType(index)">
 					<image class="wh-60 r-circle" :class="index===current?'double-border':''" :src="item.product_icon"
 						mode="aspectFill">
 					</image>
-					<view class="m-t16 sys-size-24 text-center sys-weight-600"
-						:class="{'default-text':index===current}">
+					<view class="m-t16 sys-size-24 sys-weight-600" :class="{'default-text':index===current}">
 						{{item.briefness_name}}
 					</view>
-					<!-- <view class="half-circle m-t20" :class="{'half-circle1':current==1}" v-if="current==index"></view> -->
 				</view>
 				<view class="half-circle m-t20"></view>
 			</view>
@@ -20,36 +18,36 @@
 </template>
 
 <script>
-	import {getTaskType} from "@/api/task";
+	import {
+		getTaskType
+	} from "@/api/task";
 
-  export default {
+	export default {
 		data() {
 			return {
 				current: 0,
-        navList: [
-          {
-            id:0,
-            briefness_name: '全部',
-            product_icon: '/static/img/task/task-all.png'
-          }
-        ]
-      }
-    },
-    mounted() {
-      this.getTaskType()
-    },
-    methods: {
-      getTaskType(){
-        getTaskType().then(res=>{
-          if(res.code===1){
-            this.navList.push(...res.data)
+				navList: [{
+					id: 0,
+					briefness_name: '全部',
+					product_icon: '/static/img/task/task-all.png'
+				}]
+			}
+		},
+		mounted() {
+			this.getTaskType()
+		},
+		methods: {
+			getTaskType() {
+				getTaskType().then(res => {
+					if (res.code === 1) {
+						this.navList.push(...res.data)
 
-          }
-        })
-      },
-      setType(current) {
-        // this.$nextTick(() => {
-        // 	uni.createSelectorQuery().in(this).select(".z-tabs-scroll-view").fields({
+					}
+				})
+			},
+			setType(current) {
+				// this.$nextTick(() => {
+				// 	uni.createSelectorQuery().in(this).select(".z-tabs-scroll-view").fields({
 				// 		scrollOffset: true
 				// 	}, data => {
 				// 		if (data) {
@@ -60,7 +58,7 @@
 				// })
 				if (current !== this.current) {
 					this.current = current
-          this.$emit('setProductId',this.navList[current].id)
+					this.$emit('setProductId', this.navList[current].id)
 				}
 			},
 		}
@@ -72,6 +70,7 @@
 		margin: 0 20rpx;
 		border-radius: 30rpx;
 		background: #fff;
+		width: calc(100% - 40rpx);
 	}
 
 	.default-text {
@@ -94,7 +93,7 @@
 	}
 
 	.tab-item {
-		width: 25%;
+		// width: 25%;
 	}
 
 	.double-border {

+ 58 - 53
pages/statistics/components/performance_stat.vue

@@ -1,71 +1,76 @@
 <template>
 	<view class="">
+		<StatSingleData></StatSingleData>
 		<StatLoanChart ref="workChartObj" :leftText="'任务汇总占比'"></StatLoanChart>
 		<StatRanking ref="workListObj" :is_type="3" :leftText="'放款汇总明细'"></StatRanking>
 	</view>
 </template>
 
 <script>
-import StatLoanChart from "../module/stat_loan_chart.vue"
-import StatRanking from "../module/stat_ranking.vue"
-import md5 from "js-md5";
-import {getUserPerformance} from "@/api/statistics";
+	import StatLoanChart from "../module/stat_loan_chart.vue"
+	import StatRanking from "../module/stat_ranking.vue"
+	import StatSingleData from "../module/stat_single_data.vue"
+	import md5 from "js-md5";
+	import {
+		getUserPerformance
+	} from "@/api/statistics";
 
 	export default {
-    props:{
-      'dateTypeObj':{
-        default:()=>{
-          return {
-            dateType:4,
-            selectDate:'2023-02-25',
-            money_type:1,
-            censusUserType:0,
-            product_id:5,
-          }
-        }
-      }
-    },
+		props: {
+			'dateTypeObj': {
+				default: () => {
+					return {
+						dateType: 4,
+						selectDate: '2023-02-25',
+						money_type: 1,
+						censusUserType: 0,
+						product_id: 5,
+					}
+				}
+			}
+		},
 		components: {
 			StatLoanChart,
 			StatRanking,
+			StatSingleData
+		},
+		watch: {
+			'dateTypeObj': function() {
+				this.initData()
+			}
+		},
+		mounted() {
+			this.initData()
+		},
+		data() {
+			return {
+				workList: []
+			}
 		},
-    watch: {
-      'dateTypeObj': function() {
-        this.initData()
-      }
-    },
-    mounted() {
-      this.initData()
-    },
-    data() {
-      return {
-        workList:[]
-      }
-    },
-    methods: {
-      setSendMd5() {
-        let str = JSON.stringify(this.dateTypeObj)
-        return md5(str)
-      },
-      initData() {
-        if (this.dateTypeObj.censusUserType > 0) {
-          let sendMd5 = this.setSendMd5()
-          if (sendMd5 !== this.sendMd5) {
-            this.sendMd5 = sendMd5
-            this.getUserPerformance()
+		methods: {
+			setSendMd5() {
+				let str = JSON.stringify(this.dateTypeObj)
+				return md5(str)
+			},
+			initData() {
+				if (this.dateTypeObj.censusUserType > 0) {
+					let sendMd5 = this.setSendMd5()
+					if (sendMd5 !== this.sendMd5) {
+						this.sendMd5 = sendMd5
+						this.getUserPerformance()
 
-          }
-        }
-      },
-      getUserPerformance() {
-        getUserPerformance(this.dateTypeObj).then((res)=>{
-          if(res.code===1){
-            this.$refs.workChartObj.setPeakChartData(res.data.items)
-            this.$refs.workListObj.setDataList(res.data.items)
-          }
-        })
-      },
-    }
+					}
+				}
+			},
+			getUserPerformance() {
+				getUserPerformance(this.dateTypeObj).then((res) => {
+					if (res.code === 1) {
+						this.$refs.workChartObj.setPeakChartData(res.data.items)
+						this.$refs.workListObj.setDataList(res.data.items)
+					}
+				})
+			},
+		}
 	}
 </script>
 

+ 53 - 48
pages/statistics/components/task_stat.vue

@@ -1,5 +1,6 @@
 <template>
 	<view class="">
+		<StatSingleData :genre="1"></StatSingleData>
 		<StatLoanChart ref="workChartObj" :leftText="'任务汇总占比'"></StatLoanChart>
 		<StatRanking ref="workListObj" :is_type="3" :leftText="'任务明细'"></StatRanking>
 	</view>
@@ -8,64 +9,68 @@
 <script>
 	import StatLoanChart from "../module/stat_loan_chart.vue"
 	import StatRanking from "../module/stat_ranking.vue"
-  import md5 from "js-md5";
-  import {getUserWorkload} from "@/api/statistics";
+	import StatSingleData from "../module/stat_single_data.vue"
+	import md5 from "js-md5";
+	import {
+		getUserWorkload
+	} from "@/api/statistics";
 
 	export default {
-    props:{
-      'dateTypeObj':{
-        default:()=>{
-          return {
-            dateType:4,
-            selectDate:'2023-02-25',
-            money_type:1,
-            censusUserType:0,
-            product_id:5,
-          }
-        }
-      }
-    },
+		props: {
+			'dateTypeObj': {
+				default: () => {
+					return {
+						dateType: 4,
+						selectDate: '2023-02-25',
+						money_type: 1,
+						censusUserType: 0,
+						product_id: 5,
+					}
+				}
+			}
+		},
 		components: {
 			StatLoanChart,
-			StatRanking
+			StatRanking,
+			StatSingleData
+		},
+		watch: {
+			'dateTypeObj': function() {
+				this.initData()
+			}
+		},
+		mounted() {
+			this.initData()
 		},
-    watch: {
-      'dateTypeObj': function() {
-        this.initData()
-      }
-    },
-    mounted() {
-      this.initData()
-    },
 		data() {
 			return {
-        workList:[]
+				workList: []
 			}
 		},
-    methods: {
-      setSendMd5() {
-        let str = JSON.stringify(this.dateTypeObj)
-        return md5(str)
-      },
-      initData() {
-        if (this.dateTypeObj.censusUserType > 0) {
-          let sendMd5 = this.setSendMd5()
-          if (sendMd5 !== this.sendMd5) {
-            this.sendMd5 = sendMd5
-            this.getUserWorkload()
+		methods: {
+			setSendMd5() {
+				let str = JSON.stringify(this.dateTypeObj)
+				return md5(str)
+			},
+			initData() {
+				if (this.dateTypeObj.censusUserType > 0) {
+					let sendMd5 = this.setSendMd5()
+					if (sendMd5 !== this.sendMd5) {
+						this.sendMd5 = sendMd5
+						this.getUserWorkload()
 
-          }
-        }
-      },
-      getUserWorkload() {
-        getUserWorkload(this.dateTypeObj).then((res)=>{
-          if(res.code===1){
-              this.$refs.workChartObj.setPeakChartData(res.data.items)
-              this.$refs.workListObj.setDataList(res.data.items)
-          }
-        })
-      },
-    }
+					}
+				}
+			},
+			getUserWorkload() {
+				getUserWorkload(this.dateTypeObj).then((res) => {
+					if (res.code === 1) {
+						this.$refs.workChartObj.setPeakChartData(res.data.items)
+						this.$refs.workListObj.setDataList(res.data.items)
+					}
+				})
+			},
+		}
 	}
 </script>
 

+ 26 - 35
pages/statistics/module/head_filter.vue

@@ -1,17 +1,19 @@
 <template>
 	<view>
 		<view class="head_filter row-justify-sb center p-lr30">
-			<view class="filter_item r-100  filter-bg" @click="startAnimation(1)">
+			<view class="filter_item r-100 filter-bg row-justify-c center" @click="startAnimation(1)">
 				<text class="text-color-fff size-28 sys-weight-600 p-r10">{{newUserTypeName}}</text>
-				<uni-icons :animation="animationData" class="dropdown-icon" :type="type" size="16"
-					color="#fff"></uni-icons>
+				<image class="white-arrow" :class="arrowItem == 1 && is_flag?'open':''"
+					src="/static/img/statistics/white-arrow.png" mode="aspectFill"></image>
+				<!-- 		<uni-icons :animation="animationData" class="dropdown-icon" :type="type" size="16"
+					color="#fff"></uni-icons> -->
 			</view>
-			<view class="filter_item last_item r-100 filter-bg" @click="startAnimation(2)">
+			<view class="filter_item last_item r-100 filter-bg row-justify-c center" @click="startAnimation(2)">
 				<text class="text-color-fff size-28 sys-weight-600 p-r10">{{dateName}}</text>
-				<uni-icons :animation="animationData" class="dropdown-icon" type="down" size="16"
-					color="#fff"></uni-icons>
+				<image class="white-arrow" :class="arrowItem == 2 && is_flag?'open':''"
+					src="/static/img/statistics/white-arrow.png" mode="aspectFill"></image>
 			</view>
-			<view class="last_item">
+			<view>
 				<uni-datetime-picker v-model="daterange" type="daterange" @change="onSelectTime"
 					@touchmove.stop.prevent="moveHandle">
 					<view class="last_item r-100 filter-bg row-justify-c center">
@@ -56,6 +58,8 @@
 				type: 'down',
 				animationData: {},
 				isRote: false,
+				is_flag: false,
+				arrowItem: 0,
 				animation: null,
 				newUserTypeName: '',
 				dateName: '年数据',
@@ -171,35 +175,14 @@
 			},
 			startAnimation(type) {
 				this.selectType = type
-				//旋转角度 
+				this.arrowItem = type
+				this.is_flag = true
 				this.$refs.popup.open('bottom')
-				let rota = 180;
-				//判断是否展开
-				if (this.isRote) {
-					rota = 0;
-					//标记未展开
-					this.isRote = false;
-					//隐藏需要隐藏的内容
-					this.showAddPople = false;
-				} else {
-					this.isRote = true;
-					//显示隐藏的内容
-					this.showAddPople = true;
-				}
-				//创建动画
-				this.animation = uni.createAnimation();
-				//设置旋转角度 
-				this.animation.rotate(rota).step()
-				//导出动画
-				this.animationData = this.animation.export()
 			},
 			onChangePopup(e) {
 				console.log(e.show === false);
 				if (e.show === false) {
-					let rota = 180;
-					this.animation = uni.createAnimation();
-					this.animation.rotate(rota).step()
-					this.animationData = this.animation.export()
+					this.is_flag = !this.is_flag
 				}
 			},
 			onSelectTime(e) {
@@ -222,16 +205,20 @@
 		text-align: center;
 
 		.filter_item {
-			line-height: 36px;
+			height: 65rpx;
+			line-height: 65rpx;
 			border: 2rpx solid rgba(255, 255, 255, 0.7);
 		}
 
 		.filter_item:first-child {
 			width: 290rpx;
+			height: 65rpx;
 		}
 
 		.last_item {
 			width: 180rpx;
+			height: 65rpx;
+			border: 2rpx solid rgba(255, 255, 255, 0.7);
 		}
 	}
 
@@ -239,9 +226,13 @@
 		background: rgba(0, 88, 14, 0.34);
 	}
 
-	.dropdown-icon {
-		display: inline-block;
+	.white-arrow {
+		width: 24rpx;
+		height: 12rpx;
 		transition: transform 0.3s ease-in-out;
-		/* 添加平滑的旋转动画 */
+	}
+
+	.open {
+		transform: rotateZ(180deg);
 	}
 </style>

+ 21 - 11
pages/statistics/module/stat_industry.vue

@@ -1,19 +1,13 @@
 <template>
 	<view class="page-box-bg-fff m-t20 r-30 p-30">
-		<StatisticsTitle :is_right="false" :genre="0" :leftText="'行业占比(金额排行)'" :rightText="'同比环比'" >
+		<StatisticsTitle :is_right="false" :genre="0" :leftText="'行业占比(金额排行)'" :rightText="'同比环比'">
 		</StatisticsTitle>
-		<view class="page-box-bg-fff row-justify-sb center r-30 p-r60">
+		<view class="page-box-bg-fff row-justify-sb center r-30">
 			<view class="chart_item column-c m-lr20">
 				<CircleChart :bgColor="'#2B7DFA'"></CircleChart>
 			</view>
-			<view class="">
-				<view class="row-c p-tb10" v-for="(item,index) in list" :key="index">
-					<view class="wh-14 m-r10" :style="{background:item.color}"></view>
-					<text class="size-24 text-color-576">{{item.name}}</text>
-				</view>
-			</view>
-			<view class="">
-				<view class="row-c p-tb10" v-for="(item,index) in list" :key="index">
+			<view class="row industry-box m-l30">
+				<view class="row-c p-tb10 industry-item" v-for="(item,index) in list" :key="index">
 					<view class="wh-14 m-r10" :style="{background:item.color}"></view>
 					<text class="size-24 text-color-576">{{item.name}}</text>
 				</view>
@@ -51,10 +45,19 @@
 					color: '#2B7DFA'
 				}, {
 					name: '信息传媒',
-					color: '#00BF8A'
+					color: '#2B7DFA'
 				}, {
 					name: '互联网',
 					color: '#ED9A2C'
+				}, {
+					name: '电力',
+					color: '#ED9A2C'
+				}, {
+					name: '信息传媒',
+					color: '#00BF8A'
+				}, {
+					name: '互联网',
+					color: '#00BF8A'
 				}, ]
 			};
 		},
@@ -67,4 +70,11 @@
 </script>
 
 <style lang="scss" scoped>
+	.industry-box {
+		flex-wrap: wrap;
+
+		.industry-item {
+			width: 180rpx;
+		}
+	}
 </style>

+ 10 - 11
pages/statistics/module/stat_single_data.vue

@@ -37,17 +37,16 @@
 				type: Number,
 				default: 0
 			},
-      totalMoney:{
-        default: 0
-      },
-      totalNum:{
-        default: 0
-      },
-      text:{
-        default:'放款'
-      }
-
-    },
+			totalMoney: {
+				default: 0
+			},
+			totalNum: {
+				default: 0
+			},
+			text: {
+				default: '放款'
+			}
+		},
 		data() {
 			return {
 				current: 0,

+ 72 - 58
pages/statistics/module/stat_situation.vue

@@ -8,10 +8,10 @@
 					custom-item-style="border-radius: 30rpx;" :current="current" @change="onChange"></uv-subsection>
 			</view>
 		</view>
-		<view class="">
+		<view class="" v-if="current == 0">
 			<view class="sys-from-background-color m-b16 r-20 p-20 finance_item sys-weight-400"
 				v-for="(item,index) in businessList" :key="index">
-				<view class="" >
+				<view class="">
 					<view class="row-justify-sb center">
 						<view class="row-c">
 							<text class="size-26 text-color-666">客户:</text>
@@ -32,7 +32,16 @@
 					</view>
 				</view>
 			</view>
-      <en-blank v-if="businessList.length<=0"></en-blank>
+			<en-blank v-if="businessList.length<=0"></en-blank>
+		</view>
+		<view class="finance_item sys-from-background-color m-b16 r-20 p-30 row-justify-sb center"
+			v-for="(item,index) in 5" :key="index" v-else>
+			<text class="size-28 text-color-12">郭野</text>
+			<text class="size-28 text-color-E21 sys-weight-600 m-r10">200万</text>
+			<view class="size-24">
+				<text class="text-color-000">2024/12/23</text>
+				<text class="text-color-666">用款</text>
+			</view>
 		</view>
 	</view>
 </template>
@@ -40,15 +49,20 @@
 <script>
 	import PeakChart from "@/common/chart/peak_chart.vue";
 	import StatisticsTitle from "./statistics_title.vue";
-  import {getBusinessList, getUseList} from "@/api/statistics";
-  import EnBlank from "@/components/en-utils/en-blank/en-blank.vue";
+	import StatRanking from "./stat_ranking.vue";
+	import {
+		getBusinessList,
+		getUseList
+	} from "@/api/statistics";
+	import EnBlank from "@/components/en-utils/en-blank/en-blank.vue";
 
 	export default {
 		name: 'stat_situation',
 		components: {
-      EnBlank,
+			EnBlank,
 			PeakChart,
-			StatisticsTitle
+			StatisticsTitle,
+			StatRanking
 		},
 		props: {
 			type: {
@@ -63,64 +77,64 @@
 				type: String,
 				default: '情况说明'
 			},
-      'dateTypeObj':{
-        default:()=>{
-          return {
-            dateType:4,
-            selectDate:'2023-02-25',
-            money_type:1,
-            censusUserType:0,
-            product_id:5,
-          }
-        }
-      },
+			'dateTypeObj': {
+				default: () => {
+					return {
+						dateType: 4,
+						selectDate: '2023-02-25',
+						money_type: 1,
+						censusUserType: 0,
+						product_id: 5,
+					}
+				}
+			},
 		},
 		data() {
 			return {
 				list: ['到访情况', '预计出款'],
-        current:0,
-        useNum:0,
-        usePage:1,
-        useList:[],
-        businessNum:0,
-        businessPage:1,
-        businessList:[],
+				current: 0,
+				useNum: 0,
+				usePage: 1,
+				useList: [],
+				businessNum: 0,
+				businessPage: 1,
+				businessList: [],
 			};
 		},
-    methods: {
-      onChange(e){
-        this.current=e
-        this.startList()
-      },
-      startList(){
-        if(this.dateTypeObj.censusUserType>0){
-          if(this.current===0){
-            this.getBusinessList()
-          }else {
-            this.getUseList()
-          }
-        }
-      },
-      // 到访记录
-      getBusinessList(){
-        this.dateTypeObj.page=1
-        getBusinessList(this.dateTypeObj).then((res)=>{
-          if(res.code === 1){
-            this.businessNum = res.data.totalNum
-            this.businessList = res.data.items
-          }
-        })
-      },
-      // 预计出款
-      getUseList(){
-        this.dateTypeObj.page=1
-        getUseList(this.dateTypeObj).then((res)=>{
-          this.useNum = res.data.totalNum
-          this.useNum = res.data.items
-        })
-      },
+		methods: {
+			onChange(e) {
+				this.current = e
+				this.startList()
+			},
+			startList() {
+				if (this.dateTypeObj.censusUserType > 0) {
+					if (this.current === 0) {
+						this.getBusinessList()
+					} else {
+						this.getUseList()
+					}
+				}
+			},
+			// 到访记录
+			getBusinessList() {
+				this.dateTypeObj.page = 1
+				getBusinessList(this.dateTypeObj).then((res) => {
+					if (res.code === 1) {
+						this.businessNum = res.data.totalNum
+						this.businessList = res.data.items
+					}
+				})
+			},
+			// 预计出款
+			getUseList() {
+				this.dateTypeObj.page = 1
+				getUseList(this.dateTypeObj).then((res) => {
+					this.useNum = res.data.totalNum
+					this.useNum = res.data.items
+				})
+			},
 
-    },
+		},
 	}
 </script>
 

+ 19 - 18
pages/statistics/statistics.vue

@@ -7,9 +7,10 @@
 				<HeadFilter v-model="dateTypeObj" @onTopSelect="onTopSelect" :user-status-list="userStatusList"
 					@setTimeDate="setTimeDate"></HeadFilter>
 				<view class="m-lr30 m-t30 bor-255 r-100" v-if="dateTypeObj.censusUserType === 7">
-					<uv-subsection :list="list" :bgColor="'rgba(255,255,255,0.1)'" :activeColor="'#0FB160'" key-name="product_name"
-						:inactiveColor="'#004615'" :fontSize="14" custom-style="height: 70rpx;border-radius: 30rpx;"
-						custom-item-style="border-radius: 30rpx;" :current="current" @change="onChange"></uv-subsection>
+					<uv-subsection :list="list" :bgColor="'rgba(255,255,255,0.1)'" :activeColor="'#0FB160'"
+						key-name="product_name" :inactiveColor="'#004615'" :fontSize="14"
+						custom-style="height: 70rpx;border-radius: 30rpx;" custom-item-style="border-radius: 30rpx;"
+						:current="current" @change="onChange"></uv-subsection>
 				</view>
 			</view>
 		</Nav>
@@ -68,10 +69,10 @@
 	// 业绩统计
 	import PerformanceStat from "./components/performance_stat.vue"
 
-  import {
-    getConsumeType,
-    getUserType
-  } from "@/api/statistics";
+	import {
+		getConsumeType,
+		getUserType
+	} from "@/api/statistics";
 
 	export default {
 		components: {
@@ -134,17 +135,17 @@
 			// },
 		},
 		methods: {
-      onChange(e){
-        this.current=e
-          this.dateTypeObj.product_id=this.list[e].id
-      },
-      getConsumeType(){
-         getConsumeType().then((res)=>{
-          if(res.code === 1){
-            this.list = res.data
-          }
-        })
-      },
+			onChange(e) {
+				this.current = e
+				this.dateTypeObj.product_id = this.list[e].id
+			},
+			getConsumeType() {
+				getConsumeType().then((res) => {
+					if (res.code === 1) {
+						this.list = res.data
+					}
+				})
+			},
 			setTimeDate(timeDate) {
 				this.timeData = timeDate
 			},

+ 0 - 0
static/img/statistics/Vector 234.png → static/img/statistics/white-arrow.png


+ 20 - 0
uni_modules/k-tabs-swiper/changelog.md

@@ -0,0 +1,20 @@
+## 1.1.2(2024-05-07)
+优化已知问题
+## 1.1.1(2024-05-07)
+优化已知问题
+## 1.1.0(2024-04-24)
+增加了swiper替代方案,因为过多swiper会出现性能问题,两种方案都可使用,自行选择,默认依旧为swiper。
+增加了swiper衔接滑动,即播放到末尾后重新回到开头	
+## 1.0.4(2024-04-24)
+修复已知问题
+## 1.0.3(2024-04-24)
+修复已知问题
+## 1.0.2(2024-04-24)
+修复已知问题
+## 1.0.1(2024-04-24)
+增加可以设置内容区域的高度
+
+#### 更新日志
+***
+##### 1.0.0(2024-04-23)
+正式发布

+ 103 - 0
uni_modules/k-tabs-swiper/components/example/kTabs.vue

@@ -0,0 +1,103 @@
+<template>
+	<view class="components">
+		<view>
+			<view class="title">常规:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" :bold="true" :scroll="true" height="100rpx" lineHeight="10rpx"
+				@change="changeTab" paddingItem="0 50rpx" />
+		</view>
+		<view>
+			<view class="title">数据为-数组对象:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs1" field="name" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" :bold="true" :scroll="true" height="100rpx" lineHeight="0"
+				@change="changeTab" paddingItem="0 50rpx" />
+		</view>
+		<view>
+			<view class="title">平铺:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs2" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" :scroll="false" :bold="true" height="100rpx" @change="changeTab"
+				paddingItem="0 50rpx" />
+		</view>
+		<view>
+			<view class="title">胶囊:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs" :pills="true" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" :bold="true" height="100rpx" @change="changeTab"
+				paddingItem="0 50rpx" />
+		</view>
+		<view>
+			<view class="title">胶囊:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs" :pills="true" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" pillsColor="red" :bold="true" pillsBorderRadius="100rpx"
+				height="100rpx" :lineScale="0.8" @change="changeTab" paddingItem="0 50rpx" />
+		</view>
+		<view>
+			<view class="title">自定义底部:</view>
+			<k-tabs-swiper v-model="current" :tabs="tabs" :pills="true" bgColor="#1EBB81" color="rgba(255,255,255,0.8)"
+				activeColor="#FFFFFF" fontSize="28rpx" pillsColor="red" :bold="true" pillsBorderRadius="100rpx"
+				height="100rpx" @change="changeTab" paddingItem="0 50rpx" :lineSlot="true">
+				<image class="line_img" slot="line" src="/static/k-tabs-swiper/img.png" mode="scaleToFill" />
+			</k-tabs-swiper>
+		</view>
+	</view>
+</template>
+<script>
+	import KTabsSwiper from '../k-tabs-swiper/k-tabs-swiper'
+
+	export default {
+		components: {
+			KTabsSwiper
+		},
+		data() {
+			return {
+				current: 0,
+				tabs: ['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+				tabs1: [{
+					id: 1,
+					name: '新闻',
+				}, {
+					id: 2,
+					name: '早报',
+				}, {
+					id: 1,
+					name: '军事'
+				}, {
+					id: 3,
+					name: '生活',
+
+				}, {
+					id: 4,
+					name: '地区事件',
+				}, {
+					id: 5,
+					name: '文化',
+				}, {
+					id: 6,
+					name: '军事',
+				}, {
+					id: 7,
+					name: '国内',
+				}, {
+					id: 8,
+					name: '新闻',
+				}], //用户测评日志
+				tabs2: ['全部', '待支付', '进行中', '已完成'], //用户测评日志
+			}
+		},
+		methods: {
+			changeTab(index) {
+				console.log("下标", index);
+			}
+		},
+	}
+</script>
+<style lang="scss" scoped>
+	.title {
+		font-weight: bold;
+		padding: 16rpx;
+	}
+
+	.line_img {
+		width: 42rpx;
+		height: 17rpx;
+	}
+</style>

+ 108 - 0
uni_modules/k-tabs-swiper/components/example/kTabsSwiper.vue

@@ -0,0 +1,108 @@
+<template>
+    <view class="kTabsSwiper">
+        <k-tabs-swiper
+            v-model="current" 
+            :tabs="tabs" 
+            :tabsSwiper="true"
+            bgColor="#1EBB81"
+            color="rgba(255,255,255,0.8)"
+            activeColor="#FFFFFF"
+            fontSize="28rpx"
+            lineColor="#FFFFFF"
+            :bold="true"
+            :scroll="true"
+            :fixed="true"
+            height="100rpx"
+            lineHeight="10rpx"
+            @change="changeTab"
+            @load="load"
+            paddingItem="0 50rpx"
+            >
+            <template slot="swiperContent" slot-scope="{index}">
+                <view class="item" :class="{
+                    'item-active': itemIndex % 2
+                }" v-for="(item,itemIndex) in tabsLists[index]" :key="itemIndex">
+                    <text>{{index}}+{{itemIndex}}</text>
+                </view>
+                <view class="loading">触发到底部</view>
+            </template>
+        </k-tabs-swiper>
+    </view>
+</template>
+<script>
+import KTabsSwiper from '../k-tabs-swiper/k-tabs-swiper'
+
+export default{
+    components:{
+        KTabsSwiper
+    },
+    data() {
+        return {
+            current: 0,
+            tabs:['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+            tabsLists:[],
+            isListFinished: [],
+        }
+    },
+    onLoad(options) {
+        this.init();
+    },
+    methods: {
+        //此为测试用方法
+        init(){
+            this.tabsLists = new Array(this.tabs.length).fill([]);
+            this.tabs.forEach((item,index) => {
+                this.isListFinished.push({
+                    canLoad:true,
+                    pageNum:0,
+                    pageSize:20
+                });
+            })
+            this.changeTab(0);
+        },
+        getData(index){
+            let newArr = new Array(20).fill([]);
+            this.$set(this.tabsLists,index,this.tabsLists[index].concat(newArr))
+            
+        },
+        load(index){
+            this.isListFinished[index].pageNum++;
+            uni.showToast({
+                title: `第${index}个触发底部,页码${this.isListFinished[index].pageNum}`,
+                icon: 'none',
+            })
+            this.getData(index)
+        },
+        changeTab(index){
+            uni.showToast({
+                title: `第${index}个`,
+                icon: 'none',
+            })
+            this.getData(index)
+        }
+    },
+}
+</script>
+<style lang="scss" scoped>
+.title{
+    font-weight: bold;
+    padding: 16rpx;
+}
+.line_img{
+    width: 42rpx;
+    height: 17rpx; 
+}
+.item{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100rpx;
+}
+.item-active{
+    background: rgb(30, 187, 129);
+}
+.loading{
+    text-align: center;
+    padding: 20rpx 0;
+}
+</style>

+ 453 - 0
uni_modules/k-tabs-swiper/components/k-tabs-swiper/k-tabs-swiper.vue

@@ -0,0 +1,453 @@
+<template>
+	<view class="v-tabs">
+		<scroll-view :id="getDomId" :scroll-x="scroll" :scroll-left="scroll ? scrollLeft : 0"
+			:scroll-with-animation="scroll" :style="{ position: fixed ? 'fixed' : 'relative', zIndex }">
+			<view class="v-tabs__container" :style="{
+          display: scroll ? 'inline-flex' : 'flex',
+          whiteSpace: scroll ? 'nowrap' : 'normal',
+          background: bgColor,
+          padding
+        }">
+				<view :class="['v-tabs__container-item', { disabled: !!v.disabled }, { active: current == i }]"
+					v-for="(v, i) in tabs" :key="i" :style="{
+            color: current == i ? activeColor : color,
+            fontSize: current == i ? fontSize : fontSize,
+            fontWeight: bold && current == i ? 'bold' : '',
+            justifyContent: !scroll ? 'center' : '',
+            flex: scroll ? '' : 1,
+            padding: paddingItem
+          }" @click="change(i,'tab')">
+					<view class="column-c">
+						<image class="wh-60 m-tb10 r-100" :class="current == i?'double-border':''"
+							style="display: block;" :src="v.icon" mode=""></image>
+						<slot :row="v" :index="i">{{ field ? v[field] : v }}</slot>
+					</view>
+				</view>
+				<template v-if="!!tabs.length">
+
+					<view v-if="lineSlot" class="lineSlot"
+						:class="['v-tabs__container-line', { animation: lineAnimation }]" :style="{
+                transform: `translate3d(${lineLeft}px, 0, 0)`
+                }">
+						<slot name="line" />
+					</view>
+					<view class="column-c" v-else-if="!pills"
+						:class="['v-tabs__container-line', { animation: lineAnimation }]" :style="{
+                width: lineWidth + 'px',
+                height: '30rpx',
+                borderRadius: lineRadius,
+                transform: `translate3d(${lineLeft}px, 0, 0)`
+                }">
+						<view class="triangle"></view>
+					</view>
+					<view v-else :class="['v-tabs__container-pills', { animation: lineAnimation }]" :style="{
+                background: pillsColor,
+                borderRadius: pillsBorderRadius,
+                width: currentWidth + 'px',
+                transform: `translate3d(${pillsLeft}px, 0, 0)`,
+                height
+                }" />
+				</template>
+			</view>
+		</scroll-view>
+		<!-- fixed 的站位高度 -->
+		<view class="v-tabs__placeholder" :style="{ height: fixed ? height : '0', padding }"></view>
+		<view class="v-tabs__content" v-if="tabsSwiper">
+			<swiper class="activity-swiper" v-if="!swiperType" :current="value" :duration="duration"
+				:circular="circular" @change="onSwiperChange"
+				:style="{ height: contentHeight ? contentHeight : `calc(100vh - ${height} - ${paddingBottom})`, paddingBottom: paddingBottom, paddingTop: paddingTop}">
+				<swiper-item class="activity-swiper-item" v-for="(item,index) in tabs" :key="item.key"
+					:item-id="item.key" :style="{ paddingBottom: 0, paddingTop: 0 }">
+					<scroll-view scroll-y class="scroll-list" @scrolltolower="onBottom" :style="{ height: '100%' }">
+						<slot :index="index" name="swiperContent" />
+					</scroll-view>
+				</swiper-item>
+			</swiper>
+			<view class="data_list" @touchstart="touchStart" @touchend="touchEnd" :animation="animationData" v-else>
+				<view class="data_list_content" v-for="(item,index) in tabs" :key="index">
+					<scroll-view scroll-y class="scroll-list" @scrolltolower="onBottom"
+						:style="{ height: contentHeight ? contentHeight : `calc(100vh - ${height} - ${paddingBottom})`, paddingBottom: paddingBottom, paddingTop: paddingTop}">
+						<slot :index="index" name="swiperContent" />
+					</scroll-view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		startMicroTask
+	} from './utils'
+	import props from './props'
+	/**
+	 * v-tabs
+	 * @property {Number} value 选中的下标
+	 * @property {Array} tabs tabs 列表
+	 * @property {String} bgColor = '#fff' 背景颜色
+	 * @property {String} color = '#333' 默认颜色
+	 * @property {String} activeColor = '#2979ff' 选中文字颜色
+	 * @property {String} fontSize = '28rpx' 默认文字大小
+	 * @property {String} activeFontSize = '28rpx' 选中文字大小
+	 * @property {Boolean} bold = [true | false] 选中文字是否加粗
+	 * @property {Boolean} scroll = [true | false] 是否滚动
+	 * @property {String} height = '60rpx' tab 的高度
+	 * @property {String} lineHeight = '10rpx' 下划线的高度
+	 * @property {String} lineColor = '#2979ff' 下划线的颜色
+	 * @property {Number} lineScale = 0.5 下划线的宽度缩放比例
+	 * @property {String} lineRadius = '10rpx' 下划线圆角
+	 * @property {Boolean} pills = [true | false] 是否胶囊样式
+	 * @property {String} pillsColor = '#2979ff' 胶囊背景色
+	 * @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
+	 * @property {String} field 如果是对象,显示的键名
+	 * @property {Boolean} fixed = [true | false] 是否固定
+	 * @property {String} paddingItem = '0 22rpx' 选项的边距
+	 * @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
+	 * @property {Number} zIndex = 1993 默认层级
+	 * @property {Boolean} lineSlot true 是否自定义底部滑块
+	 * @property {Boolean} tabsSwiper false 是否使用swiper
+	 * @property {Boolean} swiperType false swiper类型
+	 * @property {Boolean} circular false 是否采用衔接滑动,即播放到末尾后重新回到开头
+	 * @property {String} paddingBottom 0rpx swiper下边padding 
+	 * @property {String} paddingTop 0rpx swiper上边padding
+	 * @property {Number} duration 500 swiper滑动动画时长
+	 * @property {String} contentHeight '' swiper内容高度
+	 *
+	 * @event {Function(current)} change 改变标签触发
+	 */
+	export default {
+		name: 'kTabsSwiper',
+		props,
+		data() {
+			return {
+				lineWidth: 30,
+				currentWidth: 0, // 当前选项的宽度
+				lineLeft: 0, // 滑块距离左侧的位置
+				pillsLeft: 0, // 胶囊距离左侧的位置
+				scrollLeft: 0, // 距离左边的位置
+				container: {
+					width: 0,
+					height: 0,
+					left: 0,
+					right: 0
+				}, // 容器的宽高,左右距离
+				current: 0, // 当前选中项
+				scrollWidth: 0, // 可以滚动的宽度
+				lineSlotWidth: 0, //自定义底部的宽度
+				startX: 0,
+				startY: 0,
+				animationData: {}, // 动画
+			}
+		},
+		computed: {
+			getDomId() {
+				const len = 16
+				const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
+				const maxPos = $chars.length
+				let pwd = ''
+				for (let i = 0; i < len; i++) {
+					pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
+				}
+				return `xfjpeter_${pwd}`
+			}
+		},
+		watch: {
+			value: {
+				immediate: true,
+				handler(newVal) {
+					this.current = newVal
+					this.$nextTick(this.update)
+				}
+			},
+		},
+		methods: {
+			initScroll() {
+				this.scrollY = new Array(10).fill(0);
+			},
+			touchStart(event) {
+				this.startX = event.touches[0].pageX;
+				this.startY = event.touches[0].pageY;
+			},
+			touchEnd(event) {
+				let deltaX = event.changedTouches[0].pageX - this.startX;
+				let deltaY = event.changedTouches[0].pageY - this.startY;
+				if (Math.abs(deltaX) > Math.abs(deltaY) && Math.abs(deltaX) > 60) {
+					if (deltaX < 0) { //往左
+						if (this.current == this.tabs.length - 1) {
+							if (this.circular) {
+								this.change(0);
+							} else {
+								return
+							}
+						} else {
+							this.change(this.current * 1 + 1);
+						}
+
+						this.animate();
+
+					} else if (deltaX > 0) { //往右
+						if (this.current == 0) {
+							if (this.circular) {
+								this.change(this.tabs.length - 1);
+							} else {
+								return
+							}
+						} else {
+							this.change(this.current * 1 - 1);
+						}
+
+						this.animate();
+
+					} else { // 挪动距离0
+
+					}
+				} else {
+
+				}
+			},
+			onSwiperChange(e) {
+				this.change(e.detail.current);
+			},
+			onBottom() {
+				this.$emit("load", this.current)
+			},
+			animate() {
+				this.animation.translateX(-this.swiperWidthPx * this.current + "px").step({
+					duration: this.duration
+				})
+				this.animationData = this.animation.export()
+				setTimeout(() => {
+					this.animationData = {}
+				}, this.duration)
+			},
+			// 切换事件
+			change(index, source) {
+
+				const isDisabled = !!this.tabs[index].disabled
+				if (this.current !== index && !isDisabled) {
+					this.current = index
+					this.$emit('input', index)
+					this.$emit('change', index)
+				}
+				//如果是tab切换
+				if (this.swiperType && source == 'tab') {
+					this.animate();
+				}
+			},
+			createQueryHandler() {
+				const query = uni
+					.createSelectorQuery()
+					// #ifndef MP-ALIPAY
+					.in(this)
+				// #endif
+
+				return query
+			},
+			update() {
+				const _this = this
+				startMicroTask(() => {
+					// 没有列表的时候,不执行
+					if (!this.tabs.length) return
+					_this
+						.createQueryHandler()
+						.select(`#${this.getDomId}`)
+						.boundingClientRect(data => {
+							const {
+								width,
+								height,
+								left,
+								right
+							} = data || {}
+							// 获取容器的相关属性
+							this.container = {
+								width,
+								height,
+								left,
+								right: right - width
+							}
+							_this.lineScrollWidth();
+							_this.calcScrollWidth()
+							_this.setScrollLeft()
+							_this.setLine()
+							if (this.swiperType) {
+								_this.getSwiperWidth();
+								_this.initScroll();
+								// 创建动画实例
+								_this.animation = uni.createAnimation({
+									timingFunction: 'ease',
+									duration: 120
+								})
+							}
+						})
+						.exec()
+				})
+			},
+			getSwiperWidth() {
+				this.createQueryHandler()
+					.select(`.v-tabs__content`)
+					.boundingClientRect(data => {
+						if (!data) return;
+						this.swiperWidthPx = data.width;
+					})
+					.exec()
+			},
+			// 计算可以滚动的宽度
+			calcScrollWidth(callback) {
+				const view = this.createQueryHandler().select(`#${this.getDomId}`)
+				view.fields({
+					scrollOffset: true
+				})
+				view
+					.scrollOffset(res => {
+						if (typeof callback === 'function') {
+							callback(res)
+						} else {
+							// 获取滚动条的宽度
+							this.scrollWidth = res.scrollWidth
+						}
+					})
+					.exec()
+			},
+			// 设置滚动条滚动的进度
+			setScrollLeft() {
+				this.calcScrollWidth(res => {
+					// 动态读取 scrollLeft
+					let scrollLeft = res.scrollLeft
+					this.createQueryHandler()
+						.select(`#${this.getDomId} .v-tabs__container-item.active`)
+						.boundingClientRect(data => {
+							if (!data) return
+							// 除开当前选项外容器的一半宽度
+							let curHalfWidth = (this.container.width - data.width) / 2
+							let scrollDiff = this.scrollWidth - this.container.width
+							// 在原有滚动条的基础上 + (当前元素距离左侧的距离 - 计算的一半宽度) - 容器的外边距之类的
+							scrollLeft += data.left - curHalfWidth - this.container.left
+							// 已经滚动在左侧了
+							if (scrollLeft < 0) scrollLeft = 0
+							// 已经超出右侧了
+							else if (scrollLeft > scrollDiff) scrollLeft = scrollDiff
+							this.scrollLeft = scrollLeft
+						})
+						.exec()
+				})
+			},
+			lineScrollWidth() {
+				this.createQueryHandler()
+					.select(`#${this.getDomId} .lineSlot`)
+					.boundingClientRect(data => {
+						if (!data) return;
+						this.lineSlotWidth = data.width;
+					})
+					.exec()
+			},
+			setLine() {
+				this.calcScrollWidth(res => {
+					const scrollLeft = res.scrollLeft
+					this.createQueryHandler()
+						.select(`#${this.getDomId} .v-tabs__container-item.active`)
+						.boundingClientRect(data => {
+							if (!data) return
+							if (this.lineSlot) {
+								this.lineWidth = data.width * this.lineScale
+								this.lineLeft = scrollLeft + data.left + data.width / 2 - this.lineSlotWidth /
+									2 - this.container.left
+							} else if (this.pills) {
+								this.currentWidth = data.width
+								this.pillsLeft = scrollLeft + data.left - this.container.left
+							} else {
+								this.lineWidth = data.width * this.lineScale
+								this.lineLeft = scrollLeft + data.left + (data.width - data.width * this
+									.lineScale) / 2 - this.container.left
+							}
+						})
+						.exec()
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.v-tabs {
+		width: 100%;
+		box-sizing: border-box;
+		overflow: hidden;
+		border-radius: 10px;
+		padding: 0 20rpx;
+		background: #fff;
+
+		/* #ifdef H5 */
+		::-webkit-scrollbar {
+			display: none;
+		}
+
+		/* #endif */
+
+		&__container {
+			min-width: 100%;
+			position: relative;
+			display: inline-flex;
+			align-items: center;
+			white-space: nowrap;
+			overflow: hidden;
+			padding: 20rpx !important;
+			border-radius: 10px;
+			background: #fff;
+
+			&-item {
+				flex-shrink: 0;
+				display: flex;
+				align-items: center;
+				height: 100%;
+				position: relative;
+				z-index: 10;
+				transition: all 0.3s;
+				white-space: nowrap;
+				padding: 10rpx 40rpx !important;
+
+				&.disabled {
+					opacity: 0.5;
+					color: #999;
+				}
+			}
+
+			&-line {
+				position: absolute;
+				left: 0;
+				bottom: -20rpx;
+			}
+
+			&-pills {
+				position: absolute;
+				z-index: 9;
+			}
+
+			&-line,
+			&-pills {
+				&.animation {
+					transition: all 0.3s linear;
+				}
+			}
+		}
+	}
+
+	.data_list {
+		display: flex;
+
+		&_content {
+			flex-shrink: 0;
+			width: 100%;
+		}
+	}
+
+	.triangle {
+		width: 20rpx;
+		height: 20rpx;
+		background: #10B261;
+		border-radius: 50%;
+	}
+
+	.double-border {
+		box-shadow: 0 0 0 6rpx #fff, 0 0 0 12rpx #10B261;
+	}
+</style>

+ 128 - 0
uni_modules/k-tabs-swiper/components/k-tabs-swiper/props.js

@@ -0,0 +1,128 @@
+export default {
+  value: {
+    type: Number,
+    default: 0
+  },
+  tabs: {
+    type: Array,
+    default() {
+      return []
+    }
+  },
+  bgColor: {
+    type: String,
+    default: '#fff'
+  },
+  padding: {
+    type: String,
+    default: '0'
+  },
+  color: {
+    type: String,
+    default: '#333'
+  },
+  activeColor: {
+    type: String,
+    default: '#2979ff'
+  },
+  fontSize: {
+    type: String,
+    default: '28rpx'
+  },
+  activeFontSize: {
+    type: String,
+    default: '32rpx'
+  },
+  bold: {
+    type: Boolean,
+    default: false
+  },
+  scroll: {
+    type: Boolean,
+    default: true
+  },
+  height: {
+    type: String,
+    default: '70rpx'
+  },
+  lineColor: {
+    type: String,
+    default: '#2979ff'
+  },
+  lineHeight: {
+    type: [String, Number],
+    default: '10rpx'
+  },
+  lineScale: {
+    type: Number,
+    default: 0.5
+  },
+  lineRadius: {
+    type: String,
+    default: '10rpx'
+  },
+  pills: {
+    type: Boolean,
+    default: false
+  },
+  pillsColor: {
+    type: String,
+    default: '#2979ff'
+  },
+  pillsBorderRadius: {
+    type: String,
+    default: '10rpx'
+  },
+  field: {
+    type: String,
+    default: ''
+  },
+  fixed: {
+    type: Boolean,
+    default: false
+  },
+  paddingItem: {
+    type: String,
+    default: '0 22rpx'
+  },
+  lineAnimation: {
+    type: Boolean,
+    default: true
+  },
+  zIndex: {
+    type: Number,
+    default: 1993
+  },
+  lineSlot: {
+    type: Boolean,
+    default: false
+  },
+  tabsSwiper: {
+    type: Boolean,
+    default: false
+  },
+  paddingBottom: {
+    type: String,
+    default: '0rpx'
+  },
+  paddingTop: {
+    type: String,
+    default: '0rpx'
+  },
+  duration: {
+    type: [Number],
+    default: 500
+  },
+  contentHeight: {
+    type: String,
+    default: ''
+  },
+  swiperType: {
+    type: Boolean,
+    default: false
+  },
+  circular: {
+    type: Boolean,
+    default: false
+  },
+}

+ 12 - 0
uni_modules/k-tabs-swiper/components/k-tabs-swiper/utils.js

@@ -0,0 +1,12 @@
+export function startMicroTask(callback) {
+  if (typeof queueMicrotask === 'function') {
+    queueMicrotask(callback)
+  } else if (typeof MutationObserver === 'function') {
+    const node = document.createElement('div')
+    const observer = new MutationObserver(callback)
+    observer.observe(node, { childList: true })
+    node.textContent = 'xfjpeter'
+  } else {
+    setTimeout(callback, 0)
+  }
+}

+ 85 - 0
uni_modules/k-tabs-swiper/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "k-tabs-swiper",
+  "displayName": "tab组件、选项卡、与swiper联动",
+  "version": "1.1.2",
+  "description": "自定义tab,可以与swiper联动",
+  "keywords": [
+    "tab",
+    "tabs",
+    "选项卡",
+    "swiper"
+],
+  "repository": "",
+"engines": {
+  },
+  "dcloudext": {
+    "type": "component-vue",
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "插件不采集任何数据",
+      "permissions": "无"
+    },
+    "npmurl": ""
+  },
+  "uni_modules": {
+    "dependencies": [],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y",
+        "alipay": "y"
+      },
+      "client": {
+        "Vue": {
+          "vue2": "y",
+          "vue3": "n"
+        },
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "n",
+          "app-uvue": "n"
+        },
+        "H5-mobile": {
+          "Safari": "y",
+          "Android Browser": "y",
+          "微信浏览器(Android)": "y",
+          "QQ浏览器(Android)": "y"
+        },
+        "H5-pc": {
+          "Chrome": "y",
+          "IE": "n",
+          "Edge": "y",
+          "Firefox": "y",
+          "Safari": "y"
+        },
+        "小程序": {
+          "微信": "y",
+          "阿里": "y",
+          "百度": "y",
+          "字节跳动": "y",
+          "QQ": "y",
+          "钉钉": "y",
+          "快手": "y",
+          "飞书": "y",
+          "京东": "y"
+        },
+        "快应用": {
+          "华为": "y",
+          "联盟": "y"
+        }
+      }
+    }
+  }
+}

+ 220 - 0
uni_modules/k-tabs-swiper/readme.md

@@ -0,0 +1,220 @@
+### 插件说明
+>支持静态tab、滑动tab以及swiper联动
+
+* * *
+### 示例
+目录:uni_modules/k-tabs-swiper/components/example
+
+### 使用说明
+##### 1、基本用法
+- 视图
+```
+<k-tabs-swiper
+    v-model="current"
+    :tabs="tabs"
+    bgColor="#1EBB81"
+    color="rgba(255,255,255,0.8)"
+    activeColor="#FFFFFF"
+    fontSize="28rpx"
+    :bold="true"
+    :scroll="true"
+    height="100rpx"
+    lineHeight="10rpx"
+    @change="changeTab"
+    paddingItem="0 50rpx"
+    />
+```
+- 脚本
+```
+current: 0,
+tabs:['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+```
+##### 2、胶囊用法
+- 视图
+```
+<k-tabs-swiper
+v-model="current" 
+:tabs="tabs" 
+:pills="true"
+bgColor="#1EBB81"
+color="rgba(255,255,255,0.8)"
+activeColor="#FFFFFF"
+fontSize="28rpx"
+pillsColor="red"
+:bold="true"
+pillsBorderRadius="100rpx"
+height="100rpx"
+:lineScale="0.8"
+@change="changeTab"
+paddingItem="0 50rpx"
+/>
+```
+- 脚本
+```
+data() {
+        return {
+            current: 0,
+            tabs:['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+        }
+    }
+```
+##### 3、自定义下划线
+- 视图
+```
+<k-tabs-swiper
+v-model="current"
+:tabs="tabs"
+:pills="true"
+bgColor="#1EBB81"
+color="rgba(255,255,255,0.8)"
+activeColor="#FFFFFF"
+fontSize="28rpx"
+pillsColor="red"
+:bold="true"
+pillsBorderRadius="100rpx"
+height="100rpx"
+@change="changeTab"
+paddingItem="0 50rpx"
+:lineSlot="true"
+>
+    <image
+        class="line_img" slot="line"
+        src="../../static/k-tabs-swiper/img.png"
+        mode="scaleToFill"
+    />
+</k-tabs-swiper>
+```
+- 脚本
+```
+data() {
+        return {
+            current: 0,
+            tabs:['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+        }
+    }
+```
+##### 4、tabs与swiper联动
+- 视图
+```
+<k-tabs-swiper
+v-model="current"
+:tabs="tabs"
+:tabsSwiper="true"
+bgColor="#1EBB81"
+color="rgba(255,255,255,0.8)"
+activeColor="#FFFFFF"
+fontSize="28rpx"
+lineColor="#FFFFFF"
+:bold="true"
+:scroll="true"
+:fixed="true"
+height="100rpx"
+lineHeight="10rpx"
+@change="changeTab"
+@load="load"
+paddingItem="0 50rpx"
+>
+<template slot="swiperContent" slot-scope="{index}">
+    <view class="item" :class="{
+        'item-active': itemIndex % 2
+    }" v-for="(item,itemIndex) in tabsLists[index]" :key="itemIndex">
+        {{itemIndex}}
+    </view>
+    <view class="loading">触发到底部自行填充数据</view>
+</template>
+</k-tabs-swiper>
+```
+- 脚本
+```
+export default{
+    data() {
+        return {
+            current: 0,
+            tabs:['新闻', '早报', '军事', '生活', '地区事件', '文化', '军事', '国内', '新闻'],
+            tabsLists:[],
+            isListFinished: [],
+        }
+    },
+    onLoad(options) {
+        this.init();
+    },
+    methods: {
+        //此为测试用方法
+        init(){
+            this.tabsLists = new Array(20).fill([]);
+            this.tabs.forEach((item,index) => {
+                this.isListFinished.push({
+                    canLoad:true,
+                    pageNum:0,
+                    pageSize:20
+                });
+            })
+            this.changeTab(0);
+        },
+        getData(index){
+            let newArr = new Array(20).fill([]);
+            this.$set(this.tabsLists,index,this.tabsLists[index].concat(newArr))
+        },
+        load(index){
+            this.isListFinished[index].pageNum++;
+            uni.showToast({
+                title: `第${index}个触发底部,页码${this.isListFinished[index].pageNum}`,
+                icon: 'none',
+            })
+            this.getData(index)
+        },
+        changeTab(index){
+            uni.showToast({
+                title: `第${index}个`,
+                icon: 'none',
+            })
+            this.getData(index)
+        }
+    },
+}
+```
+
+### 文档说明
+
+* * *
+##### 1、属性说明
+
+参数|类型|默认值|说明 
+-|-|-|-
+tabs | Array | [] | 控制 tab 的列表
+value|Number|0|必传(双向绑定的值)
+color|String|'#333'|默认文字颜色
+activeColor|String|'#2979ff'|选中文字的颜色
+fontSize|String|'28rpx'|默认文字大小
+activeFontSize|String|'28rpx'|选中文字大小
+bold|Boolean|true|是否加粗选中项
+scroll|Boolean|true|是否显示滚动条,平铺设置 false
+height|String|'70rpx'|tab 高度(rpx 或 px)
+lineHeight|String|'10rpx'|滑块高度(rpx 或 px)
+lineColor|String|'#2979ff'|滑块的颜色
+lineScale|Number|0.5|滑块宽度缩放值
+lineRadius|String|'10rpx'|滑块圆角宽度
+pills|Boolean|false|是否开启胶囊
+pillsColor|String|'#2979ff'|胶囊背景颜色
+pillsBorderRadius|String|'10rpx'|胶囊圆角宽度
+field|String|''|如果 tabs 子项是对象,输入需要展示的键名
+bgColor|String|'#fff'|背景色,支持 linear-gradient 渐变
+padding|String|'0'|整个 tab padding 属性
+fixed|Boolean|false|是否固定在顶部
+paddingItem|String|'0 22rpx'|选项的边距(设置上下不生效,需要设置高度)
+lineAnimation|Boolean|true|是否需要 line 和 pills 的动画,在隐藏页面后默认移动到第一个的时候比较实用
+zIndex|Number|1993|控制 tab 的层级,默认1993
+lineSlot|Boolean|false|是否自定义底部滑块
+tabsSwiper|Boolean|false|是否使用swiper
+paddingBottom|String|'0rpx'|swiper下边padding
+duration|Number|500|swiper滑动动画时长
+contentHeight|String|''|swiper内容高度
+swiperType|Boolean|false|swiper类型-因为过多swiper会出现性能问题,因此增加了替代方案,可自行选择
+circular|Boolean|false|是否采用衔接滑动,即播放到末尾后重新回到开头	
+
+
+##### 2、事件说明
+名称|参数|说明
+-|-|-
+change | index | 改变tab选中项触发, index 选中项的下标
+load | index | swiper触底

二進制
uni_modules/k-tabs-swiper/static/k-tabs-swiper/1.gif


二進制
uni_modules/k-tabs-swiper/static/k-tabs-swiper/2.gif


二進制
uni_modules/k-tabs-swiper/static/k-tabs-swiper/img.png