ソースを参照

feat:新增贷后利率对比、完善贷后

443166679@qq.com 1 年間 前
コミット
b7c8799902

+ 45 - 13
common/task/loan-item.vue

@@ -1,16 +1,19 @@
 <template>
 	<view class="p-t20">
-		<view class="task-body m-lr20  animate__animated animate__fadeIn" v-if="taskList.length>0">
-			<view class="row-c page-box-bg-fff m-b20 r-30 box-shadow-197" v-for="(item,index) in taskList" :key="index">
+		<view class="task-body m-lr20  animate__animated animate__fadeIn" v-if="taskLists.length>0">
+			<view class="row-c page-box-bg-fff m-b20 r-30 box-shadow-197 loan-item" v-for="(item,index) in taskLists"
+				:key="index">
 				<view class="main_string" :style="{background:lineColor[item.product_id%3]}"></view>
-				<view class="row-c flex p-30">
+				<view class="row-c flex p-30 p-t60">
 					<image class="wh-80" :src="item.product_icon" mode=""></image>
 					<view class="flex m-l20">
 						<view class="row-justify-sb center flex">
 							<text class="text-color-333 sys-weight-600">{{item.product_name}}</text>
 							<view class="row-c line-40" @click.stop="makCall(item.phone)">
 								<text class="size-26 text-color-333">{{item.name}}</text>
-								<image class="wh-30 m-l16"	src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/task/task-phone.png" mode=""></image>
+								<image class="wh-30 m-l16"
+									src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/task/task-phone.png"
+									mode=""></image>
 							</view>
 						</view>
 						<view
@@ -18,10 +21,12 @@
 							style="line-height: 40rpx;">
 							<text class="size-28 text-color-E21">{{(item.loans_money/10000).toFixed(2)}}万</text>
 							<view class="">
-								<text>{{item.refund_num-item.residue_num}}/{{item.refund_num}}</text><text class="sys-weight-400">期</text>
+								<text>{{item.refund_num-item.residue_num}}/{{item.refund_num}}</text><text
+									class="sys-weight-400">期</text>
 							</view>
 							<view class="" v-if="item.status === 1">
-								<text>{{(item.repayment_money*1).toFixed(2)}}</text><text class="sys-weight-400">元</text>
+								<text>{{(item.repayment_money*1).toFixed(2)}}</text><text
+									class="sys-weight-400">元</text>
 							</view>
 							<text class="color-FF730E">{{(item.interest_rate*1).toFixed(2)}}%</text>
 						</view>
@@ -30,13 +35,16 @@
 							<view class="row-c">
 								<button
 									class="button-backgroun en_buttond left_button sys-weight-500 button_color-008FD6 size-26 r-100 m-r20"
-									type="default" hover-class="is-hover">核算</button>
+									type="default" hover-class="is-hover" @click="onCalculate">核算</button>
 								<button
 									class="button-background en_button left_button right_button sys-weight-500 button_color-008FD6 size-26 r-100"
 									type="default" hover-class="is-hover">客户分类</button>
 							</view>
 						</view>
 					</view>
+					<view class="accomplish-text" :class="{'unfinished':!is_accomplish}">
+						已完成
+					</view>
 				</view>
 			</view>
 			<view class="placeholder sys-list-background-color" v-if="is_bottom && taskList.length"></view>
@@ -60,7 +68,7 @@
 				type: Number,
 				default: 1
 			},
-			taskList: {
+			taskLists: {
 				type: Array,
 				default: () => [1]
 			},
@@ -90,14 +98,17 @@
 			return {
 				leftImg: ['task-house', 'task-business', 'task-repayment'],
 				iconList: ['task-audit', 'task-do', 'task-stay'],
-				lineColor: [ '#EF8F27','#DE5847', '#0FB160'],
+				lineColor: ['#EF8F27', '#DE5847', '#0FB160'],
 				isAjax: false
 			}
 		},
 		methods: {
-      makCall(phone){
-        tools.makingCall(phone)
-      }
+			onCalculate() {
+				this.$emit('onCalculate')
+			},
+			makCall(phone) {
+				tools.makingCall(phone)
+			}
 		}
 	}
 </script>
@@ -136,7 +147,28 @@
 		background: red;
 	}
 
+	.loan-item {
+		position: relative;
+	}
+
+	.accomplish-text {
+		font-size: 24rpx;
+		color: #00994D;
+		background-color: #e7f7ef;
+		padding: 6rpx 30rpx;
+		line-height: 30rpx;
+		border-radius: 0 30rpx 0 30rpx;
+		position: absolute;
+		right: 0;
+		top: 0;
+	}
+
+	.unfinished {
+		color: #F64646;
+		background-color: #feeded;
+	}
+
 	button::after {
 		border: none;
 	}
-</style>
+</style>

BIN
components/.DS_Store


+ 11 - 11
components/en-utils/en-select/en-select.vue

@@ -1,5 +1,5 @@
 <template>
-	<view class="select sys-background-fff ">
+	<view class="select sys-background-fff page-env-20">
 		<view class="title p-30 row-justify-sb">
 			<view class="icon"></view>
 			<text class="size-30 sys-weight-600">{{title}}</text>
@@ -16,7 +16,7 @@
 				</view>
 			</scroll-view>
 		</view>
-		<EnButton :is_fixed="true" text="确认"  @onSubmit="setAffirm(true)" ></EnButton>
+		<EnButton :is_fixed="true" text="确认" @onSubmit="setAffirm(true)"></EnButton>
 	</view>
 </template>
 
@@ -51,7 +51,7 @@
 		data() {
 			return {
 				current: -1,
-        newValue:0
+				newValue: 0
 			};
 		},
 		watch: {
@@ -62,14 +62,14 @@
 			}
 		},
 		methods: {
-      setAffirm(type){
-        this.$emit('input',this.newValue)
-        this.$emit('setAffirm',type)
-      },
+			setAffirm(type) {
+				this.$emit('input', this.newValue)
+				this.$emit('setAffirm', type)
+			},
 			onSelect(index) {
-        this.current=index
-        this.newValue=this.localData[index][this.itemKey]
-        this.$emit('input',this.newValue)
+				this.current = index
+				this.newValue = this.localData[index][this.itemKey]
+				this.$emit('input', this.newValue)
 			}
 		}
 	}
@@ -78,7 +78,7 @@
 <style lang="scss">
 	.select {
 		height: 800rpx;
-    border-radius: 20rpx 20rpx 0 0;
+		border-radius: 20rpx 20rpx 0 0;
 	}
 
 	.icon {

BIN
components/sn-swiper/.DS_Store


+ 251 - 0
components/sn-swiper/esc-swiper-item/index.vue

@@ -0,0 +1,251 @@
+<template>
+	<view class="swiper-item" ref="swiper_item" :style="itemStyle">
+		<view class="item-cntent" bubble="true" @click.stop="onClick"><slot></slot></view>
+	</view>
+</template>
+
+<script>
+import { getStyleStr } from '../../utils/style.js';
+// #ifdef APP-NVUE
+const animation = uni.requireNativePlugin('animation');
+// #endif
+/**
+ * esc-swiper-item
+ * @description esc-swiper-item (不支持使用class)
+ * @property {Number} index 索引(必填)
+ * @property {Boolean} clickAny 可以点击任意项
+ * @event {Function} click 点击事件
+ */
+export default {
+	name: 'esc-swiper-item',
+	inject: ['config'],
+	props: {
+		index: {
+			type: Number,
+			default: 0
+		},
+		clickAny: {
+			type: Boolean,
+			default: false
+		}
+	},
+	data() {
+		return {
+			isAnimated: false,
+			timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
+			duration: 0,
+			current: 0,
+			position: 0,
+			mScale: 0,
+			canClick: true
+		};
+	},
+	created() {},
+	computed: {
+		size() {
+			return this.config.size;
+		},
+		width() {
+			return this.config.width;
+		},
+		height() {
+			return this.config.height;
+		},
+		itemWidth() {
+			return this.config.itemWidth;
+		},
+		itemHeight() {
+			return this.config.itemHeight;
+		},
+		space() {
+			return this.config.space;
+		},
+		itemStyle() {
+			if (this.index == this.size - 1) {
+				return this.rightSpaceStyle();
+			} else if (this.index == this.size - 2) {
+				return this.centerSpaceStyle();
+			} else {
+				return this.leftSpaceStyle();
+			}
+		},
+		scale() {
+			if (!this.config.is3D) {
+				return 1;
+			}
+			if (this.myCurrent == this.current) {
+				return this.mScale || this.config.scale;
+			} else {
+				return this.mScale || 1;
+			}
+		},
+		// 当前swiper-item所属current索引
+		myCurrent() {
+			if (!this.config.isCircular) {
+				return this.index;
+			}
+			const p = this.index;
+			const plus = this.config.plus;
+			const actSize = this.size - plus * 2;
+			let current = 0;
+			if (p < plus) {
+				current = p + (actSize - plus);
+			} else if (p >= this.size - plus) {
+				current = p - (actSize + plus);
+			} else {
+				current = p - plus;
+			}
+			return current;
+		}
+	},
+	methods: {
+		itemSize() {
+			let style = {
+				width: this.itemWidth + 'rpx',
+				height: (this.itemHeight || this.height) + 'rpx'
+			};
+
+			if (this.config.is3D) {
+				// #ifndef APP-NVUE
+				if (this.isAnimated) {
+					style.transition = 'transform ' + this.duration + 'ms ' + this.timingFunction;
+				} else {
+					style.transition = '';
+				}
+				style.transform = 'scale(' + this.scale + ')';
+				// #endif
+				// #ifdef APP-NVUE
+				const isIOS = uni.getSystemInfoSync().platform == 'ios';
+				if (isIOS) {
+					style.transform = 'scale(' + this.scale + ')';
+				} else {
+					if (!this.isAnimated) style.transform = 'scale(' + this.scale + ')';
+				}
+				// #endif
+			}
+
+			return style;
+		},
+		leftSpaceStyle() {
+			return getStyleStr({
+				...this.itemSize(),
+				marginLeft: this.space + 'rpx'
+			});
+		},
+		centerSpaceStyle() {
+			return getStyleStr({
+				...this.itemSize(),
+				marginLeft: this.space + 'rpx',
+				marginRight: this.space + 'rpx'
+			});
+		},
+		rightSpaceStyle() {
+			return getStyleStr({
+				...this.itemSize(),
+				marginRight: this.space + 'rpx'
+			});
+		},
+		onClick(e) {
+			if (!this.canClick) {
+				return;
+			}
+			// #ifdef APP-NVUE
+			e.stopPropagation();
+			// #endif
+			// 点击任意项
+			if (this.clickAny) {
+				this.$emit('click', e);
+				return;
+			}
+			// 只能点击当前项
+			if (this.myCurrent == this.current) {
+				this.$emit('click', e);
+			}
+		},
+		restoreScale(duration) {
+			if (!this.config.is3D) {
+				return;
+			}
+			// #ifndef APP-NVUE
+			this.duration = duration;
+			this.isAnimated = true;
+			this.mScale = 0;
+			setTimeout(() => {
+				this.duration = 0;
+				this.isAnimated = false;
+			}, duration);
+			// #endif
+			// #ifdef APP-NVUE
+			this.isAnimated = true;
+			this.mScale = 0;
+			animation.transition(
+				this.$refs['swiper_item'].ref,
+				{
+					styles: {
+						transform: 'scale(' + this.scale + ')'
+					},
+					duration, //ms
+					timingFunction: this.timingFunction,
+					needLayout: false,
+					delay: 0 //ms
+				},
+				() => {
+					this.isAnimated = false;
+				}
+			);
+			// #endif
+		},
+		restoreToScale(scale, duration) {
+			if (!this.config.is3D) {
+				return;
+			}
+			// #ifndef APP-NVUE
+			this.duration = duration;
+			this.isAnimated = true;
+			this.mScale = scale;
+			setTimeout(() => {
+				this.duration = 0;
+				this.isAnimated = false;
+				this.mScale = 0;
+			}, duration);
+			// #endif
+			// #ifdef APP-NVUE
+			this.isAnimated = true;
+			animation.transition(
+				this.$refs['swiper_item'].ref,
+				{
+					styles: {
+						transform: 'scale(' + scale + ')'
+					},
+					duration, //ms
+					timingFunction: this.timingFunction,
+					needLayout: false,
+					delay: 0 //ms
+				},
+				() => {
+					this.isAnimated = false;
+					this.mScale = 0;
+				}
+			);
+			// #endif
+		}
+	}
+};
+</script>
+
+<style scoped>
+.swiper-item {
+	position: relative;
+}
+
+.item-cntent {
+	position: absolute;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+}
+</style>

+ 21 - 0
components/sn-swiper/esc-swiper/helper.js

@@ -0,0 +1,21 @@
+/**
+ * getSwiperList
+ * @description 获取Swiper数据
+ * @param {Array} list 原数据
+ * @param {Object} options 配置
+ * @param {Boolean} options.circular 是否循环
+ * @param {Number} options.plus 左右追加个数(开启循环必填,至少为2)
+ * @return {Array}
+ */
+export function getSwiperList(list, options = {
+	circular: true,
+	plus: 2
+}) {
+	if (!options.circular) {
+		return list
+	}
+	const plus = options.plus || 2
+	const leftPlusList = [...list].reverse().slice(0, plus).reverse();
+	const rightPlusList = [...list].slice(0, plus);
+	return [].concat(leftPlusList).concat(list).concat(rightPlusList);
+}

+ 198 - 0
components/sn-swiper/esc-swiper/index.vue

@@ -0,0 +1,198 @@
+<template>
+	<!-- #ifdef APP-VUE || H5 -->
+	<view class="box" :style="boxStyle">
+		<view
+			ref="container"
+			class="container"
+			:change:prop="swipe.changeData"
+			:prop="wxsData"
+			@touchstart.stop="swipe.touchstart"
+			@touchmove.stop="swipe.touchmove"
+			@touchend.stop="swipe.touchend"
+			:style="containerStyle"
+		>
+			<slot></slot>
+		</view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef MP-WEIXIN -->
+	<view class="box" :style="boxStyle">
+		<view
+			ref="container"
+			class="container"
+			:change:prop="swipe.changeData"
+			:prop="wxsData"
+			@touchstart="swipe.touchstart"
+			@touchmove="swipe.touchmove"
+			@touchend="swipe.touchend"
+			:style="containerStyle"
+		>
+			<slot></slot>
+		</view>
+	</view>
+	<!-- #endif -->
+	<!-- #ifdef APP-NVUE -->
+	<view class="box" :style="boxStyle">
+		<view ref="container" class="container" @horizontalpan="touchstart" :style="containerStyle"><slot></slot></view>
+	</view>
+	<!-- #endif -->
+	<!-- 其他平台使用 js ,长列表性能可能会有影响-->
+	<!-- #ifndef APP-PLUS || MP-WEIXIN || H5 -->
+	<view class="box" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" :style="boxStyle">
+		<view ref="container" class="container" :style="containerStyle"><slot></slot></view>
+	</view>
+	<!-- #endif -->
+</template>
+<script src="./mixins/index.wxs" module="swipe" lang="wxs"></script>
+<script>
+import SwiperMixin from './mixins/base.mixin.js';
+// #ifdef APP-VUE || MP-WEIXIN || H5
+import MpMixin from './mixins/mpwxs.js';
+// #endif
+// #ifdef APP-NVUE
+import BindingxMixin from './mixins/bindingx.js';
+// #endif
+// #ifndef APP-PLUS || MP-WEIXIN || H5
+import OtherMixin from './mixins/mpother.js';
+// #endif
+
+const mixins = [
+	// #ifdef APP-VUE || MP-WEIXIN || H5
+	MpMixin,
+	// #endif
+	// #ifdef APP-NVUE
+	BindingxMixin,
+	// #endif
+	// #ifndef APP-PLUS || MP-WEIXIN || H5
+	OtherMixin,
+	// #endif
+	SwiperMixin
+];
+
+/**
+ * esc-swiper
+ * @description 自定义swiper (不支持使用class)
+ * @property {String} mode = [normal|3d]  模式
+ * @property {Number} scale 3D模式选中项的scale
+ * @property {Number} width 宽
+ * @property {Number} height 高
+ * @property {Number} itemWidth 项宽
+ * @property {Number} itemHeight 项高
+ * @property {Number} space 间距
+ * @property {Number} plus 左右追加个数(开启循环必填,至少为2)
+ * @property {Number} current 选中项索引
+ * @property {Boolean} autoplay 自动轮播
+ * @property {Boolean} circular 是否循环,如果开启,至少需要3项
+ * @property {Boolean} bounce 阻尼效果 
+ * @event {Function} change 索引变化
+ */
+export default {
+	name: 'esc-swiper',
+	mixins,
+	props: {
+		mode: {
+			type: String,
+			default: 'normal'
+		},
+		scale: Number,
+		width: Number,
+		height: Number,
+		itemWidth: {
+			type: Number,
+			default: 0
+		},
+		itemHeight: {
+			type: Number,
+			default: 0
+		},
+		space: {
+			type: Number,
+			default: 0
+		},
+		plus: {
+			type: Number,
+			default: 0
+		},
+		autoplay: {
+			type: Boolean,
+			default: false
+		},
+		current: {
+			type: Number,
+			default: 0
+		},
+		interval: {
+			type: Number,
+			default: 5000
+		},
+		duration: {
+			type: Number,
+			default: 500
+		},
+		circular: {
+			type: Boolean,
+			default: false
+		},
+		bounce: {
+			type: Boolean,
+			default: true
+		},
+		size: {
+			type: Number,
+			default: 0
+		}
+	},
+	provide() {
+		return {
+			config: {
+				is3D: this.is3D,
+				isCircular: this.circular,
+				scale: this.scale,
+				size: this._size,
+				width: this.width,
+				height: this.height,
+				itemWidth: this.itemWidth,
+				itemHeight: this.itemHeight,
+				space: this.space,
+				plus: this.plus
+			}
+		};
+	},
+	mounted() {
+		if (this.autoplay) {
+			this.autoplayInterval = setInterval(() => {
+				this.next();
+			}, this.interval);
+		}
+	},
+	watch: {
+		autoplay(newV) {
+			if (!newV) {
+				clearInterval(this.autoplayInterval);
+			} else {
+				this.autoplayInterval = setInterval(() => {
+					this.next();
+				}, this.interval);
+			}
+		}
+	},
+	methods: {}
+};
+</script>
+
+<style scoped>
+.box {
+	position: relative;
+	overflow: hidden;
+}
+
+.container {
+	position: absolute;
+	top: 0;
+	/* #ifndef APP-NVUE */
+	display: flex;
+	/* #endif */
+	flex-direction: row;
+	align-items: center;
+}
+</style>

+ 303 - 0
components/sn-swiper/esc-swiper/mixins/base.mixin.js

@@ -0,0 +1,303 @@
+import {
+	getStyleStr
+} from '../../../utils/style.js';
+// #ifdef APP-NVUE
+const animation = uni.requireNativePlugin('animation')
+// #endif
+export default {
+	data() {
+		return {
+			timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
+			isAnimated: false,
+			isScrolling: false,
+			customDuration: 0,
+			left: 0,
+			mCurrent: this.current
+		};
+	},
+	created() {},
+	mounted() {
+		// #ifdef MP
+		this.swiperViews = this.$children
+		// #endif
+		// #ifdef APP-PLUS || H5
+		this.swiperViews = this.$slots.default.map(it => it.child)
+		// #endif
+		this._setLeft();
+		this.mCurrent = this.current
+		this._notifyCurrentForItems(this.current, this.position)
+	},
+	watch: {
+		mCurrent() {
+			let current = this.mCurrent
+			if (this.circular) {
+				if (this.position == 1) {
+					current = this.actualSize - (this.plus - 1)
+					// console.log('最前了', current)
+				} else if (this.position == this._size - 2) {
+					current = this.plus - 2;
+					// console.log('最后了', current)
+				}
+				if (current < 0) {
+					current = this.position + 1
+				}
+				current %= this.actualSize
+			}
+			// console.log('position', this.position, current)
+			this.$emit('update:current', current)
+			this.$emit('change', current)
+			this._notifyCurrentForItems(current, this.position)
+		}
+	},
+	computed: {
+		is3D() {
+			return this.mode == '3d'
+		},
+		position() {
+			return this.circular ? (this.mCurrent + this.plus) : this.mCurrent
+		},
+		manualDuration() {
+			if (this.customDuration > 0)
+				return this.customDuration
+			return this.isAnimated ? this.duration : 0
+		},
+		boxStyle() {
+			return getStyleStr({
+				width: this.width + 'rpx',
+				height: this.height + 'rpx'
+			});
+		},
+		containerStyle() {
+			const style = {
+				height: this.height + 'rpx'
+			};
+			// #ifdef APP-NVUE
+			// FIXME: 理论isAnimated=false应该不设置transform,但是ios有个奇怪的问题,top不为0导致布局错位
+			const isIOS = uni.getSystemInfoSync().platform == 'ios'
+			if (isIOS) {
+				style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
+			} else {
+				if (this.isAnimated == false) {
+					style.transform = 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)'
+				}
+			}
+			// #endif
+			// #ifndef APP-NVUE
+			style.left = this.left + 'rpx'
+			style.transition = 'left ' + this.manualDuration + 'ms ' + this.timingFunction
+			// #endif
+			return getStyleStr(style);
+		},
+		_size() {
+			return (this.$slots && this.$slots.default && this.$slots.default.length) || this.size;
+		},
+		// plus * 2
+		plusSize() {
+			return this.circular ? this.plus * 2 : 0;
+		},
+		// 真实长度
+		actualSize() {
+			return this._size - this.plusSize;
+		}
+	},
+	methods: {
+		prev() {
+			if (this.isAnimated) return;
+			if (this.isScrolling) return;
+			if (this.mCurrent == 0 && this.circular == false) return
+			this.mCurrent--;
+			this._run()
+		},
+		next() {
+			if (this.isAnimated) return;
+			if (this.isScrolling) return;
+			if (this.circular == true) {
+				this.mCurrent++;
+				if (this.mCurrent == this._size) {
+					this.mCurrent = 0;
+				}
+			} else {
+				if (this.mCurrent == this._size - 1) return
+				this.mCurrent++;
+			}
+			this._run()
+		},
+		moveTo(e) {
+			if (this.isAnimated) return
+			const {
+				deltaX,
+				left
+			} = e
+			this.isScrolling = true
+			if (!this.circular) {
+				if (
+					// 第一项,不能向右滑(上一项)
+					(deltaX > 0 && this.mCurrent == 0) ||
+					// 最后一项,不能向左滑(下一项)
+					(deltaX < 0 && this.mCurrent == this._size - 1)
+				) {
+					if (!this.bounce) return
+					// 添加阻尼滑动
+					const _left = this._left || this.wxsData.left
+					this.left = _left + (deltaX * (1 - Math.abs(deltaX) * 3 / (this.width * 5)))
+					this._set3DScale(deltaX)
+					return
+				}
+			}
+			this.left = left
+			this._set3DScale(deltaX)
+		},
+		moveEnd(e) {
+			const {
+				velocity,
+				deltaX,
+				deltaY
+			} = e
+			this.isScrolling = false
+
+			if (!this.circular) {
+				// 第一项,不能向右滑(上一项)
+				if (deltaX > 0 && this.mCurrent == 0) {
+					this._restoreStartTouch()
+					return
+				}
+				// 最后一项,不能向左滑(下一项)
+				if (deltaX < 0 && this.mCurrent == this._size - 1) {
+					this._restoreStartTouch()
+					return
+				}
+			}
+
+			const isTurnPage = Math.abs(deltaX) > this.itemWidth / 2
+			if (isTurnPage || velocity > 0.2) {
+				if (deltaX < 0) {
+					this.customDuration = 350
+					this.next()
+				} else if (deltaX > 0) {
+					this.customDuration = 350
+					this.prev()
+				}
+			} else {
+				this._restoreStartTouch()
+			}
+		},
+		_set3DScale(deltaX) {
+			if (this.is3D) {
+				const min = Math.min
+				const maxScale = Math.abs(this.scale - 1)
+				const mScale = deltaX * maxScale / this.width
+				const mRealScale = min(this.scale, this.scale - Math.abs(mScale))
+				this.swiperViews[this.position].mScale = mRealScale < 1 ? 1 : mRealScale
+				if (this.position - 1 > -1) {
+					this.swiperViews[this.position - 1].mScale = mScale > 0 ? min(this.scale, 1 + mScale) : min(1, 1 + mScale)
+				}
+				if (this.position + 1 < this._size) {
+					this.swiperViews[this.position + 1].mScale = mScale > 0 ? min(1, 1 - mScale) : min(this.scale, 1 - mScale)
+				}
+			}
+		},
+		_restoreStartTouch() {
+			const self = this
+			this.customDuration = 300
+			// #ifdef APP-VUE || MP-WEIXIN || H5
+			this.left = this.wxsData.left
+			// #endif
+			// #ifndef APP-PLUS || MP-WEIXIN || H5
+			this.left = this._left
+			// #endif
+			this._run(false)
+			if (this.is3D) {
+				this.swiperViews[this.position].restoreScale(this.manualDuration)
+				if (this.position - 1 > -1) {
+					this.swiperViews[this.position - 1].restoreScale(this.manualDuration)
+				}
+				if (this.position + 1 < this._size) {
+					this.swiperViews[this.position + 1].restoreScale(this.manualDuration)
+				}
+			}
+		},
+		_notifyCurrentForItems(current, position) {
+			this.swiperViews && this.swiperViews.forEach(it => {
+				it.current = current
+				it.position = position
+			})
+		},
+		_run(isSet = true) {
+			this.isAnimated = true;
+			if (isSet)
+				this._setLeft();
+			const self = this;
+			if (this.is3D) {
+				this.swiperViews[this.position].restoreToScale(this.scale, this.manualDuration)
+				if (this.position - 1 > -1) {
+					this.swiperViews[this.position - 1].restoreToScale(1, this.manualDuration)
+				}
+				if (this.position + 1 < this._size) {
+					this.swiperViews[this.position + 1].restoreToScale(1, this.manualDuration)
+				}
+			}
+			// #ifdef APP-NVUE
+			animation.transition(this.$refs.container, {
+				styles: {
+					transform: 'translate(' + uni.upx2px(this.left) + 'px' + ',0px)',
+				},
+				duration: this.manualDuration, //ms
+				timingFunction: this.timingFunction,
+				needLayout: false,
+				delay: 0 //ms
+			}, function() {
+				self._reset();
+			})
+			// #endif
+			// #ifndef APP-NVUE
+			setTimeout(() => {
+				this._reset();
+			}, this.manualDuration);
+			// #endif
+		},
+		_setLeft() {
+			if (this.circular == true) {
+				const s1 = (this.width - this.itemWidth - this.space * 2) / 2;
+				let left = (this.plus + this.mCurrent) * (this.space + this.itemWidth) - s1;
+				this.left = -left;
+			} else {
+				this.left = -(this.itemWidth + this.space) * this.mCurrent
+			}
+			// #ifdef APP-VUE || MP-WEIXIN || H5
+			this.wxsData = {
+				left: this.left,
+				bounce: this.bounce
+			}
+			// #endif
+		},
+		_reset() {
+			this.isScrolling = false
+			this.isAnimated = false
+			this.customDuration = 0
+			if (this.circular == true) {
+				if (this.position == 1) {
+					this.mCurrent = this.actualSize - (this.plus - 1);
+					this._setLeft();
+					this._restoreScale()
+				}
+				// -2:原数组索引-1 + plus数组索引-1
+				if (this.position == this._size - 2) {
+					this.mCurrent = this.plus - 2;
+					this._setLeft();
+					this._restoreScale()
+				}
+			}
+		},
+		_restoreScale() {
+			if (this.is3D) {
+				this.swiperViews[this.position].restoreToScale(this.scale, 0)
+				if (this.position - 1 > -1) {
+					this.swiperViews[this.position - 1].restoreToScale(1, 0)
+				}
+				if (this.position + 1 < this._size) {
+					this.swiperViews[this.position + 1].restoreToScale(1, 0)
+				}
+			}
+		}
+	}
+}

+ 91 - 0
components/sn-swiper/esc-swiper/mixins/bindingx.js

@@ -0,0 +1,91 @@
+const BindingX = uni.requireNativePlugin('bindingx');
+const animation = uni.requireNativePlugin('animation');
+export default {
+	mounted() {
+		this.container = this.getEl(this.$refs['container'])
+	},
+	methods: {
+		_notifyTouchChangeForItems(isTouchEnd) {
+			this.swiperViews && this.swiperViews.forEach(it => {
+				it.canClick = isTouchEnd
+			})
+		},
+		touchstart(e) {
+			if (this.isAnimated) return;
+			if (this.stop) return
+			this.isScrolling = true
+			this._notifyTouchChangeForItems(false)
+			this.stop = true
+			this.startTime = new Date().getTime()
+			const props = [{
+				element: this.container,
+				property: 'transform.translateX',
+				expression: uni.upx2px(this.left) + '+x'
+			}]
+			if (this.is3D) {
+				const deltaScale = `${this.scale}/${this.width}*x`
+				const currentScale = `${this.scale}-abs(x)/${this.width}*1`
+				const realScale = `min(${currentScale},${this.scale})`
+				const currentCardExp = `${realScale} < 1 ? 1 : ${realScale}`;
+				const leftCardExp = `${deltaScale} > 0 ? min(${this.scale},(1 + ${deltaScale})) : min(1,(1 + ${deltaScale}))`;
+				const rightCardExp = `${deltaScale} > 0 ? min(1,(1 - ${deltaScale})) : min(${this.scale},(1 - ${deltaScale}))`;
+				props.push({
+					element: this.getSwipteItemEl(this.position),
+					property: 'transform.scale',
+					expression: currentCardExp
+				})
+				if (this.position - 1 > -1) {
+					props.push({
+						element: this.getSwipteItemEl(this.position - 1),
+						property: 'transform.scale',
+						expression: leftCardExp
+					})
+				}
+				if (this.position + 1 > this._size) {
+					props.push({
+						element: this.getSwipteItemEl(this.position + 1),
+						property: 'transform.scale',
+						expression: rightCardExp
+					})
+				}
+			}
+			this.eventpan = BindingX.bind({
+				anchor: this.container,
+				eventType: 'pan',
+				props
+			}, (e) => {
+				if (e.state === 'end' ||
+					e.state === 'exit') {
+					setTimeout(() => {
+						this._notifyTouchChangeForItems(true)
+					}, 10)
+					const timing = new Date().getTime() - this.startTime
+					const velocity = Math.abs(e.deltaX / timing)
+					this.stop = false
+					this.isScrolling = false
+					if (this.eventpan && this.eventpan.token) {
+						BindingX.unbind({
+							token: this.eventpan.token,
+							eventType: 'pan'
+						})
+					}
+					this.moveEnd({
+						velocity,
+						deltaX: e.deltaX,
+						deltaY: e.deltaY
+					})
+				}
+			})
+		},
+		getSwipteItemEl(idx) {
+			return this.swiperViews[idx].$el.ref
+		},
+		/**
+		 * 获取ref
+		 * @param {Object} el
+		 */
+		getEl(el) {
+			return el.ref
+		}
+	}
+}

+ 143 - 0
components/sn-swiper/esc-swiper/mixins/index.wxs

@@ -0,0 +1,143 @@
+var MIN_DISTANCE = 10;
+
+function changeData(newValue, oldValue, ownerInstance, instance) {
+	var state = instance.getState();
+	if (newValue.left != undefined) {
+		state.left = newValue.left
+	}
+	if (newValue.bounce != undefined) {
+		state.bounce = newValue.bounce
+	}
+	// console.log('changeData', JSON.stringify(newValue))
+}
+
+/**
+ * 开始触摸操作
+ * @param {Object} e
+ * @param {Object} ins
+ */
+function touchstart(e, ins) {
+	var instance = e.instance;
+	// 计算滑动开始位置
+	stopTouchStart(e, ins)
+}
+
+/**
+ * 开始滑动操作
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchmove(e, ownerInstance) {
+	var instance = e.instance;
+	// 是否可以滑动页面
+	stopTouchMove(e);
+	if (e.preventDefault) {
+		// 阻止页面滚动
+		e.preventDefault()
+	}
+	// var state = instance.getState();
+	 // && state.bounce
+	move(instance, ownerInstance)
+	return false
+}
+
+/**
+ * 结束触摸操作
+ * @param {Object} e
+ * @param {Object} ownerInstance
+ */
+function touchend(e, ownerInstance) {
+	var instance = e.instance;
+	var state = instance.getState()
+	ownerInstance.callMethod('moveEnd', {
+		velocity: Math.abs(state.deltaX / state.timing),
+		direction: state.direction,
+		deltaX: state.deltaX,
+		deltaY: state.deltaY
+	})
+}
+
+/**
+ * 设置移动距离
+ * @param {Object} instance
+ * @param {Object} ownerInstance
+ */
+function move(instance, ownerInstance) {
+	var state = instance.getState()
+	var value = state.deltaX || 0
+	var state = instance.getState()
+	if (state.direction == 'horizontal') {
+		// instance.requestAnimationFrame(function() {
+		// 	instance.setStyle({
+		// 		transform: 'translateX(' + value + 'px)',
+		// 		'-webkit-transform': 'translateX(' + value + 'px)'
+		// 	})
+		// })
+		ownerInstance.callMethod('moveTo', {
+			deltaX: value,
+			deltaY: state.deltaY || 0,
+			left: state.left + value
+		})
+	}
+
+}
+
+/**
+ * 滑动中,是否禁止打开
+ * @param {Object} event
+ */
+function stopTouchMove(event) {
+	var instance = event.instance;
+	var state = instance.getState();
+	var touch = event.touches[0];
+	state.timing = getDate().getTime() - state.startTime;
+	state.deltaX = touch.clientX - state.startX;
+	state.deltaY = touch.clientY - state.startY;
+	state.offsetX = Math.abs(state.deltaX);
+	state.offsetY = Math.abs(state.deltaY);
+	state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
+}
+
+/**
+ * 设置滑动开始位置
+ * @param {Object} event
+ */
+function stopTouchStart(event) {
+	var instance = event.instance;
+	var state = instance.getState();
+	resetTouchStatus(instance);
+	var touch = event.touches[0];
+	state.startTime = getDate().getTime();
+	state.startX = touch.clientX;
+	state.startY = touch.clientY;
+}
+
+function getDirection(x, y) {
+	if (x > y && x > MIN_DISTANCE) {
+		return 'horizontal';
+	}
+	if (y > x && y > MIN_DISTANCE) {
+		return 'vertical';
+	}
+	return '';
+}
+
+/**
+ * 重置滑动状态
+ * @param {Object} event
+ */
+function resetTouchStatus(instance) {
+	var state = instance.getState();
+	state.direction = '';
+	state.deltaX = 0;
+	state.deltaY = 0;
+	state.offsetX = 0;
+	state.offsetY = 0;
+}
+
+module.exports = {
+	changeData: changeData,
+	touchstart: touchstart,
+	touchmove: touchmove,
+	touchend: touchend
+}

+ 62 - 0
components/sn-swiper/esc-swiper/mixins/mpother.js

@@ -0,0 +1,62 @@
+const MIN_DISTANCE = 10;
+export default {
+	methods: {
+		touchstart(e) {
+			this._left = this.left
+			this.stopTouchStart(e)
+		},
+		touchmove(e) {
+			// 是否可以滑动页面
+			this.stopTouchMove(e);
+			if (this.direction == 'horizontal') {
+				this.moveTo({
+					deltaX: this.deltaX,
+					deltaY: this.deltaY || 0,
+					left: this._left + this.deltaX
+				})
+			}
+			// FIXME: 冒泡
+			return false
+		},
+		touchend() {
+			this.moveEnd({
+				velocity: Math.abs(this.deltaX / this.timing),
+				direction: this.direction,
+				deltaX: this.deltaX,
+				deltaY: this.deltaY,
+			})
+		},
+		stopTouchStart(event) {
+			this.resetTouchStatus();
+			const touch = event.touches[0];
+			this.startTime = new Date().getTime();
+			this.startX = touch.clientX;
+			this.startY = touch.clientY;
+		},
+		stopTouchMove(event) {
+			const touch = event.touches[0];
+			this.timing = new Date().getTime() - this.startTime;
+			this.deltaX = touch.clientX - this.startX;
+			this.deltaY = touch.clientY - this.startY;
+			this.offsetX = Math.abs(this.deltaX);
+			this.offsetY = Math.abs(this.deltaY);
+			this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
+		},
+		getDirection(x, y) {
+			if (x > y && x > MIN_DISTANCE) {
+				return 'horizontal';
+			}
+			if (y > x && y > MIN_DISTANCE) {
+				return 'vertical';
+			}
+			return '';
+		},
+		resetTouchStatus() {
+			this.direction = '';
+			this.deltaX = 0;
+			this.deltaY = 0;
+			this.offsetX = 0;
+			this.offsetY = 0;
+		}
+	}
+}

+ 7 - 0
components/sn-swiper/esc-swiper/mixins/mpwxs.js

@@ -0,0 +1,7 @@
+export default {
+	data() {
+		return {
+			wxsData: {}
+		}
+	}
+}

+ 1 - 1
components/static/css/en-common.css

@@ -17,7 +17,7 @@
 .box {
 	/* background-color: #ffffff; */
 	border-bottom: 2rpx solid #F0F0F0;
-	padding: 32rpx 0 30rpx 0;
+	padding: 30rpx 0;
 	font-size: 32rpx;
 }
 

+ 15 - 0
components/utils/style.js

@@ -0,0 +1,15 @@
+const toLine = (name) => {
+	return name.replace(/([A-Z])/g, '-$1').toLowerCase();
+}
+/**
+ * style对象转化为style字符串
+ * @return {string}
+ */
+export const getStyleStr = (styleObject) => {
+	let transfrom = '';
+	for (let i in styleObject) {
+		let line = toLine(i);
+		transfrom += line + ':' + styleObject[i] + ';';
+	}
+	return transfrom
+}

+ 14 - 0
pages.json

@@ -60,6 +60,20 @@
       "style": {
         "navigationBarTextStyle": "white"
       }
+    },
+    {
+    	"path" : "pages/loan/module/rate_compare",
+    	"style" : 
+    	{
+    		"navigationBarTitleText" : ""
+    	}
+    },
+    {
+    	"path" : "pages/loan/module/perfect_rate",
+    	"style" : 
+    	{
+    		"navigationBarTitleText" : ""
+    	}
     }
   ],
   "subPackages": [

+ 1 - 1
pages/index/index.vue

@@ -20,7 +20,7 @@
 				</view>
 			</view>
 		</view>
-		<view class="page-box-bg-fff m-t30 m-lr20 m-b20 r-30 row-justify-sb flex p-b30">
+		<view class="page-box-bg-fff m-t30 m-lr20 r-30 row-justify-sb flex p-b30">
 			<view class="">
 				<view class="row-c">
 					<view class="pie_chart column-c">

+ 18 - 20
pages/index/module/index_column.vue

@@ -73,27 +73,25 @@
 		<view class="column_item m-l20 column-justify-sb">
 			<view class="task_item row-justify center r-30" @click="onGetTask">
 				<view class="m-l40" style="position: relative;">
-					<image class="wh-90 r-circle m-r20"
-						src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/index/index-task.png"
-						mode="">
-					</image>
-					<view class="task_num text-color-fff size-20" style="" v-if="memberData.take_num>0">
-						{{memberData.take_num}}
-					</view>
+					<uni-badge class="" :text="memberData.take_num" absolute="rightTop" size="normal" :offset="[5,5]">
+						<image class="wh-90 r-circle"
+							src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/index/index-task.png"
+							mode="">
+						</image>
+					</uni-badge>
 				</view>
-				<text class="text-color-12 sys-weight-600">领取任务</text>
+				<text class="text-color-12 sys-weight-600 m-l20">领取任务</text>
 			</view>
 			<view class="task_message row-justify center r-30" @click="onMessage">
 				<view class="m-l40" style="position: relative;">
-					<image class="wh-90 r-circle m-r20"
-						src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/index/index-money.png"
-						mode="">
-					</image>
-					<view class="task_num text-color-fff size-20" style="" v-if="memberData.noticeNum>0">
-						{{Number(memberData.noticeNum)>99?'99+':memberData.noticeNum}}
-					</view>
+					<uni-badge class="" :text="memberData.noticeNum" absolute="rightTop" size="normal" :offset="[5,5]">
+						<image class="wh-90 r-circle"
+							src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/index/index-money.png"
+							mode="">
+						</image>
+					</uni-badge>
 				</view>
-				<text class="text-color-12 sys-weight-600">任务消息</text>
+				<text class="text-color-12 sys-weight-600 m-l20">任务消息</text>
 			</view>
 		</view>
 	</view>
@@ -260,12 +258,12 @@
 	}
 
 	.task_num {
-		border-radius: 40rpx;
-		background: red;
-		padding: 2rpx 10rpx;
+		// border-radius: 40rpx;
+		// background: red;
+		// padding: 2rpx 10rpx;
 		position: absolute;
 		right: 10rpx;
 		top: -10rpx;
-		line-height: 30rpx;
+		// line-height: 30rpx;
 	}
 </style>

+ 71 - 0
pages/loan/components/column-item.vue

@@ -0,0 +1,71 @@
+<template>
+	<view class="" :class="is_center?'column-center':'column-box'">
+		<view class="m-t30">
+			<text class="center-text">8万</text>
+			<view class="text">贷款金额</view>
+		</view>
+		<view class="m-t30">
+			<text class="center-text">23.76%</text>
+			<view class="text">年利率</view>
+		</view>
+		<view class="m-t30">
+			<text class="center-text">8万</text>
+			<view class="text">贷款期数</view>
+		</view>
+		<view class="m-t30">
+			<text class="center-text">8万</text>
+			<view class="text">每期还款金额</view>
+		</view>
+		<view class="m-t30">
+			<text class="center-text">8万</text>
+			<view class="text">总利息</view>
+		</view>
+		<view class="m-t30">
+			<text class="center-text">8万</text>
+			<view class="text">总还款金额</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			is_center: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.column-box {
+		color: #333;
+		font-size: 28rpx;
+
+		.text {
+			color: #666;
+			font-size: 24rpx;
+			padding-top: 6rpx;
+		}
+	}
+
+	.column-center {
+		color: #333;
+		font-size: 28rpx;
+
+		.center-text {
+			color: #F91517;
+			font-weight: 600;
+		}
+
+		.text {
+			color: #666;
+			font-size: 24rpx;
+			padding-top: 6rpx;
+		}
+	}
+</style>

+ 44 - 2
pages/loan/loan.vue

@@ -13,10 +13,33 @@
 			</view>
 			<EnScroll ref="scroll" :navHeight="100" is_tabHeight @onRefresh="onRefresh"
 				@onScrollBottom="onScrollBottom">
-				<LoanItem :task-list="list"></LoanItem>
+				<LoanItem :task-list="list" @onCalculate="onCalculate"></LoanItem>
 			</EnScroll>
 			<Tab :tab-index="2"></Tab>
+			<uni-popup ref="popup" type="bottom" @touchmove.stop.prevent="moveHandle">
+				<view class="page-env-160 sys-background-fff r-20">
+					<view class="row-justify-sb center p-lr30 p-t30">
+						<view class="wh-25"></view>
+						<text class="size-30 sys-weight-600">核算年利率</text>
+						<image class="wh-25" src="/page_task/static/img/task-details/close.png" mode="aspectFill"
+							@click="onClose">
+						</image>
+					</view>
+					<view class="p-30 size-28 m-b50">
+						<view class="">
+							<text>当前年利率</text><text class="sys-weight-600 color-FF730E m-l10">23.7%</text>
+						</view>
+						<view class="row-justify-sb center r-10 sys-from-background-color p-30 m-t30">
+							<input class="flex" type="text" placeholder="请输入新年利率" />
+							<text class="text-color-12">%</text>
+						</view>
+					</view>
+					<EnButton text="确认核算" @onSubmit=""></EnButton>
+				</view>
+			</uni-popup>
 		</view>
+		<EnButton :is_both="1" leftText="利率对比" rightText="完善贷后" @onLeftSubmit="onRateCompare" @onSubmit="onPerfectRate">
+		</EnButton>
 	</view>
 
 </template>
@@ -112,6 +135,25 @@
 				}, 1000)
 				console.log("到底部了");
 			},
+			onRateCompare() {
+				uni.navigateTo({
+					url: "/pages/loan/module/rate_compare"
+				})
+			},
+			onPerfectRate() {
+				uni.navigateTo({
+					url: "/pages/loan/module/perfect_rate"
+				})
+			},
+			onCalculate() {
+				this.$refs.popup.open('bottom')
+			},
+			onClose() {
+				this.$refs.popup.close('bottom')
+			},
+			moveHandle() {
+				return false
+			}
 		},
 	}
 </script>
@@ -136,4 +178,4 @@
 	//   }
 
 	// }
-</style>
+</style>

+ 49 - 0
pages/loan/module/perfect_rate.vue

@@ -0,0 +1,49 @@
+<template>
+	<view class="total-page page_env-160 page-box sys-list-background-color task-bg">
+		<Nav title="完善贷后" :genre="1" is_fixed></Nav>
+		<view class="m-20">
+			<view class="sys-background-fff p-lr20 p-t20 r-30">
+				<view class="size-28 sys-weight-600">贷款信息</view>
+				<en-select label="贷款银行" v-model="number" :local-data="enterpriseTypeArr"
+					placeholder="请选择贷款银行"></en-select>
+				<en-input label="贷款金额" type="number" v-model="number" placeholder="请输入贷款金额" rightText="万元"></en-input>
+				<en-input label="贷款期数" type="number" v-model="number" placeholder="请输入贷款期数"></en-input>
+				<en-input label="年化利率" :is_border="false" type="number" v-model="number" placeholder="请输入年化利率"
+					rightText="%"></en-input>
+			</view>
+			<view class="sys-background-fff m-t20 p-lr20 p-t20 r-30">
+				<view class="size-28 sys-weight-600">贷款信息</view>
+				<en-select label="还款方式" v-model="number" :local-data="enterpriseTypeArr"
+					placeholder="请选择还款方式"></en-select>
+				<en-input label="还款日期" type="number" v-model="number" placeholder="请输入还款日期"></en-input>
+				<en-input label="还款金额" :is_border="false" type="number" v-model="number" placeholder="请输入还款金额"
+					rightText="元"></en-input>
+			</view>
+		</view>
+		<EnButton text="保存" @onSubmit="onSave"></EnButton>
+	</view>
+</template>
+
+<script>
+	import EnInput from "@/components/en-from/en-input/en-input.vue";
+	import EnSelect from "@/components/en-from/en-select/en-select.vue";
+
+	export default {
+		components: {
+			EnInput,
+			EnSelect
+		},
+		data() {
+			return {
+				number: ''
+			}
+		},
+		methods: {
+			onSave() {}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 155 - 0
pages/loan/module/rate_compare.vue

@@ -0,0 +1,155 @@
+<template>
+	<view class="total-page page_env-20 page-box sys-list-background-color task-bg">
+		<Nav title="利率对比" :genre="1" is_fixed></Nav>
+		<view class="m-20 text-color-12">
+			<view class="sys-background-fff p-30 r-30">
+				<view class="center">
+					<image class="wh-60" src="/static/img/task/task-else.png" mode="aspectFill"></image>
+					<text class="size-28 sys-weight-600 m-l20">垫资还款</text>
+				</view>
+				<view class="row-justify-sb center sys-from-background-color p-tb30 p-lr40 r-30 m-t30">
+					<view class="column-c">
+						<view class="size-26 m-b10">张三</view>
+						<text class="size-24 text-color-666">贷款人姓名</text>
+					</view>
+					<view class="column-c">
+						<view class="size-26 m-b10">{{hidePhone('17717888888')}}</view>
+						<text class="size-24 text-color-666">联系方式</text>
+					</view>
+					<view class="column-c">
+						<view class="size-26 m-b10">2024-08-08</view>
+						<text class="size-24 text-color-666">申请时间</text>
+					</view>
+				</view>
+			</view>
+			<view class="sys-background-fff p-tb30 r-30 m-t20">
+				<view class="container">
+					<view class="box left-box">
+						<text class="title">核算前年利率</text>
+						<text class="number">23.27%</text>
+					</view>
+					<view class="box middle-box">
+						<text class="title">差值</text>
+						<text class="number">5.76%</text>
+					</view>
+					<view class="box right-box">
+						<text class="title">核算后年利率</text>
+						<text class="number">18.00%</text>
+					</view>
+				</view>
+				<view class="p-lr30 flex row-justify-sb">
+					<view class="list-item">
+						<ColumnItem></ColumnItem>
+					</view>
+					<view class="list-item">
+						<ColumnItem is_center></ColumnItem>
+					</view>
+					<view class="list-item">
+						<ColumnItem></ColumnItem>
+					</view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import tools from "@/service/tools";
+	import ColumnItem from "../components/column-item.vue"
+
+	export default {
+		components: {
+			ColumnItem
+		},
+		data() {
+			return {}
+		},
+		methods: {
+			hidePhone(phone) {
+				return tools.hidePhone(phone)
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.list-item {
+		flex: 1;
+		text-align: center;
+	}
+
+	.container {
+		display: flex;
+		justify-content: space-between;
+	}
+
+	.box {
+		position: relative;
+		flex: 1;
+		height: 125rpx;
+		background-color: red;
+		text-align: center;
+		color: #fff;
+		flex-direction: column;
+		display: flex;
+		justify-content: center;
+
+		.title {
+			font-size: 26rpx
+		}
+
+		.number {
+			font-size: 28;
+			font-weight: 600;
+			padding-top: 10rpx;
+		}
+	}
+
+	.left-box {
+		position: relative;
+		right: -15px;
+		border-radius: 20rpx 0 0 20rpx;
+		clip-path: polygon(0% 0%, 100% 0%, 80% 100%, 0% 100%);
+		background: linear-gradient(270deg, #FEA666 0%, #F9503D 100%);
+	}
+
+	.middle-box {
+		position: relative;
+		clip-path: polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%);
+		background: linear-gradient(270deg, #745CFF 0%, #3993FD 100%);
+	}
+
+	.right-box {
+
+		position: relative;
+		left: -15px;
+		border-radius: 0 20rpx 20rpx 0;
+		clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 20% 100%);
+		background: linear-gradient(270deg, #F9503D 0%, #FEA666 100%);
+
+	}
+
+	.box::before {
+		content: '';
+		position: absolute;
+		top: -15rpx;
+		left: -15rpx;
+		right: -15rpx;
+		bottom: -15rpx;
+		border: 15rpx solid #f0f0f0;
+		border-radius: 20rpx;
+		pointer-events: none;
+	}
+
+	.left-box::before {
+		clip-path: polygon(0% 0%, 100% 0%, 90% 100%, 0% 100%);
+	}
+
+	.middle-box::before {
+		clip-path: polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%);
+	}
+
+	.right-box::before {
+		clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 20% 100%);
+	}
+</style>

+ 452 - 406
pages/login/index.vue

@@ -1,411 +1,457 @@
 <template>
-  <view class="page-box login-box"  >
-      <view class="login-form sys-radius-50" >
-        <view class="from-title">
-          <view class="title-list">
-            <view class="title-text  sys-size-28 text-center sys-weight-600" :class="{'default-text':type===1}" @click="setType(1)">验证码登录</view>
-            <view class="title-text sys-size-28 text-center sys-weight-600" :class="{'default-text':type===2}" @click="setType(2)">密码登录</view>
-          </view>
-          <view class="title-bg sys-background-fff" :class="{'title-bg-two':type===2}">
-            <view class="bg-icon sys-background-dominant "></view>
-          </view>
-        </view>
-        <view class="from-box sys-background-fff " :class="{'one-from':type===1,'two-from':type===2}">
-          <view class="from-animation animate__animated animate__fadeIn"  v-if="type===1" >
-            <view class="input-item  sys-from-background-color sys-radius-30 " :class="{'apply-shake':phoneShake}">
-              <en-input type="number" class="login-input" placeholder="请输入手机号"  v-model="loginData.phone" maxlength="11"></en-input>
-            </view>
-            <view class="input-item  input-send sys-from-background-color sys-radius-30" :class="{'apply-shake':codedShake}">
-              <en-input type="number" class="login-input" placeholder="请输入验证码"  v-model="loginData.code" maxlength="6"></en-input>
-              <view class="login-send text-color-dominant sys-size-28 sys-weight-400" @click="getVerifiedCode" v-if="timeNum<=0">发送验证码</view>
-              <view class="login-send text-color-dominant sys-size-28 sys-weight-400" v-else>{{ timeNum }} s</view>
-            </view>
-          </view>
-          <view class="from-animation animate__animated animate__fadeIn" v-else>
-            <view class="input-item  sys-from-background-color sys-radius-30 " :class="{'apply-shake':phoneShake}">
-              <en-input type="number" class="login-input" placeholder="请输入手机号"  v-model="loginData.phone" maxlength="11"></en-input>
-            </view>
-            <view class="input-item input-send  sys-from-background-color sys-radius-30" :class="{'apply-shake':passwordShake}">
-              <en-input type="password" class="login-input" placeholder="请输入密码"  v-model="loginData.password"></en-input>
-              <view class="login-send text-color-dominant sys-size-28 sys-weight-400" @click="goToUrl(2)" >忘记密码?</view>
-            </view>
-          </view>
-          <agreement v-model="isConsent" ref="agreement"></agreement>
-
-          <view
-              class="input-but sys-background-dominant text-color-fff sys-size-30 sys-radius-100 sys-weight-600"
-              :class="{'sys-selected-but':isLogin,'sys-unselected-but':!isLogin}"
-              @click="login"
-          >登陆</view>
-        </view>
-      </view>
-      <view class="register-box">
-        <view class="register-text sys-weight-400 sys-size-24 text-color-666">还没有账号?</view>
-        <view class="register-text text-color-dominant sys-size-24 sys-weight-400" @click="goToUrl(1)">立即注册</view>
-      </view>
-      <view class="wx-box">
-        <view class="wx-title">
-          <view class="wx-wire"></view>
-          <view class="wx-text sys-size-24 text-color-7c sys-weight-400">第三方登录</view>
-          <view class="wx-wire"></view>
-        </view>
-        <image @click="wxLogin" class="wx-logo" src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/wx-img.png" mode="aspectFill"></image>
-      </view>
-
-
-  </view>
+	<view class="page-box login-box">
+		<view class="login-form sys-radius-50">
+			<view class="from-title">
+				<view class="title-list">
+					<view class="title-text  sys-size-28 text-center sys-weight-600" :class="{'default-text':type===1}"
+						@click="setType(1)">验证码登录</view>
+					<view class="title-text sys-size-28 text-center sys-weight-600" :class="{'default-text':type===2}"
+						@click="setType(2)">密码登录</view>
+				</view>
+				<view class="title-bg sys-background-fff" :class="{'title-bg-two':type===2}">
+					<view class="bg-icon sys-background-dominant "></view>
+				</view>
+			</view>
+			<view class="from-box sys-background-fff " :class="{'one-from':type===1,'two-from':type===2}">
+				<view class="from-animation animate__animated animate__fadeIn" v-if="type===1">
+					<view class="input-item  sys-from-background-color sys-radius-30 "
+						:class="{'apply-shake':phoneShake}">
+						<en-input type="number" class="login-input" placeholder="请输入手机号" v-model="loginData.phone"
+							maxlength="11"></en-input>
+					</view>
+					<view class="input-item  input-send sys-from-background-color sys-radius-30"
+						:class="{'apply-shake':codedShake}">
+						<en-input type="number" class="login-input" placeholder="请输入验证码" v-model="loginData.code"
+							maxlength="6"></en-input>
+						<view class="login-send text-color-dominant sys-size-28 sys-weight-400" @click="getVerifiedCode"
+							v-if="timeNum<=0">发送验证码</view>
+						<view class="login-send text-color-dominant sys-size-28 sys-weight-400" v-else>{{ timeNum }} s
+						</view>
+					</view>
+				</view>
+				<view class="from-animation animate__animated animate__fadeIn" v-else>
+					<view class="input-item  sys-from-background-color sys-radius-30 "
+						:class="{'apply-shake':phoneShake}">
+						<en-input type="number" class="login-input" placeholder="请输入手机号" v-model="loginData.phone"
+							maxlength="11"></en-input>
+					</view>
+					<view class="input-item input-send  sys-from-background-color sys-radius-30"
+						:class="{'apply-shake':passwordShake}">
+						<en-input type="password" class="login-input" placeholder="请输入密码"
+							v-model="loginData.password"></en-input>
+						<view class="login-send text-color-dominant sys-size-28 sys-weight-400" @click="goToUrl(2)">
+							忘记密码?</view>
+					</view>
+				</view>
+				<agreement v-model="isConsent" ref="agreement"></agreement>
+
+				<view class="input-but sys-background-dominant text-color-fff sys-size-30 sys-radius-100 sys-weight-600"
+					:class="{'sys-selected-but':isLogin,'sys-unselected-but':!isLogin}" @click="login">登陆</view>
+			</view>
+		</view>
+		<view class="register-box">
+			<view class="register-text sys-weight-400 sys-size-24 text-color-666">还没有账号?</view>
+			<view class="register-text text-color-dominant sys-size-24 sys-weight-400" @click="goToUrl(1)">立即注册</view>
+		</view>
+		<view class="wx-box">
+			<view class="wx-title">
+				<view class="wx-wire"></view>
+				<view class="wx-text sys-size-24 text-color-7c sys-weight-400">第三方登录</view>
+				<view class="wx-wire"></view>
+			</view>
+			<image @click="wxLogin" class="wx-logo"
+				src="https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/wx-img.png"
+				mode="aspectFill"></image>
+		</view>
+
+
+	</view>
 </template>
 <script>
-  import {commonSend} from "@/api/common";
-  import tools from "@/service/tools";
-  import {login, wxLogin} from "@/api/login";
-  import EnInput from "@/components/en-from/en-input/index.vue";
-  import Agreement from "@/pages/login/model/agreement.vue";
-
-  export default {
-    components: {
-      Agreement,
-      EnInput
-
-    },
-    data() {
-      return {
-        type:1,
-        loginData: {
-          phone: '13900139110',
-          password: '',
-          code: '1234',
-        },
-        phoneShake:false,
-        passwordShake:false,
-        codedShake:false,
-        consentShake:false,
-        isConsent:false,
-        isLogin:false,
-        timeNum: 0,
-        timer: null,
-      }
-    },
-    watch:{
-      'loginData': {
-        handler() {
-          this.verifyData()
-        },
-        deep: true
-      },
-      'isConsent':function () {
-        this.verifyData()
-      }
-    },
-    mounted() {
-
-    },
-    methods: {
-      wxLogin() {
-        if (!this.isConsent) {
-          tools.error('请阅读并同意协议');
-          this.$refs.agreement.setConsentShake()
-          return;
-        }
-        if (this.isAjax) {
-          return false;
-        }
-        this.isAjax = true;
-        uni.login({
-          provider: "weixin",
-          success: (loginRes) =>{
-            wxLogin({'code':loginRes.code}).then((res)=>{
-              if(res.code===403){
-                tools.error('当前用户未注册')
-                uni.setStorageSync('openid',res.data.openid)
-                setTimeout(()=>{
-                  //跳转至注册页面
-                  uni.navigateTo({
-                    url: '/pages/login/register'
-                  });
-                },1500)
-              }else if(res.code===1){
-                tools.setLoginData(res.data,true)
-              }else {
-                tools.error(res.msg)
-              }
-              this.isAjax = false;
-            })
-          }
-        })
-
-
-      },
-      goToUrl(type){
-        if(type===1){
-          uni.navigateTo({
-            'url':'/pages/login/register'
-          })
-        }else if(type===2){
-          uni.navigateTo({
-            'url':'/pages/login/forget'
-          })
-        }else {
-
-        }
-      },
-      setShake(type){
-        if(type===1){
-          this.phoneShake=true
-        }else if(type===2){
-          this.passwordShake=true
-        }else if(type===3){
-          this.codedShake=true
-        }else if(type===4){
-          this.$refs.agreement.setConsentShake()
-        }
-        setTimeout(()=>{
-          this.phoneShake=false
-          this.passwordShake=false
-          this.codedShake=false
-        },500)
-      },
-      login() {
-        if (this.loginData.phone === '') {
-          tools.error('请输入手机号码');
-          this.setShake(1)
-          return;
-        }
-        if (this.type !== 1) {
-          if (this.loginData.password === '') {
-            this.setShake(2)
-            tools.error('请输入登陆密码');
-            return;
-          }
-        } else {
-          if (this.loginData.code === '') {
-            this.setShake(3)
-            tools.error('请输入验证码');
-            return;
-          }
-        }
-        if (!this.isConsent) {
-          this.setShake(4)
-          tools.error('请阅读并同意协议');
-          return;
-        }
-        login(this.loginData).then((res) => {
-          if (res.code === 1) {
-            tools.setLoginData(res.data, true)
-          } else {
-            tools.error(res.msg)
-          }
-        })
-      },
-      verifyData(){
-        if(this.type===1){
-          this.isLogin=this.loginData.phone!=='' && this.loginData.code!=='' && this.isConsent
-        }else {
-          this.isLogin=this.loginData.phone!=='' && this.loginData.password!=='' && this.isConsent
-        }
-      },
-      getVerifiedCode() {
-        if (this.timeNum > 0) {
-          return;
-        }
-        if (this.loginData.phone === '') {
-          tools.error("请输入手机号码")
-          return;
-        }
-        let regPhone = /^(?:(?:\+|00)86)?1\d{10}$/;
-        if (!regPhone.test(this.loginData.phone)) {
-          tools.error("手机号码格式错误")
-          return;
-        }
-        commonSend({
-          'phone': this.loginData.phone,
-          'send_type': 'retrieve'
-        }).then((res) => {
-          if (res.code === 1) {
-            tools.success(res.msg);
-            this.timeNum = 60;
-            this.timer = setInterval(() => {
-              this.timeNum--;
-              if (this.timeNum <= 0) {
-                clearInterval(this.timer);
-              }
-            }, 1000);
-          } else {
-            tools.error(res.msg);
-          }
-        })
-      },
-      setIsConsent(){
-        this.isConsent=!this.isConsent
-      },
-      setType(type){
-        if(type!==this.type){
-          this.type=type
-        }
-      },
-
-    },
-  }
+	import {
+		commonSend
+	} from "@/api/common";
+	import tools from "@/service/tools";
+	import {
+		login,
+		wxLogin
+	} from "@/api/login";
+	import EnInput from "@/components/en-from/en-input/index.vue";
+	import Agreement from "@/pages/login/model/agreement.vue";
+
+	export default {
+		components: {
+			Agreement,
+			EnInput
+
+		},
+		data() {
+			return {
+				type: 1,
+				loginData: {
+					phone: '18623152213',
+					password: '',
+					code: '1234',
+				},
+				phoneShake: false,
+				passwordShake: false,
+				codedShake: false,
+				consentShake: false,
+				isConsent: false,
+				isLogin: false,
+				timeNum: 0,
+				timer: null,
+			}
+		},
+		watch: {
+			'loginData': {
+				handler() {
+					this.verifyData()
+				},
+				deep: true
+			},
+			'isConsent': function() {
+				this.verifyData()
+			}
+		},
+		mounted() {
+
+		},
+		methods: {
+			wxLogin() {
+				if (!this.isConsent) {
+					tools.error('请阅读并同意协议');
+					this.$refs.agreement.setConsentShake()
+					return;
+				}
+				if (this.isAjax) {
+					return false;
+				}
+				this.isAjax = true;
+				uni.login({
+					provider: "weixin",
+					success: (loginRes) => {
+						wxLogin({
+							'code': loginRes.code
+						}).then((res) => {
+							if (res.code === 403) {
+								tools.error('当前用户未注册')
+								uni.setStorageSync('openid', res.data.openid)
+								setTimeout(() => {
+									//跳转至注册页面
+									uni.navigateTo({
+										url: '/pages/login/register'
+									});
+								}, 1500)
+							} else if (res.code === 1) {
+								tools.setLoginData(res.data, true)
+							} else {
+								tools.error(res.msg)
+							}
+							this.isAjax = false;
+						})
+					}
+				})
+
+
+			},
+			goToUrl(type) {
+				if (type === 1) {
+					uni.navigateTo({
+						'url': '/pages/login/register'
+					})
+				} else if (type === 2) {
+					uni.navigateTo({
+						'url': '/pages/login/forget'
+					})
+				} else {
+
+				}
+			},
+			setShake(type) {
+				if (type === 1) {
+					this.phoneShake = true
+				} else if (type === 2) {
+					this.passwordShake = true
+				} else if (type === 3) {
+					this.codedShake = true
+				} else if (type === 4) {
+					this.$refs.agreement.setConsentShake()
+				}
+				setTimeout(() => {
+					this.phoneShake = false
+					this.passwordShake = false
+					this.codedShake = false
+				}, 500)
+			},
+			login() {
+				if (this.loginData.phone === '') {
+					tools.error('请输入手机号码');
+					this.setShake(1)
+					return;
+				}
+				if (this.type !== 1) {
+					if (this.loginData.password === '') {
+						this.setShake(2)
+						tools.error('请输入登陆密码');
+						return;
+					}
+				} else {
+					if (this.loginData.code === '') {
+						this.setShake(3)
+						tools.error('请输入验证码');
+						return;
+					}
+				}
+				if (!this.isConsent) {
+					this.setShake(4)
+					tools.error('请阅读并同意协议');
+					return;
+				}
+				login(this.loginData).then((res) => {
+					if (res.code === 1) {
+						tools.setLoginData(res.data, true)
+					} else {
+						tools.error(res.msg)
+					}
+				})
+			},
+			verifyData() {
+				if (this.type === 1) {
+					this.isLogin = this.loginData.phone !== '' && this.loginData.code !== '' && this.isConsent
+				} else {
+					this.isLogin = this.loginData.phone !== '' && this.loginData.password !== '' && this.isConsent
+				}
+			},
+			getVerifiedCode() {
+				if (this.timeNum > 0) {
+					return;
+				}
+				if (this.loginData.phone === '') {
+					tools.error("请输入手机号码")
+					return;
+				}
+				let regPhone = /^(?:(?:\+|00)86)?1\d{10}$/;
+				if (!regPhone.test(this.loginData.phone)) {
+					tools.error("手机号码格式错误")
+					return;
+				}
+				commonSend({
+					'phone': this.loginData.phone,
+					'send_type': 'retrieve'
+				}).then((res) => {
+					if (res.code === 1) {
+						tools.success(res.msg);
+						this.timeNum = 60;
+						this.timer = setInterval(() => {
+							this.timeNum--;
+							if (this.timeNum <= 0) {
+								clearInterval(this.timer);
+							}
+						}, 1000);
+					} else {
+						tools.error(res.msg);
+					}
+				})
+			},
+			setIsConsent() {
+				this.isConsent = !this.isConsent
+			},
+			setType(type) {
+				if (type !== this.type) {
+					this.type = type
+				}
+			},
+
+		},
+	}
 </script>
 <style lang="scss" scoped>
-  @import "/static/css/login.css";
-  .page-box{
-    position: relative;
-    padding-top: 370rpx;
-    .login-form{
-      margin: 0 30rpx;
-      border-radius: 50rpx;
-      background-color: rgba(255,255,255,0.5);
-      .from-title{
-        border-radius: 50rpx 50rpx 0 0;
-        height: 110rpx;
-        position: relative;
-
-        .title-bg{
-          position: absolute;
-          border-radius: 50rpx 50rpx 0 0;
-          top: 0;
-          left: 0;
-          height:110rpx;
-          width: 50%;
-          transition: .5s ease;
-          z-index: 0;
-          .bg-icon{
-            margin: 86rpx auto 0 auto;
-            width: 36rpx;
-            height: 6rpx;
-            border-radius: 99rpx;
-          }
-        }
-        .title-bg-two{
-          left: 50%;
-          transition: .5s ease;
-        }
-        //.title-bg::after {
-        //  content: '';
-        //  position: absolute;
-        //  right: -50rpx;
-        //  bottom: 0;
-        //  width: 50rpx;
-        //  height:50rpx;
-        //  background-color: #fff;
-        //  border-radius: 50rpx 50rpx  50rpx 0;
-        //}
-        .title-list{
-          display: flex;
-          justify-content: space-between;
-          z-index: 1;
-          position: relative;
-          .title-text{
-            width: 50%;
-            height: 110rpx;
-            line-height: 102rpx;
-            color: #333333;
-          }
-          .default-text{
-            color: #10B261;
-          }
-          .title-text:first-child{
-            background-image: url("https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/right.png");
-            background-repeat: no-repeat;
-            background-position: right bottom;
-          }
-          .title-text:last-child{
-            background-image: url("https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/left.png");
-            background-repeat: no-repeat;
-            background-position: left bottom;
-          }
-        }
-
-      }
-      .from-box{
-        box-shadow: 0rpx 4rpx 36rpx 0rpx rgba(196,196,196,0.25);
-        border-radius: 0 0 50rpx 50rpx;
-        padding: 50rpx 45rpx;
-        .input-item{
-          height: 96rpx;
-          padding: 28rpx 40rpx;
-          box-sizing: border-box;
-          .login-input{
-            width: 100%;
-          }
-        }
-        .input-item:last-child{
-          margin-top: 30rpx;
-        }
-        .input-send{
-          display: flex;
-          justify-content: flex-start;
-          align-items: center;
-          .login-input{
-            width:calc(100% - 140rpx) ;
-          }
-          .login-send{
-            width: 140rpx;
-            text-align: center;
-          }
-        }
-
-        .input-but{
-          margin-top: 40rpx;
-          width: 100%;
-          height: 96rpx;
-          line-height: 96rpx;
-          text-align: center;
-        }
-      }
-      .one-from{
-        border-radius: 0 50rpx 50rpx 50rpx;
-        transition: 0.85s ease;
-      }
-      .two-from{
-        border-radius:  50rpx 0 50rpx 50rpx;
-        transition: 0.85s ease;
-      }
-    }
-    .register-box{
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      margin-top: 60rpx;
-      .register-text{
-        height: 34rpx;
-        line-height: 34rpx;
-      }
-      .register-text:last-child{
-        margin-right: 5rpx;
-      }
-    }
-    .wx-box{
-      position: absolute;
-      bottom: calc(60rpx + env(safe-area-inset-bottom));
-      left: 0;
-      width: 100%;
-      display: flex;
-      flex-direction: column;
-      justify-content: center;
-      .wx-title{
-        display: flex;
-        justify-content: center;
-        align-items: center;
-        .wx-wire{
-          background: linear-gradient( 90deg, #D9D9D9 0%, rgba(115,115,115,0) 100%);
-          width: 174rpx;
-          height: 2rpx;
-          border-radius: 50%;
-        }
-        .wx-text{
-          margin: 0 15rpx;
-          height: 34rpx;
-          line-height: 34rpx;
-        }
-      }
-      .wx-logo{
-        margin: 25rpx auto 0 auto;
-        width: 80rpx;
-        height: 80rpx;
-      }
-    }
-
-  }
-</style>
+	@import "/static/css/login.css";
+
+	.page-box {
+		position: relative;
+		padding-top: 370rpx;
+
+		.login-form {
+			margin: 0 30rpx;
+			border-radius: 50rpx;
+			background-color: rgba(255, 255, 255, 0.5);
+
+			.from-title {
+				border-radius: 50rpx 50rpx 0 0;
+				height: 110rpx;
+				position: relative;
+
+				.title-bg {
+					position: absolute;
+					border-radius: 50rpx 50rpx 0 0;
+					top: 0;
+					left: 0;
+					height: 110rpx;
+					width: 50%;
+					transition: .5s ease;
+					z-index: 0;
+
+					.bg-icon {
+						margin: 86rpx auto 0 auto;
+						width: 36rpx;
+						height: 6rpx;
+						border-radius: 99rpx;
+					}
+				}
+
+				.title-bg-two {
+					left: 50%;
+					transition: .5s ease;
+				}
+
+				//.title-bg::after {
+				//  content: '';
+				//  position: absolute;
+				//  right: -50rpx;
+				//  bottom: 0;
+				//  width: 50rpx;
+				//  height:50rpx;
+				//  background-color: #fff;
+				//  border-radius: 50rpx 50rpx  50rpx 0;
+				//}
+				.title-list {
+					display: flex;
+					justify-content: space-between;
+					z-index: 1;
+					position: relative;
+
+					.title-text {
+						width: 50%;
+						height: 110rpx;
+						line-height: 102rpx;
+						color: #333333;
+					}
+
+					.default-text {
+						color: #10B261;
+					}
+
+					.title-text:first-child {
+						background-image: url("https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/right.png");
+						background-repeat: no-repeat;
+						background-position: right bottom;
+					}
+
+					.title-text:last-child {
+						background-image: url("https://wealfavor-1257406827.cos.ap-beijing.myqcloud.com/new-xcx/login/left.png");
+						background-repeat: no-repeat;
+						background-position: left bottom;
+					}
+				}
+
+			}
+
+			.from-box {
+				box-shadow: 0rpx 4rpx 36rpx 0rpx rgba(196, 196, 196, 0.25);
+				border-radius: 0 0 50rpx 50rpx;
+				padding: 50rpx 45rpx;
+
+				.input-item {
+					height: 96rpx;
+					padding: 28rpx 40rpx;
+					box-sizing: border-box;
+
+					.login-input {
+						width: 100%;
+					}
+				}
+
+				.input-item:last-child {
+					margin-top: 30rpx;
+				}
+
+				.input-send {
+					display: flex;
+					justify-content: flex-start;
+					align-items: center;
+
+					.login-input {
+						width: calc(100% - 140rpx);
+					}
+
+					.login-send {
+						width: 140rpx;
+						text-align: center;
+					}
+				}
+
+				.input-but {
+					margin-top: 40rpx;
+					width: 100%;
+					height: 96rpx;
+					line-height: 96rpx;
+					text-align: center;
+				}
+			}
+
+			.one-from {
+				border-radius: 0 50rpx 50rpx 50rpx;
+				transition: 0.85s ease;
+			}
+
+			.two-from {
+				border-radius: 50rpx 0 50rpx 50rpx;
+				transition: 0.85s ease;
+			}
+		}
+
+		.register-box {
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			margin-top: 60rpx;
+
+			.register-text {
+				height: 34rpx;
+				line-height: 34rpx;
+			}
+
+			.register-text:last-child {
+				margin-right: 5rpx;
+			}
+		}
+
+		.wx-box {
+			position: absolute;
+			bottom: calc(60rpx + env(safe-area-inset-bottom));
+			left: 0;
+			width: 100%;
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+
+			.wx-title {
+				display: flex;
+				justify-content: center;
+				align-items: center;
+
+				.wx-wire {
+					background: linear-gradient(90deg, #D9D9D9 0%, rgba(115, 115, 115, 0) 100%);
+					width: 174rpx;
+					height: 2rpx;
+					border-radius: 50%;
+				}
+
+				.wx-text {
+					margin: 0 15rpx;
+					height: 34rpx;
+					line-height: 34rpx;
+				}
+			}
+
+			.wx-logo {
+				margin: 25rpx auto 0 auto;
+				width: 80rpx;
+				height: 80rpx;
+			}
+		}
+
+	}
+</style>

+ 8 - 8
pages/task/task.vue

@@ -9,8 +9,8 @@
 					:current="current" :bar-animate-mode="'worm'" @change="tabsChange" />
 			</view>
 		</view>
-    <task-ima-tab @setProductId="setProductId" :num-type="0"></task-ima-tab>
-		<EnScroll ref="scroll" :navHeight="105" is_tabHeight @onRefresh="onRefresh" @onScrollBottom="onScrollBottom">
+		<task-ima-tab @setProductId="setProductId" :num-type="0"></task-ima-tab>
+		<EnScroll ref="scroll" :navHeight="190" is_tabHeight @onRefresh="onRefresh" @onScrollBottom="onScrollBottom">
 			<view v-if="current===1">
 				<TaskItem :type="5" is_bottom :task-list="backlogList"></TaskItem>
 			</view>
@@ -103,15 +103,15 @@
 
 			},
 			getDayBacklogList() {
-        if (this.isAjax || (this.totalNum <= this.backlogList.length)) {
-          return;
-        }
+				if (this.isAjax || (this.totalNum <= this.backlogList.length)) {
+					return;
+				}
 				getDayBacklogList({
 					'selectStr': this.selectStr
 				}).then((res) => {
 					if (res.code === 1) {
 						this.backlogList = res.data.items
-            this.totalNum = res.data.totalNum
+						this.totalNum = res.data.totalNum
 					}
 				})
 			},
@@ -143,7 +143,7 @@
 			tabsChange(index) {
 				if (index !== this.current) {
 					this.current = index;
-          this.startList()
+					this.startList()
 				}
 			},
 			// 下拉刷新
@@ -166,4 +166,4 @@
 </script>
 <style lang="scss" scoped>
 
-</style>
+</style>

+ 4 - 0
static/css/common.css

@@ -198,6 +198,10 @@
 	padding-top: 40rpx;
 }
 
+.p-t60 {
+	padding-top: 60rpx;
+}
+
 .p-r10 {
 	padding-right: 10rpx;
 }

+ 33 - 0
uni_modules/uni-badge/changelog.md

@@ -0,0 +1,33 @@
+## 1.2.2(2023-01-28)
+- 修复 运行/打包 控制台警告问题
+## 1.2.1(2022-09-05)
+- 修复 当 text 超过 max-num 时,badge 的宽度计算是根据 text 的长度计算,更改为 css 计算实际展示宽度,详见:[https://ask.dcloud.net.cn/question/150473](https://ask.dcloud.net.cn/question/150473)
+## 1.2.0(2021-11-19)
+- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource)
+- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-badge](https://uniapp.dcloud.io/component/uniui/uni-badge)
+## 1.1.7(2021-11-08)
+- 优化 升级ui
+- 修改 size 属性默认值调整为 small
+- 修改 type 属性,默认值调整为 error,info 替换 default
+## 1.1.6(2021-09-22)
+- 修复 在字节小程序上样式不生效的 bug
+## 1.1.5(2021-07-30)
+- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834)
+## 1.1.4(2021-07-29)
+- 修复 去掉 nvue 不支持css 的 align-self 属性,nvue 下不暂支持 absolute 属性
+## 1.1.3(2021-06-24)
+- 优化 示例项目
+## 1.1.1(2021-05-12)
+- 新增 组件示例地址
+## 1.1.0(2021-05-12)
+- 新增 uni-badge 的 absolute 属性,支持定位
+- 新增 uni-badge 的 offset 属性,支持定位偏移
+- 新增 uni-badge 的 is-dot 属性,支持仅显示有一个小点
+- 新增 uni-badge 的 max-num 属性,支持自定义封顶的数字值,超过 99 显示99+
+- 优化 uni-badge 属性 custom-style, 支持以对象形式自定义样式
+## 1.0.7(2021-05-07)
+- 修复 uni-badge 在 App 端,数字小于10时不是圆形的bug
+- 修复 uni-badge 在父元素不是 flex 布局时,宽度缩小的bug
+- 新增 uni-badge 属性 custom-style, 支持自定义样式
+## 1.0.6(2021-02-04)
+- 调整为uni_modules目录规范

+ 268 - 0
uni_modules/uni-badge/components/uni-badge/uni-badge.vue

@@ -0,0 +1,268 @@
+<template>
+	<view class="uni-badge--x">
+		<slot />
+		<text v-if="text" :class="classNames" :style="[positionStyle, customStyle, dotStyle]"
+			class="uni-badge" @click="onClick()">{{displayValue}}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Badge 数字角标
+	 * @description 数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=21
+	 * @property {String} text 角标内容
+	 * @property {String} size = [normal|small] 角标内容
+	 * @property {String} type = [info|primary|success|warning|error] 颜色类型
+	 * 	@value info 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * @property {String} inverted = [true|false] 是否无需背景颜色
+	 * @property {Number} maxNum 展示封顶的数字值,超过 99 显示 99+
+	 * @property {String} absolute = [rightTop|rightBottom|leftBottom|leftTop] 开启绝对定位, 角标将定位到其包裹的标签的四角上
+	 * 	@value rightTop 右上
+	 * 	@value rightBottom 右下
+	 * 	@value leftTop 左上
+	 * 	@value leftBottom 左下
+	 * @property {Array[number]} offset	距定位角中心点的偏移量,只有存在 absolute 属性时有效,例如:[-10, -10] 表示向外偏移 10px,[10, 10] 表示向 absolute 指定的内偏移 10px
+	 * @property {String} isDot = [true|false] 是否显示为一个小点
+	 * @event {Function} click 点击 Badge 触发事件
+	 * @example <uni-badge text="1"></uni-badge>
+	 */
+
+	export default {
+		name: 'UniBadge',
+		emits: ['click'],
+		props: {
+			type: {
+				type: String,
+				default: 'error'
+			},
+			inverted: {
+				type: Boolean,
+				default: false
+			},
+			isDot: {
+				type: Boolean,
+				default: false
+			},
+			maxNum: {
+				type: Number,
+				default: 99
+			},
+			absolute: {
+				type: String,
+				default: ''
+			},
+			offset: {
+				type: Array,
+				default () {
+					return [0, 0]
+				}
+			},
+			text: {
+				type: [String, Number],
+				default: ''
+			},
+			size: {
+				type: String,
+				default: 'small'
+			},
+			customStyle: {
+				type: Object,
+				default () {
+					return {}
+				}
+			}
+		},
+		data() {
+			return {};
+		},
+		computed: {
+			width() {
+				return String(this.text).length * 8 + 12
+			},
+			classNames() {
+				const {
+					inverted,
+					type,
+					size,
+					absolute
+				} = this
+				return [
+					inverted ? 'uni-badge--' + type + '-inverted' : '',
+					'uni-badge--' + type,
+					'uni-badge--' + size,
+					absolute ? 'uni-badge--absolute' : ''
+				].join(' ')
+			},
+			positionStyle() {
+				if (!this.absolute) return {}
+				let w = this.width / 2,
+					h = 10
+				if (this.isDot) {
+					w = 5
+					h = 5
+				}
+				const x = `${- w  + this.offset[0]}px`
+				const y = `${- h + this.offset[1]}px`
+
+				const whiteList = {
+					rightTop: {
+						right: x,
+						top: y
+					},
+					rightBottom: {
+						right: x,
+						bottom: y
+					},
+					leftBottom: {
+						left: x,
+						bottom: y
+					},
+					leftTop: {
+						left: x,
+						top: y
+					}
+				}
+				const match = whiteList[this.absolute]
+				return match ? match : whiteList['rightTop']
+			},
+			dotStyle() {
+				if (!this.isDot) return {}
+				return {
+					width: '10px',
+					minWidth: '0',
+					height: '10px',
+					padding: '0',
+					borderRadius: '10px'
+				}
+			},
+			displayValue() {
+				const {
+					isDot,
+					text,
+					maxNum
+				} = this
+				return isDot ? '' : (Number(text) > maxNum ? `${maxNum}+` : text)
+			}
+		},
+		methods: {
+			onClick() {
+				this.$emit('click');
+			}
+		}
+	};
+</script>
+
+<style lang="scss" >
+	$uni-primary: #2979ff !default;
+	$uni-success: #4cd964 !default;
+	$uni-warning: #f0ad4e !default;
+	$uni-error: #dd524d !default;
+	$uni-info: #909399 !default;
+
+
+	$bage-size: 12px;
+	$bage-small: scale(0.8);
+
+	.uni-badge--x {
+		/* #ifdef APP-NVUE */
+		// align-self: flex-start;
+		/* #endif */
+		/* #ifndef APP-NVUE */
+		display: inline-block;
+		/* #endif */
+		position: relative;
+	}
+
+	.uni-badge--absolute {
+		position: absolute;
+	}
+
+	.uni-badge--small {
+		transform: $bage-small;
+		transform-origin: center center;
+	}
+
+	.uni-badge {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		overflow: hidden;
+		box-sizing: border-box;
+		font-feature-settings: "tnum";
+		min-width: 20px;
+		/* #endif */
+		justify-content: center;
+		flex-direction: row;
+		height: 20px;
+		padding: 0 4px;
+		line-height: 18px;
+		color: #fff;
+		border-radius: 100px;
+		background-color: $uni-info;
+		background-color: transparent;
+		border: 1px solid #fff;
+		text-align: center;
+		font-family: 'Helvetica Neue', Helvetica, sans-serif;
+		font-size: $bage-size;
+		/* #ifdef H5 */
+		z-index: 999;
+		cursor: pointer;
+		/* #endif */
+
+		&--info {
+			color: #fff;
+			background-color: $uni-info;
+		}
+
+		&--primary {
+			background-color: $uni-primary;
+		}
+
+		&--success {
+			background-color: $uni-success;
+		}
+
+		&--warning {
+			background-color: $uni-warning;
+		}
+
+		&--error {
+			background-color: $uni-error;
+		}
+
+		&--inverted {
+			padding: 0 5px 0 0;
+			color: $uni-info;
+		}
+
+		&--info-inverted {
+			color: $uni-info;
+			background-color: transparent;
+		}
+
+		&--primary-inverted {
+			color: $uni-primary;
+			background-color: transparent;
+		}
+
+		&--success-inverted {
+			color: $uni-success;
+			background-color: transparent;
+		}
+
+		&--warning-inverted {
+			color: $uni-warning;
+			background-color: transparent;
+		}
+
+		&--error-inverted {
+			color: $uni-error;
+			background-color: transparent;
+		}
+
+	}
+</style>

+ 85 - 0
uni_modules/uni-badge/package.json

@@ -0,0 +1,85 @@
+{
+  "id": "uni-badge",
+  "displayName": "uni-badge 数字角标",
+  "version": "1.2.2",
+  "description": "数字角标(徽章)组件,在元素周围展示消息提醒,一般用于列表、九宫格、按钮等地方。",
+  "keywords": [
+    "",
+    "badge",
+    "uni-ui",
+    "uniui",
+    "数字角标",
+    "徽章"
+],
+  "repository": "https://github.com/dcloudio/uni-ui",
+  "engines": {
+    "HBuilderX": ""
+  },
+  "directories": {
+    "example": "../../temps/example_temps"
+  },
+"dcloudext": {
+    "sale": {
+      "regular": {
+        "price": "0.00"
+      },
+      "sourcecode": {
+        "price": "0.00"
+      }
+    },
+    "contact": {
+      "qq": ""
+    },
+    "declaration": {
+      "ads": "无",
+      "data": "无",
+      "permissions": "无"
+    },
+    "npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui",
+    "type": "component-vue"
+  },
+  "uni_modules": {
+    "dependencies": ["uni-scss"],
+    "encrypt": [],
+    "platforms": {
+      "cloud": {
+        "tcb": "y",
+        "aliyun": "y"
+      },
+      "client": {
+        "App": {
+          "app-vue": "y",
+          "app-nvue": "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"
+        }
+      }
+    }
+  }
+}

+ 10 - 0
uni_modules/uni-badge/readme.md

@@ -0,0 +1,10 @@
+## Badge 数字角标
+> **组件名:uni-badge**
+> 代码块: `uBadge`
+
+数字角标一般和其它控件(列表、9宫格等)配合使用,用于进行数量提示,默认为实心灰色背景,
+
+### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-badge)
+#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 
+
+