1.整体技术方案的设计
- 末级页使用的是freeMark模板(语法参考中文文档
1.目录结构
├──vv-musiclive-v
│ └── templates
│ ├── article.html 文章末级页pc
│ ├── article_h5.html 文章末级页h5
│ ├── error
│ │ ├── 404_h5.htm h5报错页
│ │ └── 404.htm pc报错页
│ ├── hot
│ │ └── hot_category V篇推荐页
│ ├── include
│ │ ├── article 文章(pc)
│ │ │ ├──ad.htm 广告图模块
│ │ │ ├──admire.htm 赞赏模块
│ │ │ ├──bottomShare.htm 底部分享模块
│ │ │ ├──comment.htm 评论模块
│ │ │ ├──content.htm v篇内容
│ │ │ ├──detail_1.htm 文章详情一信息(阅读,点赞,评论,分享等)
│ │ │ ├──detail.htm 文章详情信息(阅读,点赞,评论,分享等)
│ │ │ ├──download.htm 下载弹框
│ │ │ ├──errorRight.htm 报错页右侧
│ │ │ ├──fixedShare.htm 分享模块(端内)
│ │ │ ├──likeList.htm 点赞列表
│ │ │ ├──musicBg.htm 背景音乐
│ │ │ ├──rightList.htm v篇右侧
│ │ │ ├──title.htm 文章标题
│ │ │ ├──user_img.htm 用户头像
│ │ │ ├──web_code 返回顶部和下载二维码
│ │ │ └──webShare.htm 分享模块(端外)
│ │ ├── article_h5 文章(h5)
│ │ │ ├──admire.htm 赞赏模块
│ │ │ ├──ads.htm 广告模块(微信、qq/其他浏览器)
│ │ │ ├──articleAll.htm 评论模块
│ │ │ ├──comment_like.htm 评论点赞动画
│ │ │ ├──comment_w.htm 评论模块(微信)
│ │ │ ├──comment.htm 评论模块 (端内、qq/其他浏览器)
│ │ │ ├──content.htm 文章内容(文本、图片、音频、视频、作品、文章)
│ │ │ ├──detail_1.htm 文章详情信息1(阅读,点赞,评论,分享等)
│ │ │ ├──detail.htm 文章详情信息(阅读,点赞,评论,分享等)
│ │ │ ├──down.htm 固定下载(微信、qq/其他浏览器)
│ │ │ ├──like.htm 点赞信息
│ │ │ ├──more_article.htm 推荐视频、推荐文章
│ │ │ ├──music_bg.htm 背景音乐
│ │ │ ├──qrcode.htm 二维码(生成长图功能使用)
│ │ │ ├──red_packet.htm 红包(端内)
│ │ │ ├──share.htm 分享(端内)
│ │ │ ├──user_img.htm 用户头像
│ │ │ ├──user_info.htm 用户信息
│ │ │ ├──verify.htm 手机号验证(微信)
│ │ │ └──title.htm 文章标题
│ │ ├── footer
│ │ │ └──footer.htm 端外页脚
│ │ ├── header
│ │ │ └──header.htm 端外头部
│ │ └── theme V篇模板
│ │ ├──m 移动端 1.includ引入需要的模模块(标题等) 2.style标签中修改样式 3.script标签中添加js
│ │ │ ├── default.htm 标准模板 templateCode值为 theme0
│ │ │ ├── theme1.htm 模板一 theme1和模板返回的值templateCode的值保持一致
│ │ │ ├── ···
│ │ │ └── theme26.htm 模板
│ │ ├──pc pc端(和移动一致)
│ │ └──style.htm 模板样式conf对象
│ ├── user_center
│ │ └──user_center.htm
│ ├── article.html 文章末级页pc
│ └── article_h5.html 文章末级页h5
2.模板、配色
(1)模板(现有20种不同的模板类型)
//article_html
<#if (template?? && (template.templateCode!'')=='theme0' )>
<#include "/include/theme/m/default.htm" />
<#elseif (template?? && (template.conf??) && ((template.templateCode!'')!='' ))>
<#include "/include/theme/m/${template.templateCode}.htm" />
<#else>
<#include "/include/theme/m/default.htm" />
</#if>
//模板文件theme2.htm
<div class="article_content">
<!-- 背景音乐 -->
<#include "/include/article_h5/music_bg.htm" />
<!-- 文章标题 -->
<#include "/include/article_h5/title.htm" />
<!-- 文章信息 -->
<#include "/include/article_h5/detail.htm" />
<!-- 文章内容 -->
<#include "/include/article_h5/content.htm" />
</div>
配色
conf: {
imgPath: {
pc: '', //PC端图片资源路径
m: '' //移动端图片资源路径
},
backGround: {
top: '', //内容区距页面顶部的高度 px(头图高度)
color: '', //背景平铺色
repeat: '', //背景中图平铺
inner: '', //内容区域背景色,如果颜色有透明效果,请使用rgba(233, 80, 58, 0.7)色值
},
audio: {
text: '', //音频播放器文字
border: '', //音频播放器边框色值
background: '', //音频播放器背景色
},
fontColor: {
title: '', //标题
anchor: '', //作者
time: '', //时间
preview: '', //阅读次数
link: '', //文章超链接色值
statement: '', //特别声明色值
colorA: '', //A对应色值,默认黑色&&编辑器第1色值
colorB: '', //B对应色值,编辑器第2色值
colorC: '', //C对应色值,编辑器第3色值
colorD: '', //D对应色值,编辑器第4色值
colorE: '', //E对应色值,编辑器第5色值
colorF: '', //F对应色值,编辑器第6色值
colorG: '', //G对应色值,编辑器第7色值
}
}
<style>
font[color="#000000"]{
color: ${template.conf.fontColor.colorA!'#000000'};
}
font[color="#808080"]{
color: ${template.conf.fontColor.colorB!'#808080'};
}
font[color="#ff0000"]{
color: ${template.conf.fontColor.colorC!'#ff0000'};
}
font[color="#ff8300"]{
color: ${template.conf.fontColor.colorD!'#ff8300'};
}
font[color="#00b937"]{
color: ${template.conf.fontColor.colorE!'#00b937'};
}
font[color="#007dff"]{
color: ${template.conf.fontColor.colorF!'#007dff'};
}
font[color="#bb69c0"]{
color: ${template.conf.fontColor.colorG!'#bb69c0'};
}
.article{
position: relative;
width: 100%;
background: url(${template.conf.imgPath.m!''}contentbg.jpg) repeat center 0 ${template.conf.backGround.color!'#ffffff'};
background-size: 100% auto;
}
.article-bg{
width: 100%;
background: url(${template.conf.imgPath.m!''}themebg.jpg) no-repeat center 0;
background-size: 100% auto;
}
.title_wrap .article_title{
color: ${template.conf.fontColor.title!'#222222'};
}
.article .detail_wrap .article_writer{
float: left;
color: ${template.conf.fontColor.anchor!'#222222'};
}
.article .detail_wrap .article_time{
float: left;
color: ${template.conf.fontColor.preview!'#9d9d9d'};
}
.article .detail_wrap .look_num{
float: left;
color: ${template.conf.fontColor.preview!'#9d9d9d'};
}
.article .text{
color: ${template.conf.fontColor.colorA!'#222222'};
}
.vp_wrap .audio_box{
background: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};
border: 1px solid ${template.conf.audio.border!'#ececec'}
}
.vp_wrap .audio_box .audio_name,
.vp_wrap .audio_box .audio_time,
.vp_wrap .audio_box .progress_box .current_time,
.vp_wrap .audio_box .progress_box .duration_time {
color: ${template.conf.audio.text!'#000000'};
}
.vp_wrap .audio_box .progress_box .progress .curr_bar{
background: ${template.conf.audio.text!'#000000'};
}
.vp_wrap .audio_box .audio_play_btn{
background-image: url(${template.conf.imgPath.m}audio_play.gif);
}
.vp_wrap .audio_box .audio_pause_btn {
background-image: url(${template.conf.imgPath.m}audio_play.png)
}
.bg_music_btn .bg_music_wrap1,
.bg_music_btn .bg_music_wrap2{
/* background-image: url(${template.conf.imgPath.m}bg_music.png); */
background-color: ${template.conf.audio.background!'#f6f6f6'};
}
.bg_music_btn .bg_music_wrap1 .bg_music_icon,
.bg_music_btn .bg_music_wrap2 .bg_music_icon{
/* background-color: ${template.conf.audio.text!'#222222'};; */
}
.bg_music_btn .bg_music_wrap1 .bg_music_name{
color: ${template.conf.audio.text!'#222222'};;
}
.article .music_box .audio_btn {
background-image: url(${template.conf.imgPath.m}audio_icon.png);
}
.article .img_box .media_info{
background-color: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};;
}
.vp_wrap .hyperlink {
background-image: url(${template.conf.imgPath.m}link_icon.png);
color: ${template.conf.fontColor.link!'#5072a1'};
}
.vp_wrap .copyrights{
color: ${template.conf.fontColor.statement!'#666666'};
}
/*长图文*/
.code_wrap{
border-top: 1px solid ${template.conf.fontColor.colorA!'#000000'};
}
.code_wrap .code_text{
color: ${template.conf.fontColor.colorA!'#000000'};
}
.article_more_btn{
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0,${template.conf.audio.background!'#f6f6f6'} 100%);
color: ${template.conf.audio.text!'#222222'};
}
.article_more_btn .arrow_icon{
border-right-color: ${template.conf.audio.text!'#222222'};
border-bottom-color: ${template.conf.audio.text!'#222222'};
}
.vp_wrap .refresh_icon:before{
border-color: ${template.conf.audio.text!'#222222'};
border-top-color: transparent;
}
.vp_wrap .refresh_icon:after{
border-left-color: ${template.conf.audio.text!'#222222'};
}
.vp_wrap .video_box .transcod_box{
background: ${template.conf.audio.background!'#f6f6f6'};
color: ${template.conf.audio.text!'#222222'};
}
</style>
3.js的引用(端内、微信、qq或其他浏览器)
<script type="text/javascript"
src="https://mscjs.51vv.com/wx/m/vv-base/js/??base.js,vvlib/pic-cdn-cs.js,source/md5.min.js,source/localstorage-cache.js"></script>
<#if (clientInOrOuter!'')=='inner'>
<script type="text/javascript" src="//mscjs.51vv.com/wx/m/vv-base/js/jsbridge_proxy.js"></script>
<script type="text/javascript" src="//mscjs.51vv.com/v/m/article/dist/js/article.js?v=88"></script>
<#else>
<script type="text/javascript"
src="//mscjs.51vv.com/wx/m/vv-base/js/??utils/backFlow.new.min.js,utils/report.js,source/swiper.5.1.0.min.js?v=2"></script>
<#if (appClient!'')=='weixin'>
<script type="text/javascript"
src="//mscjs.51vv.com/wx/m/vv-base/js/??source/jweixin-1.6.0.js,utils/wx.js"></script>
<script type="text/javascript"
src="//mscjs.51vv.com/v/m/article/dist/js/??share.js,article_wx.js?v=88"></script>
<#else>
<script type="text/javascript"
src="//mscjs.51vv.com/v/m/article/dist/js/article_w.js?v=88"></script>
</#if>
</#if>
4.参数控制
platfrom:client //客户端页面(pc、h5) //已经废弃
from:webview //预览页面(pc、h5)
editStatus:1 //编辑状态下的预览(pc)
qrcode: 1/2 //长图文(h5)
haswx: 0/1 //1已经安装微信 0 未安装(h5)
hasqq: 0/1 //1已经安装QQ 0 未安装(h5)
haswb: 0/1 //1已经安装微博 0 未安装(h5)
vp_ak: 参数加密 //阅读数量是否显示(只要vp_ak存在阅读次数就不显示)
iswebchat:1 //小程序末级页(platfrom:client)
h:1 //1 不显示赞赏信息
2.部分功能
1.懒加载(图片、评论、点赞、赞赏) - getBoundingClientRect API
。
//图片 1.首先给图片一个占位资源 2.判断图片是否出现在了当前视口
loadImg.each(function (index, item) {
if (-window.innerHeight / 3 < this.getBoundingClientRect().top && this.getBoundingClientRect().top < window.innerHeight * 2) {
var imgSrc = format.pictureCsFn($(this).attr('data-img'), 'cw750');
$(this).attr('src', format.waterMarkFn(imgSrc));
$(this).attr('height', 'auto');
$(this).attr('data-isLoaded', 1)
}
});
图片懒加载的三种方式
getBoundingClientRect
2.返回顶部和评论定位滚动效果
//评论定位
commentPosFn: function () {
loadImage.loadImg = [];
var bh = $(window).scrollTop();
var ch = $('#comment').offset().top;
var topT = 0;
if (parseInt(ch - bh) > window.innerHeight / 2) { //跳转到评论区
topT = ch;
this.scrollTop = $(window).scrollTop();
if ((ch - bh) > window.innerHeight) {
$(window).scrollTop(ch - window.innerHeight);
}
} else { //返回
topT = this.scrollTop || 0;
if ((topT - ch) < -window.innerHeight) {
$(window).scrollTop(topT + window.innerHeight);
}
}
setTimeout(function () {
$(window).scrollTo({ toT: topT })
}, 5)
},
3.web端发文章音视频共存
//编辑页-通知末级页关闭音视频
let iframeList = document.getElementsByTagName('iframe');
for(var i = 0; i<iframeList.length ;i++){
iframeList[i].contentWindow.postMessage({
from: 2, //web端编辑页
playSate: 1, //播放状态
},'https://music.51vv.com');
}
//末级页接收到
window.addEventListener('message',function(event){
var data = event.data;
if(data.playSate == 1) closeVoice(2);
});
3.问题总结
1.forEach报错(安卓4.)改用(for循环或each)
2.filter 导致低配ios滑动时卡顿(作品、音频)
IOS 手机的浏览器对这个属性的渲染十分吃力,进而导致渲染进程的 CPU 占用率过高,最终造成卡顿。
.opus_bg{
transform: translate3d(1px,1px,1px); //解决ios滑动进度条卡顿
filter: blur(40px);
}
3.audio的属性和方法
(1)ios微信中ajax异步回调中音视频play()无法播放
(2)IOS不能直接修改currentTime值
(3)canplay安卓重复执行、ios只执行一次
$('.opus_box').on('click',' .opus_cover',function(e){
var ele = $(this).parents('.opus_box');
if(!format.onLineFn()||!_this.pauseOpusFn(ele)) return;
var opusAudio = ele.find('.opus_audio');
if(isWeixin&&isIOS){ //解决IOS微信作品不播放--第一次播放,须是一个用户触发(click、touch)的行为
opusAudio[0].play();
opusAudio[0].pause();
}
var avid = ele.attr('data-avid');
_this.opusInfoFn(avid,2,function(res){
if(ele.find('.opus_audio').attr('src') != res.spaceav.fileURL){
var currentTime = opusAudio[0].currentTime;
ele.find('.opus_audio').attr('src', window.base.toUrl(res.spaceav.fileURL));
ele.find('.opus_audio').attr('data-src', window.base.toUrl(res.spaceav.fileURL));
if(isIOS){ //ios不能直接修改currentTime
opusAudio.on('canplay',function(){ //安卓会一直触发该事件
opusAudio[0].currentTime = currentTime;
});
}else{
opusAudio[0].currentTime = currentTime;
}
}
_this.opusPlayFn(ele);
}.bind(this),function(res){
format.toastFn('原作品已被删除或设为私密')
});
});
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。