rabin 5 anni fa
commit
9b54e3b209

+ 251 - 0
App.vue

@@ -0,0 +1,251 @@
+<script>
+	import Vue from 'vue'
+	export default {
+		onLaunch: function() {
+			uni.getSystemInfo({
+				success: function(e) {
+					// #ifndef MP
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					if (e.platform == 'android') {
+						Vue.prototype.CustomBar = e.statusBarHeight + 50;
+					} else {
+						Vue.prototype.CustomBar = e.statusBarHeight + 45;
+					};
+					// #endif
+
+					// #ifdef MP-WEIXIN
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					let custom = wx.getMenuButtonBoundingClientRect();
+					Vue.prototype.Custom = custom;
+					Vue.prototype.CustomBar = custom.bottom + custom.top - e.statusBarHeight;
+					// #endif		
+
+					// #ifdef MP-ALIPAY
+					Vue.prototype.StatusBar = e.statusBarHeight;
+					Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
+					// #endif
+				}
+			})
+
+			Vue.prototype.ColorList = [{
+					title: '嫣红',
+					name: 'red',
+					color: '#e54d42'
+				},
+				{
+					title: '桔橙',
+					name: 'orange',
+					color: '#f37b1d'
+				},
+				{
+					title: '明黄',
+					name: 'yellow',
+					color: '#fbbd08'
+				},
+				{
+					title: '橄榄',
+					name: 'olive',
+					color: '#8dc63f'
+				},
+				{
+					title: '森绿',
+					name: 'green',
+					color: '#39b54a'
+				},
+				{
+					title: '天青',
+					name: 'cyan',
+					color: '#1cbbb4'
+				},
+				{
+					title: '海蓝',
+					name: 'blue',
+					color: '#0081ff'
+				},
+				{
+					title: '姹紫',
+					name: 'purple',
+					color: '#6739b6'
+				},
+				{
+					title: '木槿',
+					name: 'mauve',
+					color: '#9c26b0'
+				},
+				{
+					title: '桃粉',
+					name: 'pink',
+					color: '#e03997'
+				},
+				{
+					title: '棕褐',
+					name: 'brown',
+					color: '#a5673f'
+				},
+				{
+					title: '玄灰',
+					name: 'grey',
+					color: '#8799a3'
+				},
+				{
+					title: '草灰',
+					name: 'gray',
+					color: '#aaaaaa'
+				},
+				{
+					title: '墨黑',
+					name: 'black',
+					color: '#333333'
+				},
+				{
+					title: '雅白',
+					name: 'white',
+					color: '#ffffff'
+				},
+			]
+
+		},
+		onShow: function() {
+			//console.log('App Show')
+		},
+		onHide: function() {
+			//console.log('App Hide')
+		}
+
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+	@import "static/colorui/main.css";
+	@import "static/colorui/icon.css";
+	
+	.nav-list {
+		display: flex;
+		flex-wrap: wrap;
+		padding: 0px 40upx 0px;
+		justify-content: space-between;
+	}
+	
+	.nav-li {
+		padding: 30upx;
+		border-radius: 12upx;
+		width: 45%;
+		margin: 0 2.5% 40upx;
+		background-image: url(https://cdn.nlark.com/yuque/0/2019/png/280374/1552996358352-assets/web-upload/cc3b1807-c684-4b83-8f80-80e5b8a6b975.png);
+		background-size: cover;
+		background-position: center;
+		position: relative;
+		z-index: 1;
+	}
+	
+	.nav-li::after {
+		content: "";
+		position: absolute;
+		z-index: -1;
+		background-color: inherit;
+		width: 100%;
+		height: 100%;
+		left: 0;
+		bottom: -10%;
+		border-radius: 10upx;
+		opacity: 0.2;
+		transform: scale(0.9, 0.9);
+	}
+	
+	.nav-li.cur {
+		color: #fff;
+		background: rgb(94, 185, 94);
+		box-shadow: 4upx 4upx 6upx rgba(94, 185, 94, 0.4);
+	}
+	
+	.nav-title {
+		font-size: 32upx;
+		font-weight: 300;
+	}
+	
+	.nav-title::first-letter {
+		font-size: 40upx;
+		margin-right: 4upx;
+	}
+	
+	.nav-name {
+		font-size: 28upx;
+		text-transform: Capitalize;
+		margin-top: 20upx;
+		position: relative;
+	}
+	
+	.nav-name::before {
+		content: "";
+		position: absolute;
+		display: block;
+		width: 40upx;
+		height: 6upx;
+		background: #fff;
+		bottom: 0;
+		right: 0;
+		opacity: 0.5;
+	}
+	
+	.nav-name::after {
+		content: "";
+		position: absolute;
+		display: block;
+		width: 100upx;
+		height: 1px;
+		background: #fff;
+		bottom: 0;
+		right: 40upx;
+		opacity: 0.3;
+	}
+	
+	.nav-name::first-letter {
+		font-weight: bold;
+		font-size: 36upx;
+		margin-right: 1px;
+	}
+	
+	.nav-li text {
+		position: absolute;
+		right: 30upx;
+		top: 30upx;
+		font-size: 52upx;
+		width: 60upx;
+		height: 60upx;
+		text-align: center;
+		line-height: 60upx;
+	}
+	
+	.text-light {
+		font-weight: 300;
+	}
+	
+	@keyframes show {
+		0% {
+			transform: translateY(-50px);
+		}
+	
+		60% {
+			transform: translateY(40upx);
+		}
+	
+		100% {
+			transform: translateY(0px);
+		}
+	}
+	
+	@-webkit-keyframes show {
+		0% {
+			transform: translateY(-50px);
+		}
+	
+		60% {
+			transform: translateY(40upx);
+		}
+	
+		100% {
+			transform: translateY(0px);
+		}
+	}
+</style>

+ 69 - 0
components/colorui/cu-custom.vue

@@ -0,0 +1,69 @@
+<template>
+	<view>
+		<view class="cu-custom" :style="[{height:CustomBar + 'px'}]">
+			<view class="cu-bar fixed" :style="style" :class="[bgImage!=''?'none-bg text-white bg-img':'',bgColor]">
+				<view class="action" @tap="BackPage" v-if="isBack">
+					<text class="cuIcon-back"></text>
+					<slot name="backText"></slot>
+				</view>
+				<view class="content" :style="[{top:StatusBar + 'px'}]">
+					<slot name="content"></slot>
+				</view>
+				<slot name="right"></slot>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				StatusBar: this.StatusBar,
+				CustomBar: this.CustomBar
+			};
+		},
+		name: 'cu-custom',
+		computed: {
+			style() {
+				var StatusBar= this.StatusBar;
+				var CustomBar= this.CustomBar;
+				var bgImage = this.bgImage;
+				var style = `height:${CustomBar}px;padding-top:${StatusBar}px;`;
+				if (this.bgImage) {
+					style = `${style}background-image:url(${bgImage});`;
+				}
+				return style
+			}
+		},
+		props: {
+			bgColor: {
+				type: String,
+				default: ''
+			},
+			isBack: {
+				type: [Boolean, String],
+				default: false
+			},
+			bgImage: {
+				type: String,
+				default: ''
+			},
+		},
+		methods: {
+			BackPage() {
+				if (getCurrentPages().length < 2 && 'undefined' !== typeof __wxConfig) {
+					let url = '/' + __wxConfig.pages[0]
+					return uni.redirectTo({url})
+				}
+				uni.navigateBack({
+					delta: 1
+				});
+			}
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 212 - 0
components/dever/config.js

@@ -0,0 +1,212 @@
+//基本配置项
+const base = {
+	debug: false
+}
+//上传配置
+const upload = {
+	url: 'http://laipinbei.txhsai.vip/yxd/api.plugs/plupload',
+	name: 'file',
+}
+
+//http request请求配置
+const request = {
+	//	服务器接口地址
+	
+	// host: "http://laipinbei.txhsai.vip/", //正式服务器
+	
+	// host: "http://test.txhsai.vip/", //测试服务器
+	host: "http://www.laipinbei.com/", //本地测试
+	
+	//	请求的参数	
+	data: {},
+	//	设置请求的 header,header 中不能设置 Referer。
+	header: {},
+	//	(需大写)有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT	
+	method: "POST",
+	//	json	如果设为json,会尝试对返回的数据做一次 JSON.parse	
+	dataType: "json",
+	//	text	设置响应的数据类型。合法值:text、arraybuffer	1.7.0
+	responseType: "text",
+	//	收到开发者服务成功返回的回调函数	
+	success() {},
+	//	接口调用失败的回调函数	
+	fail() {},
+	//	接口调用结束的回调函数(调用成功、失败都会执行)
+	complete() {},
+}
+
+//后端服务列表
+const server = {
+	// ========== 大A ================
+	//优选店幻灯片
+	'banner': 'youxuan/api.Index/indexBanner',
+	//栏目分类列表
+	'getCategotyList': 'youxuan/api.Index/categotyList',
+	//商铺列表
+	'getShopList': 'youxuan/api.Index/goodShopList',
+	//获取地区
+	'getDistrict': 'youxuan/api.Index/getDistrict',
+	//用户当前的城市
+	'getUsercity': 'youxuan/api.Index/getUsercity',
+	//切换用户当前城市
+	'setUserCity': 'youxuan/api.Index/setUsercity',
+	//商铺入驻表单-第一步
+	'setShopOne': 'youxuan/api.merchant/setShopOne',
+	//商铺入驻表单-第二步
+	'setShopTwo': 'youxuan/api.merchant/setShopTwo',
+	//用户中心-获取当前用户资料
+	'getUserInfo': 'user/api.user_center/getUserInfo',
+	//用户中心-编辑用户资料
+	'updateUserInfo': 'user/api.user_center/updateUserInfo',
+	//用户中心-分享列表
+	'getShareList': 'user/api.user_center/getShareList',
+	//用户中心-已绑定银行卡列表
+	'getUserBankList': 'user/api.bank/getUserBankList',
+	//用户中心-银行卡绑定-添加银行卡
+	'setBankAdd': 'user/api.bank/add',
+	//用户中心-银行卡绑定-获取银行列表
+	'getBankList': 'user/api.bank/getBankList',
+	//用户中心-银行卡绑定-设置默认卡
+	'setDefault': 'user/api.bank/setDefault',
+	//用户中心-提交支付密码
+	'setPayPassword': 'user/api.bank/setPayPassword',
+
+
+	// ========== 小A ================
+	//获取商铺详情
+	'getShopInfo': 'youxuan/api.Merchant/getShopInfo',
+	//获取商铺下商品列表
+	'getShopGoodsInfo': 'yxd/api.Merchant/getShopGoodsInfo',
+	//当前位置
+	'cityByPoints': 'user/api.user/getCityByPoints',
+	//获取城市
+	'getCities': 'youxuan/api.Index/getCities',
+	//获取上级
+	'getShangji': 'user/api.user/getShangji',
+	//用户登录
+	'login': 'user/api.user/login',
+	//找回密码
+	'repassword': 'user/api.user/repassword',
+	//获取验证码
+	'vcode': 'user/api.sms/vcode',
+	// 注册,第一步
+	'register': 'user/api.user/register',
+	//注册,第二步
+	'register_step': 'user/api.user/register_step',
+	//转入银行卡
+	'TransferMoneyBag': 'user/api.money_bag/transfer',
+	// 获取拼呗券列表
+	'volumeList' :'pinbei/api.volume/volumeList',
+	// 拼呗券详情:
+	 'volumeInfo': 'pinbei/api.volume/volumeInfo',
+	// 分享
+	 'share' : 'user/api.share/index',
+	//获取券余额
+	 'getQuan': 'user/api.quan',
+	//获取拼钱券详情:
+	'pintuan':'pinbei/api.volume/pintuan',
+	//拼钱券转出到钱包时,获得一些数字
+	'getNumber':'user/api.money_bag/index',
+	//拼呗可用额度提现到钱包:
+	'pbTixian':'user/api.user_center/pbaward_transfer',
+    //购买拼呗劵
+	 'pbBuy' :'pay/api.index/pb_action',
+	 //修改密码
+	 'password' :'user/api.user_center/repassword',
+	 //分享页面获取上级
+	 'getMyTop' : 'user/api.user_center/getMyTop',
+	//用户建议
+	'setFeedback' : 'user/api.user_center/setFeedback',
+	 // 加油卡列表
+	  'oilList':'shop/api.Oil_Recharge/oilList',
+	 // 加油卡充值
+	 'oilOrder':'shop/api.Oil_Recharge/createOrder',
+	 // 加油卡充值日志
+	 'oilOrderList':'shop/api.Oil_Recharge/oilOrderList',
+	//提额记录	
+	'tiE':'pinbei/api.formula/index',
+	//去提额	
+	 'toTie':'pinbei/api.formula/formula',
+	 //京东商城-领劵说明
+	 'explain':'shop/api.Jd/couponExplain',
+	//优选店-添加商品
+	 'setGoods': 'youxuan/api.Goods/setGoods',
+	 //优选店-获取商品列表
+	 'getGoodslist':'youxuan/api.Goods/getGoodslist',
+		// 获取当前商铺列表
+	  'getShoplist':'youxuan/api.Merchant/getShoplist',
+	  //获取某一个商铺信息
+	  'getMyShopInfo':'youxuan/api.Merchant/getMyShopInfo',
+	  //体验券
+	   'tiyanQuan':'experice/api.index/detail',
+	   //体验券列表
+	   'tiYanList':'experice/api.index/quanList',
+	  //体验券下单
+	  'tiYanOrder':'experice/api.index/createOrder',
+	  
+	  
+
+	// ========== 于斌 ================
+	//送钱券首页
+	'vipIndex': 'vip/api.vip/index.html',
+	//送钱券首页
+	'vipRefer': 'vip/api.vip/refer.html',
+	//购买送钱券
+	'vipBuy': 'vip/api.vip/pay_action.html',
+	//兑换券总额
+	'vipConvert': 'vip/api.vip/convert.html',
+	//首页
+	'home': 'vip/api.vip/home.html',
+	//邀请
+	'invitation': 'user/api.user/checkUser',
+	//大礼包
+	'gift': 'vip/api.vip/gift.html',
+	//大礼包购买
+	'giftBuy': 'vip/api.vip/gift_pay_action.html',
+	//钱包首页
+	'bag' : 'user/api.user_center/bag.html',
+	//提现
+	'exchangeData' : 'user/api.user_center/exchangeData.html',
+	//提现
+	'exchange' : 'user/api.user_center/exchange.html',
+	
+	
+	// ========== Abardca ================
+	//手机充值
+	'phoneList' : 'shop/api.Phone_Recharge/phoneList',
+	//创建话费订单
+	'createOrder' : 'shop/api.Phone_Recharge/createOrder',
+	//手机充值记录
+	'phoneOrderList':'shop/api.Phone_Recharge/phoneOrderList',
+	//京东商城-分类列表
+	 'Jdcates':'shop/api.Jd/cates',
+	 //京东商城-商品列表
+	 'Jdgoods':'shop/api.Jd/goods',
+	 //京东商城-商品详情
+	 'JdgoodInfo':'shop/api.Jd/goodInfo',
+	 //京东商城-领取京东券
+	 'JdgoodCoupon':'shop/api.Jd/goodCoupon',
+	 //领券记录
+	 'couponLog':'shop/api.goods/couponLog',
+	 //版本更新检测
+	 'isUpdate':'app/api.config/isUpdate',
+	 
+	 //淘宝商城-分类列表
+	  'Tbcates':'shop/api.Tb/cates',
+	  //淘宝商城-商品列表
+	  'Tbgoods':'shop/api.Tb/goods',
+	  //淘宝商城-商品详情
+	  'TbgoodInfo':'shop/api.Tb/goodInfo',
+	  //淘宝商城-领取淘宝券
+	  'TbgoodCoupon':'shop/api.Tb/goodCoupon',
+	  //淘宝商城-用券说明
+	  'TbcouponExplain':'shop/api.Tb/couponExplain'
+	
+}
+
+export default {
+	base,
+	request,
+	server,
+	upload
+}

+ 431 - 0
components/dever/index.js

@@ -0,0 +1,431 @@
+//封装好一系列常用的方法 dever
+import config from './config';
+
+//http网络请求
+var http = {
+	//token的key
+	token : 'token',
+	//获取token
+	getToken: function() {
+		return uni.getStorageSync(this.token);
+	},
+	
+	//设置token
+	setToken: function(value) {
+		return uni.setStorageSync(this.token, value);
+	},
+	
+	//设置http的option
+	option: function(options) {
+		if (!options) {
+			options = {};
+		}
+		options[this.token] = this.getToken();
+		return options;
+	},
+	
+	//request请求
+	request: function(vue, url, options, callback, err_callback) {
+		var self = this;
+		if (vue == 'post') {
+			config.request.method = 'POST';
+			vue = false;
+		} else {
+			config.request.method = 'GET';
+		}
+		if (typeof(url) == 'object') {
+			vue = url[1];
+			url = url[0];
+		}
+		if (typeof(vue) == 'object') {
+			vue.isDisabled = true;
+		}
+		self.core(url, options).then((result, state) => {
+			if (typeof(vue) == 'object') {
+				if (!vue.fetch) {
+					vue.fetch = {}
+				}
+				vue.isDisabled = false;
+				vue.fetch = Object.assign({}, vue.fetch, result)
+			}
+			
+			if (callback) {
+				callback(result);
+			}
+		}).catch((result) => {
+			if (typeof(vue) == 'object') {
+				vue.isDisabled = false;
+			}
+			if (err_callback) {
+				err_callback(result);
+			} else {
+				if (result.code == '2') {
+					dever.location(dever.login);
+				} else {
+					dever.alert(result.msg)
+				}
+			}
+		})
+	},
+	
+	core : function(url, options) {
+		var self = this;
+		options = this.option(options);
+
+		if (config.server[url]) {
+			config.request.url = config.server[url];
+		} else {
+			config.request.url = url;
+		}
+		config.request.url = config.request.host + config.request.url;
+		config.request.data = options;
+		return new Promise((resolve, reject) => {
+			config.request.complete = (response) => {
+				dever.debug(response);
+				uni.hideLoading()
+				uni.hideNavigationBarLoading();
+				if (response.statusCode === 200) {
+					if (response.data.code == '0') {
+						if (options.page && options.page > 0) {
+							page.state = true;
+							if (page.key && response.data.data[page.key].length > 0) {
+								page.data = page.data.concat(response.data.data[page.key]);
+								response.data.data[page.key] = page.data;
+							} else if (response.data.data.length > 0) {
+								page.data = page.data.concat(response.data.data);
+								response.data.data = page.data;
+							} else {
+								page.state = false;
+								resolve(response.data.data, false);
+								return;
+							}
+						}
+						resolve(response.data.data);
+					} else {
+						reject(response.data)
+					}
+				} else {
+					// 处理catch 请求,不在本页面之外处理,统一在这里处理
+					if (options && options.handle) {
+						reject(response)
+					} else {
+						try {
+							Promise.reject(response).catch(err => {
+								self.error(response.statusCode || response.errMsg);
+							});
+						} catch (e) {
+							dever.alert(e)
+						}
+					}
+				}
+			}
+			//uni.request(Object.assign({}, config, options));
+			dever.debug(config.request);
+			uni.showLoading({title: '加载中', mask: true});
+			uni.showNavigationBarLoading();
+			uni.stopPullDownRefresh();
+			uni.request(config.request);
+		})
+	},
+	
+	error : function(err) {
+		switch (err) {
+			case 401:
+				// 错误码404的处理方式
+				console.error("请求背拒绝" + err)
+				break;
+			case 404:
+				// 错误码404的处理方式
+				console.error("没有找到页面"  + err)
+				break;
+			case 500:
+				// 错误码404的处理方式
+				console.error("500服务器错误"  + err)
+				break;
+			case 405:
+				console.error("错误的请求"  + err)
+				break;
+		}
+	},
+}
+
+var page = {
+	//分页控制
+	value : 1,
+	//分页数据
+	data : [],
+	//分页所属的key
+	key : '',
+	//分页状态 true可以分页,false不能分页
+	state : true,
+	
+	//通用的获取数据方法:瀑布流分页 (1,'level')
+	get : function(config, vue, url, options, callback, err_callback) {
+		options = http.option(options);
+		if (typeof(config) == 'object') {
+			var state = config[0];
+			this.key = config[1];
+		} else {
+			var state = config;
+			this.key = '';
+		}
+		if (state == 1) {
+			this.value = 1;
+			this.data = [];
+		} else {
+			this.value++;
+		}
+		
+		if (this.state == false && state != 1) {
+			return;
+		}
+		
+		options.page = this.value;
+		http.request(vue, url, options, callback, err_callback);
+	},
+}
+
+var upload = {
+	data : {},
+	handle : function(key, count, callback) {
+		if (!count) {
+			count = 1;
+		}
+		var type = 1;
+		if (count > 1) {
+			type = 2;
+		}
+		var self = this;
+		count = parseInt(count);
+		uni.chooseImage({
+			count: count,
+			sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
+			sourceType: ['album'], //从相册选择
+			success: res => {
+				uni.showLoading();
+				res.tempFilePaths.forEach(function(item, index) {
+					//请求上传接口
+					uni.uploadFile({
+						url: config.upload.url, //仅为示例,非真实的接口地址
+						filePath: item,
+						name: config.upload.name,
+						formData: { token: http.getToken() },
+						success: res => {
+							dever.debug(res);
+							var data = JSON.parse(res.data);
+							uni.hideLoading();
+							if (data.uploaded) {
+								var backUrl = data.url;
+								if (count > 1) {
+									if (!self.data[key]) {
+										self.data[key] = [];
+									}
+									self.data[key].push(backUrl);
+								} else {
+									self.data[key] = backUrl;
+								}
+								if (callback) {
+									callback(type, self.data[key]);
+								}
+							} else if (data.uploaded == false) {
+								uni.showToast({ title: '上传失败,请重新上传', icon: 'none' });
+								uni.hideLoading();
+							}
+						}
+					});
+				});
+			},
+			fail: () => {
+				uni.showToast({ title: '图片上传失败,请重试', icon: 'none' });
+				uni.hideLoading();
+			}
+		});
+	},
+	
+	uploadDel : function(key, index, callback) {
+		var self = this;
+		uni.showModal({
+			content: '确定要删除吗?',
+			cancelText: '取消',
+			confirmText: '确定',
+			success: res => {
+				if (res.confirm) {
+					self.data[key].splice(index, 1);
+					if (callback) {
+						callback(res, index);
+					}
+				}
+			}
+		});
+	}
+}
+
+var dever = {
+	login : 'login/login',
+	web_view : '/components/dever/pages/web_view',
+	//页面跳转
+	location : function(path, go) {
+		if (path.indexOf('http') > -1) {
+			this.debug('http:' + path);
+			this.data('web_view', path);
+			/*
+			//#ifdef APP-PLUS
+			uni.navigateTo({
+				url: this.web_view
+			})
+			//#endif
+
+			//#ifdef MP-WEIXIN
+			uni.navigateTo({
+				url: this.web_view
+			})
+			//#endif
+			
+			//#ifndef H5
+			window.location.href = path;
+			//#endif
+			*/
+		   if (go) {
+			   //#ifdef APP-PLUS
+			   uni.navigateTo({
+			   	url: this.web_view
+			   })
+			   //#endif
+			   
+			   //#ifdef MP-WEIXIN
+			   uni.navigateTo({
+			   	url: this.web_view
+			   })
+			   //#endif
+			   
+			   if (go == 'location') {
+				   window.location.href = path;
+			   } else {
+				   var url = window.location.href;
+				   url = url.replace(go, 'paySuccess');
+				   url = window.btoa(url);
+				   window.location.href = path + '&refer=' + url + '&token=' + this.getToken();
+			   }
+		   } else {
+			   uni.navigateTo({
+			   	url: this.web_view
+			   })
+		   }
+		} else {
+			this.debug('navigateTo:' + path);
+			if (go) {
+				uni.switchTab({
+					url: '/pages/' + path
+				})
+			} else {
+				uni.navigateTo({
+					url: '/pages/' + path
+				})
+			}
+		}
+	},
+	
+	//提示信息
+	alert : function(msg, icon, callback) {
+		if (!icon) {
+			icon = 'none'
+		}
+		if (msg) {
+			uni.showToast({title: msg, icon: icon});
+		}
+		this.debug('alert:' + msg)
+		if (callback) {
+			this.debug('callback:' + callback)
+			setTimeout(function(){
+				callback();
+			}, 1000)
+		}
+	},
+	
+	//debug调试
+	debug : function(string) {
+		if (config.base.debug) {
+			this.log(string);
+		}
+	},
+	
+	//记录日志
+	log : function(string) {
+		console.log(string);
+	},
+	
+	//获取token
+	getToken: function() {
+		return http.getToken();
+	},
+	
+	//设置token
+	setToken: function(value) {
+		return http.setToken(value);
+	},
+	
+	//通用的提交数据的方法
+	post : function(url, options, callback, err_callback) {
+		http.request('post', url, options, callback, err_callback);
+	},
+	
+	//通用的获取数据方法
+	get : function(vue, url, options, callback, err_callback) {
+		http.request(vue, url, options, callback, err_callback);
+	},
+	
+	//通用的获取数据方法
+	page : function(config, vue, url, options, callback, err_callback) {
+		page.get(config, vue, url, options, callback, err_callback);
+	},
+
+	//上传
+	upload : function(id, count, callback) {
+		upload.handle(id, count, callback);
+	},
+	
+	//删除上传
+	uploadDel : function(id, index, callback) {
+		upload.uploadDel(id, index, callback);
+	},
+	
+	//验证登录
+	checkLogin : function() {
+		if (!this.getToken()) {
+			this.location(this.login);
+		}
+	},
+	//检查更新
+	checkUpdate : function(gotoUrl) {
+		var version = '1.0.0';//更新版本号,每次更新需要重新更换
+		http.request('post', 'isUpdate', {}, function(res){
+			console.log('version5',res)
+			if(version != res.info.app_version){
+				if(res.info.is_update == 1){
+					uni.showToast({
+						title:'当前更新版本,正在为你跳转更新',
+						icon:'none',
+						duration:3000
+					});
+					setTimeout(function(){
+						uni.navigateTo({
+							url: gotoUrl
+						});
+					}, 3000);
+				}
+			}
+		});
+	},
+	
+	//数据存储
+	data : function(key, value) {
+		if (value) {
+			uni.setStorageSync(key, value);
+			return value;
+		} else {
+			return uni.getStorageSync(key);
+		}
+	}
+}
+
+module.exports = dever

+ 28 - 0
components/dever/pages/web_view.vue

@@ -0,0 +1,28 @@
+<template>
+	<view>
+	        <web-view :src="url" @message="callback"></web-view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			url: '',
+		};
+	},
+	onLoad: function(option) {
+		this.url = this.Dever.data('web_view');
+	},
+	onShow: function() {},
+
+	methods: {
+		callback(e) {
+			
+		},
+	}
+};
+</script>
+
+<style>
+</style>

+ 30 - 0
components/mescroll-uni/mescroll-uni-option.js

@@ -0,0 +1,30 @@
+// mescroll 全局配置
+const GlobalOption = {
+	down: {
+		// 其他down的配置参数也可以写,这里只展示了常用的配置:
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		offset: 80 // 在列表顶部,下拉大于80upx,松手即可触发下拉刷新的回调
+	},
+	up: {
+		// 其他up的配置参数也可以写,这里只展示了常用的配置:
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '-- END --', // 没有更多数据的提示文本
+		offset: 80, // 距底部多远时,触发upCallback
+		isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: "http://www.mescroll.com/img/mescroll-totop.png?v=1", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+			duration: 300, // 回到顶部的动画时长,默认300ms
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: "http://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
+			tip: '~ 暂无相关数据 ~' // 提示
+		}
+	}
+}
+
+export default GlobalOption

+ 224 - 0
components/mescroll-uni/mescroll-uni.css

@@ -0,0 +1,224 @@
+/* mescroll-uni
+ * version 1.1.8
+ * 2019-11-01 wenju
+ * http://www.mescroll.com
+ */
+
+page {
+	height: 100%;
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+	-webkit-overflow-scrolling: touch; /*使iOS列表滑动流畅*/
+}
+
+.mescroll-uni-warp{
+	height: 100%;
+}
+
+.mescroll-uni {
+	position: relative;
+	width: 100%;
+	height: 100%;
+	min-height: 200upx;
+	overflow-y: auto;
+	box-sizing: border-box; /* 避免设置padding出现双滚动条的问题 */
+}
+
+/* 定位的方式固定高度 */
+.mescroll-uni-fixed{
+	z-index: 1;
+	position: fixed;
+	top: 0;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	width: auto; /* 使right生效 */
+	height: auto; /* 使bottom生效 */
+}
+
+/* 下拉刷新区域 */
+.mescroll-downwarp {
+	position: absolute;
+	top: -100%;
+	left: 0;
+	width: 100%;
+	height: 100%;
+	text-align: center;
+}
+
+/* 下拉刷新--内容区,定位于区域底部 */
+.mescroll-downwarp .downwarp-content {
+	position: absolute;
+	left: 0;
+	bottom: 0;
+	width: 100%;
+	min-height: 60upx;
+	padding: 20upx 0;
+	text-align: center;
+}
+
+/* 上拉加载区域 */
+.mescroll-upwarp {
+	min-height: 60upx;
+	padding: 30upx 0;
+	text-align: center;
+	clear: both;
+}
+
+/* 下拉刷新,上拉加载--提示文本 */
+.mescroll-downwarp .downwarp-tip,
+.mescroll-upwarp .upwarp-tip,
+.mescroll-upwarp .upwarp-nodata {
+	display: inline-block;
+	font-size: 28upx;
+	color: gray;
+	vertical-align: middle;
+}
+
+.mescroll-downwarp .downwarp-tip,
+.mescroll-upwarp .upwarp-tip {
+	margin-left: 16upx;
+}
+
+/* 下拉刷新,上拉加载--旋转进度条 */
+.mescroll-downwarp .downwarp-progress,
+.mescroll-upwarp .upwarp-progress {
+	display: inline-block;
+	width: 32upx;
+	height: 32upx;
+	border-radius: 50%;
+	border: 2upx solid gray;
+	border-bottom-color: transparent;
+	vertical-align: middle;
+}
+
+/* 旋转动画 */
+.mescroll-rotate {
+	-webkit-animation: mescrollRotate 0.6s linear infinite;
+	animation: mescrollRotate 0.6s linear infinite;
+}
+
+@-webkit-keyframes mescrollRotate {
+	0% {
+		-webkit-transform: rotate(0deg);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+	}
+}
+
+@keyframes mescrollRotate {
+	0% {
+		transform: rotate(0deg);
+	}
+
+	100% {
+		transform: rotate(360deg);
+	}
+}
+
+/* 无任何数据的空布局 */
+.mescroll-empty {
+	box-sizing: border-box;
+	width: 100%;
+	padding: 40upx;
+	text-align: center;
+}
+
+.mescroll-empty.empty-fixed {
+	z-index: 99;
+	position: fixed; /*transform会使fixed失效,最终会降级为absolute */
+	top: 20%;
+	left: 0;
+}
+
+.mescroll-empty .empty-icon {
+	width: 45%;
+}
+
+.mescroll-empty .empty-tip {
+	margin-top: 20upx;
+	font-size: 24upx;
+	color: gray;
+}
+
+.mescroll-empty .empty-btn {
+	display: inline-block;
+	margin-top: 40upx;
+	min-width: 200upx;
+	padding: 18upx;
+	font-size: 28upx;
+	border: 1upx solid #E04B28;
+	border-radius: 60upx;
+	color: #E04B28;
+}
+
+.mescroll-empty .empty-btn:active {
+	opacity: .75;
+}
+
+/* 回到顶部的按钮 */
+.mescroll-totop {
+	z-index: 9990;
+	position: fixed !important; /* 避免编译到H5,在多mescroll中定位失效 */
+	right: 20upx;
+	bottom: 120upx;
+	width: 72upx;
+	height: 72upx;
+	border-radius: 50%;
+	opacity: 0;
+}
+
+/* 显示动画--淡入 */
+.mescroll-lazy-in,
+.mescroll-fade-in {
+	-webkit-animation: mescrollFadeIn .3s linear forwards;
+	animation: mescrollFadeIn .3s linear forwards;
+}
+
+@-webkit-keyframes mescrollFadeIn {
+	0% {
+		opacity: 0;
+	}
+
+	100% {
+		opacity: 1;
+	}
+}
+
+@keyframes mescrollFadeIn {
+	0% {
+		opacity: 0;
+	}
+
+	100% {
+		opacity: 1;
+	}
+}
+
+/* 隐藏动画--淡出 */
+.mescroll-fade-out {
+	pointer-events: none;
+	-webkit-animation: mescrollFadeOut .5s linear forwards;
+	animation: mescrollFadeOut .5s linear forwards;
+}
+
+@-webkit-keyframes mescrollFadeOut {
+	0% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0;
+	}
+}
+
+@keyframes mescrollFadeOut {
+	0% {
+		opacity: 1;
+	}
+
+	100% {
+		opacity: 0;
+	}
+}

+ 747 - 0
components/mescroll-uni/mescroll-uni.js

@@ -0,0 +1,747 @@
+/* mescroll-uni
+ * version 1.1.8
+ * 2019-11-01 wenju
+ * http://www.mescroll.com
+ */
+
+export default function MeScroll(options) {
+	let me = this;
+	me.version = '1.1.8'; // mescroll版本号
+	me.options = options || {}; // 配置
+
+	me.isDownScrolling = false; // 是否在执行下拉刷新的回调
+	me.isUpScrolling = false; // 是否在执行上拉加载的回调
+	let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
+
+	// 初始化下拉刷新
+	me.initDownScroll();
+	// 初始化上拉加载,则初始化
+	me.initUpScroll();
+
+	// 自动加载
+	setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+		// 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
+		if (me.optDown.use && me.optDown.auto && hasDownCallback) {
+			if (me.optDown.autoShowLoading) {
+				me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
+			} else {
+				me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
+			}
+		}
+		// 自动触发上拉加载
+		me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
+	}, 30); // 需让me.optDown.inited和me.optUp.inited先执行
+}
+
+/* 配置参数:下拉刷新 */
+MeScroll.prototype.extendDownScroll = function(optDown) {
+	// 下拉刷新的配置
+	MeScroll.extend(optDown, {
+		use: true, // 是否启用下拉刷新; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
+		autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
+		isLock: false, // 是否锁定下拉刷新,默认false;
+		offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
+		startTop: 100, // scroll-view滚动到顶部时,此时的scroll-top不一定为0, 此值用于控制最大的误差
+		fps: 40, // 下拉节流 (值越大每秒刷新频率越高)
+		inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
+		bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
+		minAngle: 45, // 向下滑动最少偏移的角度,取值区间  [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
+		textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
+		textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
+		textLoading: '加载中 ...', // 加载中的提示文本
+		inited: null, // 下拉刷新初始化完毕的回调
+		inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
+		outOffset: null, // 下拉的距离大于offset那一刻的回调
+		onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+		beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
+		showLoading: null, // 显示下拉刷新进度的回调
+		afterLoading: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
+		endDownScroll: null, // 结束下拉刷新的回调
+		callback: function(mescroll) {
+			// 下拉刷新的回调;默认重置上拉加载列表为第一页
+			mescroll.resetUpScroll();
+		}
+	})
+}
+
+/* 配置参数:上拉加载 */
+MeScroll.prototype.extendUpScroll = function(optUp) {
+	// 上拉加载的配置
+	MeScroll.extend(optUp, {
+		use: true, // 是否启用上拉加载; 默认true
+		auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+		isLock: false, // 是否锁定上拉加载,默认false;
+		isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
+		isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
+		callback: null, // 上拉加载的回调;function(page,mescroll){ }
+		page: {
+			num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+			size: 10, // 每页数据的数量
+			time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
+		},
+		noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
+		offset: 80, // 距底部多远时,触发upCallback
+		textLoading: '加载中 ...', // 加载中的提示文本
+		textNoMore: '-- END --', // 没有更多数据的提示文本
+		inited: null, // 初始化完毕的回调
+		showLoading: null, // 显示加载中的回调
+		showNoMore: null, // 显示无更多数据的回调
+		hideUpScroll: null, // 隐藏上拉加载的回调
+		toTop: {
+			// 回到顶部按钮,需配置src才显示
+			src: null, // 图片路径,默认null (建议写成网络图,不必考虑相对路径)
+			offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
+			duration: 300, // 回到顶部的动画时长,默认300ms
+			btnClick: null, // 点击按钮的回调
+			onShow: null // 是否显示的回调
+		},
+		empty: {
+			use: true, // 是否显示空布局
+			icon: null, // 图标路径
+			tip: '~ 暂无相关数据 ~', // 提示
+			btnText: '', // 按钮
+			btnClick: null, // 点击按钮的回调
+			onShow: null // 是否显示的回调
+		},
+		onScroll: false // 是否监听滚动事件
+	})
+}
+
+/* 配置参数 */
+MeScroll.extend = function(userOption, defaultOption) {
+	if (!userOption) return defaultOption;
+	for (let key in defaultOption) {
+		if (userOption[key] == null) {
+			let def = defaultOption[key];
+			if (def != null && typeof def === 'object') {
+				userOption[key] = MeScroll.extend({}, def); // 深度匹配
+			} else {
+				userOption[key] = def;
+			}
+		} else if (typeof userOption[key] === 'object') {
+			MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
+		}
+	}
+	return userOption;
+}
+
+/* -------初始化下拉刷新------- */
+MeScroll.prototype.initDownScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optDown = me.options.down || {};
+	me.extendDownScroll(me.optDown);
+
+	me.downHight = 0; // 下拉区域的高度
+
+	// 在页面中加入下拉布局
+	if (me.optDown.use && me.optDown.inited) {
+		// 初始化完毕的回调
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optDown.inited(me);
+		}, 0)
+	}
+}
+
+/* 列表touchstart事件 */
+MeScroll.prototype.touchstartEvent = function(e) {
+	if (!this.optDown.use) return;
+
+	this.startPoint = this.getPoint(e); // 记录起点
+	this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
+	this.lastPoint = this.startPoint; // 重置上次move的点
+	this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
+	this.inTouchend = false; // 标记不是touchend
+}
+
+/* 列表touchmove事件 */
+MeScroll.prototype.touchmoveEvent = function(e) {
+	if (!this.optDown.use) return;
+	if (!this.startPoint) return;
+	let me = this;
+
+	// 节流
+	let t = new Date().getTime();
+	if (me.moveTime && t - me.moveTime < me.moveTimeDiff) { // 小于节流时间,则不处理
+		return;
+	} else {
+		me.moveTime = t
+		me.moveTimeDiff = 1000 / me.optDown.fps
+	}
+
+	let scrollTop = me.getScrollTop(); // 当前滚动条的距离
+	let curPoint = me.getPoint(e); // 当前点
+
+	let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+
+	// (向下拉&&在顶部) scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
+	// scroll-view滚动到顶部时,scrollTop不一定为0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
+	if (moveY > 0 && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop))) {
+		// 可下拉的条件
+		if (me.optDown.use && !me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
+				me.optUp.isBoth))) {
+
+			// 下拉的角度是否在配置的范围内
+			let x = Math.abs(me.lastPoint.x - curPoint.x);
+			let y = Math.abs(me.lastPoint.y - curPoint.y);
+			let z = Math.sqrt(x * x + y * y);
+			if (z !== 0) {
+				let angle = Math.asin(y / z) / Math.PI * 180; // 两点之间的角度,区间 [0,90]
+				if (angle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
+			}
+
+			// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
+			if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
+				me.inTouchend = true; // 标记执行touchend
+				me.touchendEvent(); // 提前触发touchend
+				return;
+			}
+
+			me.preventDefault(e); // 阻止默认事件
+
+			let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
+
+			// 下拉距离  < 指定距离
+			if (me.downHight < me.optDown.offset) {
+				if (me.movetype !== 1) {
+					me.movetype = 1; // 加入标记,保证只执行一次
+					me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
+
+				// 指定距离  <= 下拉距离
+			} else {
+				if (me.movetype !== 2) {
+					me.movetype = 2; // 加入标记,保证只执行一次
+					me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
+					me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
+				}
+				if (diff > 0) { // 向下拉
+					me.downHight += Math.round(diff * me.optDown.outOffsetRate); // 越往下,高度变化越小
+				} else { // 向上收
+					me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
+				}
+			}
+
+			let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
+			me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
+		}
+	}
+
+	me.lastPoint = curPoint; // 记录本次移动的点
+}
+
+/* 列表touchend事件 */
+MeScroll.prototype.touchendEvent = function(e) {
+	if (!this.optDown.use) return;
+	// 如果下拉区域高度已改变,则需重置回来
+	if (this.isMoveDown) {
+		if (this.downHight >= this.optDown.offset) {
+			// 符合触发刷新的条件
+			this.triggerDownScroll();
+		} else {
+			// 不符合的话 则重置
+			this.downHight = 0;
+			this.optDown.endDownScroll && this.optDown.endDownScroll(this);
+		}
+		this.movetype = 0;
+		this.isMoveDown = false;
+	} else if (this.getScrollTop() === this.startTop) { // 到顶/左/右/底的滑动事件
+		let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
+		// 上滑 && 检查并触发上拉
+		isScrollUp && this.triggerUpScroll(true);
+	}
+}
+
+/* 根据点击滑动事件获取第一个手指的坐标 */
+MeScroll.prototype.getPoint = function(e) {
+	if (!e) {
+		return {
+			x: 0,
+			y: 0
+		}
+	}
+	if (e.touches && e.touches[0]) {
+		return {
+			x: e.touches[0].pageX,
+			y: e.touches[0].pageY
+		}
+	} else if (e.changedTouches && e.changedTouches[0]) {
+		return {
+			x: e.changedTouches[0].pageX,
+			y: e.changedTouches[0].pageY
+		}
+	} else {
+		return {
+			x: e.clientX,
+			y: e.clientY
+		}
+	}
+}
+
+/* 触发下拉刷新 */
+MeScroll.prototype.triggerDownScroll = function() {
+	if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
+		//return true则处于完全自定义状态
+	} else {
+		this.showDownScroll(); // 下拉刷新中...
+		this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示下拉进度布局 */
+MeScroll.prototype.showDownScroll = function() {
+	this.isDownScrolling = true; // 标记下拉中
+	this.downHight = this.optDown.offset; // 更新下拉区域高度
+	this.optDown.showLoading(this, this.downHight); // 下拉刷新中...
+}
+
+/* 结束下拉刷新 */
+MeScroll.prototype.endDownScroll = function() {
+	let me = this;
+	// 结束下拉刷新的方法
+	let endScroll = function() {
+		me.downHight = 0;
+		me.isDownScrolling = false;
+		me.optDown.endDownScroll && me.optDown.endDownScroll(me);
+		me.setScrollHeight(0) // 重置滚动区域,使数据不满屏时仍可检查触发翻页
+	}
+	// 结束下拉刷新时的回调
+	let delay = 0;
+	if (me.optDown.afterLoading) delay = me.optDown.afterLoading(me); // 结束下拉刷新的延时,单位ms
+	if (typeof delay === 'number' && delay > 0) {
+		setTimeout(endScroll, delay);
+	} else {
+		endScroll();
+	}
+}
+
+/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
+MeScroll.prototype.lockDownScroll = function(isLock) {
+	if (isLock == null) isLock = true;
+	this.optDown.isLock = isLock;
+}
+
+/* -------初始化上拉加载------- */
+MeScroll.prototype.initUpScroll = function() {
+	let me = this;
+	// 配置参数
+	me.optUp = me.options.up || {
+		use: false
+	};
+	me.extendUpScroll(me.optUp);
+
+	if (!me.optUp.isBounce) me.setBounce(false); // 不允许bounce时,需禁止window的touchmove事件
+
+	if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
+	me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
+	me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
+
+	// 初始化完毕的回调
+	if (me.optUp.inited) {
+		setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
+			me.optUp.inited(me);
+		}, 0)
+	}
+}
+
+/*列表滚动事件*/
+MeScroll.prototype.scroll = function(e, onScroll) {
+	// 更新滚动条的位置
+	this.setScrollTop(e.scrollTop);
+	// 更新滚动内容高度
+	this.setScrollHeight(e.scrollHeight);
+
+	// 向上滑还是向下滑动
+	if (this.preScrollY == null) this.preScrollY = 0;
+	this.isScrollUp = e.scrollTop - this.preScrollY > 0;
+	this.preScrollY = e.scrollTop;
+
+	// 上滑 && 检查并触发上拉
+	this.isScrollUp && this.triggerUpScroll(true);
+
+	// 顶部按钮的显示隐藏
+	if (e.scrollTop >= this.optUp.toTop.offset) {
+		this.showTopBtn();
+	} else {
+		this.hideTopBtn();
+	}
+
+	// 滑动监听
+	this.optUp.onScroll && onScroll && onScroll()
+}
+
+/* 触发上拉加载 */
+MeScroll.prototype.triggerUpScroll = function(isCheck) {
+	if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
+		// 是否校验在底部; 默认不校验
+		if (isCheck === true) {
+			let canUp = false;
+			// 还有下一页 && 没有锁定 && 不在下拉中
+			if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
+				if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
+					canUp = true; // 标记可上拉
+				}
+			}
+			if (canUp === false) return;
+		}
+		this.showUpScroll(); // 上拉加载中...
+		this.optUp.page.num++; // 预先加一页,如果失败则减回
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback(this); // 执行回调,联网加载数据
+	}
+}
+
+/* 显示上拉加载中 */
+MeScroll.prototype.showUpScroll = function() {
+	this.isUpScrolling = true; // 标记上拉加载中
+	this.optUp.showLoading && this.optUp.showLoading(this); // 回调
+}
+
+/* 显示上拉无更多数据 */
+MeScroll.prototype.showNoMore = function() {
+	this.optUp.hasNext = false; // 标记无更多数据
+	this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
+}
+
+/* 隐藏上拉区域**/
+MeScroll.prototype.hideUpScroll = function() {
+	this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
+}
+
+/* 结束上拉加载 */
+MeScroll.prototype.endUpScroll = function(isShowNoMore) {
+	if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
+		if (isShowNoMore) {
+			this.showNoMore(); // isShowNoMore=true,显示无更多数据
+		} else {
+			this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
+		}
+	}
+	this.isUpScrolling = false; // 标记结束上拉加载
+}
+
+/* 重置上拉加载列表为第一页
+ *isShowLoading 是否显示进度布局;
+ * 1.默认null,不传参,则显示上拉加载的进度布局
+ * 2.传参true, 则显示下拉刷新的进度布局
+ * 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
+ */
+MeScroll.prototype.resetUpScroll = function(isShowLoading) {
+	if (this.optUp && this.optUp.use) {
+		let page = this.optUp.page;
+		this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
+		this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
+		page.num = this.startNum; // 重置为第一页
+		page.time = null; // 重置时间为空
+		if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
+			if (isShowLoading == null) {
+				this.removeEmpty(); // 移除空布局
+				this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
+			} else {
+				this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
+			}
+		}
+		this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
+		this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
+		this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
+		this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
+	}
+}
+
+/* 设置page.num的值 */
+MeScroll.prototype.setPageNum = function(num) {
+	this.optUp.page.num = num - 1;
+}
+
+/* 设置page.size的值 */
+MeScroll.prototype.setPageSize = function(size) {
+	this.optUp.page.size = size;
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalPage: 总页数(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
+	let hasNext;
+	if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据量(必传)
+ * totalSize: 列表所有数据总数量(必传)
+ * systime: 服务器时间 (可空)
+ */
+MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
+	let hasNext;
+	if (this.optUp.use && totalSize != null) {
+		let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
+		hasNext = loadSize < totalSize; // 是否还有下一页
+	}
+	this.endSuccess(dataSize, hasNext, systime);
+}
+
+/* 联网回调成功,结束下拉刷新和上拉加载
+ * dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
+ * hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
+ * systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
+ */
+MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
+	let me = this;
+	// 结束下拉刷新
+	if (me.isDownScrolling) me.endDownScroll();
+
+	// 结束上拉加载
+	if (me.optUp.use) {
+		let isShowNoMore; // 是否已无更多数据
+		if (dataSize != null) {
+			let pageNum = me.optUp.page.num; // 当前页码
+			let pageSize = me.optUp.page.size; // 每页长度
+			// 如果是第一页
+			if (pageNum === 1) {
+				if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
+			}
+			if (dataSize < pageSize || hasNext === false) {
+				// 返回的数据不满一页时,则说明已无更多数据
+				me.optUp.hasNext = false;
+				if (dataSize === 0 && pageNum === 1) {
+					// 如果第一页无任何数据且配置了空布局
+					isShowNoMore = false;
+					me.showEmpty();
+				} else {
+					// 总列表数少于配置的数量,则不显示无更多数据
+					let allDataSize = (pageNum - 1) * pageSize + dataSize;
+					if (allDataSize < me.optUp.noMoreSize) {
+						isShowNoMore = false;
+					} else {
+						isShowNoMore = true;
+					}
+					me.removeEmpty(); // 移除空布局
+				}
+			} else {
+				// 还有下一页
+				isShowNoMore = false;
+				me.optUp.hasNext = true;
+				me.removeEmpty(); // 移除空布局
+			}
+		}
+
+		// 隐藏上拉
+		me.endUpScroll(isShowNoMore);
+	}
+}
+
+/* 回调失败,结束下拉刷新和上拉加载 */
+MeScroll.prototype.endErr = function() {
+	// 结束下拉,回调失败重置回原来的页码和时间
+	if (this.isDownScrolling) {
+		let page = this.optUp.page;
+		if (page && this.prePageNum) {
+			page.num = this.prePageNum;
+			page.time = this.prePageTime;
+		}
+		this.endDownScroll();
+	}
+	// 结束上拉,回调失败重置回原来的页码
+	if (this.isUpScrolling) {
+		this.optUp.page.num--;
+		this.endUpScroll(false);
+	}
+}
+
+/* 显示空布局 */
+MeScroll.prototype.showEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
+}
+
+/* 移除空布局 */
+MeScroll.prototype.removeEmpty = function() {
+	this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
+}
+
+/* 显示回到顶部的按钮 */
+MeScroll.prototype.showTopBtn = function() {
+	if (!this.topBtnShow) {
+		this.topBtnShow = true;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
+	}
+}
+
+/* 隐藏回到顶部的按钮 */
+MeScroll.prototype.hideTopBtn = function() {
+	if (this.topBtnShow) {
+		this.topBtnShow = false;
+		this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
+	}
+}
+
+/* 获取滚动条的位置 */
+MeScroll.prototype.getScrollTop = function() {
+	return this.scrollTop || 0
+}
+
+/* 记录滚动条的位置 */
+MeScroll.prototype.setScrollTop = function(y) {
+	this.scrollTop = y;
+}
+
+/* 滚动到指定位置 */
+MeScroll.prototype.scrollTo = function(y, t) {
+	this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
+}
+
+/* 自定义scrollTo */
+MeScroll.prototype.resetScrollTo = function(myScrollTo) {
+	this.myScrollTo = myScrollTo
+}
+
+/* 滚动条到底部的距离 */
+MeScroll.prototype.getScrollBottom = function() {
+	return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
+}
+
+/* 计步器
+ star: 开始值
+ end: 结束值
+ callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
+ t: 计步时长,传0则直接回调end值;不传则默认300ms
+ rate: 周期;不传则默认30ms计步一次
+ * */
+MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
+	let diff = end - star; // 差值
+	if (t === 0 || diff === 0) {
+		callback && callback(end);
+		return;
+	}
+	t = t || 300; // 时长 300ms
+	rate = rate || 30; // 周期 30ms
+	let count = t / rate; // 次数
+	let step = diff / count; // 步长
+	let i = 0; // 计数
+	let timer = setInterval(function() {
+		if (i < count - 1) {
+			star += step;
+			callback && callback(star, timer);
+			i++;
+		} else {
+			callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
+			clearInterval(timer);
+		}
+	}, rate);
+}
+
+/* 滚动容器的高度 */
+MeScroll.prototype.getClientHeight = function(isReal) {
+	let h = this.clientHeight || 0
+	if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
+		h = this.getBodyHeight()
+	}
+	return h
+}
+MeScroll.prototype.setClientHeight = function(h) {
+	this.clientHeight = h;
+}
+
+/* 滚动内容的高度 */
+MeScroll.prototype.getScrollHeight = function() {
+	return this.scrollHeight || 0;
+}
+MeScroll.prototype.setScrollHeight = function(h) {
+	this.scrollHeight = h;
+}
+
+/* body的高度 */
+MeScroll.prototype.getBodyHeight = function() {
+	return this.bodyHeight || 0;
+}
+MeScroll.prototype.setBodyHeight = function(h) {
+	this.bodyHeight = h;
+}
+
+/* 阻止浏览器默认滚动事件 */
+MeScroll.prototype.preventDefault = function(e) {
+	// 小程序不支持e.preventDefault
+	// app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止
+	// cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
+	if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
+}
+
+/* 是否允许下拉回弹(橡皮筋效果); true或null为允许; false禁止bounce */
+MeScroll.prototype.setBounce = function(isBounce) {
+	// #ifdef H5
+	if (isBounce === false) {
+		this.optUp.isBounce = false; // 禁止
+		// 标记当前页使用了mescroll (需延时,确保page已切换)
+		setTimeout(function() {
+			let uniPageDom = document.getElementsByTagName('uni-page')[0];
+			uniPageDom && uniPageDom.setAttribute('use_mescroll', true)
+		}, 30);
+		// 避免重复添加事件
+		if (window.isSetBounce) return;
+		window.isSetBounce = true;
+		// 需禁止window的touchmove事件才能有效的阻止bounce
+		window.bounceTouchmove = function(e) {
+			let el = e.target;
+			// 当前touch的元素及父元素是否要拦截touchmove事件
+			let isPrevent = true;
+			while (el !== document.body && el !== document) {
+				if (el.tagName === 'UNI-PAGE') { // 只扫描当前页
+					if (!el.getAttribute('use_mescroll')) {
+						isPrevent = false; // 如果当前页没有使用mescroll,则不阻止
+					}
+					break;
+				}
+				let cls = el.classList;
+				if (cls) {
+					if (cls.contains('mescroll-touch')) { // 采用scroll-view 此处不能过滤mescroll-uni,否则下拉仍然有回弹
+						isPrevent = false; // mescroll-touch无需拦截touchmove事件
+						break;
+					} else if (cls.contains('mescroll-touch-x') || cls.contains('mescroll-touch-y')) {
+						// 如果配置了水平或者垂直滑动
+						let curX = e.touches ? e.touches[0].pageX : e.clientX; // 当前第一个手指距离列表顶部的距离x
+						let curY = e.touches ? e.touches[0].pageY : e.clientY; // 当前第一个手指距离列表顶部的距离y
+						if (!this.preWinX) this.preWinX = curX; // 设置上次移动的距离x
+						if (!this.preWinY) this.preWinY = curY; // 设置上次移动的距离y
+						// 计算两点之间的角度
+						let x = Math.abs(this.preWinX - curX);
+						let y = Math.abs(this.preWinY - curY);
+						let z = Math.sqrt(x * x + y * y);
+						this.preWinX = curX; // 记录本次curX的值
+						this.preWinY = curY; // 记录本次curY的值
+						if (z !== 0) {
+							let angle = Math.asin(y / z) / Math.PI * 180; // 角度区间 [0,90]
+							if ((angle <= 45 && cls.contains('mescroll-touch-x')) || (angle > 45 && cls.contains('mescroll-touch-y'))) {
+								isPrevent = false; // 水平滑动或者垂直滑动,不拦截touchmove事件
+								break;
+							}
+						}
+					}
+				}
+				el = el.parentNode; // 继续检查其父元素
+			}
+			// 拦截touchmove事件:是否可以被禁用&&是否已经被禁用 (这里不使用me.preventDefault(e)的方法,因为某些情况下会报找不到方法的异常)
+			if (isPrevent && e.cancelable && !e.defaultPrevented && typeof e.preventDefault === "function") e.preventDefault();
+		}
+		window.addEventListener('touchmove', window.bounceTouchmove, {
+			passive: false
+		});
+	} else {
+		this.optUp.isBounce = true; // 允许
+		if (window.bounceTouchmove) {
+			window.removeEventListener('touchmove', window.bounceTouchmove);
+			window.bounceTouchmove = null;
+			window.isSetBounce = false;
+		}
+	}
+	// #endif
+}

+ 294 - 0
components/mescroll-uni/mescroll-uni.vue

@@ -0,0 +1,294 @@
+<template>
+	<view class="mescroll-uni-warp">
+		<scroll-view :id="viewId" class="mescroll-uni" :class="{'mescroll-uni-fixed':fixed}" :style="{'padding-top':padTop,'padding-bottom':padBottom,'top':fixedTop,'bottom':fixedBottom}" :scroll-top="scrollTop" :scroll-with-animation="scrollAnim" @scroll="scroll" @touchstart="touchstartEvent" @touchmove="touchmoveEvent" @touchend="touchendEvent" @touchcancel="touchendEvent" :scroll-y='scrollAble' :throttle="mescroll.optUp.onScroll==null" :enable-back-to-top="true">
+			<view :style="{'transform': translateY, 'transition': transition}">
+				<!-- 下拉加载区域-->
+				<view v-if="mescroll.optDown.use" class="mescroll-downwarp">
+					<view class="downwarp-content">
+						<view class="downwarp-progress" :class="{'mescroll-rotate':isDownLoading}" :style="{'transform':downRotate}"></view>
+						<view class="downwarp-tip">{{downText}}</view>
+					</view>
+				</view>
+
+				<!-- 列表内容 -->
+				<slot></slot>
+
+				<!-- 空布局 -->
+				<view v-if="isShowEmpty" class="mescroll-empty" :class="{'empty-fixed':optEmpty.fixed}" :style="{'z-index':optEmpty.zIndex,'top':optEmpty.top}">
+					<image v-if="optEmpty.icon" class="empty-icon" :src="optEmpty.icon" mode="widthFix" />
+					<view v-if="optEmpty.tip" class="empty-tip">{{optEmpty.tip}}</view>
+					<view v-if="optEmpty.btnText" class="empty-btn" @click="emptyClick">{{optEmpty.btnText}}</view>
+				</view>
+
+				<!-- 上拉加载区域 -->
+				<view v-if="mescroll.optUp.use" class="mescroll-upwarp">
+					<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
+					<view v-show="isUpLoading">
+						<view class="upwarp-progress mescroll-rotate"></view>
+						<view class="upwarp-tip">{{mescroll.optUp.textLoading}}</view>
+					</view>
+					<!-- 无数据 -->
+					<view v-if="!isDownLoading && isUpNoMore" class="upwarp-nodata">{{mescroll.optUp.textNoMore}}</view>
+				</view>
+			</view>
+		</scroll-view>
+
+		<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
+		<image v-if="mescroll.optUp.toTop.src" class="mescroll-totop" :class="{'mescroll-fade-in':isShowToTop}" :src="mescroll.optUp.toTop.src" mode="widthFix" @click="toTopClick" />
+	</view>
+</template>
+
+<script>
+	// 引入mescroll-uni.js,处理核心逻辑
+	import MeScroll from './mescroll-uni.js';
+	// 引入全局配置
+	import GlobalOption from './mescroll-uni-option.js';
+
+	export default {
+		data() {
+			return {
+				mescroll: null, // mescroll实例
+				viewId: 'id_' + Math.random().toString(36).substr(2), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
+				downHight: 0, //下拉刷新: 容器高度
+				downRotate: 0, //下拉刷新: 圆形进度条旋转的角度
+				downText: '', //下拉刷新: 提示的文本
+				isDownReset: false, //下拉刷新: 是否显示重置的过渡动画
+				isDownLoading: false, //下拉刷新: 是否显示加载中
+				isUpLoading: false, // 上拉加载: 是否显示 "加载中..."
+				isUpNoMore: false, // 上拉加载: 是否显示 "-- END --"
+				isShowEmpty: false, // 是否显示空布局
+				isShowToTop: false, // 是否显示回到顶部按钮
+				scrollAble: true, // 是否禁止下滑 (下拉时禁止,避免抖动)
+				scrollTop: 0, // 滚动条的位置
+				scrollAnim: false, // 是否开启滚动动画
+				windowTop: 0, // 可使用窗口的顶部位置
+				windowBottom: 0 // 可使用窗口的底部位置
+			}
+		},
+		props: {
+			down: Object, // 下拉刷新的参数配置
+			up: Object, // 上拉加载的参数配置
+			top: [String, Number], // 下拉布局往下偏移的数值, 已默认单位为upx.
+			bottom: [String, Number], // 上拉布局往上偏移的数值, 已默认单位为upx.
+			fixed: { // 是否通过fixed固定mescroll的高度, 默认true
+				type: Boolean,
+				default () {
+					return false
+				}
+			}
+		},
+		computed: {
+			// top数值,单位upx,需转成px. 目的是使下拉布局往下偏移
+			numTop() {
+				return uni.upx2px(Number(this.top || 0))
+			},
+			fixedTop() {
+				return this.fixed ? (this.numTop + this.windowTop) + 'px' : 0
+			},
+			padTop() {
+				return !this.fixed ? this.numTop + 'px' : 0
+			},
+			// bottom数值,单位upx,需转成px 目的是使上拉布局往上偏移
+			numBottom() {
+				return uni.upx2px(Number(this.bottom || 0))
+			},
+			fixedBottom() {
+				return this.fixed ? (this.numBottom + this.windowBottom) + 'px' : 0
+			},
+			padBottom() {
+				return !this.fixed ? this.numBottom + 'px' : 0
+			},
+			// 空布局的配置
+			optEmpty() {
+				return this.mescroll.optUp.empty
+			},
+			// 过渡
+			transition() {
+				return this.isDownReset ? 'transform 300ms' : ''
+			},
+			translateY() {
+				return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : '' // transform会使fixed失效,需注意把fixed元素写在mescroll之外
+			}
+		},
+		methods: {
+			//注册列表滚动事件,用于下拉刷新
+			scroll(e) {
+				this.mescroll.scroll(e.detail, () => {
+					this.$emit('scroll', this.mescroll) // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
+				})
+			},
+			//注册列表touchstart事件,用于下拉刷新
+			touchstartEvent(e) {
+				this.mescroll.touchstartEvent(e);
+			},
+			//注册列表touchmove事件,用于下拉刷新
+			touchmoveEvent(e) {
+				this.mescroll.touchmoveEvent(e);
+			},
+			//注册列表touchend事件,用于下拉刷新
+			touchendEvent(e) {
+				this.mescroll.touchendEvent(e);
+			},
+			// 点击空布局的按钮回调
+			emptyClick() {
+				this.$emit('emptyclick', this.mescroll)
+			},
+			// 点击回到顶部的按钮回调
+			toTopClick() {
+				this.isShowToTop = false; // 回到顶部按钮需要先隐藏,再执行回到顶部,避免闪动
+				this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); // 执行回到顶部
+				this.$emit('topclick', this.mescroll); // 派发点击回到顶部按钮的回调
+			},
+			// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
+			setClientHeight() {
+				if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
+					this.isExec = true; // 避免多次获取
+					this.$nextTick(() => { // 确保dom已渲染
+						let view = uni.createSelectorQuery().in(this).select('#' + this.viewId);
+						view.boundingClientRect(data => {
+							this.isExec = false;
+							if (data) {
+								this.mescroll.setClientHeight(data.height);
+							} else if (this.clientNum != 3) { // 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
+								this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
+								setTimeout(() => {
+									this.setClientHeight()
+								}, this.clientNum * 100)
+							}
+						}).exec();
+					})
+				}
+			}
+		},
+		// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
+		created() {
+			let vm = this;
+
+			let diyOption = {
+				// 下拉刷新的配置
+				down: {
+					inOffset(mescroll) {
+						// 下拉的距离进入offset范围内那一刻的回调
+						vm.scrollAble = false; // 禁止下拉,避免抖动 (自定义mescroll组件时,此行不可删)
+						vm.isDownReset = false; // 不重置高度 (自定义mescroll组件时,此行不可删)
+						vm.isDownLoading = false; // 不显示加载中
+						vm.downText = mescroll.optDown.textInOffset; // 设置文本
+					},
+					outOffset(mescroll) {
+						// 下拉的距离大于offset那一刻的回调
+						vm.scrollAble = false; // 禁止下拉,避免抖动 (自定义mescroll组件时,此行不可删)
+						vm.isDownReset = false; // 不重置高度 (自定义mescroll组件时,此行不可删)
+						vm.isDownLoading = false; // 不显示加载中
+						vm.downText = mescroll.optDown.textOutOffset; // 设置文本
+					},
+					onMoving(mescroll, rate, downHight) {
+						// 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downRotate = 'rotate(' + 360 * rate + 'deg)'; // 设置旋转角度
+					},
+					showLoading(mescroll, downHight) {
+						// 显示下拉刷新进度的回调
+						vm.scrollAble = true; // 开启下拉 (自定义mescroll组件时,此行不可删)
+						vm.isDownReset = true; // 重置高度 (自定义mescroll组件时,此行不可删)
+						vm.isDownLoading = true; // 显示加载中
+						vm.downHight = downHight; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+						vm.downText = mescroll.optDown.textLoading; // 设置文本
+					},
+					endDownScroll(mescroll) {
+						vm.scrollAble = true; // 开启下拉 (自定义mescroll组件时,此行不可删)
+						vm.isDownReset = true; // 重置高度 (自定义mescroll组件时,此行不可删)
+						vm.isDownLoading = false; // 不显示加载中
+						vm.downHight = 0; // 设置下拉区域的高度 (自定义mescroll组件时,此行不可删)
+					},
+					// 派发下拉刷新的回调
+					callback: function(mescroll) {
+						vm.$emit('down', mescroll)
+					}
+				},
+				// 上拉加载的配置
+				up: {
+					// 显示加载中的回调
+					showLoading() {
+						vm.isUpLoading = true;
+						vm.isUpNoMore = false;
+					},
+					// 显示无更多数据的回调
+					showNoMore() {
+						vm.isUpLoading = false;
+						vm.isUpNoMore = true;
+					},
+					// 隐藏上拉加载的回调
+					hideUpScroll() {
+						vm.isUpLoading = false;
+						vm.isUpNoMore = false;
+					},
+					// 空布局
+					empty: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowEmpty = isShow;
+						}
+					},
+					// 回到顶部
+					toTop: {
+						onShow(isShow) { // 显示隐藏的回调
+							vm.isShowToTop = isShow;
+						}
+					},
+					// 派发上拉加载的回调
+					callback: function(mescroll) {
+						vm.$emit('up', mescroll);
+						// 更新容器的高度 (多mescroll的情况)
+						vm.setClientHeight()
+					}
+				}
+			}
+
+			MeScroll.extend(diyOption, GlobalOption); // 混入全局的配置
+			let myOption = JSON.parse(JSON.stringify({
+				'down': vm.down,
+				'up': vm.up
+			})) // 深拷贝,避免对props的影响
+			MeScroll.extend(myOption, diyOption); // 混入具体界面的配置
+
+			// 初始化MeScroll对象
+			vm.mescroll = new MeScroll(myOption);
+			vm.mescroll.viewId = vm.viewId; // 附带id
+			// init回调mescroll对象
+			vm.$emit('init', vm.mescroll);
+
+			// 设置高度
+			uni.getSystemInfo({
+				success(res) {
+					if (res.windowTop) vm.windowTop = res.windowTop; // 修正app和H5的top值
+					if (res.windowBottom) vm.windowBottom = res.windowBottom; // 修正app和H5的bottom值
+					vm.mescroll.setBodyHeight(res.windowHeight); // 使down的bottomOffset生效
+				}
+			});
+
+			// 因为使用的是scrollview,这里需自定义scrollTo
+			vm.mescroll.resetScrollTo((y, t) => {
+				let curY = vm.mescroll.getScrollTop()
+				if (t === 0) {
+					vm.scrollAnim = false;
+					vm.scrollTop = curY;
+					vm.$nextTick(function() {
+						vm.scrollTop = y
+					})
+				} else {
+					vm.scrollAnim = true;
+					vm.mescroll.getStep(curY, y, step => { // 此写法可支持配置t
+						vm.scrollTop = step
+					}, t)
+				}
+			})
+		},
+		mounted() {
+			// 设置容器的高度
+			this.setClientHeight()
+		}
+	}
+</script>
+
+<style>
+	@import "./mescroll-uni.css";
+</style>

+ 25 - 0
main.js

@@ -0,0 +1,25 @@
+import Vue from 'vue'
+import App from './App'
+
+Vue.config.productionTip = false
+
+import ucenter from './pages/ucenter/home.vue'
+Vue.component('ucenter',ucenter)
+
+import res from './pages/res/home.vue'
+Vue.component('res',res)
+
+import cuCustom from './components/colorui/cu-custom.vue'
+Vue.component('cu-custom',cuCustom)
+
+import MescrollUni from './components/mescroll-uni/mescroll-uni.vue';
+Vue.component('MescrollUni',MescrollUni)
+
+App.mpType = 'app'
+
+const app = new Vue({
+    ...App
+})
+import Dever from './components/dever'
+Vue.prototype.Dever = Dever
+app.$mount()

+ 81 - 0
manifest.json

@@ -0,0 +1,81 @@
+{
+	"name" : "buykey",
+	"appid" : "__UNI__8DBD656",
+	"description": "",
+	"versionName": "1.0.0",
+	"versionCode": "100",
+	"transformPx": false,
+    /* 5+App特有相关 */
+	"app-plus": {
+		"usingComponents": true,
+    "nvueCompiler": "uni-app",
+		"splashscreen": {
+			"alwaysShowBeforeRender": true,
+			"waiting": true,
+			"autoclose": true,
+			"delay": 0
+		},
+        /* 模块配置 */
+		"modules": {
+
+		},
+        /* 应用发布信息 */
+		"distribute": {
+            /* android打包配置 */
+			"android": {
+				"permissions": ["<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+					"<uses-permission android:name=\"android.permission.READ_CONTACTS\"/>",
+					"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+					"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+					"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+					"<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CAMERA\"/>",
+					"<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
+					"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+					"<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
+					"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+					"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+					"<uses-permission android:name=\"android.permission.CALL_PHONE\"/>",
+					"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>",
+					"<uses-feature android:name=\"android.hardware.camera\"/>",
+					"<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>",
+					"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+				]
+			},
+            /* ios打包配置 */
+			"ios": {
+
+			},
+            /* SDK配置 */
+			"sdkConfigs": {
+
+			}
+		}
+	},
+    /* 快应用特有相关 */
+	"quickapp": {
+
+	},
+    /* 小程序特有相关 */
+	"mp-weixin": {
+		"appid": "",
+		"setting": {
+			"urlCheck": false
+		},
+		"usingComponents": true
+	},
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    }
+}

+ 34 - 0
pages.json

@@ -0,0 +1,34 @@
+{
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/index/index",
+			"style": {}
+		},
+		{
+			"path": "pages/res/product",
+			"style": {}
+		}
+	],
+	"globalStyle": {
+		"mp-alipay": {
+			/* 支付宝小程序特有相关 */
+			"transparentTitle": "always",
+			"allowsBounceVertical": "NO"
+		},
+		"navigationBarBackgroundColor": "#0081ff",
+		"navigationBarTitleText": "buykey",
+		"navigationStyle": "custom",
+		"navigationBarTextStyle": "white",
+		"enablePullDownRefresh" : false
+	},
+	"usingComponts": true,
+		"condition": { //模式配置,仅开发期间生效
+		"current": 0, //当前激活的模式(list 的索引项)
+		"list": [{
+				"name": "表单", //模式名称
+				"path": "pages/component/form", //启动页面
+				"query": "" //启动参数
+			}
+		]
+	}
+}

+ 67 - 0
pages/index/index.vue

@@ -0,0 +1,67 @@
+<template>
+	<view>
+		<ucenter v-if="page=='ucenter'"></ucenter>
+		<res v-if="page=='res'"></res>
+		<view class="cu-bar tabbar bg-white shadow foot">
+			<view class="action" :class="page=='ucenter'?'text-green':'text-gray'" @click="goPage" data-cur="ucenter">
+				<view class="cuIcon-homefill"></view> 首页
+			</view>
+			<view class="action" :class="page=='res'?'text-green':'text-gray'" @click="goPage" data-cur="res">
+				<view class="cuIcon-similar"></view> 发现
+			</view>
+			<view class="action text-gray add-action">
+				<button class="cu-btn cuIcon-add bg-green shadow"></button>
+				发布
+			</view>
+			<view class="action" :class="page=='protect'?'text-green':'text-gray'">
+				<view class="cuIcon-my">
+					<view class="cu-tag badge">99</view>
+				</view>
+				守护
+			</view>
+			<view class="action text-gray">
+				<view class="cuIcon-card">
+					<view class="cu-tag badge"></view>
+				</view>
+				时光
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				page: 'ucenter'
+			}
+		},
+		onLoad: function(option) {
+			//验证登录
+			//this.Dever.checkLogin();
+			//this.getList(1);
+		},
+		onShow: function() {},
+		
+		// 重新加载
+		onPullDownRefresh: function() {
+			
+		},
+		// 触底刷新
+		onReachBottom: function() {
+			//this.getList(2);
+			//console.info(333);
+		},
+		methods: {
+			goPage: function(e) {
+				this.page = e.currentTarget.dataset.cur
+			},
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>
+

+ 368 - 0
pages/res/home.vue

@@ -0,0 +1,368 @@
+<template name="res">
+	<view>
+		<view>
+			<cu-custom bgColor="bg-gradual-green">
+				<block slot="content">发现</block>
+			</cu-custom>
+		</view>
+		
+		<view class="VerticalBox">
+			<scroll-view class="VerticalNav nav" scroll-y scroll-with-animation :scroll-top="verticalNavTop" style="height:calc(100vh - 200upx)">
+				<view class="cu-item" :class="index==tabCur?'text-green cur':''" v-for="(item,index) in list" :key="index" @tap="TabSelect"
+				 :data-id="index">
+					{{item.name}}
+				</view>
+			</scroll-view>
+			<scroll-view class="VerticalMain" scroll-y scroll-with-animation @scroll="VerticalMain" style="height:calc(100vh - 200upx)">
+				<view class="VerticalMainPadding">
+					<swiper class="round-dot radius shadow-blur" :indicator-dots="true" :circular="true" :autoplay="true" interval="5000"
+					 duration="500" style="height:100px;">
+						<swiper-item v-for="(item,index) in 4" :key="index">
+							<image :src="'https://ossweb-img.qq.com/images/lol/web201310/skin/big3900'+index+ '.jpg'" mode="aspectFill"></image>
+						</swiper-item>
+					</swiper>
+					<scroll-view scroll-x class="bg-white nav" scroll-with-animation :scroll-left="cateScrollLeft">
+						<view class="cu-item" :class="index==cateTabCur?'text-green cur':''" v-for="(item,index) in 10" :key="index" @tap="tabSelect" :data-id="index">
+							Tab{{index}}
+						</view>
+					</scroll-view>
+					<mescroll-uni :up="upOption" :down="downOption" @down="down" @up="up">
+						<view class="cu-list menu-avatar">
+							<view class="cu-item cur" @click="goPage" data-id="1">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+							<view class="cu-item cur">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+							<view class="cu-item cur">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+							<view class="cu-item cur">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+							<view class="cu-item cur">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+							<view class="cu-item cur">
+								<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg);">
+									<view class="cu-tag badge">99+</view>
+								</view>
+								<view class="content">
+									<view class="text-black">
+										<text class="text-cut">瓦洛兰之盾-塔里克</text>
+										<view class="cu-tag round bg-orange sm">战士</view>
+									</view>
+									<view class="text-gray text-sm flex">
+										<text class="text-cut">
+											<text class="cuIcon-infofill text-red  margin-right-xs"></text>
+											我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。我已天理为凭,踏入这片荒芜,不再受凡人的枷锁遏制。
+										</text>
+									</view>
+									<view class="action">
+										<view class='cu-tag line-red'>限时秒杀</view>
+										<view class='cu-tag line-blue'>加战斗力</view>
+									</view>
+									
+									<view class="flex-sub">
+										<view class="text-xl">
+											<text class="text-red">80.00</text>
+										</view>
+									</view>
+								</view>
+							</view>
+							
+						</view>
+					</mescroll-uni>
+				</view>
+			</scroll-view>
+		</view>
+		
+		<view class='cu-tabbar-height'></view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "home",
+		data() {
+			return {
+				downOption: {
+					auto: false //是否在初始化后,自动执行下拉回调callback; 默认true
+				},
+				upOption: {
+					use: true, // 是否启用上拉加载; 默认true
+					auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
+				},
+				
+				list: [{
+					id: 1,
+					name: '商品',
+				},{
+					id: 2,
+					name: '图片',
+				}],
+				tabCur: 0,
+				mainCur: 0,
+				verticalNavTop: 0,
+				load: true,
+				cateTabCur: 0,
+				cateScrollLeft: 0
+			}
+		},
+		mounted: function(option) {
+			
+		},
+		
+		methods: {
+			/*下拉刷新的回调 */
+			down(option) {
+				//联网加载数据
+				console.info(2222);
+			},
+			/*上拉加载的回调: option携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
+			up(option) {
+				//联网加载数据
+				this.listCur = this.list[0];
+				console.info(2222);
+			},
+			
+			TabSelect(e) {
+				this.tabCur = e.currentTarget.dataset.id;
+				this.mainCur = e.currentTarget.dataset.id;
+				this.verticalNavTop = (e.currentTarget.dataset.id - 1) * 50
+			},
+			VerticalMain(e) {
+				// #ifdef MP-ALIPAY
+				   return false  //支付宝小程序暂时不支持双向联动 
+				// #endif
+			},
+			tabSelect(e) {
+				this.cateTabCur = e.currentTarget.dataset.id;
+				this.cateScrollLeft = (e.currentTarget.dataset.id - 1) * 60
+			},
+			goPage(e) {
+				var id = e.currentTarget.dataset.id;
+				this.Dever.location('res/product?id=' + id);
+			}
+		}
+	}
+</script>
+
+<style>
+	.fixed {
+		position: fixed;
+		z-index: 99;
+	}
+
+	.VerticalNav.nav {
+		width: 200upx;
+		white-space: initial;
+	}
+
+	.VerticalNav.nav .cu-item {
+		width: 100%;
+		text-align: center;
+		background-color: #fff;
+		margin: 0;
+		border: none;
+		height: 100%;
+		position: relative;
+	}
+
+	.VerticalNav.nav .cu-item.cur {
+		background-color: #f1f1f1;
+	}
+
+	.VerticalNav.nav .cu-item.cur::after {
+		content: "";
+		width: 8upx;
+		height: 30upx;
+		border-radius: 10upx 0 0 10upx;
+		position: absolute;
+		background-color: currentColor;
+		top: 0;
+		right: 0upx;
+		bottom: 0;
+		margin: auto;
+	}
+
+	.VerticalBox {
+		display: flex;
+		overflow: hidden;
+	}
+
+	.VerticalMain {
+		background-color: #f1f1f1;
+		flex: 1;
+		width: 80%;
+	}
+	.cu-list.menu-avatar>.cu-item .content {
+		width: calc(100% - 56px - 35px);
+		left:112px;
+		top: 10px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .cu-avatar {
+		left: 5px;
+		top: 15px;
+		width: 95px;
+		height: 95px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .content>uni-view:first-child {
+		font-size: 15px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item {
+		 height: 120px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .action {
+		width:100%;
+		text-align: inherit;
+		margin-top: 2px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .action uni-view+uni-view {
+		margin-top: 0px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .flex-sub {
+		margin-top: 5px;
+	}
+	
+	.cu-list.menu-avatar>.cu-item .flex .text-cut {
+	    max-width: 228px;
+	}
+
+	.VerticalMainPadding {
+		padding-left: 3px;
+		padding-right: 3px;
+		padding-top: 3px;
+	}
+</style>

+ 265 - 0
pages/res/product.vue

@@ -0,0 +1,265 @@
+<template name="ucenter">
+	<view>
+		<scroll-view scroll-y class="page">
+			<view class="fixed">
+				<cu-custom bgColor="bg-shadeTop text-white">
+					<block slot="content">微风的Buykey</block>
+				</cu-custom>
+			</view>
+			
+			<swiper class="screen-swiper" :class="dotStyle?'square-dot':'round-dot'" :indicator-dots="true" :circular="true"
+			 :autoplay="true" interval="5000" duration="500">
+				<swiper-item v-for="(item,index) in swiperList" :key="index">
+					<image :src="item.url" mode="aspectFill" v-if="item.type=='image'"></image>
+					<video :src="item.url" autoplay loop muted :show-play-btn="false" :controls="false" objectFit="cover" v-if="item.type=='video'"></video>
+				</swiper-item>
+			</swiper>
+			
+			<view class="cu-list grid" :class="['col-' + gridCol,gridBorder?'':'no-border']">
+				<view class="cu-item" v-for="(item,index) in cuIconList" :key="index" v-if="index<gridCol*2">
+					<view :class="['cuIcon-' + item.cuIcon,'text-' + item.color]">
+						<view class="cu-tag badge" v-if="item.badge!=0">
+							<block v-if="item.badge!=1">{{item.badge>99?'99+':item.badge}}</block>
+						</view>
+					</view>
+					<text>{{item.name}}</text>
+				</view>
+			</view>
+			
+			<view class="cu-bar bg-white solid-bottom margin-top hide">
+				<view class="action">
+					<text class="cuIcon-title text-orange "></text> 最新动态
+				</view>
+			</view>
+			
+			<view>
+				<view class="cu-timeline">
+					<view class="cu-time">昨天</view>
+					<view class="cu-item cur cuIcon-noticefill">
+						<view class="content bg-green shadow-blur">
+							<text>22:22</text> 【广州市】快件已到达地球
+						</view>
+					</view>
+					<view class="cu-item text-red cuIcon-attentionforbidfill">
+						<view class="content bg-red shadow-blur">
+							这是第一次,我家的铲屎官走了这么久。久到足足有三天!!
+						</view>
+					</view>
+					<view class="cu-item text-grey cuIcon-evaluate_fill">
+						<view class="content bg-grey shadow-blur">
+							这是第一次,我家的铲屎官走了这么久。
+						</view>
+					</view>
+					<view class="cu-item text-blue">
+						<view class="bg-blue content">
+							<text>20:00</text> 【月球】快件已到达月球,准备发往地球
+						</view>
+						<view class="bg-cyan content">
+							<text>10:00</text> 【银河系】快件已到达银河系,准备发往月球
+						</view>
+					</view>
+				</view>
+				
+				<view class="cu-timeline">
+					<view class="cu-time">06-17</view>
+					<view class="cu-item">
+						<view class="content">
+							<text>01:30</text> 【喵星】 MX-12138 已揽收,准备发往银河系
+						</view>
+					</view>
+				</view>
+				
+				<view class="cu-timeline">
+					<view class="cu-time">06-17</view>
+					<view class="cu-item">
+						<view class="content">
+							<view class="cu-capsule radius">
+								<view class="cu-tag bg-cyan">上午</view>
+								<view class="cu-tag line-cyan">10:00</view>
+							</view>
+							<view class="margin-top">这是第一次,我家的铲屎官走了这么久。久到足足有三天!! 在听到他的脚步声响在楼梯间的那一刻,我简直想要破门而出,对着他狠狠地吼上10分钟,然后再看心情要不要他进门。</view>
+						</view>
+					</view>
+					<view class="cu-item text-blue">
+						<view class="bg-blue shadow-blur content">
+							<view class="cu-list menu-avatar radius">
+								<view class="cu-item">
+									<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10006.jpg);"></view>
+									<view class="content">
+										<view class="text-grey">文晓港</view>
+										<view class="text-gray text-sm">
+											<text class="cuIcon-infofill text-red"></text> 消息未送达</view>
+									</view>
+									<view class="action">
+										<view class="text-grey text-xs">22:20</view>
+										<view class="cu-tag round bg-grey sm">5</view>
+									</view>
+								</view>
+								<view class="cu-item">
+									<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10006.jpg);">
+										<view class="cu-tag badge">99+</view>
+									</view>
+									<view class="content">
+										<view class="text-grey">文晓港
+											<view class="cu-tag round orange sm">SVIP</view>
+										</view>
+										<view class="text-gray text-sm">
+											<text class="cuIcon-redpacket_fill text-red"></text> 收到红包</view>
+									</view>
+									<view class="action">
+										<view class="text-grey text-xs">22:20</view>
+										<text class="cuIcon-notice_forbid_fill text-gray"></text>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="cu-tabbar-height"></view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "ucenter",
+		data() {
+			return {
+				cuIconList: [{
+					cuIcon: 'location',
+					color: 'red',
+					badge: 120,
+					name: '商品'
+				}, {
+					cuIcon: 'recordfill',
+					color: 'orange',
+					badge: 1,
+					name: '身份'
+				}, {
+					cuIcon: 'picfill',
+					color: 'yellow',
+					badge: 0,
+					name: '图像'
+				}, {
+					cuIcon: 'noticefill',
+					color: 'olive',
+					badge: 22,
+					name: '通知'
+				}, {
+					cuIcon: 'upstagefill',
+					color: 'cyan',
+					badge: 0,
+					name: '排行榜'
+				}, {
+					cuIcon: 'clothesfill',
+					color: 'blue',
+					badge: 0,
+					name: '皮肤'
+				}, {
+					cuIcon: 'discoverfill',
+					color: 'purple',
+					badge: 0,
+					name: '发现'
+				}, {
+					cuIcon: 'questionfill',
+					color: 'mauve',
+					badge: 0,
+					name: '帮助'
+				}, {
+					cuIcon: 'commandfill',
+					color: 'purple',
+					badge: 0,
+					name: '问答'
+				}, {
+					cuIcon: 'brandfill',
+					color: 'mauve',
+					badge: 0,
+					name: '版权'
+				}],
+				modalName: null,
+				gridCol: 4,
+				gridBorder: true,
+				
+				
+				cardCur: 0,
+				swiperList: [{
+					id: 0,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg'
+				}, {
+					id: 1,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big37006.jpg',
+				}, {
+					id: 2,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg'
+				}, {
+					id: 3,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg'
+				}, {
+					id: 4,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg'
+				}, {
+					id: 5,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg'
+				}, {
+					id: 6,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg'
+				}],
+				dotStyle: true,
+			};
+		},
+		mounted: function(option) {
+			console.info(111);
+		},
+		methods: {
+			Gridchange(e) {
+				this.gridCol = e.detail.value
+			},
+			Gridswitch(e) {
+				this.gridBorder = e.detail.value
+			},
+		}
+	}
+</script>
+
+<style>
+	.fixed {
+		position: fixed;
+		z-index: 99;
+	}
+	.page {
+		height: 100Vh;
+		width: 100vw;
+	}
+
+	.page.show {
+		overflow: hidden;
+	}
+
+	.switch-sex::after {
+		content: "\e716";
+	}
+
+	.switch-sex::before {
+		content: "\e7a9";
+	}
+
+	.switch-music::after {
+		content: "\e66a";
+	}
+
+	.switch-music::before {
+		content: "\e6db";
+	}
+	
+	.cu-list.grid>.cu-item [class*=cuIcon] {
+		font-size:50px;
+	}
+</style>

+ 289 - 0
pages/res/shop.vue

@@ -0,0 +1,289 @@
+<template name="res">
+	<mescroll-uni :down="mescroll" @down="down" @up="up">
+		<view class="fixed">
+			<cu-custom bgColor="bg-shadeTop text-white">
+				<block slot="content">发现</block>
+			</cu-custom>
+		</view>
+		
+		<view class="cu-bar bg-white solid-bottom margin-top hide">
+			<view class="action">
+				<text class="cuIcon-title text-orange "></text> 最新动态
+			</view>
+		</view>
+		
+		<!--背景效果-->
+		<image src="https://yhtx.itianc.com/wxxcx/57b6c21fa7290.jpg" mode="aspectFill" class="canui-head-vague"></image>
+		<view class="canui-head-gradient"></view>
+		
+		<!--标题栏区域-->
+		<view class="canui-head-custom">
+		    <view class='canui-shop-title' bindtap='btnback'>
+		        <text class="icon-back"></text> <text>XXXX旗舰店</text>
+		    </view>
+		    <view class="canui-shop-synopsis text-sm">
+		        <text class="canui-xzwz">店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介店铺简介</text>
+		    </view>
+		</view>
+		
+		<!--搜索框-->
+		<view class="cu-bar search">
+		    <view class='search-form round'>
+		        <text class="icon-search"></text>
+		        <input type="text" placeholder="搜索店铺内的商品" confirm-type="search" placeholder-class="canui-input-placeholder"></input>
+		    </view>
+		    <view class='action'>
+		        <button class='cu-btn shadow-blur round canui-btn-wxjn' bindtap="search">搜索</button>
+		    </view>
+		</view>
+		
+		<!--菜单导航栏-->
+		<scroll-view scroll-x class="nav text-left canui-shop-table">
+		    <view v-for="(item,index) in SortMenu" :key="index" class="cu-item" :class="item.id==TabCur?'cur':''" bindtap='tabSelect' :data-id="item.id">
+		        {{item.name}}
+		    </view>
+		</scroll-view>
+		
+		<!--商品列表-->
+		<view class='nav-list canui-shop-goods-list'>
+		    <navigator v-for="(item,index) in ShopList" :key="index" class="nav-li" open-type="navigate" hover-class='none'>
+		        <image :src="item.image" mode="aspectFill"></image>
+		        <view class="nav-li-box">
+		            <view class="nav-title canui-xzwz text-sm">{{item.title}}</view>
+		            <view class="shop-zx">
+		                <text class="text-price text-red text-xs">{{item.price}} </text>
+		                <text class="text-gray text-sm">{{item.sales}}人已兑换</text>
+		            </view>
+		        </view>
+		    </navigator>
+		</view>
+		
+		<view class='cu-tabbar-height'></view>
+	</mescroll-uni>
+</template>
+
+<script>
+	export default {
+		name: "res",
+		data() {
+			return {
+				mescroll: {
+					auto: false //是否在初始化后,自动执行下拉回调callback; 默认true
+				},
+				TabCur: 0,
+				scrollLeft:0,
+				SortMenu: [{id:0,name:"综合"},{id:1,name:"销量"},{id:2,name:"新品"},{id:3,name:"价格"}],
+				ShopList: [{
+					index: 1,
+					image: 'https://image.weilanwl.com/img/4x3-1.jpg',
+					title: '商品名称商品名称商品名称商品名称',
+					price: '100',
+					sales: '2.2万'
+				},{
+					index: 2,
+					image: 'https://image.weilanwl.com/img/4x3-2.jpg',
+					title: '商品名称商品名称',
+					price: '1000',
+					sales: '85'
+				},{
+					index: 3,
+					image: 'https://image.weilanwl.com/img/4x3-3.jpg',
+					title: '商品名称商品名称商品名称商品名称',
+					price: '39.9',
+					sales: '2000'
+				},{
+					index: 4,
+					image: 'https://image.weilanwl.com/img/4x3-4.jpg',
+					title: '商品名称商品名称商品名称商品名称',
+					price: '100',
+					sales: '2.2万'
+				},{
+					index: 5,
+					image: 'https://image.weilanwl.com/img/4x3-3.jpg',
+					title: '商品名称商品名称商品名称商品名称',
+					price: '39.9',
+					sales: '2000'
+				},{
+					index: 6,
+					image: 'https://image.weilanwl.com/img/4x3-4.jpg',
+					title: '商品名称商品名称商品名称商品名称',
+					price: '100',
+					sales: '2.2万'
+				}],
+			};
+		},
+		mounted: function(option) {
+			
+		},
+		
+		methods: {
+			/*下拉刷新的回调 */
+			down(option) {
+				//联网加载数据
+				console.info(2222);
+			},
+			/*上拉加载的回调: option携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
+			up(option) {
+				//联网加载数据
+				console.info(3333);
+			},
+		}
+	}
+</script>
+
+<style>
+	.canui-head-gradient{
+	    position: absolute;
+	    background-image:linear-gradient(rgba(255, 255, 255, 0.01), rgba(241, 241, 241, 1));
+	    width: 100%;
+	    height: 600rpx;
+	    top: 0;
+	}
+	
+	/*-------标题栏-------*/
+	.canui-head-custom{
+	    position: relative;
+	    width: 100%;
+	    top: 0;
+	    height:100rpx;
+	}
+	.canui-shop-title{
+	    display:flex;
+	    align-items:left;
+	    justify-content:left;
+	    max-width:100%;
+	    padding:10rpx;
+	    padding-right:320rpx;
+	}
+	.canui-shop-title:first-child{
+	    margin-left:20rpx;
+	    font-size:33rpx;
+	}
+	.canui-shop-title:last-child{
+	    margin-right:30rpx;
+	}
+	.canui-shop-title:first-child>text[class*="icon"] {
+	    margin-left:-0.3em;
+	    margin-right:0.3em;
+	    margin-top:3rpx;
+	}
+	.canui-shop-title > text[class*="icon"], .canui-shop-title > view[class*="icon"] {
+	    font-size:36rpx;
+	}
+	.canui-shop-synopsis{
+	    padding:0 30rpx;
+	}
+	
+	
+	/*-------关注按钮-------*/
+	.canui-head-box{
+	    position:absolute;
+	    top:26px;
+	    right:192rpx;
+	    background:rgba(0,0,0,0.2);
+	    border-radius:20px;
+	    padding:4.5px 10px;
+	    border:1px solid rgba(255,255,255,0.3);
+	    font-size:28rpx;
+	}
+	.canui-head-box text{
+	    font-size:15px;
+	    margin-right:3rpx;
+	}
+	
+	/*-------搜索框区域-------*/
+	.cu-bar{
+	    padding-top:15rpx;
+	}
+	.cu-bar .search-form{
+	    background:rgba(241,241,241,0.3);
+	}
+	.cu-bar .search-form [class*="icon"]{
+	    margin:0 0.5em 0 0.4em;
+	    font-size:38rpx;
+	}
+	.cu-bar .search-form input{
+	    font-size:26rpx;
+	}
+	.canui-input-placeholder{
+
+	}
+	.canui-btn-wxjn{
+
+	}
+	.canui-btn-wxjn:not([class*="bg-"]) {
+	    background:rgba(241,241,241,0.3);
+	}
+	
+	/*-------菜单导航栏-------*/
+	.canui-shop-table{
+	    padding:15rpx 15rpx;
+	}
+	.nav .cu-item {
+	    height:60rpx;
+	    line-height:60rpx;
+	    margin:0 10rpx;
+	    padding:0 30rpx;
+	    color: #f1f1f1;
+	}
+	.nav .cu-item.cur{
+	    border-bottom:0;
+	    background:rgba(241,241,241,0.3);
+	    border-radius:55px;
+	    color: rgba(254,0,0,0.8);
+	}
+	
+	/*-------商品列表-------*/
+	.canui-shop-goods-list{
+	    padding:10rpx 20rpx 0px;
+	}
+	.canui-shop-goods-list .nav-li{
+	    background-image:initial;
+	    background-size:initial;
+	    background-position:initial;
+	    background:initial;
+	    padding:0;
+	    width:345rpx;
+	    margin:0 5rpx 20rpx;
+	    border-radius:0;
+	}
+	.canui-shop-goods-list .nav-li image{
+	    width:100%;
+	    height:345rpx;
+	    z-index:99999;
+	    border-radius:15rpx 15rpx 0 0;
+	}
+	.canui-shop-goods-list .nav-li .nav-li-box{
+	    position: relative;
+	    background: #Ffff;
+	    padding: 10rpx 20rpx;
+	    border-radius: 0 0 15rpx 15rpx;
+	    box-shadow: 0 0 10rpx rgba(0, 0, 0, 0.1);
+	    top: -6rpx;
+	    z-index: 0;
+	}
+	.canui-shop-goods-list .nav-li .nav-li-box .nav-title {
+	    font-size: 28 rpx;
+	}
+	.canui-shop-goods-list .nav-li text{
+	    position: relative;
+	    right:initial;
+	    top:initial;
+	    font-size:inherit;
+	    width:inherit;
+	    height:initial;
+	    text-align:initial;
+	    line-height:inherit;
+	}
+	.canui-shop-goods-list .nav-li .shop-zx{
+	    position: relative;
+	    padding:10rpx 0;
+	}
+	.canui-shop-goods-list .nav-li .shop-zx .text-sm{
+	    font-size:20rpx;
+	}
+	.canui-shop-goods-list .nav-li .shop-zx .text-price{
+	    font-size:30rpx;
+	    margin-right:8rpx;
+	}
+</style>

+ 265 - 0
pages/ucenter/home.vue

@@ -0,0 +1,265 @@
+<template name="ucenter">
+	<view>
+		<scroll-view scroll-y class="page">
+			<view class="fixed">
+				<cu-custom bgColor="bg-shadeTop text-white">
+					<block slot="content">微风的Buykey</block>
+				</cu-custom>
+			</view>
+			
+			<swiper class="screen-swiper" :class="dotStyle?'square-dot':'round-dot'" :indicator-dots="true" :circular="true"
+			 :autoplay="true" interval="5000" duration="500">
+				<swiper-item v-for="(item,index) in swiperList" :key="index">
+					<image :src="item.url" mode="aspectFill" v-if="item.type=='image'"></image>
+					<video :src="item.url" autoplay loop muted :show-play-btn="false" :controls="false" objectFit="cover" v-if="item.type=='video'"></video>
+				</swiper-item>
+			</swiper>
+			
+			<view class="cu-list grid" :class="['col-' + gridCol,gridBorder?'':'no-border']">
+				<view class="cu-item" v-for="(item,index) in cuIconList" :key="index" v-if="index<gridCol*2">
+					<view :class="['cuIcon-' + item.cuIcon,'text-' + item.color]">
+						<view class="cu-tag badge" v-if="item.badge!=0">
+							<block v-if="item.badge!=1">{{item.badge>99?'99+':item.badge}}</block>
+						</view>
+					</view>
+					<text>{{item.name}}</text>
+				</view>
+			</view>
+			
+			<view class="cu-bar bg-white solid-bottom margin-top hide">
+				<view class="action">
+					<text class="cuIcon-title text-orange "></text> 最新动态
+				</view>
+			</view>
+			
+			<view>
+				<view class="cu-timeline">
+					<view class="cu-time">昨天</view>
+					<view class="cu-item cur cuIcon-noticefill">
+						<view class="content bg-green shadow-blur">
+							<text>22:22</text> 【广州市】快件已到达地球
+						</view>
+					</view>
+					<view class="cu-item text-red cuIcon-attentionforbidfill">
+						<view class="content bg-red shadow-blur">
+							这是第一次,我家的铲屎官走了这么久。久到足足有三天!!
+						</view>
+					</view>
+					<view class="cu-item text-grey cuIcon-evaluate_fill">
+						<view class="content bg-grey shadow-blur">
+							这是第一次,我家的铲屎官走了这么久。
+						</view>
+					</view>
+					<view class="cu-item text-blue">
+						<view class="bg-blue content">
+							<text>20:00</text> 【月球】快件已到达月球,准备发往地球
+						</view>
+						<view class="bg-cyan content">
+							<text>10:00</text> 【银河系】快件已到达银河系,准备发往月球
+						</view>
+					</view>
+				</view>
+				
+				<view class="cu-timeline">
+					<view class="cu-time">06-17</view>
+					<view class="cu-item">
+						<view class="content">
+							<text>01:30</text> 【喵星】 MX-12138 已揽收,准备发往银河系
+						</view>
+					</view>
+				</view>
+				
+				<view class="cu-timeline">
+					<view class="cu-time">06-17</view>
+					<view class="cu-item">
+						<view class="content">
+							<view class="cu-capsule radius">
+								<view class="cu-tag bg-cyan">上午</view>
+								<view class="cu-tag line-cyan">10:00</view>
+							</view>
+							<view class="margin-top">这是第一次,我家的铲屎官走了这么久。久到足足有三天!! 在听到他的脚步声响在楼梯间的那一刻,我简直想要破门而出,对着他狠狠地吼上10分钟,然后再看心情要不要他进门。</view>
+						</view>
+					</view>
+					<view class="cu-item text-blue">
+						<view class="bg-blue shadow-blur content">
+							<view class="cu-list menu-avatar radius">
+								<view class="cu-item">
+									<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10006.jpg);"></view>
+									<view class="content">
+										<view class="text-grey">文晓港</view>
+										<view class="text-gray text-sm">
+											<text class="cuIcon-infofill text-red"></text> 消息未送达</view>
+									</view>
+									<view class="action">
+										<view class="text-grey text-xs">22:20</view>
+										<view class="cu-tag round bg-grey sm">5</view>
+									</view>
+								</view>
+								<view class="cu-item">
+									<view class="cu-avatar round lg" style="background-image:url(https://ossweb-img.qq.com/images/lol/web201310/skin/big10006.jpg);">
+										<view class="cu-tag badge">99+</view>
+									</view>
+									<view class="content">
+										<view class="text-grey">文晓港
+											<view class="cu-tag round orange sm">SVIP</view>
+										</view>
+										<view class="text-gray text-sm">
+											<text class="cuIcon-redpacket_fill text-red"></text> 收到红包</view>
+									</view>
+									<view class="action">
+										<view class="text-grey text-xs">22:20</view>
+										<text class="cuIcon-notice_forbid_fill text-gray"></text>
+									</view>
+								</view>
+							</view>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="cu-tabbar-height"></view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "ucenter",
+		data() {
+			return {
+				cuIconList: [{
+					cuIcon: 'location',
+					color: 'red',
+					badge: 120,
+					name: '商品'
+				}, {
+					cuIcon: 'recordfill',
+					color: 'orange',
+					badge: 1,
+					name: '身份'
+				}, {
+					cuIcon: 'picfill',
+					color: 'yellow',
+					badge: 0,
+					name: '图像'
+				}, {
+					cuIcon: 'noticefill',
+					color: 'olive',
+					badge: 22,
+					name: '通知'
+				}, {
+					cuIcon: 'upstagefill',
+					color: 'cyan',
+					badge: 0,
+					name: '排行榜'
+				}, {
+					cuIcon: 'clothesfill',
+					color: 'blue',
+					badge: 0,
+					name: '皮肤'
+				}, {
+					cuIcon: 'discoverfill',
+					color: 'purple',
+					badge: 0,
+					name: '发现'
+				}, {
+					cuIcon: 'questionfill',
+					color: 'mauve',
+					badge: 0,
+					name: '帮助'
+				}, {
+					cuIcon: 'commandfill',
+					color: 'purple',
+					badge: 0,
+					name: '问答'
+				}, {
+					cuIcon: 'brandfill',
+					color: 'mauve',
+					badge: 0,
+					name: '版权'
+				}],
+				modalName: null,
+				gridCol: 4,
+				gridBorder: true,
+				
+				
+				cardCur: 0,
+				swiperList: [{
+					id: 0,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg'
+				}, {
+					id: 1,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big37006.jpg',
+				}, {
+					id: 2,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg'
+				}, {
+					id: 3,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big10001.jpg'
+				}, {
+					id: 4,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big25011.jpg'
+				}, {
+					id: 5,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big21016.jpg'
+				}, {
+					id: 6,
+					type: 'image',
+					url: 'https://ossweb-img.qq.com/images/lol/web201310/skin/big99008.jpg'
+				}],
+				dotStyle: true,
+			};
+		},
+		mounted: function(option) {
+			console.info(111);
+		},
+		methods: {
+			Gridchange(e) {
+				this.gridCol = e.detail.value
+			},
+			Gridswitch(e) {
+				this.gridBorder = e.detail.value
+			},
+		}
+	}
+</script>
+
+<style>
+	.fixed {
+		position: fixed;
+		z-index: 99;
+	}
+	.page {
+		height: 100Vh;
+		width: 100vw;
+	}
+
+	.page.show {
+		overflow: hidden;
+	}
+
+	.switch-sex::after {
+		content: "\e716";
+	}
+
+	.switch-sex::before {
+		content: "\e7a9";
+	}
+
+	.switch-music::after {
+		content: "\e66a";
+	}
+
+	.switch-music::before {
+		content: "\e6db";
+	}
+	
+	.cu-list.grid>.cu-item [class*=cuIcon] {
+		font-size:50px;
+	}
+</style>

+ 184 - 0
static/colorui/animation.css

@@ -0,0 +1,184 @@
+/* 
+  Animation 微动画  
+  基于ColorUI组建库的动画模块 by 文晓港 2019年3月26日19:52:28
+ */
+
+/* css 滤镜 控制黑白底色gif的 */
+.gif-black{  
+  mix-blend-mode: screen;  
+}
+.gif-white{  
+  mix-blend-mode: multiply; 
+}
+
+
+/* Animation css */
+[class*=animation-] {
+    animation-duration: .5s;
+    animation-timing-function: ease-out;
+    animation-fill-mode: both
+}
+
+.animation-fade {
+    animation-name: fade;
+    animation-duration: .8s;
+    animation-timing-function: linear
+}
+
+.animation-scale-up {
+    animation-name: scale-up
+}
+
+.animation-scale-down {
+    animation-name: scale-down
+}
+
+.animation-slide-top {
+    animation-name: slide-top
+}
+
+.animation-slide-bottom {
+    animation-name: slide-bottom
+}
+
+.animation-slide-left {
+    animation-name: slide-left
+}
+
+.animation-slide-right {
+    animation-name: slide-right
+}
+
+.animation-shake {
+    animation-name: shake
+}
+
+.animation-reverse {
+    animation-direction: reverse
+}
+
+@keyframes fade {
+    0% {
+        opacity: 0
+    }
+
+    100% {
+        opacity: 1
+    }
+}
+
+@keyframes scale-up {
+    0% {
+        opacity: 0;
+        transform: scale(.2)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes scale-down {
+    0% {
+        opacity: 0;
+        transform: scale(1.8)
+    }
+
+    100% {
+        opacity: 1;
+        transform: scale(1)
+    }
+}
+
+@keyframes slide-top {
+    0% {
+        opacity: 0;
+        transform: translateY(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes slide-bottom {
+    0% {
+        opacity: 0;
+        transform: translateY(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateY(0)
+    }
+}
+
+@keyframes shake {
+
+    0%,
+    100% {
+        transform: translateX(0)
+    }
+
+    10% {
+        transform: translateX(-9px)
+    }
+
+    20% {
+        transform: translateX(8px)
+    }
+
+    30% {
+        transform: translateX(-7px)
+    }
+
+    40% {
+        transform: translateX(6px)
+    }
+
+    50% {
+        transform: translateX(-5px)
+    }
+
+    60% {
+        transform: translateX(4px)
+    }
+
+    70% {
+        transform: translateX(-3px)
+    }
+
+    80% {
+        transform: translateX(2px)
+    }
+
+    90% {
+        transform: translateX(-1px)
+    }
+}
+
+@keyframes slide-left {
+    0% {
+        opacity: 0;
+        transform: translateX(-100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}
+
+@keyframes slide-right {
+    0% {
+        opacity: 0;
+        transform: translateX(100%)
+    }
+
+    100% {
+        opacity: 1;
+        transform: translateX(0)
+    }
+}

File diff suppressed because it is too large
+ 36 - 0
static/colorui/icon.css


+ 3912 - 0
static/colorui/main.css

@@ -0,0 +1,3912 @@
+/*
+  ColorUi for uniApp  v2.1.6 | by 文晓港 2019-05-31 10:44:24
+  仅供学习交流,如作它用所承受的法律责任一概与作者无关  
+  
+  *使用ColorUi开发扩展与插件时,请注明基于ColorUi开发 
+  
+  (QQ交流群:240787041)
+*/
+
+/* ==================
+        初始化
+ ==================== */
+body {
+	background-color: #f1f1f1;
+	font-size: 28upx;
+	color: #333333;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+}
+
+view,
+scroll-view,
+swiper,
+button,
+input,
+textarea,
+label,
+navigator,
+image {
+	box-sizing: border-box;
+}
+
+.round {
+	border-radius: 5000upx;
+}
+
+.radius {
+	border-radius: 6upx;
+}
+
+/* ==================
+          图片
+ ==================== */
+
+image {
+	max-width: 100%;
+	display: inline-block;
+	position: relative;
+	z-index: 0;
+}
+
+image.loading::before {
+	content: "";
+	background-color: #f5f5f5;
+	display: block;
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	z-index: -2;
+}
+
+image.loading::after {
+	content: "\e7f1";
+	font-family: "cuIcon";
+	position: absolute;
+	top: 0;
+	left: 0;
+	width: 32upx;
+	height: 32upx;
+	line-height: 32upx;
+	right: 0;
+	bottom: 0;
+	z-index: -1;
+	font-size: 32upx;
+	margin: auto;
+	color: #ccc;
+	-webkit-animation: cuIcon-spin 2s infinite linear;
+	animation: cuIcon-spin 2s infinite linear;
+	display: block;
+}
+
+.response {
+	width: 100%;
+}
+
+/* ==================
+         开关
+ ==================== */
+
+switch,
+checkbox,
+radio {
+	position: relative;
+}
+
+switch::after,
+switch::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 0%;
+	left: 0upx;
+	font-size: 26upx;
+	line-height: 26px;
+	width: 50%;
+	text-align: center;
+	pointer-events: none;
+	transform: scale(0, 0);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+	bottom: 0;
+	height: 26px;
+	margin: auto;
+}
+
+switch::before {
+	content: "\e646";
+	right: 0;
+	transform: scale(1, 1);
+	left: auto;
+}
+
+switch[checked]::after,
+switch.checked::after {
+	transform: scale(1, 1);
+}
+
+switch[checked]::before,
+switch.checked::before {
+	transform: scale(0, 0);
+}
+
+/* #ifndef MP-ALIPAY */
+radio::before,
+checkbox::before {
+	font-family: "cuIcon";
+	content: "\e645";
+	position: absolute;
+	color: #ffffff !important;
+	top: 50%;
+	margin-top: -8px;
+	right: 5px;
+	font-size: 32upx;
+	line-height: 16px;
+	pointer-events: none;
+	transform: scale(1, 1);
+	transition: all 0.3s ease-in-out 0s;
+	z-index: 9;
+}
+
+radio .wx-radio-input,
+checkbox .wx-checkbox-input,
+radio .uni-radio-input,
+checkbox .uni-checkbox-input {
+	margin: 0;
+	width: 24px;
+	height: 24px;
+}
+
+checkbox.round .wx-checkbox-input,
+checkbox.round .uni-checkbox-input {
+	border-radius: 100upx;
+}
+
+/* #endif */
+
+switch[checked]::before {
+	transform: scale(0, 0);
+}
+
+switch .wx-switch-input,
+switch .uni-switch-input {
+	border: none;
+	padding: 0 24px;
+	width: 48px;
+	height: 26px;
+	margin: 0;
+	border-radius: 100upx;
+}
+
+switch .wx-switch-input:not([class*="bg-"]),
+switch .uni-switch-input:not([class*="bg-"]) {
+	background: #8799a3 !important;
+}
+
+switch .wx-switch-input::after,
+switch .uni-switch-input::after {
+	margin: auto;
+	width: 26px;
+	height: 26px;
+	border-radius: 100upx;
+	left: 0upx;
+	top: 0upx;
+	bottom: 0upx;
+	position: absolute;
+	transform: scale(0.9, 0.9);
+	transition: all 0.1s ease-in-out 0s;
+}
+
+switch .wx-switch-input.wx-switch-input-checked::after,
+switch .uni-switch-input.uni-switch-input-checked::after {
+	margin: auto;
+	left: 22px;
+	box-shadow: none;
+	transform: scale(0.9, 0.9);
+}
+
+radio-group {
+	display: inline-block;
+}
+
+
+
+switch.radius .wx-switch-input::after,
+switch.radius .wx-switch-input,
+switch.radius .wx-switch-input::before,
+switch.radius .uni-switch-input::after,
+switch.radius .uni-switch-input,
+switch.radius .uni-switch-input::before {
+	border-radius: 10upx;
+}
+
+switch .wx-switch-input::before,
+radio.radio::before,
+checkbox .wx-checkbox-input::before,
+radio .wx-radio-input::before,
+switch .uni-switch-input::before,
+radio.radio::before,
+checkbox .uni-checkbox-input::before,
+radio .uni-radio-input::before {
+	display: none;
+}
+
+radio.radio[checked]::after,
+radio.radio .uni-radio-input-checked::after {
+	content: "";
+	background-color: transparent;
+	display: block;
+	position: absolute;
+	width: 8px;
+	height: 8px;
+	z-index: 999;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	border-radius: 200upx;
+	/* #ifndef MP */
+	border: 7px solid #ffffff !important;
+	/* #endif */
+
+	/* #ifdef MP */
+	border: 8px solid #ffffff !important;
+	/* #endif */
+}
+
+.switch-sex::after {
+	content: "\e71c";
+}
+
+.switch-sex::before {
+	content: "\e71a";
+}
+
+.switch-sex .wx-switch-input,
+.switch-sex .uni-switch-input {
+	background: #e54d42 !important;
+	border-color: #e54d42 !important;
+}
+
+.switch-sex[checked] .wx-switch-input,
+.switch-sex.checked .uni-switch-input {
+	background: #0081ff !important;
+	border-color: #0081ff !important;
+}
+
+switch.red[checked] .wx-switch-input.wx-switch-input-checked,
+checkbox.red[checked] .wx-checkbox-input,
+radio.red[checked] .wx-radio-input,
+switch.red.checked .uni-switch-input.uni-switch-input-checked,
+checkbox.red.checked .uni-checkbox-input,
+radio.red.checked .uni-radio-input {
+	background-color: #e54d42 !important;
+	border-color: #e54d42 !important;
+	color: #ffffff !important;
+}
+
+switch.orange[checked] .wx-switch-input,
+checkbox.orange[checked] .wx-checkbox-input,
+radio.orange[checked] .wx-radio-input,
+switch.orange.checked .uni-switch-input,
+checkbox.orange.checked .uni-checkbox-input,
+radio.orange.checked .uni-radio-input {
+	background-color: #f37b1d !important;
+	border-color: #f37b1d !important;
+	color: #ffffff !important;
+}
+
+switch.yellow[checked] .wx-switch-input,
+checkbox.yellow[checked] .wx-checkbox-input,
+radio.yellow[checked] .wx-radio-input,
+switch.yellow.checked .uni-switch-input,
+checkbox.yellow.checked .uni-checkbox-input,
+radio.yellow.checked .uni-radio-input {
+	background-color: #fbbd08 !important;
+	border-color: #fbbd08 !important;
+	color: #333333 !important;
+}
+
+switch.olive[checked] .wx-switch-input,
+checkbox.olive[checked] .wx-checkbox-input,
+radio.olive[checked] .wx-radio-input,
+switch.olive.checked .uni-switch-input,
+checkbox.olive.checked .uni-checkbox-input,
+radio.olive.checked .uni-radio-input {
+	background-color: #8dc63f !important;
+	border-color: #8dc63f !important;
+	color: #ffffff !important;
+}
+
+switch.green[checked] .wx-switch-input,
+switch[checked] .wx-switch-input,
+checkbox.green[checked] .wx-checkbox-input,
+checkbox[checked] .wx-checkbox-input,
+radio.green[checked] .wx-radio-input,
+radio[checked] .wx-radio-input,
+switch.green.checked .uni-switch-input,
+switch.checked .uni-switch-input,
+checkbox.green.checked .uni-checkbox-input,
+checkbox.checked .uni-checkbox-input,
+radio.green.checked .uni-radio-input,
+radio.checked .uni-radio-input {
+	background-color: #39b54a !important;
+	border-color: #39b54a !important;
+	color: #ffffff !important;
+	border-color: #39B54A !important;
+}
+
+switch.cyan[checked] .wx-switch-input,
+checkbox.cyan[checked] .wx-checkbox-input,
+radio.cyan[checked] .wx-radio-input,
+switch.cyan.checked .uni-switch-input,
+checkbox.cyan.checked .uni-checkbox-input,
+radio.cyan.checked .uni-radio-input {
+	background-color: #1cbbb4 !important;
+	border-color: #1cbbb4 !important;
+	color: #ffffff !important;
+}
+
+switch.blue[checked] .wx-switch-input,
+checkbox.blue[checked] .wx-checkbox-input,
+radio.blue[checked] .wx-radio-input,
+switch.blue.checked .uni-switch-input,
+checkbox.blue.checked .uni-checkbox-input,
+radio.blue.checked .uni-radio-input {
+	background-color: #0081ff !important;
+	border-color: #0081ff !important;
+	color: #ffffff !important;
+}
+
+switch.purple[checked] .wx-switch-input,
+checkbox.purple[checked] .wx-checkbox-input,
+radio.purple[checked] .wx-radio-input,
+switch.purple.checked .uni-switch-input,
+checkbox.purple.checked .uni-checkbox-input,
+radio.purple.checked .uni-radio-input {
+	background-color: #6739b6 !important;
+	border-color: #6739b6 !important;
+	color: #ffffff !important;
+}
+
+switch.mauve[checked] .wx-switch-input,
+checkbox.mauve[checked] .wx-checkbox-input,
+radio.mauve[checked] .wx-radio-input,
+switch.mauve.checked .uni-switch-input,
+checkbox.mauve.checked .uni-checkbox-input,
+radio.mauve.checked .uni-radio-input {
+	background-color: #9c26b0 !important;
+	border-color: #9c26b0 !important;
+	color: #ffffff !important;
+}
+
+switch.pink[checked] .wx-switch-input,
+checkbox.pink[checked] .wx-checkbox-input,
+radio.pink[checked] .wx-radio-input,
+switch.pink.checked .uni-switch-input,
+checkbox.pink.checked .uni-checkbox-input,
+radio.pink.checked .uni-radio-input {
+	background-color: #e03997 !important;
+	border-color: #e03997 !important;
+	color: #ffffff !important;
+}
+
+switch.brown[checked] .wx-switch-input,
+checkbox.brown[checked] .wx-checkbox-input,
+radio.brown[checked] .wx-radio-input,
+switch.brown.checked .uni-switch-input,
+checkbox.brown.checked .uni-checkbox-input,
+radio.brown.checked .uni-radio-input {
+	background-color: #a5673f !important;
+	border-color: #a5673f !important;
+	color: #ffffff !important;
+}
+
+switch.grey[checked] .wx-switch-input,
+checkbox.grey[checked] .wx-checkbox-input,
+radio.grey[checked] .wx-radio-input,
+switch.grey.checked .uni-switch-input,
+checkbox.grey.checked .uni-checkbox-input,
+radio.grey.checked .uni-radio-input {
+	background-color: #8799a3 !important;
+	border-color: #8799a3 !important;
+	color: #ffffff !important;
+}
+
+switch.gray[checked] .wx-switch-input,
+checkbox.gray[checked] .wx-checkbox-input,
+radio.gray[checked] .wx-radio-input,
+switch.gray.checked .uni-switch-input,
+checkbox.gray.checked .uni-checkbox-input,
+radio.gray.checked .uni-radio-input {
+	background-color: #f0f0f0 !important;
+	border-color: #f0f0f0 !important;
+	color: #333333 !important;
+}
+
+switch.black[checked] .wx-switch-input,
+checkbox.black[checked] .wx-checkbox-input,
+radio.black[checked] .wx-radio-input,
+switch.black.checked .uni-switch-input,
+checkbox.black.checked .uni-checkbox-input,
+radio.black.checked .uni-radio-input {
+	background-color: #333333 !important;
+	border-color: #333333 !important;
+	color: #ffffff !important;
+}
+
+switch.white[checked] .wx-switch-input,
+checkbox.white[checked] .wx-checkbox-input,
+radio.white[checked] .wx-radio-input,
+switch.white.checked .uni-switch-input,
+checkbox.white.checked .uni-checkbox-input,
+radio.white.checked .uni-radio-input {
+	background-color: #ffffff !important;
+	border-color: #ffffff !important;
+	color: #333333 !important;
+}
+
+/* ==================
+          边框
+ ==================== */
+
+/* -- 实线 -- */
+
+.solid,
+.solid-top,
+.solid-right,
+.solid-bottom,
+.solid-left,
+.solids,
+.solids-top,
+.solids-right,
+.solids-bottom,
+.solids-left,
+.dashed,
+.dashed-top,
+.dashed-right,
+.dashed-bottom,
+.dashed-left {
+	position: relative;
+}
+
+.solid::after,
+.solid-top::after,
+.solid-right::after,
+.solid-bottom::after,
+.solid-left::after,
+.solids::after,
+.solids-top::after,
+.solids-right::after,
+.solids-bottom::after,
+.solids-left::after,
+.dashed::after,
+.dashed-top::after,
+.dashed-right::after,
+.dashed-bottom::after,
+.dashed-left::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+}
+
+.solid::after {
+	border: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-top::after {
+	border-top: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-right::after {
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-bottom::after {
+	border-bottom: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solid-left::after {
+	border-left: 1upx solid rgba(0, 0, 0, 0.1);
+}
+
+.solids::after {
+	border: 8upx solid #eee;
+}
+
+.solids-top::after {
+	border-top: 8upx solid #eee;
+}
+
+.solids-right::after {
+	border-right: 8upx solid #eee;
+}
+
+.solids-bottom::after {
+	border-bottom: 8upx solid #eee;
+}
+
+.solids-left::after {
+	border-left: 8upx solid #eee;
+}
+
+/* -- 虚线 -- */
+
+.dashed::after {
+	border: 1upx dashed #ddd;
+}
+
+.dashed-top::after {
+	border-top: 1upx dashed #ddd;
+}
+
+.dashed-right::after {
+	border-right: 1upx dashed #ddd;
+}
+
+.dashed-bottom::after {
+	border-bottom: 1upx dashed #ddd;
+}
+
+.dashed-left::after {
+	border-left: 1upx dashed #ddd;
+}
+
+/* -- 阴影 -- */
+
+.shadow[class*='white'] {
+	--ShadowSize: 0 1upx 6upx;
+}
+
+.shadow-lg {
+	--ShadowSize: 0upx 40upx 100upx 0upx;
+}
+
+.shadow-warp {
+	position: relative;
+	box-shadow: 0 0 10upx rgba(0, 0, 0, 0.1);
+}
+
+.shadow-warp:before,
+.shadow-warp:after {
+	position: absolute;
+	content: "";
+	top: 20upx;
+	bottom: 30upx;
+	left: 20upx;
+	width: 50%;
+	box-shadow: 0 30upx 20upx rgba(0, 0, 0, 0.2);
+	transform: rotate(-3deg);
+	z-index: -1;
+}
+
+.shadow-warp:after {
+	right: 20upx;
+	left: auto;
+	transform: rotate(3deg);
+}
+
+.shadow-blur {
+	position: relative;
+}
+
+.shadow-blur::before {
+	content: "";
+	display: block;
+	background: inherit;
+	filter: blur(10upx);
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	top: 10upx;
+	left: 10upx;
+	z-index: -1;
+	opacity: 0.4;
+	transform-origin: 0 0;
+	border-radius: inherit;
+	transform: scale(1, 1);
+}
+
+/* ==================
+          按钮
+ ==================== */
+
+.cu-btn {
+	position: relative;
+	border: 0upx;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0 30upx;
+	font-size: 28upx;
+	height: 64upx;
+	line-height: 1;
+	text-align: center;
+	text-decoration: none;
+	overflow: visible;
+	margin-left: initial;
+	transform: translate(0upx, 0upx);
+	margin-right: initial;
+}
+
+.cu-btn::after {
+	display: none;
+}
+
+.cu-btn:not([class*="bg-"]) {
+	background-color: #f0f0f0;
+}
+
+.cu-btn[class*="line"] {
+	background-color: transparent;
+}
+
+.cu-btn[class*="line"]::after {
+	content: " ";
+	display: block;
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: 12upx;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-btn.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-btn[class*="lines"]::after {
+	border: 6upx solid currentColor;
+}
+
+.cu-btn[class*="bg-"]::after {
+	display: none;
+}
+
+.cu-btn.sm {
+	padding: 0 20upx;
+	font-size: 20upx;
+	height: 48upx;
+}
+
+.cu-btn.lg {
+	padding: 0 40upx;
+	font-size: 32upx;
+	height: 80upx;
+}
+
+.cu-btn.cuIcon.sm {
+	width: 48upx;
+	height: 48upx;
+}
+
+.cu-btn.cuIcon {
+	width: 64upx;
+	height: 64upx;
+	border-radius: 500upx;
+	padding: 0;
+}
+
+button.cuIcon.lg {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-btn.shadow-blur::before {
+	top: 4upx;
+	left: 4upx;
+	filter: blur(6upx);
+	opacity: 0.6;
+}
+
+.cu-btn.button-hover {
+	transform: translate(1upx, 1upx);
+}
+
+.block {
+	display: block;
+}
+
+.cu-btn.block {
+	display: flex;
+}
+
+.cu-btn[disabled] {
+	opacity: 0.6;
+	color: #ffffff;
+}
+
+/* ==================
+          徽章
+ ==================== */
+
+.cu-tag {
+	font-size: 24upx;
+	vertical-align: middle;
+	position: relative;
+	display: inline-flex;
+	align-items: center;
+	justify-content: center;
+	box-sizing: border-box;
+	padding: 0upx 16upx;
+	height: 48upx;
+	font-family: Helvetica Neue, Helvetica, sans-serif;
+	white-space: nowrap;
+}
+
+.cu-tag:not([class*="bg"]):not([class*="line"]) {
+	background-color: #f1f1f1;
+}
+
+.cu-tag[class*="line-"]::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border: 1upx solid currentColor;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	box-sizing: border-box;
+	border-radius: inherit;
+	z-index: 1;
+	pointer-events: none;
+}
+
+.cu-tag.radius[class*="line"]::after {
+	border-radius: 12upx;
+}
+
+.cu-tag.round[class*="line"]::after {
+	border-radius: 1000upx;
+}
+
+.cu-tag[class*="line-"]::after {
+	border-radius: 0;
+}
+
+.cu-tag+.cu-tag {
+	margin-left: 10upx;
+}
+
+.cu-tag.sm {
+	font-size: 20upx;
+	padding: 0upx 12upx;
+	height: 32upx;
+}
+
+.cu-capsule {
+	display: inline-flex;
+	vertical-align: middle;
+}
+
+.cu-capsule+.cu-capsule {
+	margin-left: 10upx;
+}
+
+.cu-capsule .cu-tag {
+	margin: 0;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:last-child::after {
+	border-left: 0upx solid transparent;
+}
+
+.cu-capsule .cu-tag[class*="line-"]:first-child::after {
+	border-right: 0upx solid transparent;
+}
+
+.cu-capsule.radius .cu-tag:first-child {
+	border-top-left-radius: 6upx;
+	border-bottom-left-radius: 6upx;
+}
+
+.cu-capsule.radius .cu-tag:last-child::after,
+.cu-capsule.radius .cu-tag[class*="line-"] {
+	border-top-right-radius: 12upx;
+	border-bottom-right-radius: 12upx;
+}
+
+.cu-capsule.round .cu-tag:first-child {
+	border-top-left-radius: 200upx;
+	border-bottom-left-radius: 200upx;
+	text-indent: 4upx;
+}
+
+.cu-capsule.round .cu-tag:last-child::after,
+.cu-capsule.round .cu-tag:last-child {
+	border-top-right-radius: 200upx;
+	border-bottom-right-radius: 200upx;
+	text-indent: -4upx;
+}
+
+.cu-tag.badge {
+	border-radius: 200upx;
+	position: absolute;
+	top: -10upx;
+	right: -10upx;
+	font-size: 20upx;
+	padding: 0upx 10upx;
+	height: 28upx;
+	color: #ffffff;
+}
+
+.cu-tag.badge:not([class*="bg-"]) {
+	background-color: #dd514c;
+}
+
+.cu-tag:empty:not([class*="cuIcon-"]) {
+	padding: 0upx;
+	width: 16upx;
+	height: 16upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+.cu-tag[class*="cuIcon-"] {
+	width: 32upx;
+	height: 32upx;
+	top: -4upx;
+	right: -4upx;
+}
+
+/* ==================
+          头像
+ ==================== */
+
+.cu-avatar {
+	font-variant: small-caps;
+	margin: 0;
+	padding: 0;
+	display: inline-flex;
+	text-align: center;
+	justify-content: center;
+	align-items: center;
+	background-color: #ccc;
+	color: #ffffff;
+	white-space: nowrap;
+	position: relative;
+	width: 64upx;
+	height: 64upx;
+	background-size: cover;
+	background-position: center;
+	vertical-align: middle;
+	font-size: 1.5em;
+}
+
+.cu-avatar.sm {
+	width: 48upx;
+	height: 48upx;
+	font-size: 1em;
+}
+
+.cu-avatar.lg {
+	width: 96upx;
+	height: 96upx;
+	font-size: 2em;
+}
+
+.cu-avatar.xl {
+	width: 128upx;
+	height: 128upx;
+	font-size: 2.5em;
+}
+
+.cu-avatar .avatar-text {
+	font-size: 0.4em;
+}
+
+.cu-avatar-group {
+	direction: rtl;
+	unicode-bidi: bidi-override;
+	padding: 0 10upx 0 40upx;
+	display: inline-block;
+}
+
+.cu-avatar-group .cu-avatar {
+	margin-left: -30upx;
+	border: 4upx solid #f1f1f1;
+	vertical-align: middle;
+}
+
+.cu-avatar-group .cu-avatar.sm {
+	margin-left: -20upx;
+	border: 1upx solid #f1f1f1;
+}
+
+/* ==================
+         进度条
+ ==================== */
+
+.cu-progress {
+	overflow: hidden;
+	height: 28upx;
+	background-color: #ebeef5;
+	display: inline-flex;
+	align-items: center;
+	width: 100%;
+}
+
+.cu-progress+view,
+.cu-progress+text {
+	line-height: 1;
+}
+
+.cu-progress.xs {
+	height: 10upx;
+}
+
+.cu-progress.sm {
+	height: 20upx;
+}
+
+.cu-progress view {
+	width: 0;
+	height: 100%;
+	align-items: center;
+	display: flex;
+	justify-items: flex-end;
+	justify-content: space-around;
+	font-size: 20upx;
+	color: #ffffff;
+	transition: width 0.6s ease;
+}
+
+.cu-progress text {
+	align-items: center;
+	display: flex;
+	font-size: 20upx;
+	color: #333333;
+	text-indent: 10upx;
+}
+
+.cu-progress.text-progress {
+	padding-right: 60upx;
+}
+
+.cu-progress.striped view {
+	background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+	background-size: 72upx 72upx;
+}
+
+.cu-progress.active view {
+	animation: progress-stripes 2s linear infinite;
+}
+
+@keyframes progress-stripes {
+	from {
+		background-position: 72upx 0;
+	}
+
+	to {
+		background-position: 0 0;
+	}
+}
+
+/* ==================
+          加载
+ ==================== */
+
+.cu-load {
+	display: block;
+	line-height: 3em;
+	text-align: center;
+}
+
+.cu-load::before {
+	font-family: "cuIcon";
+	display: inline-block;
+	margin-right: 6upx;
+}
+
+.cu-load.loading::before {
+	content: "\e67a";
+	animation: cuIcon-spin 2s infinite linear;
+}
+
+.cu-load.loading::after {
+	content: "加载中...";
+}
+
+.cu-load.over::before {
+	content: "\e64a";
+}
+
+.cu-load.over::after {
+	content: "没有更多了";
+}
+
+.cu-load.erro::before {
+	content: "\e658";
+}
+
+.cu-load.erro::after {
+	content: "加载失败";
+}
+
+.cu-load.load-cuIcon::before {
+	font-size: 32upx;
+}
+
+.cu-load.load-cuIcon::after {
+	display: none;
+}
+
+.cu-load.load-cuIcon.over {
+	display: none;
+}
+
+.cu-load.load-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 140upx;
+	left: 0;
+	margin: auto;
+	width: 260upx;
+	height: 260upx;
+	background-color: #ffffff;
+	border-radius: 10upx;
+	box-shadow: 0 0 0upx 2000upx rgba(0, 0, 0, 0.5);
+	display: flex;
+	align-items: center;
+	flex-direction: column;
+	justify-content: center;
+	font-size: 28upx;
+	z-index: 9999;
+	line-height: 2.4em;
+}
+
+.cu-load.load-modal [class*="cuIcon-"] {
+	font-size: 60upx;
+}
+
+.cu-load.load-modal image {
+	width: 70upx;
+	height: 70upx;
+}
+
+.cu-load.load-modal::after {
+	content: "";
+	position: absolute;
+	background-color: #ffffff;
+	border-radius: 50%;
+	width: 200upx;
+	height: 200upx;
+	font-size: 10px;
+	border-top: 6upx solid rgba(0, 0, 0, 0.05);
+	border-right: 6upx solid rgba(0, 0, 0, 0.05);
+	border-bottom: 6upx solid rgba(0, 0, 0, 0.05);
+	border-left: 6upx solid #f37b1d;
+	animation: cuIcon-spin 1s infinite linear;
+	z-index: -1;
+}
+
+.load-progress {
+	pointer-events: none;
+	top: 0;
+	position: fixed;
+	width: 100%;
+	left: 0;
+	z-index: 2000;
+}
+
+.load-progress.hide {
+	display: none;
+}
+
+.load-progress .load-progress-bar {
+	position: relative;
+	width: 100%;
+	height: 4upx;
+	overflow: hidden;
+	transition: all 200ms ease 0s;
+}
+
+.load-progress .load-progress-spinner {
+	position: absolute;
+	top: 10upx;
+	right: 10upx;
+	z-index: 2000;
+	display: block;
+}
+
+.load-progress .load-progress-spinner::after {
+	content: "";
+	display: block;
+	width: 24upx;
+	height: 24upx;
+	-webkit-box-sizing: border-box;
+	box-sizing: border-box;
+	border: solid 4upx transparent;
+	border-top-color: inherit;
+	border-left-color: inherit;
+	border-radius: 50%;
+	-webkit-animation: load-progress-spinner 0.4s linear infinite;
+	animation: load-progress-spinner 0.4s linear infinite;
+}
+
+@-webkit-keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+@keyframes load-progress-spinner {
+	0% {
+		-webkit-transform: rotate(0);
+		transform: rotate(0);
+	}
+
+	100% {
+		-webkit-transform: rotate(360deg);
+		transform: rotate(360deg);
+	}
+}
+
+/* ==================
+          列表
+ ==================== */
+.grayscale {
+	filter: grayscale(1);
+}
+
+.cu-list+.cu-list {
+	margin-top: 30upx
+}
+
+.cu-list>.cu-item {
+	transition: all .6s ease-in-out 0s;
+	transform: translateX(0upx)
+}
+
+.cu-list>.cu-item.move-cur {
+	transform: translateX(-260upx)
+}
+
+.cu-list>.cu-item .move {
+	position: absolute;
+	right: 0;
+	display: flex;
+	width: 260upx;
+	height: 100%;
+	transform: translateX(100%)
+}
+
+.cu-list>.cu-item .move view {
+	display: flex;
+	flex: 1;
+	justify-content: center;
+	align-items: center
+}
+
+.cu-list.menu-avatar {
+	overflow: hidden;
+}
+
+.cu-list.menu-avatar>.cu-item {
+	position: relative;
+	display: flex;
+	padding-right: 10upx;
+	height: 140upx;
+	background-color: #ffffff;
+	justify-content: flex-end;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item>.cu-avatar {
+	position: absolute;
+	left: 30upx
+}
+
+.cu-list.menu-avatar>.cu-item .flex .text-cut {
+	max-width: 510upx
+}
+
+.cu-list.menu-avatar>.cu-item .content {
+	position: absolute;
+	left: 146upx;
+	width: calc(100% - 96upx - 60upx - 120upx - 20upx);
+	line-height: 1.6em;
+}
+
+.cu-list.menu-avatar>.cu-item .content.flex-sub {
+	width: calc(100% - 96upx - 60upx - 20upx);
+}
+
+.cu-list.menu-avatar>.cu-item .content>view:first-child {
+	font-size: 30upx;
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu-avatar>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu-avatar>.cu-item .action {
+	width: 100upx;
+	text-align: center
+}
+
+.cu-list.menu-avatar>.cu-item .action view+view {
+	margin-top: 10upx
+}
+
+.cu-list.menu-avatar.comment>.cu-item .content {
+	position: relative;
+	left: 0;
+	width: auto;
+	flex: 1;
+}
+
+.cu-list.menu-avatar.comment>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	height: auto
+}
+
+.cu-list.menu-avatar.comment .cu-avatar {
+	align-self: flex-start
+}
+
+.cu-list.menu>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 0 30upx;
+	min-height: 100upx;
+	background-color: #ffffff;
+	justify-content: space-between;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item:last-child:after {
+	border: none
+}
+
+.cu-list.menu-avatar>.cu-item:after,
+.cu-list.menu>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-bottom: 1upx solid #ddd;
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.menu>.cu-item.grayscale {
+	background-color: #f5f5f5
+}
+
+.cu-list.menu>.cu-item.cur {
+	background-color: #fcf7e9
+}
+
+.cu-list.menu>.cu-item.arrow {
+	padding-right: 90upx
+}
+
+.cu-list.menu>.cu-item.arrow:before {
+	position: absolute;
+	top: 0;
+	right: 30upx;
+	bottom: 0;
+	display: block;
+	margin: auto;
+	width: 30upx;
+	height: 30upx;
+	color: #8799a3;
+	content: "\e6a3";
+	text-align: center;
+	font-size: 34upx;
+	font-family: cuIcon;
+	line-height: 30upx
+}
+
+.cu-list.menu>.cu-item button.content {
+	padding: 0;
+	background-color: transparent;
+	justify-content: flex-start
+}
+
+.cu-list.menu>.cu-item button.content:after {
+	display: none
+}
+
+.cu-list.menu>.cu-item .cu-avatar-group .cu-avatar {
+	border-color: #ffffff
+}
+
+.cu-list.menu>.cu-item .content>view:first-child {
+	display: flex;
+	align-items: center
+}
+
+.cu-list.menu>.cu-item .content>text[class*=cuIcon] {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	text-align: center
+}
+
+.cu-list.menu>.cu-item .content>image {
+	display: inline-block;
+	margin-right: 10upx;
+	width: 1.6em;
+	height: 1.6em;
+	vertical-align: middle
+}
+
+.cu-list.menu>.cu-item .content {
+	font-size: 30upx;
+	line-height: 1.6em;
+	flex: 1
+}
+
+.cu-list.menu>.cu-item .content .cu-tag.sm {
+	display: inline-block;
+	margin-left: 10upx;
+	height: 28upx;
+	font-size: 16upx;
+	line-height: 32upx
+}
+
+.cu-list.menu>.cu-item .action .cu-tag:empty {
+	right: 10upx
+}
+
+.cu-list.menu {
+	display: block;
+	overflow: hidden
+}
+
+.cu-list.menu.sm-border>.cu-item:after {
+	left: 30upx;
+	width: calc(200% - 120upx)
+}
+
+.cu-list.grid>.cu-item {
+	position: relative;
+	display: flex;
+	padding: 20upx 0 30upx;
+	transition-duration: 0s;
+	flex-direction: column
+}
+
+.cu-list.grid>.cu-item:after {
+	position: absolute;
+	top: 0;
+	left: 0;
+	box-sizing: border-box;
+	width: 200%;
+	height: 200%;
+	border-right: 1px solid rgba(0, 0, 0, .1);
+	border-bottom: 1px solid rgba(0, 0, 0, .1);
+	border-radius: inherit;
+	content: " ";
+	transform: scale(.5);
+	transform-origin: 0 0;
+	pointer-events: none
+}
+
+.cu-list.grid>.cu-item text {
+	display: block;
+	margin-top: 10upx;
+	color: #888;
+	font-size: 26upx;
+	line-height: 40upx
+}
+
+.cu-list.grid>.cu-item [class*=cuIcon] {
+	position: relative;
+	display: block;
+	margin-top: 20upx;
+	width: 100%;
+	font-size: 48upx
+}
+
+.cu-list.grid>.cu-item .cu-tag {
+	right: auto;
+	left: 50%;
+	margin-left: 20upx
+}
+
+.cu-list.grid {
+	background-color: #ffffff;
+	text-align: center
+}
+
+.cu-list.grid.no-border>.cu-item {
+	padding-top: 10upx;
+	padding-bottom: 20upx
+}
+
+.cu-list.grid.no-border>.cu-item:after {
+	border: none
+}
+
+.cu-list.grid.no-border {
+	padding: 20upx 10upx
+}
+
+.cu-list.grid.col-3>.cu-item:nth-child(3n):after,
+.cu-list.grid.col-4>.cu-item:nth-child(4n):after,
+.cu-list.grid.col-5>.cu-item:nth-child(5n):after {
+	border-right-width: 0
+}
+
+.cu-list.card-menu {
+	overflow: hidden;
+	margin-right: 30upx;
+	margin-left: 30upx;
+	border-radius: 20upx
+}
+
+
+/* ==================
+          操作条
+ ==================== */
+
+.cu-bar {
+	display: flex;
+	position: relative;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-bar .action {
+	display: flex;
+	align-items: center;
+	height: 100%;
+	justify-content: center;
+	max-width: 100%;
+}
+
+.cu-bar .action.border-title {
+	position: relative;
+	top: -10upx;
+}
+
+.cu-bar .action.border-title text[class*="bg-"]:last-child {
+	position: absolute;
+	bottom: -0.5rem;
+	min-width: 2rem;
+	height: 6upx;
+	left: 0;
+}
+
+.cu-bar .action.sub-title {
+	position: relative;
+	top: -0.2rem;
+}
+
+.cu-bar .action.sub-title text {
+	position: relative;
+	z-index: 1;
+}
+
+.cu-bar .action.sub-title text[class*="bg-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.2rem;
+	border-radius: 6upx;
+	width: 100%;
+	height: 0.6rem;
+	left: 0.6rem;
+	opacity: 0.3;
+	z-index: 0;
+}
+
+.cu-bar .action.sub-title text[class*="text-"]:last-child {
+	position: absolute;
+	display: inline-block;
+	bottom: -0.7rem;
+	left: 0.5rem;
+	opacity: 0.2;
+	z-index: 0;
+	text-align: right;
+	font-weight: 900;
+	font-size: 36upx;
+}
+
+.cu-bar.justify-center .action.border-title text:last-child,
+.cu-bar.justify-center .action.sub-title text:last-child {
+	left: 0;
+	right: 0;
+	margin: auto;
+	text-align: center;
+}
+
+.cu-bar .action:first-child {
+	margin-left: 30upx;
+	font-size: 30upx;
+}
+
+.cu-bar .action text.text-cut {
+	text-align: left;
+	width: 100%;
+}
+
+.cu-bar .cu-avatar:first-child {
+	margin-left: 20upx;
+}
+
+.cu-bar .action:first-child>text[class*="cuIcon-"] {
+	margin-left: -0.3em;
+	margin-right: 0.3em;
+}
+
+.cu-bar .action:last-child {
+	margin-right: 30upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"],
+.cu-bar .action>view[class*="cuIcon-"] {
+	font-size: 36upx;
+}
+
+.cu-bar .action>text[class*="cuIcon-"]+text[class*="cuIcon-"] {
+	margin-left: 0.5em;
+}
+
+.cu-bar .content {
+	position: absolute;
+	text-align: center;
+	width: calc(100% - 340upx);
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+	margin: auto;
+	height: 60upx;
+	font-size: 32upx;
+	line-height: 60upx;
+	cursor: none;
+	pointer-events: none;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.cu-bar.ios .content {
+	bottom: 7px;
+	height: 30px;
+	font-size: 32upx;
+	line-height: 30px;
+}
+
+.cu-bar.btn-group {
+	justify-content: space-around;
+}
+
+.cu-bar.btn-group button {
+	padding: 20upx 32upx;
+}
+
+.cu-bar.btn-group button {
+	flex: 1;
+	margin: 0 20upx;
+	max-width: 50%;
+}
+
+.cu-bar .search-form {
+	background-color: #f5f5f5;
+	line-height: 64upx;
+	height: 64upx;
+	font-size: 24upx;
+	color: #333333;
+	flex: 1;
+	display: flex;
+	align-items: center;
+	margin: 0 30upx;
+}
+
+.cu-bar .search-form+.action {
+	margin-right: 30upx;
+}
+
+.cu-bar .search-form input {
+	flex: 1;
+	padding-right: 30upx;
+	height: 64upx;
+	line-height: 64upx;
+	font-size: 26upx;
+	background-color: transparent;
+}
+
+.cu-bar .search-form [class*="cuIcon-"] {
+	margin: 0 0.5em 0 0.8em;
+}
+
+.cu-bar .search-form [class*="cuIcon-"]::before {
+	top: 0upx;
+}
+
+.cu-bar.fixed,
+.nav.fixed {
+	position: fixed;
+	width: 100%;
+	top: 0;
+	z-index: 1024;
+	box-shadow: 0 1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.foot {
+	position: fixed;
+	width: 100%;
+	bottom: 0;
+	z-index: 1024;
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar {
+	padding: 0;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+	padding-bottom: calc(env(safe-area-inset-bottom) / 2);
+}
+
+.cu-tabbar-height {
+	min-height: 100upx;
+	height: calc(100upx + env(safe-area-inset-bottom) / 2);
+}
+
+.cu-bar.tabbar.shadow {
+	box-shadow: 0 -1upx 6upx rgba(0, 0, 0, 0.1);
+}
+
+.cu-bar.tabbar .action {
+	font-size: 22upx;
+	position: relative;
+	flex: 1;
+	text-align: center;
+	padding: 0;
+	display: block;
+	height: auto;
+	line-height: 1;
+	margin: 0;
+	background-color: inherit;
+	overflow: initial;
+}
+
+.cu-bar.tabbar.shop .action {
+	width: 140upx;
+	flex: initial;
+}
+
+.cu-bar.tabbar .action.add-action {
+	position: relative;
+	z-index: 2;
+	padding-top: 50upx;
+}
+
+.cu-bar.tabbar .action.add-action [class*="cuIcon-"] {
+	position: absolute;
+	width: 70upx;
+	z-index: 2;
+	height: 70upx;
+	border-radius: 50%;
+	line-height: 70upx;
+	font-size: 50upx;
+	top: -35upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	padding: 0;
+}
+
+.cu-bar.tabbar .action.add-action::after {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 100upx;
+	top: -50upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	box-shadow: 0 -3upx 8upx rgba(0, 0, 0, 0.08);
+	border-radius: 50upx;
+	background-color: inherit;
+	z-index: 0;
+}
+
+.cu-bar.tabbar .action.add-action::before {
+	content: "";
+	position: absolute;
+	width: 100upx;
+	height: 30upx;
+	bottom: 30upx;
+	left: 0;
+	right: 0;
+	margin: auto;
+	background-color: inherit;
+	z-index: 1;
+}
+
+.cu-bar.tabbar .btn-group {
+	flex: 1;
+	display: flex;
+	justify-content: space-around;
+	align-items: center;
+	padding: 0 10upx;
+}
+
+.cu-bar.tabbar button.action::after {
+	border: 0;
+}
+
+.cu-bar.tabbar .action [class*="cuIcon-"] {
+	width: 100upx;
+	position: relative;
+	display: block;
+	height: auto;
+	margin: 0 auto 10upx;
+	text-align: center;
+	font-size: 40upx;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image {
+	margin: 0 auto;
+}
+
+.cu-bar.tabbar .action .cuIcon-cu-image image {
+	width: 50upx;
+	height: 50upx;
+	display: inline-block;
+}
+
+.cu-bar.tabbar .submit {
+	align-items: center;
+	display: flex;
+	justify-content: center;
+	text-align: center;
+	position: relative;
+	flex: 2;
+	align-self: stretch;
+}
+
+.cu-bar.tabbar .submit:last-child {
+	flex: 2.6;
+}
+
+.cu-bar.tabbar .submit+.submit {
+	flex: 2;
+}
+
+.cu-bar.tabbar.border .action::before {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	border-right: 1upx solid rgba(0, 0, 0, 0.1);
+	z-index: 3;
+}
+
+.cu-bar.tabbar.border .action:last-child:before {
+	display: none;
+}
+
+.cu-bar.input {
+	padding-right: 20upx;
+	background-color: #ffffff;
+}
+
+.cu-bar.input input {
+	overflow: initial;
+	line-height: 64upx;
+	height: 64upx;
+	min-height: 64upx;
+	flex: 1;
+	font-size: 30upx;
+	margin: 0 20upx;
+}
+
+.cu-bar.input .action {
+	margin-left: 20upx;
+}
+
+.cu-bar.input .action [class*="cuIcon-"] {
+	font-size: 48upx;
+}
+
+.cu-bar.input input+.action {
+	margin-right: 20upx;
+	margin-left: 0upx;
+}
+
+.cu-bar.input .action:first-child [class*="cuIcon-"] {
+	margin-left: 0upx;
+}
+
+.cu-custom {
+	display: block;
+	position: relative;
+}
+
+.cu-custom .cu-bar .content {
+	width: calc(100% - 440upx);
+}
+
+/* #ifdef MP-ALIPAY */
+.cu-custom .cu-bar .action .cuIcon-back {
+	opacity: 0;
+}
+
+/* #endif */
+
+.cu-custom .cu-bar .content image {
+	height: 60upx;
+	width: 240upx;
+}
+
+.cu-custom .cu-bar {
+	min-height: 0px;
+	/* #ifdef MP-WEIXIN */
+	padding-right: 220upx;
+	/* #endif */
+	/* #ifdef MP-ALIPAY */
+	padding-right: 150upx;
+	/* #endif */
+	box-shadow: 0upx 0upx 0upx;
+	z-index: 9999;
+}
+
+.cu-custom .cu-bar .border-custom {
+	position: relative;
+	background: rgba(0, 0, 0, 0.15);
+	border-radius: 1000upx;
+	height: 30px;
+}
+
+.cu-custom .cu-bar .border-custom::after {
+	content: " ";
+	width: 200%;
+	height: 200%;
+	position: absolute;
+	top: 0;
+	left: 0;
+	border-radius: inherit;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	border: 1upx solid #ffffff;
+	opacity: 0.5;
+}
+
+.cu-custom .cu-bar .border-custom::before {
+	content: " ";
+	width: 1upx;
+	height: 110%;
+	position: absolute;
+	top: 22.5%;
+	left: 0;
+	right: 0;
+	margin: auto;
+	transform: scale(0.5);
+	transform-origin: 0 0;
+	pointer-events: none;
+	box-sizing: border-box;
+	opacity: 0.6;
+	background-color: #ffffff;
+}
+
+.cu-custom .cu-bar .border-custom text {
+	display: block;
+	flex: 1;
+	margin: auto !important;
+	text-align: center;
+	font-size: 34upx;
+}
+
+/* ==================
+         导航栏
+ ==================== */
+
+.nav {
+	white-space: nowrap;
+}
+
+::-webkit-scrollbar {
+	display: none;
+}
+
+.nav .cu-item {
+	height: 90upx;
+	display: inline-block;
+	line-height: 90upx;
+	margin: 0 10upx;
+	padding: 0 20upx;
+}
+
+.nav .cu-item.cur {
+	border-bottom: 4upx solid;
+}
+
+/* ==================
+         时间轴
+ ==================== */
+
+.cu-timeline {
+	display: block;
+	background-color: #ffffff;
+}
+
+.cu-timeline .cu-time {
+	width: 120upx;
+	text-align: center;
+	padding: 20upx 0;
+	font-size: 26upx;
+	color: #888;
+	display: block;
+}
+
+.cu-timeline>.cu-item {
+	padding: 30upx 30upx 30upx 120upx;
+	position: relative;
+	display: block;
+	z-index: 0;
+}
+
+.cu-timeline>.cu-item:not([class*="text-"]) {
+	color: #ccc;
+}
+
+.cu-timeline>.cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	width: 1upx;
+	background-color: #ddd;
+	left: 60upx;
+	height: 100%;
+	top: 0;
+	z-index: 8;
+}
+
+.cu-timeline>.cu-item::before {
+	font-family: "cuIcon";
+	display: block;
+	position: absolute;
+	top: 36upx;
+	z-index: 9;
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item:not([class*="cuIcon-"])::before {
+	content: "\e763";
+}
+
+.cu-timeline>.cu-item[class*="cuIcon-"]::before {
+	background-color: #ffffff;
+	width: 50upx;
+	height: 50upx;
+	text-align: center;
+	border: none;
+	line-height: 50upx;
+	left: 36upx;
+}
+
+.cu-timeline>.cu-item>.content {
+	padding: 30upx;
+	border-radius: 6upx;
+	display: block;
+	line-height: 1.6;
+}
+
+.cu-timeline>.cu-item>.content:not([class*="bg-"]) {
+	background-color: #f1f1f1;
+	color: #333333;
+}
+
+.cu-timeline>.cu-item>.content+.content {
+	margin-top: 20upx;
+}
+
+/* ==================
+         聊天
+ ==================== */
+
+.cu-chat {
+	display: flex;
+	flex-direction: column;
+}
+
+.cu-chat .cu-item {
+	display: flex;
+	padding: 30upx 30upx 70upx;
+	position: relative;
+}
+
+.cu-chat .cu-item>.cu-avatar {
+	width: 80upx;
+	height: 80upx;
+}
+
+.cu-chat .cu-item>.main {
+	max-width: calc(100% - 260upx);
+	margin: 0 40upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>image {
+	height: 320upx;
+}
+
+.cu-chat .cu-item>.main .content {
+	padding: 20upx;
+	border-radius: 6upx;
+	display: inline-flex;
+	max-width: 100%;
+	align-items: center;
+	font-size: 30upx;
+	position: relative;
+	min-height: 80upx;
+	line-height: 40upx;
+	text-align: left;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"]) {
+	background-color: #ffffff;
+	color: #333333;
+}
+
+.cu-chat .cu-item .date {
+	position: absolute;
+	font-size: 24upx;
+	color: #8799a3;
+	width: calc(100% - 320upx);
+	bottom: 20upx;
+	left: 160upx;
+}
+
+.cu-chat .cu-item .action {
+	padding: 0 30upx;
+	display: flex;
+	align-items: center;
+}
+
+.cu-chat .cu-item>.main .content::after {
+	content: "";
+	top: 27upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: 100;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+}
+
+.cu-chat .cu-item.self>.main .content::after {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item>.main .content::before {
+	content: "";
+	top: 30upx;
+	transform: rotate(45deg);
+	position: absolute;
+	z-index: -1;
+	display: inline-block;
+	overflow: hidden;
+	width: 24upx;
+	height: 24upx;
+	left: -12upx;
+	right: initial;
+	background-color: inherit;
+	filter: blur(5upx);
+	opacity: 0.3;
+}
+
+.cu-chat .cu-item>.main .content:not([class*="bg-"])::before {
+	background-color: #333333;
+	opacity: 0.1;
+}
+
+.cu-chat .cu-item.self>.main .content::before {
+	left: auto;
+	right: -12upx;
+}
+
+.cu-chat .cu-item.self {
+	justify-content: flex-end;
+	text-align: right;
+}
+
+.cu-chat .cu-info {
+	display: inline-block;
+	margin: 20upx auto;
+	font-size: 24upx;
+	padding: 8upx 12upx;
+	background-color: rgba(0, 0, 0, 0.2);
+	border-radius: 6upx;
+	color: #ffffff;
+	max-width: 400upx;
+	line-height: 1.4;
+}
+
+/* ==================
+         卡片
+ ==================== */
+
+.cu-card {
+	display: block;
+	overflow: hidden;
+}
+
+.cu-card>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+	border-radius: 10upx;
+	margin: 30upx;
+}
+
+.cu-card>.cu-item.shadow-blur {
+	overflow: initial;
+}
+
+.cu-card.no-card>.cu-item {
+	margin: 0upx;
+	border-radius: 0upx;
+}
+
+.cu-card .grid.grid-square {
+	margin-bottom: -20upx;
+}
+
+.cu-card.case .image {
+	position: relative;
+}
+
+.cu-card.case .image image {
+	width: 100%;
+}
+
+.cu-card.case .image .cu-tag {
+	position: absolute;
+	right: 0;
+	top: 0;
+}
+
+.cu-card.case .image .cu-bar {
+	position: absolute;
+	bottom: 0;
+	width: 100%;
+	background-color: transparent;
+	padding: 0upx 30upx;
+}
+
+.cu-card.case.no-card .image {
+	margin: 30upx 30upx 0;
+	overflow: hidden;
+	border-radius: 10upx;
+}
+
+.cu-card.dynamic {
+	display: block;
+}
+
+.cu-card.dynamic>.cu-item {
+	display: block;
+	background-color: #ffffff;
+	overflow: hidden;
+}
+
+.cu-card.dynamic>.cu-item>.text-content {
+	padding: 0 30upx 0;
+	max-height: 6.4em;
+	overflow: hidden;
+	font-size: 30upx;
+	margin-bottom: 20upx;
+}
+
+.cu-card.dynamic>.cu-item .square-img {
+	width: 100%;
+	height: 200upx;
+	border-radius: 6upx;
+}
+
+.cu-card.dynamic>.cu-item .only-img {
+	width: 100%;
+	height: 320upx;
+	border-radius: 6upx;
+}
+
+/* card.dynamic>.cu-item .comment {
+  padding: 20upx;
+  background-color: #f1f1f1;
+  margin: 0 30upx 30upx;
+  border-radius: 6upx;
+} */
+
+.cu-card.article {
+	display: block;
+}
+
+.cu-card.article>.cu-item {
+	padding-bottom: 30upx;
+}
+
+.cu-card.article>.cu-item .title {
+	font-size: 30upx;
+	font-weight: 900;
+	color: #333333;
+	line-height: 100upx;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content {
+	display: flex;
+	padding: 0 30upx;
+}
+
+.cu-card.article>.cu-item .content>image {
+	width: 240upx;
+	height: 6.4em;
+	margin-right: 20upx;
+	border-radius: 6upx;
+}
+
+.cu-card.article>.cu-item .content .desc {
+	flex: 1;
+	display: flex;
+	flex-direction: column;
+	justify-content: space-between;
+}
+
+.cu-card.article>.cu-item .content .text-content {
+	font-size: 28upx;
+	color: #888;
+	height: 4.8em;
+	overflow: hidden;
+}
+
+/* ==================
+         表单
+ ==================== */
+
+.cu-form-group {
+	background-color: #ffffff;
+	padding: 1upx 30upx;
+	display: flex;
+	align-items: center;
+	min-height: 100upx;
+	justify-content: space-between;
+}
+
+.cu-form-group+.cu-form-group {
+	border-top: 1upx solid #eee;
+}
+
+.cu-form-group .title {
+	text-align: justify;
+	padding-right: 30upx;
+	font-size: 30upx;
+	position: relative;
+	height: 60upx;
+	line-height: 60upx;
+}
+
+.cu-form-group input {
+	flex: 1;
+	font-size: 30upx;
+	color: #555;
+	padding-right: 20upx;
+}
+
+.cu-form-group>text[class*="cuIcon-"] {
+	font-size: 36upx;
+	padding: 0;
+	box-sizing: border-box;
+}
+
+.cu-form-group textarea {
+	margin: 32upx 0 30upx;
+	height: 4.6em;
+	width: 100%;
+	line-height: 1.2em;
+	flex: 1;
+	font-size: 28upx;
+	padding: 0;
+}
+
+.cu-form-group.align-start .title {
+	height: 1em;
+	margin-top: 32upx;
+	line-height: 1em;
+}
+
+.cu-form-group picker {
+	flex: 1;
+	padding-right: 40upx;
+	overflow: hidden;
+	position: relative;
+}
+
+.cu-form-group picker .picker {
+	line-height: 100upx;
+	font-size: 28upx;
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+	width: 100%;
+	text-align: right;
+}
+
+.cu-form-group picker::after {
+	font-family: cuIcon;
+	display: block;
+	content: "\e6a3";
+	position: absolute;
+	font-size: 34upx;
+	color: #8799a3;
+	line-height: 100upx;
+	width: 60upx;
+	text-align: center;
+	top: 0;
+	bottom: 0;
+	right: -20upx;
+	margin: auto;
+}
+
+.cu-form-group textarea[disabled],
+.cu-form-group textarea[disabled] .placeholder {
+	color: transparent;
+}
+
+/* ==================
+         模态窗口
+ ==================== */
+
+.cu-modal {
+	position: fixed;
+	top: 0;
+	right: 0;
+	bottom: 0;
+	left: 0;
+	z-index: 1110;
+	opacity: 0;
+	outline: 0;
+	text-align: center;
+	-ms-transform: scale(1.185);
+	transform: scale(1.185);
+	backface-visibility: hidden;
+	perspective: 2000upx;
+	background: rgba(0, 0, 0, 0.6);
+	transition: all 0.3s ease-in-out 0s;
+	pointer-events: none;
+}
+
+.cu-modal::before {
+	content: "\200B";
+	display: inline-block;
+	height: 100%;
+	vertical-align: middle;
+}
+
+.cu-modal.show {
+	opacity: 1;
+	transition-duration: 0.3s;
+	-ms-transform: scale(1);
+	transform: scale(1);
+	overflow-x: hidden;
+	overflow-y: auto;
+	pointer-events: auto;
+}
+
+.cu-dialog {
+	position: relative;
+	display: inline-block;
+	vertical-align: middle;
+	margin-left: auto;
+	margin-right: auto;
+	width: 680upx;
+	max-width: 100%;
+	background-color: #f8f8f8;
+	border-radius: 10upx;
+	overflow: hidden;
+}
+
+.cu-modal.bottom-modal::before {
+	vertical-align: bottom;
+}
+
+.cu-modal.bottom-modal .cu-dialog {
+	width: 100%;
+	border-radius: 0;
+}
+
+.cu-modal.bottom-modal {
+	margin-bottom: -1000upx;
+}
+
+.cu-modal.bottom-modal.show {
+	margin-bottom: 0;
+}
+
+.cu-modal.drawer-modal {
+	transform: scale(1);
+	display: flex;
+}
+
+.cu-modal.drawer-modal .cu-dialog {
+	height: 100%;
+	min-width: 200upx;
+	border-radius: 0;
+	margin: initial;
+	transition-duration: 0.3s;
+}
+
+.cu-modal.drawer-modal.justify-start .cu-dialog {
+	transform: translateX(-100%);
+}
+
+.cu-modal.drawer-modal.justify-end .cu-dialog {
+	transform: translateX(100%);
+}
+
+.cu-modal.drawer-modal.show .cu-dialog {
+	transform: translateX(0%);
+}
+.cu-modal .cu-dialog>.cu-bar:first-child .action{
+  min-width: 100rpx;
+  margin-right: 0;
+  min-height: 100rpx;
+}
+/* ==================
+         轮播
+ ==================== */
+swiper .a-swiper-dot {
+	display: inline-block;
+	width: 16upx;
+	height: 16upx;
+	background: rgba(0, 0, 0, .3);
+	border-radius: 50%;
+	vertical-align: middle;
+}
+
+swiper[class*="-dot"] .wx-swiper-dots,
+swiper[class*="-dot"] .a-swiper-dots,
+swiper[class*="-dot"] .uni-swiper-dots {
+	display: flex;
+	align-items: center;
+	width: 100%;
+	justify-content: center;
+}
+
+swiper.square-dot .wx-swiper-dot,
+swiper.square-dot .a-swiper-dot,
+swiper.square-dot .uni-swiper-dot {
+	background-color: #ffffff;
+	opacity: 0.4;
+	width: 10upx;
+	height: 10upx;
+	border-radius: 20upx;
+	margin: 0 8upx !important;
+}
+
+swiper.square-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.square-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.square-dot .uni-swiper-dot.uni-swiper-dot-active {
+	opacity: 1;
+	width: 30upx;
+}
+
+swiper.round-dot .wx-swiper-dot,
+swiper.round-dot .a-swiper-dot,
+swiper.round-dot .uni-swiper-dot {
+	width: 10upx;
+	height: 10upx;
+	position: relative;
+	margin: 4upx 8upx !important;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active::after,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active::after,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active::after {
+	content: "";
+	position: absolute;
+	width: 10upx;
+	height: 10upx;
+	top: 0upx;
+	left: 0upx;
+	right: 0;
+	bottom: 0;
+	margin: auto;
+	background-color: #ffffff;
+	border-radius: 20upx;
+}
+
+swiper.round-dot .wx-swiper-dot.wx-swiper-dot-active,
+swiper.round-dot .a-swiper-dot.a-swiper-dot-active,
+swiper.round-dot .uni-swiper-dot.uni-swiper-dot-active {
+	width: 18upx;
+	height: 18upx;
+}
+
+.screen-swiper {
+	min-height: 375upx;
+}
+
+.screen-swiper image,
+.screen-swiper video,
+.swiper-item image,
+.swiper-item video {
+	width: 100%;
+	display: block;
+	height: 100%;
+	margin: 0;
+	pointer-events: none;
+}
+
+.card-swiper {
+	height: 420upx !important;
+}
+
+.card-swiper swiper-item {
+	width: 610upx !important;
+	left: 70upx;
+	box-sizing: border-box;
+	padding: 40upx 0upx 70upx;
+	overflow: initial;
+}
+
+.card-swiper swiper-item .swiper-item {
+	width: 100%;
+	display: block;
+	height: 100%;
+	border-radius: 10upx;
+	transform: scale(0.9);
+	transition: all 0.2s ease-in 0s;
+	overflow: hidden;
+}
+
+.card-swiper swiper-item.cur .swiper-item {
+	transform: none;
+	transition: all 0.2s ease-in 0s;
+}
+
+
+.tower-swiper {
+	height: 420upx;
+	position: relative;
+	max-width: 750upx;
+	overflow: hidden;
+}
+
+.tower-swiper .tower-item {
+	position: absolute;
+	width: 300upx;
+	height: 380upx;
+	top: 0;
+	bottom: 0;
+	left: 50%;
+	margin: auto;
+	transition: all 0.2s ease-in 0s;
+	opacity: 1;
+}
+
+.tower-swiper .tower-item.none {
+	opacity: 0;
+}
+
+.tower-swiper .tower-item .swiper-item {
+	width: 100%;
+	height: 100%;
+	border-radius: 6upx;
+	overflow: hidden;
+}
+
+/* ==================
+          步骤条
+ ==================== */
+
+.cu-steps {
+	display: flex;
+}
+
+scroll-view.cu-steps {
+	display: block;
+	white-space: nowrap;
+}
+
+scroll-view.cu-steps .cu-item {
+	display: inline-block;
+}
+
+.cu-steps .cu-item {
+	flex: 1;
+	text-align: center;
+	position: relative;
+	min-width: 100upx;
+}
+
+.cu-steps .cu-item:not([class*="text-"]) {
+	color: #8799a3;
+}
+
+.cu-steps .cu-item [class*="cuIcon-"],
+.cu-steps .cu-item .num {
+	display: block;
+	font-size: 40upx;
+	line-height: 80upx;
+}
+
+.cu-steps .cu-item::before,
+.cu-steps .cu-item::after,
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "";
+	display: block;
+	position: absolute;
+	height: 0px;
+	width: calc(100% - 80upx);
+	border-bottom: 1px solid #ccc;
+	left: calc(0px - (100% - 80upx) / 2);
+	top: 40upx;
+	z-index: 0;
+}
+
+.cu-steps.steps-arrow .cu-item::before,
+.cu-steps.steps-arrow .cu-item::after {
+	content: "\e6a3";
+	font-family: 'cuIcon';
+	height: 30upx;
+	border-bottom-width: 0px;
+	line-height: 30upx;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	color: #ccc;
+}
+
+.cu-steps.steps-bottom .cu-item::before,
+.cu-steps.steps-bottom .cu-item::after {
+	bottom: 40upx;
+	top: initial;
+}
+
+.cu-steps .cu-item::after {
+	border-bottom: 1px solid currentColor;
+	width: 0px;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"]::after {
+	width: calc(100% - 80upx);
+	color: currentColor;
+}
+
+.cu-steps .cu-item:first-child::before,
+.cu-steps .cu-item:first-child::after {
+	display: none;
+}
+
+.cu-steps .cu-item .num {
+	width: 40upx;
+	height: 40upx;
+	border-radius: 50%;
+	line-height: 40upx;
+	margin: 20upx auto;
+	font-size: 24upx;
+	border: 1px solid currentColor;
+	position: relative;
+	overflow: hidden;
+}
+
+.cu-steps .cu-item[class*="text-"] .num {
+	background-color: currentColor;
+}
+
+.cu-steps .cu-item .num::before,
+.cu-steps .cu-item .num::after {
+	content: attr(data-index);
+	position: absolute;
+	left: 0;
+	right: 0;
+	top: 0;
+	bottom: 0;
+	margin: auto;
+	transition: all 0.3s ease-in-out 0s;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num::before {
+	transform: translateY(-40upx);
+	color: #ffffff;
+}
+
+.cu-steps .cu-item .num::after {
+	transform: translateY(40upx);
+	color: #ffffff;
+	transition: all 0.3s ease-in-out 0s;
+}
+
+.cu-steps .cu-item[class*="text-"] .num::after {
+	content: "\e645";
+	font-family: 'cuIcon';
+	color: #ffffff;
+	transform: translateY(0upx);
+}
+
+.cu-steps .cu-item[class*="text-"] .num.err::after {
+	content: "\e646";
+}
+
+/* ==================
+          布局
+ ==================== */
+
+/*  -- flex弹性布局 -- */
+
+.flex {
+	display: flex;
+}
+
+.basis-xs {
+	flex-basis: 20%;
+}
+
+.basis-sm {
+	flex-basis: 40%;
+}
+
+.basis-df {
+	flex-basis: 50%;
+}
+
+.basis-lg {
+	flex-basis: 60%;
+}
+
+.basis-xl {
+	flex-basis: 80%;
+}
+
+.flex-sub {
+	flex: 1;
+}
+
+.flex-twice {
+	flex: 2;
+}
+
+.flex-treble {
+	flex: 3;
+}
+
+.flex-direction {
+	flex-direction: column;
+}
+
+.flex-wrap {
+	flex-wrap: wrap;
+}
+
+.align-start {
+	align-items: flex-start;
+}
+
+.align-end {
+	align-items: flex-end;
+}
+
+.align-center {
+	align-items: center;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.self-start {
+	align-self: flex-start;
+}
+
+.self-center {
+	align-self: flex-center;
+}
+
+.self-end {
+	align-self: flex-end;
+}
+
+.self-stretch {
+	align-self: stretch;
+}
+
+.align-stretch {
+	align-items: stretch;
+}
+
+.justify-start {
+	justify-content: flex-start;
+}
+
+.justify-end {
+	justify-content: flex-end;
+}
+
+.justify-center {
+	justify-content: center;
+}
+
+.justify-between {
+	justify-content: space-between;
+}
+
+.justify-around {
+	justify-content: space-around;
+}
+
+/* grid布局 */
+
+.grid {
+	display: flex;
+	flex-wrap: wrap;
+}
+
+.grid.grid-square {
+	overflow: hidden;
+}
+
+.grid.grid-square .cu-tag {
+	position: absolute;
+	right: 0;
+	top: 0;
+	border-bottom-left-radius: 6upx;
+	padding: 6upx 12upx;
+	height: auto;
+	background-color: rgba(0, 0, 0, 0.5);
+}
+
+.grid.grid-square>view>text[class*="cuIcon-"] {
+	font-size: 52upx;
+	position: absolute;
+	color: #8799a3;
+	margin: auto;
+	top: 0;
+	bottom: 0;
+	left: 0;
+	right: 0;
+	display: flex;
+	justify-content: center;
+	align-items: center;
+	flex-direction: column;
+}
+
+.grid.grid-square>view {
+	margin-right: 20upx;
+	margin-bottom: 20upx;
+	border-radius: 6upx;
+	position: relative;
+	overflow: hidden;
+}
+.grid.grid-square>view.bg-img image {
+	width: 100%;
+	height: 100%;
+	position: absolute;
+}
+.grid.col-1.grid-square>view {
+	padding-bottom: 100%;
+	height: 0;
+	margin-right: 0;
+}
+
+.grid.col-2.grid-square>view {
+	padding-bottom: calc((100% - 20upx)/2);
+	height: 0;
+	width: calc((100% - 20upx)/2);
+}
+
+.grid.col-3.grid-square>view {
+	padding-bottom: calc((100% - 40upx)/3);
+	height: 0;
+	width: calc((100% - 40upx)/3);
+}
+
+.grid.col-4.grid-square>view {
+	padding-bottom: calc((100% - 60upx)/4);
+	height: 0;
+	width: calc((100% - 60upx)/4);
+}
+
+.grid.col-5.grid-square>view {
+	padding-bottom: calc((100% - 80upx)/5);
+	height: 0;
+	width: calc((100% - 80upx)/5);
+}
+
+.grid.col-2.grid-square>view:nth-child(2n),
+.grid.col-3.grid-square>view:nth-child(3n),
+.grid.col-4.grid-square>view:nth-child(4n),
+.grid.col-5.grid-square>view:nth-child(5n) {
+	margin-right: 0;
+}
+
+.grid.col-1>view {
+	width: 100%;
+}
+
+.grid.col-2>view {
+	width: 50%;
+}
+
+.grid.col-3>view {
+	width: 33.33%;
+}
+
+.grid.col-4>view {
+	width: 25%;
+}
+
+.grid.col-5>view {
+	width: 20%;
+}
+
+/*  -- 内外边距 -- */
+
+.margin-0 {
+	margin: 0;
+}
+
+.margin-xs {
+	margin: 10upx;
+}
+
+.margin-sm {
+	margin: 20upx;
+}
+
+.margin {
+	margin: 30upx;
+}
+
+.margin-lg {
+	margin: 40upx;
+}
+
+.margin-xl {
+	margin: 50upx;
+}
+
+.margin-top-xs {
+	margin-top: 10upx;
+}
+
+.margin-top-sm {
+	margin-top: 20upx;
+}
+
+.margin-top {
+	margin-top: 30upx;
+}
+
+.margin-top-lg {
+	margin-top: 40upx;
+}
+
+.margin-top-xl {
+	margin-top: 50upx;
+}
+
+.margin-right-xs {
+	margin-right: 10upx;
+}
+
+.margin-right-sm {
+	margin-right: 20upx;
+}
+
+.margin-right {
+	margin-right: 30upx;
+}
+
+.margin-right-lg {
+	margin-right: 40upx;
+}
+
+.margin-right-xl {
+	margin-right: 50upx;
+}
+
+.margin-bottom-xs {
+	margin-bottom: 10upx;
+}
+
+.margin-bottom-sm {
+	margin-bottom: 20upx;
+}
+
+.margin-bottom {
+	margin-bottom: 30upx;
+}
+
+.margin-bottom-lg {
+	margin-bottom: 40upx;
+}
+
+.margin-bottom-xl {
+	margin-bottom: 50upx;
+}
+
+.margin-left-xs {
+	margin-left: 10upx;
+}
+
+.margin-left-sm {
+	margin-left: 20upx;
+}
+
+.margin-left {
+	margin-left: 30upx;
+}
+
+.margin-left-lg {
+	margin-left: 40upx;
+}
+
+.margin-left-xl {
+	margin-left: 50upx;
+}
+
+.margin-lr-xs {
+	margin-left: 10upx;
+	margin-right: 10upx;
+}
+
+.margin-lr-sm {
+	margin-left: 20upx;
+	margin-right: 20upx;
+}
+
+.margin-lr {
+	margin-left: 30upx;
+	margin-right: 30upx;
+}
+
+.margin-lr-lg {
+	margin-left: 40upx;
+	margin-right: 40upx;
+}
+
+.margin-lr-xl {
+	margin-left: 50upx;
+	margin-right: 50upx;
+}
+
+.margin-tb-xs {
+	margin-top: 10upx;
+	margin-bottom: 10upx;
+}
+
+.margin-tb-sm {
+	margin-top: 20upx;
+	margin-bottom: 20upx;
+}
+
+.margin-tb {
+	margin-top: 30upx;
+	margin-bottom: 30upx;
+}
+
+.margin-tb-lg {
+	margin-top: 40upx;
+	margin-bottom: 40upx;
+}
+
+.margin-tb-xl {
+	margin-top: 50upx;
+	margin-bottom: 50upx;
+}
+
+.padding-0 {
+	padding: 0;
+}
+
+.padding-xs {
+	padding: 10upx;
+}
+
+.padding-sm {
+	padding: 20upx;
+}
+
+.padding {
+	padding: 30upx;
+}
+
+.padding-lg {
+	padding: 40upx;
+}
+
+.padding-xl {
+	padding: 50upx;
+}
+
+.padding-top-xs {
+	padding-top: 10upx;
+}
+
+.padding-top-sm {
+	padding-top: 20upx;
+}
+
+.padding-top {
+	padding-top: 30upx;
+}
+
+.padding-top-lg {
+	padding-top: 40upx;
+}
+
+.padding-top-xl {
+	padding-top: 50upx;
+}
+
+.padding-right-xs {
+	padding-right: 10upx;
+}
+
+.padding-right-sm {
+	padding-right: 20upx;
+}
+
+.padding-right {
+	padding-right: 30upx;
+}
+
+.padding-right-lg {
+	padding-right: 40upx;
+}
+
+.padding-right-xl {
+	padding-right: 50upx;
+}
+
+.padding-bottom-xs {
+	padding-bottom: 10upx;
+}
+
+.padding-bottom-sm {
+	padding-bottom: 20upx;
+}
+
+.padding-bottom {
+	padding-bottom: 30upx;
+}
+
+.padding-bottom-lg {
+	padding-bottom: 40upx;
+}
+
+.padding-bottom-xl {
+	padding-bottom: 50upx;
+}
+
+.padding-left-xs {
+	padding-left: 10upx;
+}
+
+.padding-left-sm {
+	padding-left: 20upx;
+}
+
+.padding-left {
+	padding-left: 30upx;
+}
+
+.padding-left-lg {
+	padding-left: 40upx;
+}
+
+.padding-left-xl {
+	padding-left: 50upx;
+}
+
+.padding-lr-xs {
+	padding-left: 10upx;
+	padding-right: 10upx;
+}
+
+.padding-lr-sm {
+	padding-left: 20upx;
+	padding-right: 20upx;
+}
+
+.padding-lr {
+	padding-left: 30upx;
+	padding-right: 30upx;
+}
+
+.padding-lr-lg {
+	padding-left: 40upx;
+	padding-right: 40upx;
+}
+
+.padding-lr-xl {
+	padding-left: 50upx;
+	padding-right: 50upx;
+}
+
+.padding-tb-xs {
+	padding-top: 10upx;
+	padding-bottom: 10upx;
+}
+
+.padding-tb-sm {
+	padding-top: 20upx;
+	padding-bottom: 20upx;
+}
+
+.padding-tb {
+	padding-top: 30upx;
+	padding-bottom: 30upx;
+}
+
+.padding-tb-lg {
+	padding-top: 40upx;
+	padding-bottom: 40upx;
+}
+
+.padding-tb-xl {
+	padding-top: 50upx;
+	padding-bottom: 50upx;
+}
+
+/* -- 浮动 --  */
+
+.cf::after,
+.cf::before {
+	content: " ";
+	display: table;
+}
+
+.cf::after {
+	clear: both;
+}
+
+.fl {
+	float: left;
+}
+
+.fr {
+	float: right;
+}
+
+/* ==================
+          背景
+ ==================== */
+
+.line-red::after,
+.lines-red::after {
+	border-color: #e54d42;
+}
+
+.line-orange::after,
+.lines-orange::after {
+	border-color: #f37b1d;
+}
+
+.line-yellow::after,
+.lines-yellow::after {
+	border-color: #fbbd08;
+}
+
+.line-olive::after,
+.lines-olive::after {
+	border-color: #8dc63f;
+}
+
+.line-green::after,
+.lines-green::after {
+	border-color: #39b54a;
+}
+
+.line-cyan::after,
+.lines-cyan::after {
+	border-color: #1cbbb4;
+}
+
+.line-blue::after,
+.lines-blue::after {
+	border-color: #0081ff;
+}
+
+.line-purple::after,
+.lines-purple::after {
+	border-color: #6739b6;
+}
+
+.line-mauve::after,
+.lines-mauve::after {
+	border-color: #9c26b0;
+}
+
+.line-pink::after,
+.lines-pink::after {
+	border-color: #e03997;
+}
+
+.line-brown::after,
+.lines-brown::after {
+	border-color: #a5673f;
+}
+
+.line-grey::after,
+.lines-grey::after {
+	border-color: #8799a3;
+}
+
+.line-gray::after,
+.lines-gray::after {
+	border-color: #aaaaaa;
+}
+
+.line-black::after,
+.lines-black::after {
+	border-color: #333333;
+}
+
+.line-white::after,
+.lines-white::after {
+	border-color: #ffffff;
+}
+
+.bg-red {
+	background-color: #e54d42;
+	color: #ffffff;
+}
+
+.bg-orange {
+	background-color: #f37b1d;
+	color: #ffffff;
+}
+
+.bg-yellow {
+	background-color: #fbbd08;
+	color: #333333;
+}
+
+.bg-olive {
+	background-color: #8dc63f;
+	color: #ffffff;
+}
+
+.bg-green {
+	background-color: #39b54a;
+	color: #ffffff;
+}
+
+.bg-cyan {
+	background-color: #1cbbb4;
+	color: #ffffff;
+}
+
+.bg-blue {
+	background-color: #0081ff;
+	color: #ffffff;
+}
+
+.bg-purple {
+	background-color: #6739b6;
+	color: #ffffff;
+}
+
+.bg-mauve {
+	background-color: #9c26b0;
+	color: #ffffff;
+}
+
+.bg-pink {
+	background-color: #e03997;
+	color: #ffffff;
+}
+
+.bg-brown {
+	background-color: #a5673f;
+	color: #ffffff;
+}
+
+.bg-grey {
+	background-color: #8799a3;
+	color: #ffffff;
+}
+
+.bg-gray {
+	background-color: #f0f0f0;
+	color: #333333;
+}
+
+.bg-black {
+	background-color: #333333;
+	color: #ffffff;
+}
+
+.bg-white {
+	background-color: #ffffff;
+	color: #666666;
+}
+
+.bg-shadeTop {
+	background-image: linear-gradient(rgba(0, 0, 0, 1), rgba(0, 0, 0, 0.01));
+	color: #ffffff;
+}
+
+.bg-shadeBottom {
+	background-image: linear-gradient(rgba(0, 0, 0, 0.01), rgba(0, 0, 0, 1));
+	color: #ffffff;
+}
+
+.bg-red.light {
+	color: #e54d42;
+	background-color: #fadbd9;
+}
+
+.bg-orange.light {
+	color: #f37b1d;
+	background-color: #fde6d2;
+}
+
+.bg-yellow.light {
+	color: #fbbd08;
+	background-color: #fef2ced2;
+}
+
+.bg-olive.light {
+	color: #8dc63f;
+	background-color: #e8f4d9;
+}
+
+.bg-green.light {
+	color: #39b54a;
+	background-color: #d7f0dbff;
+}
+
+.bg-cyan.light {
+	color: #1cbbb4;
+	background-color: #d2f1f0;
+}
+
+.bg-blue.light {
+	color: #0081ff;
+	background-color: #cce6ff;
+}
+
+.bg-purple.light {
+	color: #6739b6;
+	background-color: #e1d7f0;
+}
+
+.bg-mauve.light {
+	color: #9c26b0;
+	background-color: #ebd4ef;
+}
+
+.bg-pink.light {
+	color: #e03997;
+	background-color: #f9d7ea;
+}
+
+.bg-brown.light {
+	color: #a5673f;
+	background-color: #ede1d9;
+}
+
+.bg-grey.light {
+	color: #8799a3;
+	background-color: #e7ebed;
+}
+
+.bg-gradual-red {
+	background-image: linear-gradient(45deg, #f43f3b, #ec008c);
+	color: #ffffff;
+}
+
+.bg-gradual-orange {
+	background-image: linear-gradient(45deg, #ff9700, #ed1c24);
+	color: #ffffff;
+}
+
+.bg-gradual-green {
+	background-image: linear-gradient(45deg, #39b54a, #8dc63f);
+	color: #ffffff;
+}
+
+.bg-gradual-purple {
+	background-image: linear-gradient(45deg, #9000ff, #5e00ff);
+	color: #ffffff;
+}
+
+.bg-gradual-pink {
+	background-image: linear-gradient(45deg, #ec008c, #6739b6);
+	color: #ffffff;
+}
+
+.bg-gradual-blue {
+	background-image: linear-gradient(45deg, #0081ff, #1cbbb4);
+	color: #ffffff;
+}
+
+.shadow[class*="-red"] {
+	box-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.shadow[class*="-orange"] {
+	box-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.shadow[class*="-yellow"] {
+	box-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.shadow[class*="-olive"] {
+	box-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.shadow[class*="-green"] {
+	box-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.shadow[class*="-cyan"] {
+	box-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.shadow[class*="-blue"] {
+	box-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.shadow[class*="-purple"] {
+	box-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.shadow[class*="-mauve"] {
+	box-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.shadow[class*="-pink"] {
+	box-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.shadow[class*="-brown"] {
+	box-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.shadow[class*="-grey"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-gray"] {
+	box-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.shadow[class*="-black"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.shadow[class*="-white"] {
+	box-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.text-shadow[class*="-red"] {
+	text-shadow: 6upx 6upx 8upx rgba(204, 69, 59, 0.2);
+}
+
+.text-shadow[class*="-orange"] {
+	text-shadow: 6upx 6upx 8upx rgba(217, 109, 26, 0.2);
+}
+
+.text-shadow[class*="-yellow"] {
+	text-shadow: 6upx 6upx 8upx rgba(224, 170, 7, 0.2);
+}
+
+.text-shadow[class*="-olive"] {
+	text-shadow: 6upx 6upx 8upx rgba(124, 173, 55, 0.2);
+}
+
+.text-shadow[class*="-green"] {
+	text-shadow: 6upx 6upx 8upx rgba(48, 156, 63, 0.2);
+}
+
+.text-shadow[class*="-cyan"] {
+	text-shadow: 6upx 6upx 8upx rgba(28, 187, 180, 0.2);
+}
+
+.text-shadow[class*="-blue"] {
+	text-shadow: 6upx 6upx 8upx rgba(0, 102, 204, 0.2);
+}
+
+.text-shadow[class*="-purple"] {
+	text-shadow: 6upx 6upx 8upx rgba(88, 48, 156, 0.2);
+}
+
+.text-shadow[class*="-mauve"] {
+	text-shadow: 6upx 6upx 8upx rgba(133, 33, 150, 0.2);
+}
+
+.text-shadow[class*="-pink"] {
+	text-shadow: 6upx 6upx 8upx rgba(199, 50, 134, 0.2);
+}
+
+.text-shadow[class*="-brown"] {
+	text-shadow: 6upx 6upx 8upx rgba(140, 88, 53, 0.2);
+}
+
+.text-shadow[class*="-grey"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-gray"] {
+	text-shadow: 6upx 6upx 8upx rgba(114, 130, 138, 0.2);
+}
+
+.text-shadow[class*="-black"] {
+	text-shadow: 6upx 6upx 8upx rgba(26, 26, 26, 0.2);
+}
+
+.bg-img {
+	background-size: cover;
+	background-position: center;
+	background-repeat: no-repeat;
+}
+
+.bg-mask {
+	background-color: #333333;
+	position: relative;
+}
+
+.bg-mask::after {
+	content: "";
+	border-radius: inherit;
+	width: 100%;
+	height: 100%;
+	display: block;
+	background-color: rgba(0, 0, 0, 0.4);
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	top: 0;
+}
+
+.bg-mask view,
+.bg-mask cover-view {
+	z-index: 5;
+	position: relative;
+}
+
+.bg-video {
+	position: relative;
+}
+
+.bg-video video {
+	display: block;
+	height: 100%;
+	width: 100%;
+	-o-object-fit: cover;
+	object-fit: cover;
+	position: absolute;
+	top: 0;
+	z-index: 0;
+	pointer-events: none;
+}
+
+/* ==================
+          文本
+ ==================== */
+
+.text-xs {
+	font-size: 20upx;
+}
+
+.text-sm {
+	font-size: 24upx;
+}
+
+.text-df {
+	font-size: 28upx;
+}
+
+.text-lg {
+	font-size: 32upx;
+}
+
+.text-xl {
+	font-size: 36upx;
+}
+
+.text-xxl {
+	font-size: 44upx;
+}
+
+.text-sl {
+	font-size: 80upx;
+}
+
+.text-xsl {
+	font-size: 120upx;
+}
+
+.text-Abc {
+	text-transform: Capitalize;
+}
+
+.text-ABC {
+	text-transform: Uppercase;
+}
+
+.text-abc {
+	text-transform: Lowercase;
+}
+
+.text-price::before {
+	content: "¥";
+	font-size: 80%;
+	margin-right: 4upx;
+}
+
+.text-cut {
+	text-overflow: ellipsis;
+	white-space: nowrap;
+	overflow: hidden;
+}
+
+.text-bold {
+	font-weight: bold;
+}
+
+.text-center {
+	text-align: center;
+}
+
+.text-content {
+	line-height: 1.6;
+}
+
+.text-left {
+	text-align: left;
+}
+
+.text-right {
+	text-align: right;
+}
+
+.text-red,
+.line-red,
+.lines-red {
+	color: #e54d42;
+}
+
+.text-orange,
+.line-orange,
+.lines-orange {
+	color: #f37b1d;
+}
+
+.text-yellow,
+.line-yellow,
+.lines-yellow {
+	color: #fbbd08;
+}
+
+.text-olive,
+.line-olive,
+.lines-olive {
+	color: #8dc63f;
+}
+
+.text-green,
+.line-green,
+.lines-green {
+	color: #39b54a;
+}
+
+.text-cyan,
+.line-cyan,
+.lines-cyan {
+	color: #1cbbb4;
+}
+
+.text-blue,
+.line-blue,
+.lines-blue {
+	color: #0081ff;
+}
+
+.text-purple,
+.line-purple,
+.lines-purple {
+	color: #6739b6;
+}
+
+.text-mauve,
+.line-mauve,
+.lines-mauve {
+	color: #9c26b0;
+}
+
+.text-pink,
+.line-pink,
+.lines-pink {
+	color: #e03997;
+}
+
+.text-brown,
+.line-brown,
+.lines-brown {
+	color: #a5673f;
+}
+
+.text-grey,
+.line-grey,
+.lines-grey {
+	color: #8799a3;
+}
+
+.text-gray,
+.line-gray,
+.lines-gray {
+	color: #aaaaaa;
+}
+
+.text-black,
+.line-black,
+.lines-black {
+	color: #333333;
+}
+
+.text-white,
+.line-white,
+.lines-white {
+	color: #ffffff;
+}

BIN
static/logo.png


+ 76 - 0
uni.scss

@@ -0,0 +1,76 @@
+/**
+ * 这里是uni-app内置的常用样式变量
+ *
+ * uni-app 官方扩展插件及插件市场(https://ext.dcloud.net.cn)上很多三方插件均使用了这些样式变量
+ * 如果你是插件开发者,建议你使用scss预处理,并在插件代码中直接使用这些变量(无需 import 这个文件),方便用户通过搭积木的方式开发整体风格一致的App
+ *
+ */
+
+/**
+ * 如果你是App开发者(插件使用者),你可以通过修改这些变量来定制自己的插件主题,实现自定义主题功能
+ *
+ * 如果你的项目同样使用了scss预处理,你也可以直接在你的 scss 代码中使用如下变量,同时无需 import 这个文件
+ */
+
+/* 颜色变量 */
+
+/* 行为相关颜色 */
+$uni-color-primary: #007aff;
+$uni-color-success: #4cd964;
+$uni-color-warning: #f0ad4e;
+$uni-color-error: #dd524d;
+
+/* 文字基本颜色 */
+$uni-text-color:#333;//基本色
+$uni-text-color-inverse:#fff;//反色
+$uni-text-color-grey:#999;//辅助灰色,如加载更多的提示信息
+$uni-text-color-placeholder: #808080;
+$uni-text-color-disable:#c0c0c0;
+
+/* 背景颜色 */
+$uni-bg-color:#ffffff;
+$uni-bg-color-grey:#f8f8f8;
+$uni-bg-color-hover:#f1f1f1;//点击状态颜色
+$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
+
+/* 边框颜色 */
+$uni-border-color:#c8c7cc;
+
+/* 尺寸变量 */
+
+/* 文字尺寸 */
+$uni-font-size-sm:24upx;
+$uni-font-size-base:28upx;
+$uni-font-size-lg:32upx;
+
+/* 图片尺寸 */
+$uni-img-size-sm:40upx;
+$uni-img-size-base:52upx;
+$uni-img-size-lg:80upx;
+
+/* Border Radius */
+$uni-border-radius-sm: 4upx;
+$uni-border-radius-base: 6upx;
+$uni-border-radius-lg: 12upx;
+$uni-border-radius-circle: 50%;
+
+/* 水平间距 */
+$uni-spacing-row-sm: 10px;
+$uni-spacing-row-base: 20upx;
+$uni-spacing-row-lg: 30upx;
+
+/* 垂直间距 */
+$uni-spacing-col-sm: 8upx;
+$uni-spacing-col-base: 16upx;
+$uni-spacing-col-lg: 24upx;
+
+/* 透明度 */
+$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
+
+/* 文章场景相关 */
+$uni-color-title: #2C405A; // 文章标题颜色
+$uni-font-size-title:40upx;
+$uni-color-subtitle: #555555; // 二级标题颜色
+$uni-font-size-subtitle:36upx;
+$uni-color-paragraph: #3F536E; // 文章段落颜色
+$uni-font-size-paragraph:30upx;

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