Ver Fonte

阅读器

hjr há 4 meses atrás
pai
commit
23639ce073

+ 248 - 0
components/lz-red-book/lz-red-book.vue

@@ -0,0 +1,248 @@
+<template>
+	<view class="lzRedBook" :style="[{height:set.screenHeight+'px'},bookStyle]" @click.stop="clickCenter">
+		<!-- <view class="center">{{ bookText }}</view> -->
+		<swiper class="swiper-box" @change="change" @animationfinish="animationfinish" :current="0" :vertical="scrollDirection=='leftRight'?false:true" :skip-hidden-item-layout="true" :style="{height:set.screenHeight+'px'}">
+			<swiper-item v-for="(item ,index) in swiper.bookTextArr" :key="index">
+				<view class="swiper-item">
+					<view class="swiper-text">
+						{{item}}
+					</view>
+					<!-- 底部电池部分 -->
+					<view class="item-footer" :style="bookStyle">
+						<view class="f-left">
+							<text class="iconfont icon-dianchi"><text class="icon-dianchi-center" :style="{ width: system.quantity + '%' }"></text></text>
+							<text class="time">{{ system.time }}</text>
+						</view>
+						<view class="f-center"></view>
+						<view class="f-right">
+							{{swiper.pageNum}}/{{swiper.bookTextArr.length}}
+						</view>
+					</view>
+				</view>
+			</swiper-item>
+		</swiper>
+		<!-- 这里是动态计算一页多少字的 -->
+		<view class="opcity" >{{bookTextNew}}</view>
+	</view>
+	
+</template>
+
+<script>
+let DLTime, timeInter;
+let copyBookText='',forNum=100,addNum=400,reduceNum=400//默认一页从100个字开始计算,超出就减少,少了就增加
+export default {
+	props: {
+		bookText: {
+			type: String,
+			default: ''
+		},
+		bookStyle: {
+			//书的样式
+			type: Object,
+			default: function() {
+				return {};
+			}
+		},
+		scrollDirection: {
+			//滚动方向leftRight左右,上下topBottom
+			type: String,
+			default: 'leftRight'
+		},
+	},
+	data() {
+		return {
+			set:{
+				screenHeight: '', //屏幕宽度
+				screenWidth:'',//屏幕宽度
+				boxHight:0,
+			},
+			bookTextNew:'',
+			swiper:{
+				bookTextArr:[],//书的文本格式化(以每页多少字为数组的一项
+				pageNum:1,
+				vertical:false,//滑动方向是否为纵向
+				mode: 'round',
+				isEnd:false,//是否滑到最后一个了触发请求下一个数据
+				isStart:false,//是否滑到最开始的地方
+			},
+			isEndFor:false,//是否循环结束
+			system: {
+				quantity: 0, //系统电量
+				time: '' //系统时间
+			},
+		};
+	},
+	mounted() {
+		//初始化
+		this.init()
+		// #ifdef APP-PLUS
+			//每分钟获取一次电量
+			this.dianliang();
+			DLTime = setInterval(() => {
+				this.dianliang();
+			}, 60000);
+			//每秒获取一次时间
+			timeInter = setInterval(() => {
+				this.getTimes();
+		}, 1000);
+		// #endif
+	},
+	methods: {
+		//初始化
+		init(){
+			let that=this
+			that.isEndFor=false
+			copyBookText=this.bookText
+			that.swiper.bookTextArr=[]
+			// 获取元素信息
+			that.getSystemInfo();
+		},
+		//获取系统信息
+		getSystemInfo() {
+			let that = this;
+			uni.getSystemInfo({
+				success: function(res) {
+					that.set.screenHeight = res.screenHeight;
+					that.set.screenWidth = res.screenWidth;
+					//动态计算每一页文字数
+					if(copyBookText.length>100){
+						forNum=100
+						that.forGet()//默认100个字起步
+					}else{
+						that.isEndFor=true
+						that.swiper.bookTextArr.push(copyBookText)
+					}
+				}
+			});
+		},
+		//循环获取一页多少文字,默认从100个字,然后动态获取文字内容高度与屏幕高度对比,如果文字高度小于屏幕高度,就加40个字
+		forGet(){
+			let that=this
+			that.bookTextNew=copyBookText.substr(0,forNum)
+			let String=copyBookText.substr(forNum)
+			if(String.length>0){//如果一章大于100个字
+				that.$nextTick(function(){
+					var opcity = uni.createSelectorQuery().select('.opcity');
+					opcity.boundingClientRect(data => {
+						if(data.height<that.set.screenHeight-60 && that.isEndFor==false){
+							forNum+=50
+							that.forGet()
+						}else{
+							that.swiper.bookTextArr.push(that.bookTextNew)
+							//拿到除去上一页的文字
+							copyBookText=copyBookText.substr(forNum)
+							//动态计算每一页文字数
+							that.getNextPage()
+						}
+					}).exec();
+				})
+			}else{
+				console.log(copyBookText);
+				that.isEndFor=true
+				that.swiper.bookTextArr.push(copyBookText)
+			}
+		},
+		//动态计算每一页文字数
+		getNextPage(){
+			let that=this
+			// debugger
+			if(copyBookText.length>100){
+				forNum=100
+				that.forGet()//默认100个字起步
+			}else{
+				that.isEndFor=true
+				that.swiper.bookTextArr.push(copyBookText)
+			}
+			console.log(that.swiper.bookTextArr);
+		},
+		//滑动时触发
+		change(e) {
+			console.log(e);
+			this.swiper.pageNum = e.detail.current+1;
+			this.swiper.isEnd=false
+			this.swiper.isStart=false
+		},
+		animationfinish(){
+			if(this.swiper.isEnd){
+				console.log('已经划到最后一个了');
+				this.$emit('scrollEnd');
+			}
+			if(this.swiper.isStart){
+				console.log('已经划到最开始');
+				this.$emit('scrollStart');
+			}
+			if(this.swiper.pageNum==this.swiper.bookTextArr.length){
+				this.swiper.isEnd=true//已经划到最后
+			}else{
+				this.swiper.isEnd=false
+			}
+			if(this.swiper.pageNum==1){
+				this.swiper.isStart=true//已经划到最开始
+			}else{
+				this.swiper.isStart=false
+			}
+		},
+		//获取系统电量
+		dianliang() {
+			var that = this;
+			if (uni.getSystemInfoSync().platform != 'ios') {
+				var main = plus.android.runtimeMainActivity();
+				var Intent = plus.android.importClass('android.content.Intent');
+				var recevier = plus.android.implements('io.dcloud.feature.internal.reflect.BroadcastReceiver', {
+					onReceive: function(context, intent) {
+						var action = intent.getAction();
+						if (action == Intent.ACTION_BATTERY_CHANGED) {
+							var level = intent.getIntExtra('level', 0); //电量
+							var voltage = intent.getIntExtra('voltage', 0); //电池电压
+							var temperature = intent.getIntExtra('temperature', 0); //电池温度
+							that.system.quantity = level; //电量
+						}
+					}
+				});
+				var IntentFilter = plus.android.importClass('android.content.IntentFilter');
+				var filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
+				main.registerReceiver(recevier, filter);
+			} else {
+				var UIDevice = plus.ios.import('UIDevice');
+				var dev = UIDevice.currentDevice();
+				if (!dev.isBatteryMonitoringEnabled()) {
+					dev.setBatteryMonitoringEnabled(true);
+				}
+				var level = dev.batteryLevel();
+				that.system.quantity = level * 100;
+			}
+		},
+		getTimes() {
+			var times = new Date();
+			this.system.time =
+				(times.getHours() < 10 ? '0' + times.getHours() : times.getHours()) + ':' + (times.getMinutes() < 10 ? '0' + times.getMinutes() : times.getMinutes());
+		},
+		//点击中间位置
+		clickCenter() {
+			this.swiper.isStart=false
+			this.$emit('clickCenter');
+		}
+		
+		
+	}
+};
+</script>
+
+<style scoped lang="scss">
+.lzRedBook {
+	font-size: 18px;overflow: hidden;
+	.opcity{
+		background: red;overflow: hidden;padding: 30px;box-sizing: border-box;opacity: 0;
+	}
+	.swiper-text{
+		padding:20px;box-sizing: border-box;
+	}
+	.swiper-box{
+		width: 100%;
+	}
+	.item-footer {
+		position: absolute;bottom: 0;width: 100%;height: 20px;display: flex;justify-content: space-between;align-items: center;padding:0 20px;font-size: 10px!important;
+		
+	}
+}
+</style>

+ 132 - 0
components/uni-icons/icons.js

@@ -0,0 +1,132 @@
+export default {
+	"pulldown": "\ue588",
+	"refreshempty": "\ue461",
+	"back": "\ue471",
+	"forward": "\ue470",
+	"more": "\ue507",
+	"more-filled": "\ue537",
+	"scan": "\ue612",
+	"qq": "\ue264",
+	"weibo": "\ue260",
+	"weixin": "\ue261",
+	"pengyouquan": "\ue262",
+	"loop": "\ue565",
+	"refresh": "\ue407",
+	"refresh-filled": "\ue437",
+	"arrowthindown": "\ue585",
+	"arrowthinleft": "\ue586",
+	"arrowthinright": "\ue587",
+	"arrowthinup": "\ue584",
+	"undo-filled": "\ue7d6",
+	"undo": "\ue406",
+	"redo": "\ue405",
+	"redo-filled": "\ue7d9",
+	"bars": "\ue563",
+	"chatboxes": "\ue203",
+	"camera": "\ue301",
+	"chatboxes-filled": "\ue233",
+	"camera-filled": "\ue7ef",
+	"cart-filled": "\ue7f4",
+	"cart": "\ue7f5",
+	"checkbox-filled": "\ue442",
+	"checkbox": "\ue7fa",
+	"arrowleft": "\ue582",
+	"arrowdown": "\ue581",
+	"arrowright": "\ue583",
+	"smallcircle-filled": "\ue801",
+	"arrowup": "\ue580",
+	"circle": "\ue411",
+	"eye-filled": "\ue568",
+	"eye-slash-filled": "\ue822",
+	"eye-slash": "\ue823",
+	"eye": "\ue824",
+	"flag-filled": "\ue825",
+	"flag": "\ue508",
+	"gear-filled": "\ue532",
+	"reload": "\ue462",
+	"gear": "\ue502",
+	"hand-thumbsdown-filled": "\ue83b",
+	"hand-thumbsdown": "\ue83c",
+	"hand-thumbsup-filled": "\ue83d",
+	"heart-filled": "\ue83e",
+	"hand-thumbsup": "\ue83f",
+	"heart": "\ue840",
+	"home": "\ue500",
+	"info": "\ue504",
+	"home-filled": "\ue530",
+	"info-filled": "\ue534",
+	"circle-filled": "\ue441",
+	"chat-filled": "\ue847",
+	"chat": "\ue263",
+	"mail-open-filled": "\ue84d",
+	"email-filled": "\ue231",
+	"mail-open": "\ue84e",
+	"email": "\ue201",
+	"checkmarkempty": "\ue472",
+	"list": "\ue562",
+	"locked-filled": "\ue856",
+	"locked": "\ue506",
+	"map-filled": "\ue85c",
+	"map-pin": "\ue85e",
+	"map-pin-ellipse": "\ue864",
+	"map": "\ue364",
+	"minus-filled": "\ue440",
+	"mic-filled": "\ue332",
+	"minus": "\ue410",
+	"micoff": "\ue360",
+	"mic": "\ue302",
+	"clear": "\ue434",
+	"smallcircle": "\ue868",
+	"close": "\ue404",
+	"closeempty": "\ue460",
+	"paperclip": "\ue567",
+	"paperplane": "\ue503",
+	"paperplane-filled": "\ue86e",
+	"person-filled": "\ue131",
+	"contact-filled": "\ue130",
+	"person": "\ue101",
+	"contact": "\ue100",
+	"images-filled": "\ue87a",
+	"phone": "\ue200",
+	"images": "\ue87b",
+	"image": "\ue363",
+	"image-filled": "\ue877",
+	"location-filled": "\ue333",
+	"location": "\ue303",
+	"plus-filled": "\ue439",
+	"plus": "\ue409",
+	"plusempty": "\ue468",
+	"help-filled": "\ue535",
+	"help": "\ue505",
+	"navigate-filled": "\ue884",
+	"navigate": "\ue501",
+	"mic-slash-filled": "\ue892",
+	"search": "\ue466",
+	"settings": "\ue560",
+	"sound": "\ue590",
+	"sound-filled": "\ue8a1",
+	"spinner-cycle": "\ue465",
+	"download-filled": "\ue8a4",
+	"personadd-filled": "\ue132",
+	"videocam-filled": "\ue8af",
+	"personadd": "\ue102",
+	"upload": "\ue402",
+	"upload-filled": "\ue8b1",
+	"starhalf": "\ue463",
+	"star-filled": "\ue438",
+	"star": "\ue408",
+	"trash": "\ue401",
+	"phone-filled": "\ue230",
+	"compose": "\ue400",
+	"videocam": "\ue300",
+	"trash-filled": "\ue8dc",
+	"download": "\ue403",
+	"chatbubble-filled": "\ue232",
+	"chatbubble": "\ue202",
+	"cloud-download": "\ue8e4",
+	"cloud-upload-filled": "\ue8e5",
+	"cloud-upload": "\ue8e6",
+	"cloud-download-filled": "\ue8e9",
+	"headphones":"\ue8bf",
+	"shop":"\ue609"
+}

Diff do ficheiro suprimidas por serem muito extensas
+ 10 - 0
components/uni-icons/uni-icons.vue


+ 198 - 0
components/uni-swiper-dot/uni-swiper-dot.vue

@@ -0,0 +1,198 @@
+<template>
+	<view class="uni-swiper__warp">
+		<slot />
+		<view v-if="mode === 'default'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='default'>
+			<view v-for="(item,index) in info" :style="{
+        'width': (index === current? dots.width*2:dots.width ) + 'px','height':dots.width/3 +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border-radius':'0px'}" :key="index" class="uni-swiper__dots-item uni-swiper__dots-bar" />
+		</view>
+		<view v-if="mode === 'dot'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='dot'>
+			<view v-for="(item,index) in info" :style="{
+        'width': dots.width + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}" :key="index" class="uni-swiper__dots-item" />
+		</view>
+		<view v-if="mode === 'round'" :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box" key='round'>
+			<view v-for="(item,index) in info" :class="[index === current&&'uni-swiper__dots-long']" :style="{
+		    'width':(index === current? dots.width*3:dots.width ) + 'px','height':dots.height +'px' ,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}" :key="index" class="uni-swiper__dots-item " />
+		</view>
+		<view v-if="mode === 'nav'" key='nav' :style="{'background-color':dotsStyles.backgroundColor,'bottom':'0'}" class="uni-swiper__dots-box uni-swiper__dots-nav">
+			<text :style="{'color':dotsStyles.color}" class="uni-swiper__dots-nav-item">{{ (current+1)+"/"+info.length +' ' +info[current][field] }}</text>
+		</view>
+		<view v-if="mode === 'indexes'" key='indexes' :style="{'bottom':dots.bottom + 'px'}" class="uni-swiper__dots-box">
+			<view v-for="(item,index) in info" :style="{
+        'width':dots.width + 'px','height':dots.height +'px' ,'color':index === current?dots.selectedColor:dots.color,'background-color':index !== current?dots.backgroundColor:dots.selectedBackgroundColor,'border':index !==current ? dots.border:dots.selectedBorder}" :key="index" class="uni-swiper__dots-item uni-swiper__dots-indexes"><text class="uni-swiper__dots-indexes-text">{{ index+1 }}</text></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * SwiperDod 轮播图指示点
+	 * @description 自定义轮播图指示点
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=284
+	 * @property {Number} current 当前指示点索引,必须是通过 `swiper` 的 `change` 事件获取到的 `e.detail.current`
+	 * @property {String} mode = [default|round|nav|indexes] 指示点的类型
+	 * 	@value defualt 默认指示点
+	 * 	@value round 圆形指示点
+	 * 	@value nav 条形指示点
+	 * 	@value indexes 索引指示点
+	 * @property {String} field mode 为 nav 时,显示的内容字段(mode = nav 时必填)
+	 * @property {String} info 轮播图的数据,通过数组长度决定指示点个数
+	 * @property {Object} dotsStyles 指示点样式
+	 * @event {Function} clickItem 组件触发点击事件时触发,e={currentIndex}
+	 */
+
+	export default {
+		name: 'UniSwiperDot',
+		props: {
+			info: {
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			current: {
+				type: Number,
+				default: 0
+			},
+			dotsStyles: {
+				type: Object,
+				default () {
+					return {}
+				}
+			},
+			// 类型 :default(默认) indexes long nav
+			mode: {
+				type: String,
+				default: 'default'
+			},
+			// 只在 nav 模式下生效,变量名称
+			field: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				dots: {
+					width: 8,
+					height: 8,
+					bottom: 10,
+					color: '#fff',
+					backgroundColor: 'rgba(0, 0, 0, .3)',
+					border: '1px rgba(0, 0, 0, .3) solid',
+					selectedBackgroundColor: '#333',
+					selectedBorder: '1px rgba(0, 0, 0, .9) solid'
+				}
+			}
+		},
+		watch: {
+			dotsStyles(newVal) {
+				this.dots = Object.assign(this.dots, this.dotsStyles)
+			},
+			mode(newVal) {
+				if (newVal === 'indexes') {
+					this.dots.width = 20
+					this.dots.height = 20
+				} else {
+					this.dots.width = 8
+					this.dots.height = 8
+				}
+			}
+
+		},
+		created() {
+			if (this.mode === 'indexes') {
+				this.dots.width = 20
+				this.dots.height = 20
+			}
+			this.dots = Object.assign(this.dots, this.dotsStyles)
+		}
+	}
+</script>
+
+<style scoped>
+	.uni-swiper__warp {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: column;
+		position: relative;
+		overflow: hidden;
+	}
+
+	.uni-swiper__dots-box {
+		position: absolute;
+		bottom: 10px;
+		left: 0;
+		right: 0;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-swiper__dots-item {
+		width: 8px;
+		border-radius: 100px;
+		margin-left: 6px;
+		background-color: rgba(0, 0, 0, 0.4);
+		/* transition: width 0.2s linear;  不要取消注释,不然会不能变色
+ */
+	}
+
+	.uni-swiper__dots-item:first-child {
+		margin: 0;
+	}
+
+	.uni-swiper__dots-default {
+		border-radius: 100px;
+	}
+
+	.uni-swiper__dots-long {
+		border-radius: 50px;
+	}
+
+	.uni-swiper__dots-bar {
+		border-radius: 50px;
+	}
+
+	.uni-swiper__dots-nav {
+		bottom: 0px;
+		height: 40px;
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		flex: 1;
+		flex-direction: row;
+		justify-content: flex-start;
+		align-items: center;
+		background-color: rgba(0, 0, 0, 0.2);
+	}
+
+	.uni-swiper__dots-nav-item {
+		/* overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap; */
+		font-size: 28rpx;
+		color: #fff;
+		margin: 0 15px;
+	}
+
+	.uni-swiper__dots-indexes {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		/* flex: 1;
+ */
+		justify-content: center;
+		align-items: center;
+	}
+
+	.uni-swiper__dots-indexes-text {
+		color: #fff;
+		font-size: 24rpx;
+	}
+</style>

+ 226 - 0
components/uni-tag/uni-tag.vue

@@ -0,0 +1,226 @@
+<template>
+	<view :class="[
+      'uni-tag--' + type,
+      disabled === true || disabled === 'true' ? 'uni-tag--disabled' : '',
+      inverted === true || inverted === 'true' ? type + '-uni-tag--inverted' : '',
+      circle === true || circle === 'true' ? 'uni-tag--circle' : '',
+      mark === true || mark === 'true' ? 'uni-tag--mark' : '',
+      'uni-tag--' + size
+    ]" @click="onClick()" class="uni-tag" v-if="text">
+		<text :class="[type === 'default' ? 'uni-tag--default':'uni-tag-text',inverted === true || inverted === 'true' ? 'uni-tag-text--'+type : '',size === 'small' ? 'uni-tag-text--small':'' ]">{{ text }}</text>
+	</view>
+</template>
+
+<script>
+	/**
+	 * Tag 标签
+	 * @description 用于展示1个或多个文字标签,可点击切换选中、不选中的状态
+	 * @tutorial https://ext.dcloud.net.cn/plugin?id=35
+	 * @property {String} text 标签内容
+	 * @property {String} size = [normal|small] 大小尺寸
+	 * 	@value normal 正常
+	 * 	@value small 小尺寸
+	 * @property {String} type = [default|primary|success|warning|error|royal]  颜色类型
+	 * 	@value default 灰色
+	 * 	@value primary 蓝色
+	 * 	@value success 绿色
+	 * 	@value warning 黄色
+	 * 	@value error 红色
+	 * 	@value royal 紫色
+	 * @property {Boolean} disabled = [true|false] 是否为禁用状态
+	 * @property {Boolean} inverted = [true|false] 是否无需背景颜色(空心标签)
+	 * @property {Boolean} circle = [true|false] 是否为圆角
+	 * @event {Function} click 点击 Tag 触发事件
+	 */
+
+	export default {
+		name: "UniTag",
+		props: {
+			type: {
+				// 标签类型default、primary、success、warning、error、royal
+				type: String,
+				default: "default"
+			},
+			size: {
+				// 标签大小 normal, small
+				type: String,
+				default: "normal"
+			},
+			// 标签内容
+			text: {
+				type: String,
+				default: ""
+			},
+			disabled: {
+				// 是否为禁用状态
+				type: [Boolean, String],
+				defalut: false
+			},
+			inverted: {
+				// 是否为空心
+				type: [Boolean, String],
+				defalut: false
+			},
+			circle: {
+				// 是否为圆角样式
+				type: [Boolean, String],
+				defalut: false
+			},
+			mark: {
+				// 是否为标记样式
+				type: [Boolean, String],
+				defalut: false
+			}
+		},
+		methods: {
+			onClick() {
+				if (this.disabled === true || this.disabled === "true") {
+					return;
+				}
+				this.$emit("click");
+			}
+		}
+	};
+</script>
+
+<style scoped>
+	.uni-tag {
+		/* #ifndef APP-NVUE */
+		display: flex;
+		/* #endif */
+		padding: 0px 16px;
+		height: 30px;
+		line-height: 30px;
+		justify-content: center;
+		color: #333;
+		border-radius: 6rpx;
+		background-color: #f8f8f8;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #f8f8f8;
+	}
+
+	.uni-tag--circle {
+		border-radius: 15px;
+	}
+
+	.uni-tag--mark {
+		border-top-left-radius: 0;
+		border-bottom-left-radius: 0;
+		border-top-right-radius: 15px;
+		border-bottom-right-radius: 15px;
+	}
+
+	.uni-tag--disabled {
+		opacity: 0.5;
+	}
+
+	.uni-tag--small {
+		height: 20px;
+		padding: 0px 8px;
+		line-height: 20px;
+		font-size: 24rpx;
+	}
+
+	.uni-tag--default {
+		color: #333;
+		font-size: 28rpx;
+	}
+
+	.uni-tag-text--small {
+		font-size: 24rpx !important;
+	}
+
+	.uni-tag-text {
+		color: #fff;
+		font-size: 28rpx;
+	}
+
+	.uni-tag-text--primary {
+		color: #007aff !important;
+	}
+
+	.uni-tag-text--success {
+		color: #4cd964 !important;
+	}
+
+	.uni-tag-text--warning {
+		color: #f0ad4e !important;
+	}
+
+	.uni-tag-text--error {
+		color: #dd524d !important;
+	}
+
+	.uni-tag--primary {
+		color: #fff;
+		background-color: #007aff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #007aff;
+	}
+
+	.primary-uni-tag--inverted {
+		color: #007aff;
+		background-color: #ffffff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #007aff;
+	}
+
+	.uni-tag--success {
+		color: #fff;
+		background-color: #4cd964;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #4cd964;
+	}
+
+	.success-uni-tag--inverted {
+		color: #4cd964;
+		background-color: #ffffff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #4cd964;
+	}
+
+	.uni-tag--warning {
+		color: #fff;
+		background-color: #f0ad4e;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #f0ad4e;
+	}
+
+	.warning-uni-tag--inverted {
+		color: #f0ad4e;
+		background-color: #ffffff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #f0ad4e;
+	}
+
+	.uni-tag--error {
+		color: #fff;
+		background-color: #dd524d;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #dd524d;
+	}
+
+	.error-uni-tag--inverted {
+		color: #dd524d;
+		background-color: #ffffff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #dd524d;
+	}
+
+	.uni-tag--inverted {
+		color: #333;
+		background-color: #ffffff;
+		border-width: 1rpx;
+		border-style: solid;
+		border-color: #f8f8f8;
+	}
+</style>

+ 7 - 1
pages.json

@@ -94,7 +94,13 @@
 				"navigationBarTitleText": "字体大小",
 				"navigationStyle": "custom"
 			}
-		}
+		},{
+			"path": "pages/redBook/index",
+			"style": {
+				"navigationBarTitleText": "阅读",
+				"navigationStyle": "custom"
+			}
+		},
 	],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",

+ 237 - 0
pages/redBook/index.vue

@@ -0,0 +1,237 @@
+<template>
+	<view class="redBook" :style="{ height: set.screenHeight,background:set.background, }">
+		<lz-red-book ref="lzRedBook" :bookText="content_text" :scrollDirection="set.scrollDirection" :bookStyle="{ background:set.background,'font-size':set.fontSize+'px','line-height':set.lineHeight+'px','color':set.fontColor}"
+		@clickCenter="clickCenter"
+		@scrollEnd="scrollEnd"
+		@scrollStart="scrollStart"
+		></lz-red-book>
+		
+		<!-- 遮罩层上部分 -->
+		<view class="mask-top" :style="{top:mask.showMask?0:-100+'upx','background':mask.background}">
+			<view style="letter-spacing: 10px; line-height: 20px;">usahfufasijdiajij</view>
+		</view>
+		<!-- 遮罩层下部分 -->
+		<view class="mask-bottom" :style="{bottom:mask.showMask?0:-300+'upx','background':mask.background}">
+			<view class="v1">
+				<view class="slider-warp">
+					字体:
+					<slider class="slider" block-size="20" activeColor="#FFCC33" :step="2" backgroundColor="#000000" block-color="#8A6DE9" :value="set.fontSize" @change="sliderChange($event,'fontSize')" min="18" max="30"/>
+				</view>
+				<view class="slider-warp">
+					间距:
+					<slider class="slider" block-size="20" activeColor="#FFCC33" :step="2" backgroundColor="#000000" block-color="#8A6DE9" :value="set.lineHeight" @change="sliderChange($event,'padding')" min="26" max="40"/>
+				</view>
+			</view>
+			<view class="v1">
+				滚动方向:
+				<uni-tag text="左右" :inverted="set.scrollDirection=='topBottom' ? true : false" type="primary" @click="changeScrollDirection('leftRight')" size="small"/>
+				<uni-tag text="上下" :inverted="set.scrollDirection=='leftRight' ? true : false" type="primary" @click="changeScrollDirection('topBottom')" size="small" style="color: #333333; margin-left: 10px;"/>
+			</view>
+			<view class="v2">
+				<view v-for="(item,index) in arr" :key="index" :class="mask.backgroundIndex==index?'color-warp':''" class="v1-color" @click="changeBackground(index)">
+					<uni-icons type="smallcircle-filled" size="26" :color="item.color" ></uni-icons>
+				</view>
+			</view>
+			<view class="v3">
+				<view class="v3-item">
+					<uni-icons type="settings" size="20" ></uni-icons>目录
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+export default {
+	data() {
+		return {
+			mask:{//遮罩层
+				showMask:false,
+				background:'#fff',
+				backgroundIndex:0,
+			},
+			set: {
+				background:'#f0f0f0',//页面背景颜色
+				fontSize:18,//字体大小
+				lineHeight:33,//字体间距
+				fontColor:'#000',//字体颜色
+				scrollDirection:'leftRight',//滚动方向leftRight左右,上下topBottom
+			},
+			arr:[
+				{
+					background:'#f0f0f0',//背景色
+					maskBg:'#fff',//遮罩层色
+					fontColor:'#524d51',//字体颜色
+					color:'#f5f5f5',//选择圆圈颜色
+				},
+				{
+					background:'#d8c9aa',//背景色
+					maskBg:'#f3e4c3',//遮罩层色
+					fontColor:'#3c2506',//字体颜色
+					color:'#e0d1aa',//选择圆圈颜色
+				},
+				{
+					background:'#daba94',//背景色
+					maskBg:'#f8dcb4',//遮罩层色
+					fontColor:'#3c2506',//字体颜色
+					color:'#d8b784',//选择圆圈颜色
+				},
+				{
+					background:'#cfb793',//背景色
+					maskBg:'#f8dcb4',//遮罩层色
+					fontColor:'#674923',//字体颜色
+					color:'#d6b781',//选择圆圈颜色
+				},
+				{
+					background:'#aac9aa',//背景色
+					maskBg:'#cdeccd',//遮罩层色
+					fontColor:'#2c1e1e',//字体颜色
+					color:'#abcaab',//选择圆圈颜色
+				},
+				{
+					background:'#333b3d',//背景色
+					maskBg:'#313439',//遮罩层色
+					fontColor:'#7e8894',//字体颜色
+					color:'#626a75',//选择圆圈颜色
+				}
+			],
+			//正文
+			content_text:
+				`第一章&nbsp;&nbsp;陨落的天才<br>&nbsp;&nbsp;&nbsp;&nbsp;“斗之力,三段!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;
+				望着测验魔石碑上面闪亮得甚至有些刺眼的五个大字,少年面无表情,唇角有着一抹自嘲,紧握的手掌,因为大力,而导致略微尖锐的指甲深深的刺进了掌心之中,
+				带来一阵阵钻心的疼痛…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“萧炎,斗之力,三段!级别:低级!”测验魔石碑之旁,一位中年男子,看了一眼碑上所显示出来的信息,
+				语气漠然的将之公布了出来…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;中年男子话刚刚脱口,便是不出意外的在人头汹涌的广场上带起了一阵嘲讽的骚动。<br><br>&nbsp;
+				&nbsp;&nbsp;&nbsp;“三段?嘿嘿,果然不出我所料,这个“天才”这一年又是在原地踏步!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“哎,这废物真是把家族的脸都给丢光了。
+				”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“要不是族长是他的父亲,这种废物,早就被驱赶出家族,任其自生自灭了,哪还有机会待在家族中白吃白喝。”<br><br>&nbsp;
+				&nbsp;&nbsp;&nbsp;“唉,昔年那名闻乌坦城的天才少年,如今怎么落魄成这般模样了啊?”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“谁知道呢,或许做了什么亏心事,
+				惹得神灵降怒了吧…”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;周围传来的不屑嘲笑以及惋惜轻叹,落在那如木桩待在原地的少年耳中,恍如一根根利刺狠狠的扎在心脏一般,
+				让得少年呼吸微微急促。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;少年缓缓抬起头来,露出一张有些清秀的稚嫩脸庞,漆黑的眸子木然的在周围那些嘲讽的同龄人身上扫过,
+				少年嘴角的自嘲,似乎变得更加苦涩了。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“这些人,都如此刻薄势力吗?或许是因为三年前他们曾经在自己面前露出过最谦卑的笑容
+				,所以,如今想要讨还回去吧…”苦涩的一笑,萧炎落寞的转身,安静的回到了队伍的最后一排,孤单的身影,与周围的世界,有些格格不入。<br><br>&nbsp;&nbsp;&nbsp;
+				&nbsp;“下一个,萧媚!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;听着测验人的喊声,一名少女快的人群中跑出,少女刚刚出场,附近的议论声便是小了许多,一双双略微火
+				热的目光,牢牢的锁定着少女的脸颊…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;少女年龄不过十四左右,虽然并算不上绝色,不过那张稚气未脱的小脸,却是蕴含着淡淡的妩媚
+				,清纯与妩媚,矛盾的集合,让得她成功的成为了全场瞩目的焦点…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;少女快步上前,小手轻车熟路的触摸着漆黑的魔石碑,然后缓缓闭
+				上眼睛…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;在少女闭眼片刻之后,漆黑的魔石碑之上再次亮起了光芒…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“斗之气:七段!”<br>
+				<br>&nbsp;&nbsp;&nbsp;&nbsp;“萧媚,斗之气:七段!级别:高级!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“耶!”听着测验员所喊出的成绩,少女脸颊扬起了得意的笑容
+				…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“啧啧,七段斗之气,真了不起,按这进度,恐怕顶多只需要三年时间,她就能称为一名真正的斗者了吧…”<br><br>&nbsp;&nbsp;&n
+				bsp;&nbsp;“不愧是家族中种子级别的人物啊…”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;听着人群中传来的一阵阵羡慕声,少女脸颊上的笑容更是多了几分,虚荣心,这是很多
+				女孩都无法抗拒的诱惑…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;与平日里的几个姐妹互相笑谈着,萧媚的视线,忽然的透过周围的人群,停在了人群外的那一道孤单身影上…<br>
+				<br>&nbsp;&nbsp;&nbsp;&nbsp;皱眉思虑了瞬间,萧媚还是打消了过去的念头,现在的两人,已经不在同一个阶层之上,以萧炎最近几年的表现,成年后,顶多只能作为家族中
+				的下层人员,而天赋优秀的她,则将会成为家族重点培养的强者,前途可以说是不可限量。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“唉…”莫名的轻叹了一口气,萧媚脑中忽然浮现
+				出三年前那意气风的少年,四岁练气,十岁拥有九段斗之气,十一岁突破十段斗之气,成功凝聚斗之气旋,一跃成为家族百年之内最年轻的斗者!<br><br>&nbsp;&nbsp;&nbsp;&n
+				bsp;当初的少年,自信而且潜力无可估量,不知让得多少少女对其春心荡漾,当然,这也包括以前的萧媚。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;然而天才的道路,貌似总是曲折的
+				,三年之前,这名声望达到巅峰的天才少年,却是突兀的接受到了有生以来最残酷的打击,不仅辛辛苦苦修炼十数载方才凝聚的斗之气旋,一夜之间,化为乌有,而且体内的斗之气
+				,也是随着时间的流逝,变得诡异的越来越少。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;斗之气消失的直接结果,便是导致其实力不断的后退。<br><br>&nbsp;&nbsp;&nbsp;&nb
+				sp;从天才的神坛,一夜跌落到了连普通人都不如的地步,这种打击,让得少年从此失魂落魄,天才之名,也是逐渐的被不屑与嘲讽所替代。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;
+				站的越高,摔得越狠,这次的跌落,或许就再也没有爬起的机会。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“下一个,萧薰儿!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;喧闹的人群中
+				,测试员的声音,再次响了起来。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;随着这有些清雅的名字响起,人群忽然的安静了下来,所有的视线,豁然转移。<br><br>&nbsp;&nbsp;&nbsp
+				;&nbsp;在众人视线汇聚之处,一位身着紫色衣裙的少女,正淡雅的站立,平静的稚嫩俏脸,并未因为众人的注目而改变分毫。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;少女清冷淡然的气质
+				,犹如清莲初绽,小小年纪,却已初具脱俗气质,难以想象,日后若是长大,少女将会如何的倾国倾城…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;这名紫裙少女,论起美貌与气质来,比
+				先前的萧媚,无疑还要更胜上几分,也难怪在场的众人都是这般动作。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;莲步微移,名为萧薰儿的少女行到魔石碑之前,小手伸出,镶着黑
+				金丝的紫袖滑落而下,露出一截雪白娇嫩的皓腕,然后轻触着石碑…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;微微沉静,石碑之上,刺眼的光芒再次绽放。<br><br>&nbsp;&nbsp
+				;&nbsp;&nbsp;“斗之气:九段!级别:高级!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;望着石碑之上的字体,场中陷入了一阵寂静。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“…
+				竟然到九段了,真是恐怖!家族中年轻一辈的第一人,恐怕非薰儿小姐莫属了。”寂静过后,周围的少年,都是不由自主的咽了一口唾沫,眼神充满敬畏…<br><br>&nbsp;&nbsp
+				;&nbsp;&nbsp;斗之气,每位斗者的必经之路,初阶斗之气分一至十段,当体内斗之气到达十段之时,便能凝聚斗之气旋,成为一名受人尊重的斗者!<br><br>&nbsp;&nbsp;
+				&nbsp;&nbsp;人群中,萧媚皱着浅眉盯着石碑前的紫裙少女,脸颊上闪过一抹嫉妒…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;望着石碑上的信息,一旁的中年测验员漠然的脸庞上
+				竟然也是罕见的露出了一丝笑意,对着少女略微恭声道:“薰儿小姐,半年之后,你应该便能凝聚斗气之旋,如果你成功的话,那么以十四岁年龄成为一名真正的斗者,你是萧家百
+				年内的第二人!”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;是的,第二人,那位第一人,便是褪去了天才光环的萧炎。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“谢谢。”少女微微点
+				了点头,平淡的小脸并未因为他的夸奖而出现喜悦,安静的回转过身,然后在众人炽热的注目中,缓缓的行到了人群最后面的那颓废少年面前…<br><br>&nbsp;&nbsp;&nbsp;&
+				nbsp;“萧炎哥哥。”在经过少年身旁时,少女顿下了脚步,对着萧炎恭敬的弯了弯腰,美丽的俏脸上,居然露出了让周围少女为之嫉妒的清雅笑容。<br><br>&nbsp;&nbsp;&nbs
+				p;&nbsp;“我现在还有资格让你怎么叫么?”望着面前这颗已经成长为家族中最璀璨的明珠,萧炎苦涩的道,她是在自己落魄后,极为少数还对自己依旧保持着尊敬的人。<br><br>
+				&nbsp;&nbsp;&nbsp;&nbsp;“萧炎哥哥,以前你曾经与薰儿说过,要能放下,才能拿起,提放自如,是自在人!”萧薰儿微笑着柔声道,略微稚嫩的嗓音,却是暖人心肺。<br>
+				<br>&nbsp;&nbsp;&nbsp;&nbsp;“呵呵,自在人?我也只会说而已,你看我现在的模样,象自在人吗?而且…这世界,本来就不属于我。”萧炎自嘲的一笑,意兴阑珊的道。<br
+				><br>&nbsp;&nbsp;&nbsp;&nbsp;面对着萧炎的颓废,萧薰儿纤细的眉毛微微皱了皱,认真的道:“萧炎哥哥,虽然并不知道你究竟是怎么回事,不过,薰儿相信,你会重新站起
+				来,取回属于你的荣耀与尊严…”话到此处,微顿了顿,少女白皙的俏脸,头一次露出淡淡的绯红:“当年的萧炎哥哥,的确很吸引人…”<br><br>&nbsp;&nbsp;&nbsp;&nbsp;“
+				呵呵…”面对着少女毫不掩饰的坦率话语,少年尴尬的笑了一声,可却未再说什么,人不风流枉少年,可现在的他,实在没这资格与心情,落寞的回转过身,对着广场之外缓缓行去
+				…<br><br>&nbsp;&nbsp;&nbsp;&nbsp;站在原地望着少年那恍如与世隔绝的孤独背影,萧薰儿踌躇了一会,然后在身后一干嫉妒的狼嚎声中,快步追了上去,与少年并肩而行…`
+		};
+	},
+	onLoad(option) {
+		// #ifdef APP-PLUS
+		plus.navigator.setFullscreen(true);//隐藏状态栏
+		//#endif
+	},
+	methods: {
+		
+		//点击中间
+		clickCenter(){
+			let that=this
+			that.mask.showMask=!that.mask.showMask
+		},
+		//滚动到最后一页
+		scrollEnd(){
+			uni.showToast({
+				title: '最后一页了'
+			});
+		},
+		//滚动到第一页
+		scrollStart(){
+			uni.showToast({
+				title: '第一页'
+			});
+		},
+		//滑块设置字体间距或大小
+		sliderChange(e,type) {
+			let that=this
+			that.$refs.lzRedBook.init()
+			if(type=='fontSize'){
+				console.log('value 发生变化:' + e.detail.value)
+				that.set.fontSize=e.detail.value
+			}else{
+				that.set.lineHeight=e.detail.value
+			}
+			//重新计算页面页数
+			uni.$emit('lz-red-book-change')
+		},
+		//修改滚动方向
+		changeScrollDirection(text){
+			let that=this
+			that.set.scrollDirection=text
+			//重新计算页面页数
+			uni.$emit('lz-red-book-change','changeScrollDirection')
+		},
+		//修改背景颜色
+		changeBackground(index){
+			let that=this
+			that.mask.backgroundIndex=index
+			that.set.background=that.arr[index].background//背景颜色
+			that.set.fontColor=that.arr[index].fontColor//字体颜色
+			that.mask.background=that.arr[index].maskBg//遮罩背景色
+			
+		},
+		
+	}
+};
+</script>
+
+<style scoped lang="scss">
+.redBook {
+	width: 100%;height: 100%;
+	.mask-top{
+		position: fixed;height: 40upx;transition: all 0.2s;width: 100%;z-index: 1000;margin: auto;border-radius:0 0 4px 4px ;
+	}
+	.mask-bottom{
+		position: fixed;height: 300upx;transition: all 0.2s;width: 100%;z-index: 1000;margin: auto;border-radius: 10px 10px 0 0;
+		padding: 10px;box-sizing: border-box;
+		.v1{
+			width: 100%;display: flex;align-items: center;
+			.slider-warp{
+				display: flex;flex: 1;align-items: center;
+				.slider{flex: 1;}
+			}
+		}
+		.v2{
+			display: flex;width: 100%;justify-content: space-around;margin-top: 10px;
+			.color-warp{
+				border: 1px solid #6d583b;border-radius: 50%;width: 26px;height: 26px;display: flex;justify-content: center;align-items: center;
+			}
+		}
+		.v3{
+			margin-top: 10px;
+			.v3-item{
+				width: 100px;height: 30px;background: #f7f7f7;display: flex;justify-content: center;align-items: center;
+			}
+		}
+	}
+}
+</style>

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff