瀏覽代碼

切换wind

db 3 年之前
父節點
當前提交
8c9a361771
共有 46 個文件被更改,包括 4562 次插入777 次删除
  1. 0 4
      .hbuilderx/launch.json
  2. 10 1
      App.vue
  3. 90 17
      activityPages/activityDetail/activityDetail.vue
  4. 20 20
      activityPages/activityDetail/jurisdiction/components.vue
  5. 1 1
      activityPages/activitySearch/activitySearch.vue
  6. 76 0
      components/statement.vue
  7. 24 0
      config/api.js
  8. 2 2
      config/config.js
  9. 2 1
      manifest.json
  10. 30 2
      pages.json
  11. 1 1
      pages/activity/activity.vue
  12. 1 1
      pages/applyResult/applyResult.vue
  13. 2 2
      pages/index/index.vue
  14. 1 1
      pages/my/my.vue
  15. 80 79
      pages/reportDetail/reportDetail.vue
  16. 2 2
      pages/reportForm/components/coverGuide.vue
  17. 671 577
      pages/reportForm/reportForm.vue
  18. 10 3
      reportPages/IndustryReport/IndustryReport.vue
  19. 二進制
      reportPages/image/play_icon.png
  20. 二進制
      reportPages/image/suspend_icon.png
  21. 46 0
      reportPages/index.scss
  22. 2 63
      reportPages/industrialReport/industrialReport.vue
  23. 51 0
      reportPages/jurisdiction.scss
  24. 119 0
      reportPages/reportSecretDetail/components/reportChoiceness.vue
  25. 134 0
      reportPages/reportSecretDetail/components/researchSummary.vue
  26. 285 0
      reportPages/reportSecretDetail/reportSecretDetail.vue
  27. 273 0
      reportPages/roadEssence/roadEssence.vue
  28. 148 0
      reportPages/secretDetails/secretDetails.vue
  29. 二進制
      static/img/act_search.png
  30. 二進制
      static/img/advice_ico.png
  31. 二進制
      static/img/auth_bg.png
  32. 二進制
      static/img/card_default.png
  33. 二進制
      static/img/guide-2.png
  34. 二進制
      static/img/guide-3.png
  35. 二進制
      static/img/home_share.png
  36. 二進制
      static/img/noauth.png
  37. 二進制
      static/img/success_ico.png
  38. 160 0
      uni_modules/mp-html/README.md
  39. 62 0
      uni_modules/mp-html/changelog.md
  40. 432 0
      uni_modules/mp-html/components/mp-html/mp-html.vue
  41. 524 0
      uni_modules/mp-html/components/mp-html/node/node.vue
  42. 1223 0
      uni_modules/mp-html/components/mp-html/parser.js
  43. 79 0
      uni_modules/mp-html/package.json
  44. 0 0
      uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
  45. 0 0
      uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
  46. 1 0
      uni_modules/mp-html/static/app-plus/mp-html/local.html

+ 0 - 4
.hbuilderx/launch.json

@@ -6,10 +6,6 @@
      	{
      		"launchtype" : "local"
      	},
-     	"h5" : 
-     	{
-     		"launchtype" : "local"
-     	},
      	"mp-weixin" : 
      	{
      		"launchtype" : "local"

+ 10 - 1
App.vue

@@ -17,7 +17,8 @@
 			isBind:null,// 是否需要绑定手机号/邮箱
 			userInfo:null,//用户信息
 			access_token:'',
-			loadOver:''
+			loadOver:'',
+            bgAudioManager:uni.getBackgroundAudioManager()
 		},
 		methods:{
 			/* 微信code换临时token */
@@ -243,4 +244,12 @@
         	line-height: 48rpx;
         
         }
+        .forbid-copy {
+            -webkit-user-select: none;
+                -khtml-user-select: none;
+                -moz-user-select: none;
+                -ms-user-select: none;
+                user-select: none;
+        }
+       
 </style>

+ 90 - 17
activityPages/activityDetail/activityDetail.vue

@@ -75,7 +75,28 @@
 						    <text class="default copy-link" @click="copyLink" >复制链接</text>
 						</view>
 					</view>
-				</view>
+				</view>
+                <view class="network" v-if="detailData.LinkParticipants">
+                	<view class="network-left">链接参会:</view>
+                	<view class="network-right network-zoom" style="color: #2C83FF;">
+                		<view>
+                		    <text class="default text_zoom">{{detailData.LinkParticipants}}</text>
+                            <view>
+                                点击<text class="default copy-link copy-zoom" @click="copyLink" >复制链接</text>在手机浏览器打开,并输入会议密码
+                            </view>
+                		</view>
+                	</view>
+                </view>
+                <view v-if="detailData.AppAttendance" class="network">
+                	<view class="network-left">App参会: </view>
+                	<view class="network-right">
+                	 <rich-text :nodes="detailData.AppAttendance"></rich-text>
+                	</view>
+                </view>
+                <view v-if="detailData.ConferencePassword" class="network">
+                	<view class="network-left">拨入密码:</view>
+                	<view class="network-right">{{detailData.ActivityTypeName=='公司调研电话会'&&detailData.IsLimitPeople==1 && detailData.IsSignup==0?'请报名获取':detailData.ConferencePassword}}</view>
+                </view>
 				<view v-if="detailData.Address" class="network">
 					<view class="network-left">活动地址:</view>
 					<view class="network-right" v-if="detailData.IsSignup==0 && detailData.ActivityTypeName=='公司线下调研'&&detailData.IsLimitPeople==1">请报名获取
@@ -339,15 +360,29 @@
                 const date = new Date(str)
                 const times = date.getTime()
                 const num = new Date().getTime()
-                if (times - num <= 3600000) {
-                	uni.showModal({
-                		confirmText: '知道了',
-                		showCancel: false,
-                		confirmColor: '#3385FF',
-                		content:'活动开始前1小时内无法提交问题'
-                	})
-                	return
+                if(this.detailData.IsResearch){
+                    if (times - num <= 900000) {
+                    	uni.showModal({
+                    		confirmText: '知道了',
+                    		showCancel: false,
+                    		confirmColor: '#3385FF',
+                    		content:'活动开始前15分钟内无法提交问题'
+                    	})
+                    	return
+                    }
+                }else{
+                    if (times - num <= 3600000) {
+                    	uni.showModal({
+                    		confirmText: '知道了',
+                    		showCancel: false,
+                    		confirmColor: '#3385FF',
+                    		content:'活动开始前1小时内无法提交问题'
+                    	})
+                    	return
+                    }
                 }
+               
+               
 				uni.navigateTo({
 					url: '/activityPages/generationAsk/generationAsk?id='+this.id
 				})
@@ -416,7 +451,7 @@
 			},
             copyLink(){
                 uni.setClipboardData({
-                    data: this.detailData.OnlineParticipation,
+                    data: this.detailData.LinkParticipants|| this.detailData.OnlineParticipation,
                     success: function () {
                       uni.showToast({
                           title: '复制成功,可在浏览器打开',
@@ -428,12 +463,27 @@
             }
 		},
 		onLoad(option) {
-			this.id = option.id || ''
+            this.id = option.id || ''
+          	 
+			
 		},
 		onShow() {
 			this.$store.dispatch("checkHandle").then(res=>{
-				this.countryCcode()//判断是否加区号
-				this.getActivityDetail()
+                app.globalData.isAuth = res.IsAuth;
+                app.globalData.isBind = res.IsBind;
+                if((!res.IsAuth) && (!res.IsBind)) { //已授权已绑定            
+                	this.countryCcode()//判断是否加区号
+                	this.getActivityDetail()
+                }else if(res.IsAuth) { //未授权
+                	uni.navigateTo({
+                		url:'/pages/authGuide/authGuide'
+                	})
+                }else if(res.IsBind && !res.IsAuth){ //已授权未绑定
+                	uni.navigateTo({
+                		url:'/pages/login/login'
+                	})
+                }
+				
 			})
 			
 		},
@@ -545,6 +595,28 @@
 				width: 480rpx;
                
 			}
+            .network-zoom {
+               .text_zoom {
+                   width: 100%;
+                   word-break:break-all ;
+                   color: #333333;
+               }
+                view {
+                    padding: 0 !important;
+                    margin: 0 !important;
+                    }
+                    .copy-zoom {
+                       
+                        display: inline-block;
+                        padding: 5rpx 17rpx !important;
+                        border-radius: 34rpx;
+                        background-color:#EBF4FF;
+                        font-size: 24rpx;
+                        color: #2C83FF ;
+                        margin: 0 10rpx;
+                          margin-top: 30rpx;
+                    }
+            }
             .network-link {
                 width: 520rpx !important;
                 view {
@@ -557,10 +629,11 @@
                           width: 350rpx;
                         }
                     .copy-link {
-                        padding: 4rpx 10rpx !important;
-                        border-radius: 5rpx;
-                        background-color:#3385FF;
-                        color: #fff;
+                        padding: 5rpx 17rpx !important;
+                        border-radius: 34rpx;
+                        background-color:#EBF4FF;
+                        font-size: 24rpx;
+                        color: #2C83FF ;
                     }
                 }
             }

+ 20 - 20
activityPages/activityDetail/jurisdiction/components.vue

@@ -1,6 +1,6 @@
 <template>
 	<view class="noauth-cont" v-if="haveAuth===2||haveAuth===3||haveAuth===4">
-		<image src="@/static/img/noauth.png" class="noauth-ico"></image>
+		<image src="https://hzstatic.hzinsights.com/cygx/czbk/noauth.png" class="noauth-ico"></image>
 		<block v-if="haveAuth==3">
 			<view class="tip">{{industryMsg}}</view>
 			<view class="btn-cont" @click="applyAuth">
@@ -16,11 +16,11 @@
 		<view class="tip" v-if="haveAuth===2">
 			<text style="margin-bottom: 20rpx;">
 				{{industryMsg}}
-			</text>
-			<text>
-				若想参加可以联系对口销售
 			</text>
-			<text @click="callPhone(sellerMobile)">{{sellerName}}:<text style="color:#D4BF86; display: inline-block;">{{sellerMobile}}</text></text>
+			<text>
+				若想参加可以联系对口销售
+			</text>
+			<text @click="callPhone(sellerMobile)">{{sellerName}}:<text style="color:#D4BF86; display: inline-block;">{{sellerMobile}}</text></text>
 			<text>开通{{msgType=='Type'?'对应行业':'该行业'}}的试用权限</text>
 		</view>
 		<view class="btn-cont back-btn" @click="backIndex"> 返回</view>
@@ -44,14 +44,14 @@
 			sellerMobile: {
 				type: String,
 				required: true
-			},
-			sellerName: {
-				type: String,
-				required: true
-			},
-			msgType: {
-				type: String,
-				required: true
+			},
+			sellerName: {
+				type: String,
+				required: true
+			},
+			msgType: {
+				type: String,
+				required: true
 			}
 		},
 		methods: {
@@ -72,12 +72,12 @@
 			},
 			// 返回首頁
 			backIndex() {
-				uni.navigateBack({
-					fail(){
-						uni.switchTab({
-							url:'/pages/index/index'
-						})
-					}
+				uni.navigateBack({
+					fail(){
+						uni.switchTab({
+							url:'/pages/index/index'
+						})
+					}
 				})
 			},
 			callPhone(num) {
@@ -146,4 +146,4 @@
 			}
 		}
 	}
-</style>
+</style>

+ 1 - 1
activityPages/activitySearch/activitySearch.vue

@@ -215,7 +215,7 @@
 		</view>
 		<!-- 缺审部分 -->
 		<view class="nodata" v-else>
-			<image src="@/static/img/act_search.png" mode="" class="nodata_ico"></image>
+			<image src="https://hzstatic.hzinsights.com/cygx/czbk/act_search.png" mode="" class="nodata_ico"></image>
 			<text>未找到搜索结果</text>
 		</view>
 		<!-- 各种自定义弹框 -->

+ 76 - 0
components/statement.vue

@@ -0,0 +1,76 @@
+<template>
+    <view class="mask-content">
+        <u-mask :show="show" @click="onClickHide">
+            <view class="warp">
+               <view class="content">
+                   <view class="title">
+                        免责声明
+                    </view>
+                    <text>1、本报告仅供弘则弥道(上海)投资咨询有限公司正式签约的机构客户使用,不会仅因接收人/接受机构收到本报告而将其视为客户。</text>
+                   <text>2、本报告根据国际和行业通行的准则,以合法渠道获得这些信息,尽可能保证可靠、准确和完整,但并不保证报告所述信息的准确性和完整性,也不保证本报告所包含的信息或建议在本报告发出后不会发生任何变更。本报告中所提供的信息仅供参考。</text>
+                   <text>3、报告中的内容不对投资者做出的最终操作建议做任何的担保,也没有任何形式的分享投资收益或者分担投资损失的书面或口头承诺。不作为客户在投资、法律、会计或税务等方面的最终操作建议,也不作为道义的、责任的和法律的依据或者凭证,无论是否已经明示或者暗示。</text>         
+                   <text>4、在任何情况下,本公司不对客户/接受人/接受机构因使用报告中内容所引致的一切损失负责任,客户/接受人/接受机构需自行承担全部风险。</text>
+               </view>
+                <view class="button" @click="onClickHide">
+                    知道了
+                </view>
+            </view>
+        </u-mask>
+    </view>
+</template>
+
+<script>
+    export default {
+        props: {
+            show: {
+                type: Boolean,
+                default: false
+            }
+        },
+        data() {
+            return {
+
+            }
+        },
+        methods: {
+            onClickHide() {
+                this.$parent.isShowStatement=false
+            },
+        }
+    }
+</script>
+
+<style scoped lang="scss">
+    .mask-content {
+        position: relative;
+    }
+    .warp {
+        position: absolute;
+        top: 50%;
+        left: 50%;
+        transform: translate(-50%,-50%);
+        width: 80%;
+        background-color: #fff;
+        .content {
+            padding: 30rpx 30rpx 20rpx;
+        }
+        .title {
+            color: #333;
+            text-align: center;
+            font-size: 32rpx;
+            margin-bottom: 10rpx;
+        }
+        text {
+            margin-bottom: 8rpx;
+             font-size: 24rpx;
+             color: #666;
+        }
+        .button {
+            height: 80rpx;
+            line-height: 80rpx;
+            border-top: 1rpx solid #eaeaea;
+            color: #2680eb;
+            text-align: center;
+        }
+    }
+</style>

+ 24 - 0
config/api.js

@@ -210,6 +210,30 @@ export const Reports = {
     reportListNew: params => {
     	return getHttp('/report/industry/reportListNew',params)
     },
+    /* 获取是否展示绝密内参接口*/
+    reportIsShow: params => {
+    	return getHttp('/report/isShow',params)
+    },
+    /* 获取报告精选、本周研究汇总、上周纪要汇总列表接口*/
+    reportListByType: params => {
+    	return getHttp('/report/reportList/byType',params)
+    },
+    /* 获取报告精选详情接口*/
+    reportSelectionDetail: params => {
+    	return getHttp('/report/reportSelection/detail',params)
+    },
+    /* 获取本周研究汇总详情接口*/
+    researchSummaryDetail: params => {
+    	return getHttp('/report/researchSummary/detail',params)
+    },
+    /* 获取上周研究汇总详情接口*/
+    minutesSummaryDetail: params => {
+    	return getHttp('/report/minutesSummary/detail',params)
+    },
+    /* 获取报告详情接口 /  路演精华*/
+    roadshowEssence: params => {
+    	return getHttp('/report/roadshowEssence/detail',params)
+    },
 }
 export const activity ={
 	/* 获取活动列表接口*/

+ 2 - 2
config/config.js

@@ -1,6 +1,6 @@
 
-//export const baseUrl = 'http://8.136.199.33:8500/api';//小程序开发接口地址
-export const baseUrl = 'https://cygx.hzinsights.com/api';//小程序线上接口地址
+export const baseUrl = 'http://8.136.199.33:8500/api';//小程序开发接口地址
+//export const baseUrl = 'https://cygx.hzinsights.com/api';//小程序线上接口地址
 // #ifdef H5
 export const H5baseUrl=process.env.NODE_ENV === 'development'?window.location.origin+'/':baseUrl
 // #endif

+ 2 - 1
manifest.json

@@ -71,7 +71,8 @@
         "permission" : {},
         "uniStatistics" : {
             "enable" : false
-        }
+        },
+        "requiredBackgroundModes": ["audio"]
     },
     "mp-alipay" : {
         "usingComponents" : true,

+ 30 - 2
pages.json

@@ -182,7 +182,34 @@
 				}
 			
 			}
-		]
+		    ,{
+                    "path" : "secretDetails/secretDetails",
+                    "style" :                                                                                    
+                {
+                    "navigationBarTitleText": "",
+                    "enablePullDownRefresh": false
+                }
+                
+                }
+                ,{
+                    "path" : "reportSecretDetail/reportSecretDetail",
+                    "style" :                                                                                    
+                {
+                    "navigationBarTitleText": "",
+                    "enablePullDownRefresh": false
+                }
+                
+                }
+                ,{
+                    "path" : "roadEssence/roadEssence",
+                    "style" :                                                                                    
+                {
+                    "navigationBarTitleText": "路演精华",
+                    "enablePullDownRefresh": false
+                }
+                
+                }
+            ]
 	}],
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
@@ -195,7 +222,8 @@
 			"van-dropdown-item": "/wxcomponents/vant/dist/dropdown-item/index",
 			"van-notice-bar": "/wxcomponents/vant/dist/notice-bar/index",
 			"van-tab": "/wxcomponents/vant/dist/tab/index",
-			"van-tabs": "/wxcomponents/vant/dist/tabs/index"
+			"van-tabs": "/wxcomponents/vant/dist/tabs/index",
+            "van-transition": "/wxcomponents/vant/dist/transition/index"
 		}
 	},
 	"tabBar": {

+ 1 - 1
pages/activity/activity.vue

@@ -225,7 +225,7 @@
 		</view>
 		<!-- 缺审显示 -->
 		<view class="nodata" :class="tabsActive == 0?'':'nodataTwo'" v-else>
-			<image src="@/static/img/act_search.png" mode="" class="nodata_ico"></image>
+			<image src="https://hzstatic.hzinsights.com/cygx/czbk/act_search.png" mode="" class="nodata_ico"></image>
 			<text>{{tabsActive==1?'暂无日程':"暂无活动"}}</text>
 		</view>
 		<!-- 所有自定义弹框 -->

+ 1 - 1
pages/applyResult/applyResult.vue

@@ -1,7 +1,7 @@
 <template>
 	<view class="applyResult-container container">
 		<view class="middle-cont">
-			<image src="@/static/img/success_ico.png" class="success_ico"></image>
+			<image src="https://hzstatic.hzinsights.com/cygx/czbk/success_ico.png" class="success_ico"></image>
 			<text>申请已提交</text>
 			<text>请等待销售人员与您联系</text>
 			<!-- <view class="contract-cont">

+ 2 - 2
pages/index/index.vue

@@ -80,7 +80,7 @@
 			<image src="@/static/img/nodata.png" mode="" class="nodata_ico"></image>
 			<text>暂时没有行业数据</text>
 		</view>
-		<image class="advice_ico" src="@/static/img/advice_ico.png" @click="adviceHandle"></image>
+		<image class="advice_ico" src="https://hzstatic.hzinsights.com/cygx/czbk/advice_ico.png" @click="adviceHandle"></image>
 	</view>
 </template>
 
@@ -293,7 +293,7 @@ export default {
 		return {
 			title: '您手边的弘则研究素材检索库',
 			path:  '/pages/index/index?tabid='+this.tabAct_id,
-			imageUrl: this.tabAct_id==0 ?'/static/img/home_share.png' : '' ,
+			imageUrl: this.tabAct_id==0 ?'https://hzstatic.hzinsights.com/cygx/czbk/home_share.png' : '' ,
 			success: (res)=> {
 			},
 			fail: (err)=> {

+ 1 - 1
pages/my/my.vue

@@ -20,7 +20,7 @@
 			</view>
 		</view>
 		<view class="auth-cont">
-			<image src="@/static/img/auth_bg.png" class="auth_bg"></image>
+			<image src="https://hzstatic.hzinsights.com/cygx/czbk/auth_bg.png" class="auth_bg"></image>
 			<view class="auth-info">
 				<template v-if="isLogin">
 					<text class="info-label">我的权限:</text>

+ 80 - 79
pages/reportDetail/reportDetail.vue

@@ -1,14 +1,14 @@
-<template>
+<template>
 	<view class="container reportDetail-container">
 		<block v-if="haveAuth===1">
-			<!-- 链接地址 -->
+			<!-- 链接地址 -->
 			<web-view :src="linkurl+'?id='+ id +'&fromType=mpwechat&token='+access_token"></web-view>
 		</block>
 		<view class="noauth-cont" v-else-if="haveAuth===2||haveAuth===3||haveAuth===4||haveAuth===5">
-			<image src="@/static/img/noauth.png" class="noauth-ico"></image>
+			<image src="https://hzstatic.hzinsights.com/cygx/czbk/noauth.png" class="noauth-ico"></image>
 			<block v-if="haveAuth!==3">
 				<view class="tip">您暂无权限查看{{industry}}内容,若想查看可以申请开通哦</view>
-				<view class="btn-cont"  @click="applyAuth">
+				<view class="btn-cont"  @click="applyAuth">
                 立即申请
 				</view>	
 			</block>
@@ -21,37 +21,37 @@
 				<view>开通该行业的试用权限</view>
 			</view>
 	
-			<view class="btn-cont back-btn" @click="backIndex">
+			<view class="btn-cont back-btn" @click="backIndex">
         返回			
 			</view>
-		</view>
-	</view>
-</template>
-
+		</view>
+	</view>
+</template>
+
 <script>
 	import { Report,User ,Reports} from '@/config/api.js'
-	let app = getApp();
-	export default {
-		data() {
+	let app = getApp();
+	export default {
+		data() {
 			return {
 				haveAuth:false,
 				// haveFree:false,//是否付费
 				access_token:'',//用户标识
 				isIphoneX:false,//判断机型
 				reportInfo:'',
-				linkurl:'https://details.hzinsights.com/raiReportDtl',//线上链接地址
-				//linkurl:'http://192.168.2.66:2000/raiReportDtl',//链接地址 
+				//linkurl:'https://details.hzinsights.com/raiReportDtl',//线上链接地址
+				linkurl:'http://192.168.2.66:2000/raiReportDtl',//链接地址 
 				showNav:false,
 				id:'',
 				isShowTip:false,
 				sale_name:'',//可联系销售名称
 				sale_number:'',//可联系销售电话
-				industry:'',//行业
-				readTiem:0,
-				setIntervalTiem:null
-			};
-		},
-		computed:{
+				industry:'',//行业
+				readTiem:0,
+				setIntervalTiem:null
+			};
+		},
+		computed:{
 		},
 		methods: {
 			/* 获取详情 */
@@ -59,9 +59,9 @@
 				Report.reportDtl({
 					ArticleId: Number(this.id) 
 				}).then(res => {
-					if(res.Ret === 200) {
-                       uni.setNavigationBarTitle({
-                           title:res.Data.Detail.IsSummary == 1 ? "纪要详情" : "报告详情"
+					if(res.Ret === 200) {
+                       uni.setNavigationBarTitle({
+                           title:res.Data.Detail.IsSummary == 1 ? "纪要详情" : "报告详情"
                        })
 						this.haveAuth = res.Data.HasPermission;
 						this.industry = res.Data.Detail.CategoryName;
@@ -69,7 +69,7 @@
 						this.sale_number = res.Data.Detail.SellerMobile;
 						if(res.Data.HasPermission === 1) { //有访问权限
 							this.reportInfo = res.Data.Detail;
-							this.access_token = this.access_token || this.$db.get('access_token');
+							this.access_token = this.access_token || this.$db.get('access_token');
 							this.$store.dispatch("statistics",{PageType:'ReportParticulars',DetailId:this.id})
 						}
 					}
@@ -102,13 +102,13 @@
 					});
 			},
 			// 返回首頁
-			backIndex() {
-				uni.navigateBack({
-					fail(){
-						uni.switchTab({
-							url:'/pages/index/index'
-						})
-					}
+			backIndex() {
+				uni.navigateBack({
+					fail(){
+						uni.switchTab({
+							url:'/pages/index/index'
+						})
+					}
 				})
 			},
 			callPhone(num) {
@@ -160,10 +160,10 @@
 				})
 			}
 		},
-		onShow() {
-		this.readTiem=0
-		this.setIntervalTiem=setInterval(() => {
-			      this.readTiem++
+		onShow() {
+		this.readTiem=0
+		this.setIntervalTiem=setInterval(() => {
+			      this.readTiem++
 			    },1000)
 			let page = getCurrentPages();//查看路径
 			if(page.length === 1) { //分享入口
@@ -183,11 +183,11 @@
 					}
 				})				
 			}else { // 跳转入口
-				this.getDetail();
+				this.getDetail();
 				
 			}
 		},
-		onLoad(option) {
+		onLoad(option) {
 			// console.log(option)
 			/* 兼容iphonex底部 */
 			// uni.getSystemInfo({
@@ -198,47 +198,47 @@
 			// 	   }
 			// 	}
 			// })
-			this.id = option.id || '';
+			this.id = option.id || '';
 			
 		},
 		 /**
 		    * 用户点击分享
 		  */
-		onShareAppMessage: function (res) {
-            if(this.id) {
-				return {
-					title: this.reportInfo.Title,
-					path: '/pages/reportDetail/reportDetail?id='+this.id,
-					success: (res)=> {
-					},
-					fail: (err)=> {
-					}
-				}
+		onShareAppMessage: function (res) {
+            if(this.id) {
+				return {
+					title: this.reportInfo.Title,
+					path: '/pages/reportDetail/reportDetail?id='+this.id,
+					success: (res)=> {
+					},
+					fail: (err)=> {
+					}
+				}
 			}
 			
-		},
-		onHide(){
-			clearInterval(this.setIntervalTiem)
-			Reports.addStopTime({
-				ArticleId:Number(this.id) ,
-				StopTime:this.readTiem
-			}).then(res=>{
-				
-			})
-		},
-		onUnload(){
-			clearInterval(this.setIntervalTiem)
-			Reports.addStopTime({
-				ArticleId:Number(this.id),
-				StopTime:this.readTiem
-			}).then(res=>{
-				
-			})
-		}
-	}
-</script>
-
-<style lang="scss" scoped>
+		},
+		onHide(){
+			clearInterval(this.setIntervalTiem)
+			Reports.addStopTime({
+				ArticleId:Number(this.id) ,
+				StopTime:this.readTiem
+			}).then(res=>{
+				
+			})
+		},
+		onUnload(){
+			clearInterval(this.setIntervalTiem)
+			Reports.addStopTime({
+				ArticleId:Number(this.id),
+				StopTime:this.readTiem
+			}).then(res=>{
+				
+			})
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
 .reportDetail-container {
 	background-color: #fff;
 	padding: 20rpx 34rpx 134rpx;
@@ -282,7 +282,8 @@
 		align-items: center;
 		flex-direction: row;
 		background-color: #fff;
-		box-shadow: 0 	-3rpx 6rpx rgba($color: #6A6A6A, $alpha: 0.16);
		.handle-item {
+		box-shadow: 0 	-3rpx 6rpx rgba($color: #6A6A6A, $alpha: 0.16);
+		.handle-item {
 			font-size: 24rpx;
 			color: #D0CFD5;
 			text-align: center;
@@ -299,7 +300,7 @@
 		.button-item {
 			background-color: transparent;
 			line-height: normal;
-		}
+		}
 	}
 	.noauth-cont {
 		padding-top: 150rpx;
@@ -324,16 +325,16 @@
 		.btn-cont {
 			width: 368rpx;
 			height: 80rpx;
-			// position: relative;
+			// position: relative;
 			background:linear-gradient(268deg, #2DDBFF 0%, #1599FF 49%, #005EFF 100%);
 			color: #fff;
 			font-size: 34rpx;
 			margin: 0 auto;
 			text-align: center;
 			line-height: 80rpx;
-			&.back-btn {
-				background:linear-gradient(268deg, #2DDBFF 0%, #1599FF 49%, #005EFF 100%)!important;
-				// border: 2rpx solid #3385FF;
+			&.back-btn {
+				background:linear-gradient(268deg, #2DDBFF 0%, #1599FF 49%, #005EFF 100%)!important;
+				// border: 2rpx solid #3385FF;
 				color:  #fff;
 				margin-top: 30rpx;
 			}
@@ -351,5 +352,5 @@
 			}
 		}
 	}
-}
-</style>
+}
+</style>

+ 2 - 2
pages/reportForm/components/coverGuide.vue

@@ -4,12 +4,12 @@
 				<view class="top-bg">
 					<image style="width: 80rpx;height: 80rpx;" src="../../../static/img/guide-1.png" mode=""></image>
 					<view class="guide-tow">
-						<image style="width: 181rpx;height: 239rpx;" src="../../../static/img/guide-2.png" mode=""></image>
+						<image style="width: 181rpx;height: 239rpx;" src="https://hzstatic.hzinsights.com/cygx/czbk/guide-2.png" mode=""></image>
 					</view>
 					<view class="content-text">
 						<text>新增产业关注功能</text>
 						<text>点击关注后可获取产业内容更新提醒</text>
-						<image @click="isShow" style="width: 237rpx;height: 104rpx;" src="../../../static/img/guide-3.png" mode=""></image>
+						<image @click="isShow" style="width: 237rpx;height: 104rpx;" src="https://hzstatic.hzinsights.com/cygx/czbk/guide-3.png" mode=""></image>
 					</view>
 				</view>
 				

+ 671 - 577
pages/reportForm/reportForm.vue

@@ -1,594 +1,688 @@
 <template>
-	<view class="reportForm-container">
-		<!-- tabs -->
-		<view class="index-fixed">
-			<view class="index-header">
-				<input type="text" placeholder="搜索您想要的产业资源包" placeholder-class="sea_ipt_placeholder" class="sea_ipt"
-					v-model="searchTxt" disabled @click="goSearch" />
-				<icon type="search" size="15" class="search_ico" />
-			</view>
-			<view class="tab-cont">
-				<scroll-view scroll-x="true" @scroll="scrollMove" :scroll-left="scrollLeft" scroll-with-animation class="scroll-tab" :scroll-into-view="'_'+tabIndex" >
-					<block v-for="(item, index) in tabBars" :key="item.ChartPermissionId">
-						<view :id="'_'+index" class="scroll-tab-item"
-							:class="{ active: tabAct_id == item.ChartPermissionId }"
-							@click.stop="toggleTab(item,index)">
-							{{item.PermissionName}}
-							<image src="@/static/img/border_act.png" mode="" class="border_act"
-								v-if="tabAct_id == item.ChartPermissionId"></image>
-						</view>
-					</block>
-					<view class="limit-box" v-if="limitIsShow">
-						<image class="limit-img" src="../../static/img/limit_icon.png" mode=""></image>
-					</view>
-				</scroll-view>
+    <view class="reportForm-container">
+        <!-- tabs -->
+        <view class="index-fixed">
+            <view class="index-header">
+                <input type="text" placeholder="搜索您想要的产业资源包" placeholder-class="sea_ipt_placeholder" class="sea_ipt"
+                    v-model="searchTxt" disabled @click="goSearch" />
+                <icon type="search" size="15" class="search_ico" />
+            </view>
+            <view class="tab-cont">
+                <scroll-view scroll-x="true" @scroll="scrollMove" :scroll-left="scrollLeft" scroll-with-animation
+                    class="scroll-tab" :scroll-into-view="'_'+tabIndex">
+                    <block v-for="(item, index) in tabBars" :key="item.ChartPermissionId">
+                        <view :id="'_'+index" class="scroll-tab-item"
+                            :class="{ active: tabAct_id == item.ChartPermissionId }"
+                            @click.stop="toggleTab(item,index)">
+                            {{item.PermissionName}}
+                            <image src="@/static/img/border_act.png" mode="" class="border_act"
+                                v-if="tabAct_id == item.ChartPermissionId"></image>
+                        </view>
+                    </block>
+                    <view class="limit-box" v-if="limitIsShow">
+                        <image class="limit-img" src="../../static/img/limit_icon.png" mode=""></image>
+                    </view>
+                </scroll-view>
 
-			</view>
-			<view class="lucency" v-if="tabBars.length>6"></view>
-		</view>
-		<!-- 内容 -->
-		<view class="strategy" v-if="strategyIndex==4">
-			<view class="tab-cont-two">
-				<scroll-view scroll-x="true" scroll-with-animation class="scroll-tab-tow">
-					<block v-for="(item, index) in tabBarsTow" :key="item.CategoryId">
-						<view :id="'__'+index" class="scroll-tab-item"
-							:class="{ active: tabAct_idTwo == item.CategoryId }" @click.stop="toggleTabTwo(item,index)">
-							{{item.MatchTypeName}}
-							<text class="reg-text" v-if="item.IsRed"></text>
-						</view>
-					</block>
-				</scroll-view>
-			</view>
-			<view class="row">
+            </view>
+            <view class="lucency" v-if="tabBars.length>6"></view>
+        </view>
+        <!-- 内容 -->
+        <view class="strategy" v-if="strategyIndex==4">
+            <view class="tab-cont-two">
+                <scroll-view scroll-x="true" scroll-with-animation class="scroll-tab-tow">
+                    <block v-for="(item, index) in tabBarsTow" :key="item.CategoryId">
+                        <view :id="'__'+index" class="scroll-tab-item"
+                            :class="{ active: tabAct_idTwo == item.CategoryId }" @click.stop="toggleTabTwo(item,index)">
+                            {{item.MatchTypeName}}
+                            <text class="reg-text" v-if="item.IsRed"></text>
+                        </view>
+                    </block>
+                </scroll-view>
+            </view>
+            <view class="row">
 
-			</view>
-			<!-- 子组件 -->
-			<strategy :strategyIndexTwo="strategyIndexTwo" :pageNumFather='pageNumFather' :matchTypeName="matchTypeName"
-				:tabAct_idTwo="tabAct_idTwo" :isNum="isNum" :isSwitchover="isSwitchover" @hideIsred="hideIsred" />
-		</view>
-		<view class="" v-else-if="strategyIndex==5">
-			<researchChoose :strategyIndex="strategyIndex" :tabAct="tabAct_id" :pageNumFather="pageNumFather" :isNum="isNum"/>
-		</view>
-		<!-- </view> -->
-		<view class="industrial_eport_one" v-else>
-			<!-- 行业报告 -->
-			<view class="industry" v-if="tradeList">
-				<view style="height: 20rpx;"></view>
-				<view class="industry-top">
-					<view class="img-top-box">
-						<image src="@/static/img/industry-ico.png"></image>
-						<text>行业综述</text>
-					</view>
-					<view>
+            </view>
+            <!-- 子组件 -->
+            <strategy :strategyIndexTwo="strategyIndexTwo" :pageNumFather='pageNumFather' :matchTypeName="matchTypeName"
+                :tabAct_idTwo="tabAct_idTwo" :isNum="isNum" :isSwitchover="isSwitchover" @hideIsred="hideIsred" />
+        </view>
+        <view class="" v-else-if="strategyIndex==5">
+            <researchChoose :strategyIndex="strategyIndex" :tabAct="tabAct_id" :pageNumFather="pageNumFather"
+                :isNum="isNum" />
+        </view>
+        <!-- </view> -->
+        <view class="industrial_eport_one" v-else>
+            <!-- 行业报告 -->
+            <view class="industry" v-if="tradeList">
+                <view style="height: 20rpx;"></view>
+                <view class="industry-top">
+                    <view class="img-top-box">
+                        <image src="@/static/img/industry-ico.png"></image>
+                        <text>行业综述</text>
+                    </view>
+                    <view>
 
-					</view>
-				</view>
-				<view class="industry-box" @click="isClickHandle(item.CategoryId)" v-for="item in tradeList"
-					:key="item.CategoryId">
-					<view class="box-left">
-						{{item.MatchTypeName}}
-						<text v-if="item.IsRed"></text>
-					</view>
-					<view class="box-right">
-						<text>{{item.UpdateTime}}更新</text>
-						<u-icon name="arrow-right" color="#BDBDBD" size="34"></u-icon>
-					</view>
-				</view>
-			</view>
-			<!-- 产业报告 -->
-			<view class="industry">
-				<view style="height: 12rpx;" v-if="!tradeList"></view>
-				<view class="industry-top industry-sticky">
-					<view class="img-top-box">
-						<image src="@/static/img/property_ico.png" style="height: 50rpx;"></image>
-						<text class="text-sub">细分产业</text>
-					</view>
-					<van-dropdown-menu active-color="#333333">
-						<van-dropdown-item id="menuItem" @open="isscroll" :title="overallArrangementName">
-							<view class="menu-items-tow">
-								<view class="items-tow" @click="pitchClick(item,index)" v-for="(item,index) in pitchOn"
-									:key="item.id">
-									<view>
-										<u-icon v-show="pitchOnId==item.id" name="checkbox-mark" color="#2C83FF"
-											size="24"></u-icon>
-									</view>
-									<text :class="pitchOnId==item.id?'items-act':''">{{item.name}}</text>
-								</view>
-							</view>
-							<view style="background-color: #f8f8fa;width: 100%;">
-								<view style="margin: 0 auto;width: 682rpx;border-bottom: 2rpx dashed  #999;">	
-								</view>
-							</view>
-							<view class="menu-items">
-								<view class="menu-items-box" @click="overallBtn(index,item)"
-									v-for="(item,index) in overallArrangement" :key="item.id">
-									<view class="items-box">
-										<u-icon v-show="item.isShow" name="checkbox-mark" color="#2C83FF" size="24">
-										</u-icon>
-									</view>
-									<text>{{item.name}}</text>
-								</view>
-							</view>
-							<view class="replacement-box">
-								<view class="replacement">
-									<text @click="replacementBtn" class="replacement-box">重置</text>
-									<text @click="replacementConfirm">确定</text>
-								</view>
-							</view>
-						</van-dropdown-item>
-					</van-dropdown-menu>
-				</view>
-				<!-- 需要循环的地方 -->
-				<view class="forindustry" v-for="item in industryList" :key="item.IndustrialManagementId">
-					<!-- 火锅底料这个位置 -->
-					<view class="industry-content">
-						<view class="industry-box-left" @click="reportFllow(item.IndustrialManagementId)">
-							<image src="@/static/img/top_ico.png" v-if="item.IsFollow"></image>
-							<image src="@/static/img/top_no_ico.png" v-else></image>
-						</view>
-						<view class="industry-box-right" @click="goIndustryReport(item.IndustrialManagementId)">
-							<view class="ndustry-box-read">
-								<text>{{item.IndustryName}}</text>
-								<image v-if="item.IsHot" src="../../static/img/ammunition_ico.png" mode=""></image>
-							</view>
-							<view class="ndustry-box-arrow">
-								<text v-if="item.IsRed" class="read"></text>
-								<text class="ndustry-box-text">{{item.UpdateTime}}更新</text>
-								<u-icon name="arrow-right" color="#BDBDBD" size="34"></u-icon>
-							</view>
-						</view>
-					</view>
-					<view class="content-box" v-if="item.IndustrialSubjectList.length>6">
-						<u-read-more :toggle="true" :show-height="item.IndustrialSubjectList.length>6 ? 140 :150"
-							:shadow-style="shadowStyle" close-text="展开" color="#D1D1D1">
-							<view class="read-more">
-								<view v-for="val in item.IndustrialSubjectList" :key="val.IndustrialSubjectId"
-									@click="goIndustryReport(item.IndustrialManagementId)" class="text-box">
-									{{val.SubjectName}}
-								</view>
-							</view>
-						</u-read-more>
-					</view>
-					<view class="content-box" v-else @click="goIndustryReport(item.IndustrialManagementId)">
-						<view class="read-more">
-							<view v-for="val in item.IndustrialSubjectList" :key="val.IndustrialSubjectId"
-								class="text-box">{{val.SubjectName}}</view>
-						</view>
-					</view>
-				</view>
-				<u-loadmore :status="status" icon-type="flower" :load-text="loadText" margin-top="20"
-					v-if="totalPage>1" />
-			</view>
-		</view>
-		<coverGuide :isGuideShow="isGuideShow" />
-        <u-modal v-model="goFollowShow" :content-style="{fontSize: '32rpx'}" @confirm="goFollowShowBtn"
-        	:show-cancel-button="isCancelBtn" :confirm-text="confirmText" @cancel="isCancelBtn=false"
-             :show-title="false" :cancel-style="{borderRight:'1rpx solid #EBEBEB'}"
-             :confirm-style="{fontWeight: '700'}">
-        	<view class="slot-content">
-        		<rich-text :nodes="accounts"></rich-text>
-        	</view>
+                    </view>
+                </view>
+                <view class="industry-box" @click="isClickHandle(item.CategoryId)" v-for="item in tradeList"
+                    :key="item.CategoryId">
+                    <view class="box-left">
+                        {{item.MatchTypeName}}
+                        <text v-if="item.IsRed"></text>
+                    </view>
+                    <view class="box-right">
+                        <text>{{item.UpdateTime}}更新</text>
+                        <u-icon name="arrow-right" color="#BDBDBD" size="34"></u-icon>
+                    </view>
+                </view>
+            </view>
+            <!-- 产业报告 -->
+            <view class="industry">
+                <view style="height: 12rpx;" v-if="!tradeList"></view>
+                <view class="industry-top industry-sticky">
+                    <view class="img-top-box">
+                        <image src="@/static/img/property_ico.png" style="height: 50rpx;"></image>
+                        <text class="text-sub">细分产业</text>
+                    </view>
+                    <van-dropdown-menu active-color="#333333">
+                        <van-dropdown-item id="menuItem" @open="isscroll" :title="overallArrangementName">
+                            <view class="menu-items-tow">
+                                <view class="items-tow" @click="pitchClick(item,index)" v-for="(item,index) in pitchOn"
+                                    :key="item.id">
+                                    <view>
+                                        <u-icon v-show="pitchOnId==item.id" name="checkbox-mark" color="#2C83FF"
+                                            size="24"></u-icon>
+                                    </view>
+                                    <text :class="pitchOnId==item.id?'items-act':''">{{item.name}}</text>
+                                </view>
+                            </view>
+                            <view style="background-color: #f8f8fa;width: 100%;">
+                                <view style="margin: 0 auto;width: 682rpx;border-bottom: 2rpx dashed  #999;">
+                                </view>
+                            </view>
+                            <view class="menu-items">
+                                <view class="menu-items-box" @click="overallBtn(index,item)"
+                                    v-for="(item,index) in overallArrangement" :key="item.id">
+                                    <view class="items-box">
+                                        <u-icon v-show="item.isShow" name="checkbox-mark" color="#2C83FF" size="24">
+                                        </u-icon>
+                                    </view>
+                                    <text>{{item.name}}</text>
+                                </view>
+                            </view>
+                            <view class="replacement-box">
+                                <view class="replacement">
+                                    <text @click="replacementBtn" class="replacement-box">重置</text>
+                                    <text @click="replacementConfirm">确定</text>
+                                </view>
+                            </view>
+                        </van-dropdown-item>
+                    </van-dropdown-menu>
+                </view>
+                <!-- 需要循环的地方 -->
+                <view class="forindustry" v-for="item in industryList" :key="item.IndustrialManagementId">
+                    <!-- 火锅底料这个位置 -->
+                    <view class="industry-content">
+                        <view class="industry-box-left" @click="reportFllow(item.IndustrialManagementId)">
+                            <image src="@/static/img/top_ico.png" v-if="item.IsFollow"></image>
+                            <image src="@/static/img/top_no_ico.png" v-else></image>
+                        </view>
+                        <view class="industry-box-right" @click="goIndustryReport(item.IndustrialManagementId)">
+                            <view class="ndustry-box-read">
+                                <text>{{item.IndustryName}}</text>
+                                <image v-if="item.IsHot" src="../../static/img/ammunition_ico.png" mode=""></image>
+                            </view>
+                            <view class="ndustry-box-arrow">
+                                <text v-if="item.IsRed" class="read"></text>
+                                <text class="ndustry-box-text">{{item.UpdateTime}}更新</text>
+                                <u-icon name="arrow-right" color="#BDBDBD" size="34"></u-icon>
+                            </view>
+                        </view>
+                    </view>
+                    <view class="content-box" v-if="item.IndustrialSubjectList.length>6">
+                        <u-read-more :toggle="true" :show-height="item.IndustrialSubjectList.length>6 ? 140 :150"
+                            :shadow-style="shadowStyle" close-text="展开" color="#D1D1D1">
+                            <view class="read-more">
+                                <view v-for="val in item.IndustrialSubjectList" :key="val.IndustrialSubjectId"
+                                    @click="goIndustryReport(item.IndustrialManagementId)" class="text-box">
+                                    {{val.SubjectName}}
+                                </view>
+                            </view>
+                        </u-read-more>
+                    </view>
+                    <view class="content-box" v-else @click="goIndustryReport(item.IndustrialManagementId)">
+                        <view class="read-more">
+                            <view v-for="val in item.IndustrialSubjectList" :key="val.IndustrialSubjectId"
+                                class="text-box">{{val.SubjectName}}</view>
+                        </view>
+                    </view>
+                </view>
+                <u-loadmore :status="status" icon-type="flower" :load-text="loadText" margin-top="20"
+                    v-if="totalPage>1" />
+            </view>
+        </view>
+        <coverGuide :isGuideShow="isGuideShow" />
+        <u-modal v-model="goFollowShow" :content-style="{fontSize: '32rpx'}" @confirm="goFollowShowBtn"
+            :show-cancel-button="isCancelBtn" :confirm-text="confirmText" @cancel="isCancelBtn=false"
+            :show-title="false" :cancel-style="{borderRight:'1rpx solid #EBEBEB'}" :confirm-style="{fontWeight: '700'}">
+            <view class="slot-content">
+                <rich-text :nodes="accounts"></rich-text>
+            </view>
         </u-modal>
-	</view>
+        <view class="content-intimate" v-if="reportShow">
+            <van-transition :show="showTransition" name="fade-right">
+                <view class="content">
+                    <view @click="goSecretDetail('1')">
+                        <text>报告</text>
+                        <text>精选</text>
+                    </view>
+                    <view class="cont-border" @click="goSecretDetail('2')">
+                        <text>本周研</text>
+                        <text>究汇总</text>
+                    </view>
+                    <view @click="goSecretDetail('3')">
+                        <text>上周纪</text>
+                        <text>要汇总</text>
+                    </view>
+                </view>
+            </van-transition>
+            <image @click="showTransition=!showTransition" src="https://hzstatic.hzinsights.com/cygx/czbk/intimate-icon.png" mode=""></image>
+        </view>
+    </view>
 </template>
 
 <script>
-	import strategy from "./components/strategy.vue"
-	import researchChoose from "./components/researchChoose.vue"
-	import coverGuide from "./components/coverGuide.vue"
-	import {Throttle,Debounce } from '@/config/util.js'
-	import { Reports } from '@/config/api.js'
-	let app = getApp()
-	export default {
-		components: {
-			strategy,
-			researchChoose,
-			coverGuide
-		},
-		data() {
-			return {
-				tabAct_id: '',
-				tabAct_idTwo: '',
-				tabBars: [],
-				pageNumFather: '',
-				shadowStyle: {
-					backgroundImage: "none"
-				},
-				tabBarsTow: [],
-				pitchOn: [{
-					name: '按最近更新排序',
-					id: 'NewTime'
-				}, {
-					name: '按推荐关注排序',
-					id: 'Recommend',
-				}],
-				pitchOnId: 'NewTime',
-				//pitchOnName: '按最近更新排序',
-				isNum: 1,
-				strategyIndex: '',
-				strategyIndexTwo: 0,
-				isSwitchover: 1,
-				tradeList: [],
-				OrderColumn: '',
-				industryList: [],
-				loadText: {
-					loadmore: '上拉加载更多',
-					loading: '加载中',
-					nomore: '已经到底了'
-				},
-				refresh: false, //正在下拉
-				page_no: 1,
-				pageSize: 10,
-				status: 'loadmore',
-				haveData: true,
-				totalPage: '',
-				matchTypeName: '',
-				overallArrangement: [{
-					name: '新布局产业',
-					id: '1',
-					isShow: false
-				}, {
-					name: '深度研究产业',
-					id: '2',
-					isShow: false
-				}, ],
-				overallArrangementId: '',
-				overallArrangementName: '按最近更新排序',
-				isScrollShow: false,
-				isGuideShow:false,
-				limitIsShow:false,//限免显示隐藏
-                goFollowShow:false,
-                accounts:'',
-                confirmText:'知道了',
-                isCancelBtn:false,
-                scrollLeft:0
-			}
-		},
-		 onLoad(option) {
-			this.loadList(option)
-		},
-		watch: {
-			//监听tabs的变化
-			tabAct_id: {
-				handler() {
-					this.initList()
-				},
-				immediate: true
-			}
-		},
-		methods: {
-			//获取一级事件
-			getClassify() {
-				Reports.getClassify().then(res => {
-					if(res.Ret!==200) return
-					this.tabBars = res.Data.List ||[]
-					if (!this.tabAct_id) {
-						this.tabAct_id = res.Data.List[0].ChartPermissionId
-						this.$store.dispatch("statistics",{PageType:'Report',ChartPermissionId:Number(this.tabAct_id)})
-					}
-					this.limitIsShow=this.tabBars.some(item=> item.IsShowSustainable)
-				})
-			},
-			//获取二级事件
-			getstrategyAll() {
-				Reports.getstrategyAll().then(res => {
-					this.tabBarsTow = res.Data.List
-					if (!this.tabAct_idTwo) {
-						this.tabAct_idTwo = res.Data.List[0].CategoryId
-					}
-					this.matchTypeName = res.Data.List[0].MatchTypeName
-				})
-			},
-			//tabs切换事件
-			toggleTab(item, index) {
-				this.strategyIndex = index
-				if (this.tabAct_id !== item.ChartPermissionId) {
-					this.tabAct_id = item.ChartPermissionId;
-					this.$store.dispatch("statistics",{PageType:'Report',ChartPermissionId:Number(this.tabAct_id)})
-					this.pageNum = 1;
-					uni.pageScrollTo({
-						scrollTop: 0,
-						duration: 0,
-					});
-				}
-               this.getRectTab(index)
-			},
-            getRectTab(index){
-                // const query = uni.createSelectorQuery().in(this);
-                // query.select(`#_${index}`).boundingClientRect(rect => {
-                //          var screen = wx.getSystemInfoSync().windowWidth/2;
-                //         //获取点击item的左边坐标
-                //         var left = rect.left;
-                //         //获取item的宽度de 一半
-                //         var subhalfwidth= rect.width/2
-                //         //需要scrollview 移动的距离是
-                //         var juli = left-screen
-                //         var zuizhongjuli = juli+subhalfwidth
-                //         this.scrollLeft = this.scrollLeft+=zuizhongjuli
-                // }).exec();
-            },
-             scrollMove(e) {
-                this.scrollLeft = e.detail.scrollLeft;
-              },
-			//tabs切换二级事件
-			toggleTabTwo(item, index) {
-				this.matchTypeName = item.MatchTypeName
-				this.strategyIndexTwo = index
-				if (this.tabAct_idTwo !== item.CategoryId) {
-					this.tabAct_idTwo = item.CategoryId;
-					this.pageNum = 1;
-					uni.pageScrollTo({
-						scrollTop: 0,
-						duration: 0,
-					});
-				}
-			},
-			//点击产业报告的筛选条件
-			pitchClick(item) {
-				this.pitchOnName = item.name
-				this.OrderColumn = item.id
-				if (this.pitchOnId !== item.id) {
-					this.pitchOnId = item.id;
-				}
-			},
-			//获取报告所有品种接口
-			getTradeList() {
-				Reports.getTradeList({
-					ChartPermissionId: this.tabAct_id
-				}).then(res => {
-					if (res.Ret == 200) {
-						this.tradeList = res.Data.List || []
-					}
-				})
-			},
-			//获取产业报告所有品种接口
-			getIndustryList() {
-				Reports.getIndustryList({
-					ChartPermissionId: this.tabAct_id,
-					OrderColumn: this.OrderColumn,
-					PageSize: this.pageSize,
-					CurrentIndex: this.page_no,
-					IsNewLabel: this.overallArrangementId.includes(1) ? '1' : '0',
-					IsDeepLabel: this.overallArrangementId.includes(2) ? '1' : '0'
-				}).then(res => {
-					// this.industryList=res.Data.List
-					this.status = this.page_no < res.Data.Paging.Pages ? 'loadmore' : 'nomore';
-					this.totalPage = res.Data.Paging.Pages; //总页数
-					if (this.page_no === 1) {
-						this.industryList = res.Data.List || [];
-						this.haveData = this.industryList.length ? true : false
-						if (this.refresh) {
-							uni.stopPullDownRefresh();
-							this.refresh = false;
-						}
-					} else {
-						this.industryList = this.industryList.concat(res.Data.List)
-					}
+    import strategy from "./components/strategy.vue"
+    import researchChoose from "./components/researchChoose.vue"
+    import coverGuide from "./components/coverGuide.vue"
+    import {
+        Throttle,
+        Debounce
+    } from '@/config/util.js'
+    import {
+        Reports
+    } from '@/config/api.js'
+    let app = getApp()
+    export default {
+        components: {
+            strategy,
+            researchChoose,
+            coverGuide
+        },
+        data() {
+            return {
+                tabAct_id: '',
+                tabAct_idTwo: '',
+                tabBars: [],
+                pageNumFather: '',
+                shadowStyle: {
+                    backgroundImage: "none"
+                },
+                tabBarsTow: [],
+                pitchOn: [{
+                    name: '按最近更新排序',
+                    id: 'NewTime'
+                }, {
+                    name: '按推荐关注排序',
+                    id: 'Recommend',
+                }],
+                pitchOnId: 'NewTime',
+                //pitchOnName: '按最近更新排序',
+                isNum: 1,
+                strategyIndex: '',
+                strategyIndexTwo: 0,
+                isSwitchover: 1,
+                tradeList: [],
+                OrderColumn: '',
+                industryList: [],
+                loadText: {
+                    loadmore: '上拉加载更多',
+                    loading: '加载中',
+                    nomore: '已经到底了'
+                },
+                refresh: false, //正在下拉
+                page_no: 1,
+                pageSize: 10,
+                status: 'loadmore',
+                haveData: true,
+                totalPage: '',
+                matchTypeName: '',
+                overallArrangement: [{
+                    name: '新布局产业',
+                    id: '1',
+                    isShow: false
+                }, {
+                    name: '深度研究产业',
+                    id: '2',
+                    isShow: false
+                }, ],
+                overallArrangementId: '',
+                overallArrangementName: '按最近更新排序',
+                isScrollShow: false,
+                isGuideShow: false,
+                limitIsShow: false, //限免显示隐藏
+                goFollowShow: false,
+                accounts: '',
+                confirmText: '知道了',
+                isCancelBtn: false,
+                scrollLeft: 0,
+                showTransition: false,//点击绝密后的隐现
+                reportShow:false,//绝密标签的隐现
+            }
+        },
+        onLoad(option) {
+            this.loadList(option)
+        },
+        watch: {
+            //监听tabs的变化
+            tabAct_id: {
+                handler() {
+                    this.initList()
+                },
+                immediate: true
+            }
+        },
+        methods: {
+            //获取一级事件
+            getClassify() {
+                Reports.getClassify().then(res => {
+                    if (res.Ret !== 200) return
+                    this.tabBars = res.Data.List || []
+                    if (!this.tabAct_id) {
+                        this.tabAct_id = res.Data.List[0].ChartPermissionId
+                        this.$store.dispatch("statistics", {
+                            PageType: 'Report',
+                            ChartPermissionId: Number(this.tabAct_id)
+                        })
+                    }
+                    this.limitIsShow = this.tabBars.some(item => item.IsShowSustainable)
+                })
+            },
+            //获取二级事件
+            getstrategyAll() {
+                Reports.getstrategyAll().then(res => {
+                    this.tabBarsTow = res.Data.List
+                    if (!this.tabAct_idTwo) {
+                        this.tabAct_idTwo = res.Data.List[0].CategoryId
+                    }
+                    this.matchTypeName = res.Data.List[0].MatchTypeName
+                })
+            },
+            //tabs切换事件
+            toggleTab(item, index) {
+                this.strategyIndex = index
+                if (this.tabAct_id !== item.ChartPermissionId) {
+                    this.tabAct_id = item.ChartPermissionId;
+                    this.$store.dispatch("statistics", {
+                        PageType: 'Report',
+                        ChartPermissionId: Number(this.tabAct_id)
+                    })
+                    this.pageNum = 1;
+                    uni.pageScrollTo({
+                        scrollTop: 0,
+                        duration: 0,
+                    });
+                }
+                this.getRectTab(index)
+            },
+         async reportIsShow(){
+                const res = await Reports.reportIsShow()
+                if(res.Ret===200){
+                    this.reportShow=res.Data.IsShow
+                }
+            },
+            getRectTab(index) {
+                // const query = uni.createSelectorQuery().in(this);
+                // query.select(`#_${index}`).boundingClientRect(rect => {
+                //          var screen = wx.getSystemInfoSync().windowWidth/2;
+                //         //获取点击item的左边坐标
+                //         var left = rect.left;
+                //         //获取item的宽度de 一半
+                //         var subhalfwidth= rect.width/2
+                //         //需要scrollview 移动的距离是
+                //         var juli = left-screen
+                //         var zuizhongjuli = juli+subhalfwidth
+                //         this.scrollLeft = this.scrollLeft+=zuizhongjuli
+                // }).exec();
+            },
+            scrollMove(e) {
+                this.scrollLeft = e.detail.scrollLeft;
+            },
+            //tabs切换二级事件
+            toggleTabTwo(item, index) {
+                this.matchTypeName = item.MatchTypeName
+                this.strategyIndexTwo = index
+                if (this.tabAct_idTwo !== item.CategoryId) {
+                    this.tabAct_idTwo = item.CategoryId;
+                    this.pageNum = 1;
+                    uni.pageScrollTo({
+                        scrollTop: 0,
+                        duration: 0,
+                    });
+                }
+            },
+            //点击产业报告的筛选条件
+            pitchClick(item) {
+                this.pitchOnName = item.name
+                this.OrderColumn = item.id
+                if (this.pitchOnId !== item.id) {
+                    this.pitchOnId = item.id;
+                }
+            },
+            //获取报告所有品种接口
+            getTradeList() {
+                Reports.getTradeList({
+                    ChartPermissionId: this.tabAct_id
+                }).then(res => {
+                    if (res.Ret == 200) {
+                        this.tradeList = res.Data.List || []
+                    }
+                })
+            },
+            //获取产业报告所有品种接口
+            getIndustryList() {
+                Reports.getIndustryList({
+                    ChartPermissionId: this.tabAct_id,
+                    OrderColumn: this.OrderColumn,
+                    PageSize: this.pageSize,
+                    CurrentIndex: this.page_no,
+                    IsNewLabel: this.overallArrangementId.includes(1) ? '1' : '0',
+                    IsDeepLabel: this.overallArrangementId.includes(2) ? '1' : '0'
+                }).then(res => {
+                    // this.industryList=res.Data.List
+                    this.status = this.page_no < res.Data.Paging.Pages ? 'loadmore' : 'nomore';
+                    this.totalPage = res.Data.Paging.Pages; //总页数
+                    if (this.page_no === 1) {
+                        this.industryList = res.Data.List || [];
+                        this.haveData = this.industryList.length ? true : false
+                        if (this.refresh) {
+                            uni.stopPullDownRefresh();
+                            this.refresh = false;
+                        }
+                    } else {
+                        this.industryList = this.industryList.concat(res.Data.List)
+                    }
+
+                })
+            },
+            //跳转季度策略
+            isClickHandle(id) {
+                this.public({
+                    type: 'show'
+                }, true, '/reportPages/industrialReport/industrialReport?id=', id)
+            },
+            //跳转产业报告
+            goIndustryReport(id) {
+                this.public({
+                    type: 'show'
+                }, true, '/reportPages/IndustryReport/IndustryReport?id=', id)
+            },
+            //点击关注的图标
+            reportFllow(id) {
+                Reports.reportFllow({
+                    IndustrialManagementId: id
+                }).then(res => {
+                    if (res.Ret === 200) {
+                        if (res.Data.Status == 1) {
+                            this.goFollowShow = true
+                            this.confirmText = res.Data.GoFollow ? '去关注' : '知道了'
+                            if (res.Data.GoFollow) {
+                                this.accounts = `产业关注成功 <br> 想要及时获取该产业内容的更新推送,请关注【弘则研究】公众号`
+                                this.isCancelBtn = true
+                            } else {
+                                this.accounts = '产业关注成功,产业报告更新时,【弘则研究】公众号会为您推送微信消息提醒'
+                            }
+                        }
+                        this.industryList.forEach(key => {
+                            if (key.IndustrialManagementId == id) {
+                                if (key.IsFollow == 1) {
+                                    key.IsFollow = 0
+                                    uni.showToast({
+                                        title: '已取消关注',
+                                        icon: 'none',
+                                        duration: 2000
+                                    });
+                                } else {
+                                    key.IsFollow = 1
+
+                                }
+                            }
+                        })
+                    }
+                })
+            },
+            goFollowShowBtn() {
+                if (this.confirmText == '去关注') {
+                    uni.navigateTo({
+                        url: '/activityPages/accountsOfficial/accountsOfficial'
+                    })
+                }
+                this.goFollowShow = false
+            },
+            hideIsred(is) {
+                this.tabBarsTow[this.strategyIndexTwo].IsRed = is
+            },
+            /* 新布局产业选项*/
+            overallBtn(index, item) {
+                this.overallArrangement.forEach(key => {
+                    if (key.id == item.id) {
+                        key.isShow = !key.isShow
+                    }
+                })
 
-				})
-			},
-			//跳转季度策略
-			isClickHandle(id) {
-				this.public({type:'show'},true,'/reportPages/industrialReport/industrialReport?id=',id)
-			},
-			//跳转产业报告
-			goIndustryReport(id) {
-				this.public({type:'show'},true,'/reportPages/IndustryReport/IndustryReport?id=',id)
-			},
-			//点击关注的图标
-			reportFllow(id) {
-				Reports.reportFllow({
-					IndustrialManagementId: id
-				}).then(res => {
-					if (res.Ret === 200) {         
-                        if(res.Data.Status==1){
-                          this.goFollowShow=true
-                          this.confirmText =  res.Data.GoFollow ? '去关注':'知道了'
-                          if(res.Data.GoFollow){
-                              this.accounts=`产业关注成功 <br> 想要及时获取该产业内容的更新推送,请关注【弘则研究】公众号`
-                              this.isCancelBtn=true
-                          }else {
-                              this.accounts='产业关注成功,产业报告更新时,【弘则研究】公众号会为您推送微信消息提醒'
-                          }
-                        }
-					 this.industryList.forEach(key => {
-						 if(key.IndustrialManagementId == id){
-							 if(key.IsFollow==1){
-								key.IsFollow=0 
-                                uni.showToast({
-                                    title: '已取消关注',
-                                    icon:'none',
-                                    duration: 2000
-                                });
-							 }else{
-								 key.IsFollow=1
-                                 
-							 }
-						 }
-					 })
-					}
-				})
-			},
-            goFollowShowBtn(){
-                if(this.confirmText=='去关注') {
-                    uni.navigateTo({
-                        url: '/activityPages/accountsOfficial/accountsOfficial'
-                    })
-                }
-                this.goFollowShow=false
             },
-			hideIsred(is) {
-				this.tabBarsTow[this.strategyIndexTwo].IsRed = is
-			},
-			/* 新布局产业选项*/
-			overallBtn(index, item) {
-				this.overallArrangement.forEach(key => {
-					if (key.id == item.id) {
-						key.isShow = !key.isShow
-					}
-				})
+            /* 新布局产业选项确定按钮 */
+            replacementConfirm() {
+                const arr = []
+                this.overallArrangement.forEach(key => {
+                    if (key.isShow) {
+                        arr.push(key.id)
+                    }
+                })
+                this.overallArrangementId = arr.join(',')
+                this.overallArrangementName = this.pitchOnName
+                this.page_no = 1;
+                this.status = 'loadmore'
+                this.getIndustryList()
+                this.selectComponent('#menuItem').toggle();
+            },
+            /* 新布局产业选项重置按钮 */
+            replacementBtn() {
+                this.OrderColumn = 'NewTime'
+                this.pitchOnId = 'NewTime'
+                this.overallArrangement.forEach(key => key.isShow = false)
+                this.overallArrangementName = '按最近排序更新'
+            },
+            /* 判断页面滚动 */
+            isscroll: Debounce(function() {
+                this.isScrollShow = true
+            }),
+            /* 搜索 */
+            goSearch() {
+                this.public({
+                    type: 'show'
+                }, true, '/reportPages/reportSearch/reportSearch')
+            },
+            /* 跳转 */
+            public(type, flag, purl, price = '') {
+                return new Promise((resolve, reject) => {
+                    this.$store.dispatch('checkHandle', type).then(res => {
+                        app.globalData.isAuth = res.IsAuth;
+                        app.globalData.isBind = res.IsBind;
+                        if ((!res.IsAuth) && (!res.IsBind)) { //已授权已绑定
+                            if (flag) {
+                                uni.navigateTo({
+                                    url: purl + price,
+                                });
+                            }
+                        } else if (res.IsAuth) { //未授权
+                            uni.navigateTo({
+                                url: '/pages/authGuide/authGuide'
+                            })
+                            return
+                        } else if (res.IsBind && !res.IsAuth) { //已授权未绑定
+                            uni.navigateTo({
+                                url: '/pages/login/login'
+                            })
+                            return
+                        }
+                    })
+                })
+            },
+            /* 初始 */
+            initList() {
+                if (this.tabAct_id && (this.strategyIndex !== 4 && this.strategyIndex !== 5)) {
+                    this.OrderColumn = 'NewTime'
+                    this.pitchOnId = 'NewTime'
+                    this.overallArrangementName = '按最近更新排序'
+                    this.overallArrangementId = ''
+                    this.page_no = 1;
+                    this.refresh = true;
+                    this.getIndustryList()
+                    this.getTradeList()
+                    this.overallArrangement.forEach(key => key.isShow = false)
+                }
+                this.strategyIndex == 4 ? this.getstrategyAll() : this.tabAct_idTwo = ''
+                if (this.isScrollShow) {
+                    this.selectComponent('#menuItem').toggle(false);
+                    this.isScrollShow = false
+                }
+                this.isNum = 1
+            },
+            /* 页面加载 */
+            loadList(option) {
+                if (!this.$db.get('guideSole')) { //新手指引
+                    this.isGuideShow = true
+                }
 
-			},
-			/* 新布局产业选项确定按钮 */
-			replacementConfirm() {
-				const arr = []
-				this.overallArrangement.forEach(key => {
-					if (key.isShow) {
-						arr.push(key.id)
-					}
-				})
-				this.overallArrangementId = arr.join(',')
-				this.overallArrangementName = this.pitchOnName
-				this.page_no = 1;
-				this.status = 'loadmore'
-				this.getIndustryList()
-				this.selectComponent('#menuItem').toggle();
-			},
-			/* 新布局产业选项重置按钮 */
-			replacementBtn() {
-				this.OrderColumn = 'NewTime'
-				this.pitchOnId = 'NewTime'
-				this.overallArrangement.forEach(key => key.isShow = false)
-				this.overallArrangementName = '按最近排序更新'
-			},
-			/* 判断页面滚动 */
-			isscroll:Debounce(function(){
-				this.isScrollShow = true
-			}),
-			/* 搜索 */
-			goSearch() {
-				this.public({type:'show'},true,'/reportPages/reportSearch/reportSearch')
-			},
-			/* 跳转 */
-            public(type,flag,purl,price=''){
-				return new Promise((resolve,reject) => {
-				this.$store.dispatch('checkHandle',type).then(res => {
-					app.globalData.isAuth = res.IsAuth;
-					app.globalData.isBind = res.IsBind;
-					if ((!res.IsAuth) && (!res.IsBind)) { //已授权已绑定
-						if(flag){
-							uni.navigateTo({
-								url: purl+price,
-							});
-						}
-					} else if (res.IsAuth) { //未授权
-						uni.navigateTo({
-							url: '/pages/authGuide/authGuide'
-						})
-						return
-					} else if (res.IsBind && !res.IsAuth) { //已授权未绑定
-						uni.navigateTo({
-							url: '/pages/login/login'
-						})
-						return
-					}
-				})
-			})
-			},
-            /* 初始 */
-            initList(){
-                if (this.tabAct_id && (this.strategyIndex !== 4 && this.strategyIndex !== 5)) {
-                	this.OrderColumn = 'NewTime'
-                	this.pitchOnId = 'NewTime'
-                	this.overallArrangementName = '按最近更新排序'
-                	this.overallArrangementId = '' 
-                	this.page_no = 1;
-                	this.refresh = true;
-                	this.getIndustryList()
-                	this.getTradeList()
-                	this.overallArrangement.forEach(key => key.isShow = false)
-                }
-                this.strategyIndex == 4 ? this.getstrategyAll() : this.tabAct_idTwo = ''
-                if (this.isScrollShow) {
-                	this.selectComponent('#menuItem').toggle(false);
-                	this.isScrollShow = false
-                }
-                this.isNum=1
-            },
-           /* 页面加载 */
-            loadList(option){
-                if(!this.$db.get('guideSole')) { //新手指引
-                	this.isGuideShow=true
-                }
-                 
-                 this.$store.dispatch("checkHandle",{type:'load',val:option}).then(res=>{
-                	 app.globalData.isAuth = res.IsAuth;
-                	 app.globalData.isBind = res.IsBind;
-                	app.globalData.isSx=true
-                 	this.tabAct_id = option.tab || ''
-                 	if (option.tabs !== '' && option.tabs) {
-                 		this.strategyIndex = 4
-                 		this.tabAct_idTwo = option.tabs
-                 	}
-                	if(this.tabAct_id==31){
-                		this.strategyIndex = 5
-                	}
-                 	this.getClassify()
-                 })
-                this.$db.set('guideSole',1)//新手指引
+                this.$store.dispatch("checkHandle", {
+                    type: 'load',
+                    val: option
+                }).then(res => {
+                    app.globalData.isAuth = res.IsAuth;
+                    app.globalData.isBind = res.IsBind;
+                    app.globalData.isSx = true
+                    this.tabAct_id = option.tab || ''
+                    if (option.tabs !== '' && option.tabs) {
+                        this.strategyIndex = 4
+                        this.tabAct_idTwo = option.tabs
+                    }
+                    if (this.tabAct_id == 31) {
+                        this.strategyIndex = 5
+                    }
+                    this.getClassify()
+                    this.reportIsShow()
+                })
+                this.$db.set('guideSole', 1) //新手指引
             },
-		},
-		/* 触底 */
-		onReachBottom: Throttle(function() {
-               if (this.strategyIndex == 4 || this.strategyIndex == 5) {
-                this.isNum++
-                return
+            goSecretDetail(type){
+                uni.navigateTo({
+                    url:'/reportPages/secretDetails/secretDetails?type='+type
+                })
+            }
+        },
+        /* 触底 */
+        onReachBottom: Throttle(function() {
+            if (this.strategyIndex == 4 || this.strategyIndex == 5) {
+                this.isNum++
+                return
+            }
+            if (this.status === 'nomore') return;
+            this.status = 'loading';
+            this.page_no++;
+            this.getIndustryList()
+        }),
+        /* 下拉刷新 */
+        onPullDownRefresh: Throttle(function() {
+            if (this.strategyIndex == 4 || this.strategyIndex == 5) {
+                this.pageNumFather = 1
+            } else {
+                this.industryList = []
+                this.pageNumFather = null
+                this.page_no = 1;
+                this.refresh = true;
+                this.getIndustryList()
+                this.getTradeList()
+            }
+            wx.stopPullDownRefresh();
+        }),
+        onShow() {
+            if (this.tabAct_id) {
+                this.$store.dispatch("statistics", {
+                    PageType: 'Report',
+                    ChartPermissionId: Number(this.tabAct_id)
+                })
+            }
+            if (this.tabAct_id && app.globalData.isSx) {
+                this.getTradeList()
+            }
+        },
+        /**
+         * 用户点击分享
+         */
+        onShareAppMessage: function(res) {
+            return {
+                title: "报告",
+                path: '/pages/reportForm/reportForm?tab=' + this.tabAct_id + '&tabs=' + this.tabAct_idTwo,
+                success: (res) => {},
+                fail: (err) => {}
+            }
+        },
+        /**
+         *监听页面滚动
+         */
+        onPageScroll() {
+            if (this.isScrollShow) {
+                this.selectComponent('#menuItem').toggle(false);
+                this.isScrollShow = false
             }
-			if (this.status === 'nomore') return;
-			this.status = 'loading';
-			this.page_no++;
-			this.getIndustryList()
-		}),
-		/* 下拉刷新 */
-		onPullDownRefresh: Throttle(function() {
-			if (this.strategyIndex == 4 || this.strategyIndex == 5) {
-				this.pageNumFather = 1
-			} else {
-				this.industryList = []
-				this.pageNumFather = null
-				this.page_no = 1;
-				this.refresh = true;
-				this.getIndustryList()
-				this.getTradeList()
-			}
-			wx.stopPullDownRefresh();
-		}),
-		onShow() {
-			if(this.tabAct_id){
-				this.$store.dispatch("statistics",{PageType:'Report',ChartPermissionId:Number(this.tabAct_id)})
-			}
-			if (this.tabAct_id && app.globalData.isSx) {
-				this.getTradeList()
-			}
-		},
-		/**
-		 * 用户点击分享
-		 */
-		onShareAppMessage: function(res) {
-			return {
-				title: "报告",
-				path: '/pages/reportForm/reportForm?tab=' + this.tabAct_id + '&tabs=' + this.tabAct_idTwo,
-				success: (res) => {},
-				fail: (err) => {}
-			}
-		},
-		/**
-		 *监听页面滚动
-		 */
-		onPageScroll() {
-			if (this.isScrollShow) {
-				this.selectComponent('#menuItem').toggle(false);
-				this.isScrollShow = false
-			}
 
-		},
-		onHide(){
-			if(this.strategyIndex==4 || this.strategyIndex==5) return
-			this.selectComponent('#menuItem').toggle(false);
-		},
-	}
+        },
+        onHide() {
+          if(  this.showTransition) {
+                this.showTransition= false
+          }
+            if (this.strategyIndex == 4 || this.strategyIndex == 5) return
+            this.selectComponent('#menuItem').toggle(false);
+        },
+    }
 </script>
 
-<style scoped lang="scss">
+<style scoped lang="scss">
     @import './index.scss';
-</style>
+
+    .content-intimate {
+        position: fixed;
+        display: flex;
+        align-items: center;
+        bottom: 96rpx;
+        right: 41rpx;
+        height: 156rpx;
+        .content {
+            width: 432rpx;
+            height: 112rpx;
+            background-color: #FFF;
+            display: flex;
+            border-radius: 56rpx;
+            overflow: hidden;
+            .cont-border {
+                margin: 0 2rpx;
+            }
+            view {
+                flex: 1;
+                background-color: #3385FF;
+                font-size: 30rpx;
+                color: #fff;
+                padding-top: 15rpx;
+                text-align: center;
+            }
+        }
+
+        image {
+            width: 156rpx;
+            height: 100%;
+            z-index: 99;
+        }
+    }
+</style>

+ 10 - 3
reportPages/IndustryReport/IndustryReport.vue

@@ -168,9 +168,16 @@
    		app.globalData.isAuth = res.IsAuth;
    		app.globalData.isBind = res.IsBind;
    		if((!res.IsAuth) && (!res.IsBind)) { // 已授权已绑定
-   			uni.navigateTo({
-   				url:'/pages/reportDetail/reportDetail?id=' + item.ArticleId,
-   			});
+        if(item.IsHaveVideo){
+            //跳转路演精华
+            uni.navigateTo({
+                url:'/reportPages/roadEssence/roadEssence?id='+item.ArticleId
+            })
+        }else {
+            uni.navigateTo({
+            	url:'/pages/reportDetail/reportDetail?id=' + item.ArticleId,
+            });
+        }			
    		}else if(res.IsAuth) { //未授权
    			uni.navigateTo({
    				url:'/pages/authGuide/authGuide'

二進制
reportPages/image/play_icon.png


二進制
reportPages/image/suspend_icon.png


+ 46 - 0
reportPages/index.scss

@@ -0,0 +1,46 @@
+.collect-ul {
+    // margin-top: 30rpx;s
+  	padding-top: 4rpx;
+  	.collect-ltem {
+  		display: flex;
+  		padding: 30rpx 34rpx;
+  		background: #fff;
+  		margin-bottom: 4rpx;
+  		align-items: center;
+  		justify-content: space-between;
+  		.title {
+        position: relative;
+  			max-width: 625rpx;
+  			color: #4A4A4A;
+  			font-size: 34rpx;
+        padding-left: 28rpx;
+        .reg-text {
+          position: absolute;
+          top: 15rpx;
+          left:0rpx;
+          width: 14rpx;
+          height: 14rpx;
+          background-color: #FF0000;
+          border-radius: 50%;
+          z-index: 9;
+        }
+  		}
+  		.desc {
+            display: flex;
+            align-items: center;
+            width: 100%;
+  			margin-top: 17rpx;
+            padding-left: 28rpx;
+  			width: 625rpx;
+  			color: #999;
+  		}
+        .publishDate {
+            margin-right: 30rpx;
+            white-space: nowrap;
+        }
+        .text-name {
+            color: #2C83FF;
+            font-size: 26rpx;
+        }
+  	}
+  }

+ 2 - 63
reportPages/industrialReport/industrialReport.vue

@@ -138,23 +138,6 @@
             }
             
         }
-        
-        
-      
-   //      if(this.genreIs=='标的'){
-   //         .then(res=>{
-   //              console.log(res);
-   //          })
-            
-   //          return
-   //      }
-   //  	Reports.getTactics({
-   //  		PageSize: this.pageSize,
-   //  		CurrentIndex: this.page_no,
-			// CategoryId:this.categoryId
-   //  	}).then(res => {
-    		
-   //  	})
     },
    goDetail(item,index) {
    	/* 无需授权且已绑定 检验是或否有权限 */
@@ -210,53 +193,9 @@
 </script>
 
 <style scoped lang="scss">
+ @import '../index.scss';
 .industrial-container {
   background-color: #f6f6f6;
-  .collect-ul {
-    // margin-top: 30rpx;s
-  	padding-top: 4rpx;
-  	.collect-ltem {
-  		display: flex;
-  		padding: 30rpx 34rpx;
-  		background: #fff;
-  		margin-bottom: 4rpx;
-  		align-items: center;
-  		justify-content: space-between;
-  		.title {
-        position: relative;
-  			max-width: 625rpx;
-  			color: #4A4A4A;
-  			font-size: 34rpx;
-        padding-left: 28rpx;
-        .reg-text {
-          position: absolute;
-          top: 15rpx;
-          left:0rpx;
-          width: 14rpx;
-          height: 14rpx;
-          background-color: #FF0000;
-          border-radius: 50%;
-          z-index: 9;
-        }
-  		}
-  		.desc {
-            display: flex;
-            align-items: center;
-            width: 100%;
-  			margin-top: 17rpx;
-            padding-left: 28rpx;
-  			width: 625rpx;
-  			color: #999;
-  		}
-        .publishDate {
-            margin-right: 30rpx;
-            white-space: nowrap;
-        }
-        .text-name {
-            color: #2C83FF;
-            font-size: 26rpx;
-        }
-  	}
-  }
+  
 }
 </style>

+ 51 - 0
reportPages/jurisdiction.scss

@@ -0,0 +1,51 @@
+ .noauth-cont {
+    	padding-top: 150rpx;
+    	text-align: center;
+    	font-size: 28rpx;
+    	.noauth-ico {
+    		width: 365rpx;
+    		height: 229rpx;
+    		margin-bottom: 70rpx;
+    	}
+    	.tip {
+    		width: 532rpx;
+    		margin: 0 auto 100rpx;
+    		.contract {
+    			padding: 40rpx 90rpx 0;
+    			line-height: 44rpx;
+    			text {
+    				display: inline-block;
+    			}
+    		}
+    	}
+    	.btn-cont {
+    		width: 368rpx;
+    		height: 80rpx;
+    		// position: relative;
+    		background:linear-gradient(268deg, #2DDBFF 0%, #1599FF 49%, #005EFF 100%);
+    		color: #fff;
+    		font-size: 34rpx;
+    		margin: 0 auto;
+    		text-align: center;
+    		line-height: 80rpx;
+    		&.back-btn {
+    			background:linear-gradient(268deg, #2DDBFF 0%, #1599FF 49%, #005EFF 100%)!important;
+    			// border: 2rpx solid #3385FF;
+    			color:  #fff;
+    			margin-top: 30rpx;
+    		}
+    		.btn_bg {
+    			width: 100%;
+    			height: 80rpx;
+    			position: absolute;
+    			left: 0;
+    			top: 0;
+    		}
+    		.btn-txt {
+    			width: 100%;
+    			position: absolute;
+    			z-index: 1;
+    		}
+    	}
+    }
+    

+ 119 - 0
reportPages/reportSecretDetail/components/reportChoiceness.vue

@@ -0,0 +1,119 @@
+<template>
+    <view>
+       <view class="container-report forbid-copy" v-if="dataListResearch.length>0">
+          <view class="content" v-for="(item,index) in dataListResearch" :key="index">
+              <view class="content-title">
+                  <view></view>
+                  <image :src="item.IcoLink" mode=""></image>
+                  <text style="margin-right: 26rpx;">{{item.ListName}}</text>
+                  <view></view>
+              </view>
+            <view class="content-list"  v-for="(key,num) in item.List" :key="num">
+                 <view class="list-title" :class="num == 0 ? '' :'list-tophight'" v-if="key.PermissionName">
+                     <image :src="key.IcoLink" mode=""></image>
+                     <text>{{key.PermissionName}}:</text>
+                 </view>
+                 <view class="list-boby" :class="{'list-boby-border': indexs !== 0 ,'no-top':!key.PermissionName}"  v-for="(val,indexs) in key.List" :key="indexs">
+                       <mp-html :content="val.Body"/>
+                    <view class="list-detali" v-if="val.ReportLink" @click="goListDetali(val)" > 点击查看详情 </view>
+                 </view>
+            </view>
+              </view>
+          </view>
+       </view>
+    </view>
+</template>
+
+<script>
+    export default {
+        props:{
+            dataListResearch:{
+                type:Array,
+                required:true,
+                default:[]
+            }
+        },
+        data() {
+            return {
+                
+            }
+        },
+        methods: {
+            goListDetali(item){
+                if(item.IsHaveVideo){
+                    //跳转路演精华
+                    uni.navigateTo({
+                        url:'/reportPages/roadEssence/roadEssence?id='+item.ReportLink
+                    })
+                }else {
+                    uni.navigateTo({
+                        url:'/pages/reportDetail/reportDetail?id='+item.ReportLink
+                    })
+                }
+            }
+        }
+    }
+</script>
+
+<style lang="scss" scope>
+.container-report {
+    .content {
+        color: #4A4A4A;
+        .content-title {
+            display: flex;
+            font-size: 32rpx;
+            font-weight: 700;
+            align-items: center;
+            justify-content: center;
+            margin-bottom: 60rpx;
+            image {
+                width: 48rpx;
+                height: 44rpx;
+                margin: 0 20rpx 0 26rpx;
+            }
+            view {
+               flex: 1;
+                border: 2rpx dashed #333333;
+            }
+        }
+        .content-list {
+            font-size: 32rpx;
+            font-weight: 400;
+            .list-title {
+                display: flex;
+                align-items: center;
+                image {
+                    width: 48rpx;
+                    height: 44rpx;
+                }
+                text {
+                    margin-left: 10rpx;
+                }
+                
+            }
+            .list-boby {
+                margin-bottom:30rpx;
+                padding-top: 30rpx;
+            }
+            .no-top {
+                padding-top: 0rpx !important;
+            }
+            .list-tophight {
+                margin-top: 60rpx;
+            }
+            .list-boby-border {
+                border-top: 2rpx dashed #E2E2E2;
+            }
+            .list-detali {
+                font-size: 28rpx;
+                color: #3385FF;
+                margin: 20rpx 0;
+            }
+        }
+      
+    }
+  
+}
+
+</style>
+

+ 134 - 0
reportPages/reportSecretDetail/components/researchSummary.vue

@@ -0,0 +1,134 @@
+<template>
+    <!-- 精选/上周、研究汇总 -->
+    <view class="container-summary forbid-copy" v-if="dataList.length>0">
+       <view class="content" v-for="(item,index) in dataList" :key="index">
+           <view class="content-title">
+               <image :src="item.IcoLink" mode=""></image>
+               <text>{{item.PermissionName}}</text>
+           </view>
+          <view class="content-list"  v-for="(key,num) in item.List" :key="num">
+                <text class="list-subject" v-if="key.SubjectName">{{key.SubjectName}}:</text>
+                <mp-html :content="key.Body"/>
+               <view class="subject-detali" v-if="key.ReportLink">
+                  <text style="color: #3385FF;" @click="reportLinkDetali(key)">点击查看</text>
+               </view>
+               <view class="subject-detali" v-else>
+                  <text>相关调研纪要、深度报告请</text> 
+                  <text style="color: #3385FF;margin-left: 10rpx;" @click="industry(key.List)">点击查看</text>
+               </view>
+           </view>
+       </view>
+       <view class="select-box">
+       <u-popup v-model="areacodeShow" mode="bottom"  @close="cancel">
+       	<view class="box" style="color: #2C83FF;" v-for="(item,index) in list" 
+        :key="item.IndustrialManagementId" @click="industryDetitle(item)">
+        {{item.IndustryName}}</view>
+       	<view class="box box-bottom" style="color: #A9AFB8;" @click="cancel">取消</view>
+       </u-popup>
+       </view>
+    </view>
+</template>
+
+<script>
+    export default {
+        props:{
+            dataList:{
+                type:Array,
+                default:[],
+                required:true
+            }
+        },
+        data() {
+            return {
+                list:[],
+                areacodeShow:false
+            }
+        },
+        methods: {
+            reportLinkDetali(item){
+                if(item.IsHaveVideo){
+                    //跳转路演精华
+                    uni.navigateTo({
+                        url:'/reportPages/roadEssence/roadEssence?id='+item.ReportLink
+                    })
+                }else{
+                    uni.navigateTo({
+                        url:'/pages/reportDetail/reportDetail?id='+item.ReportLink
+                    })
+                }
+            },
+            industry(item){
+                if(item.length>1){
+                    this.list = item
+                    this.areacodeShow=true
+                }else if (item.length > 0 || item.length==1){
+                    uni.navigateTo({
+                        url:'/reportPages/IndustryReport/IndustryReport?id='+item[0].IndustrialManagementId
+                    })
+                }
+            },
+            industryDetitle(item){
+                uni.navigateTo({
+                    url:'/reportPages/IndustryReport/IndustryReport?id='+item.IndustrialManagementId
+                })
+                
+                 this.areacodeShow=false
+            }, 
+            cancel(){
+                this.areacodeShow=false
+            },
+        },
+        watch:{
+        },
+    }
+</script>
+
+<style lang="scss" scope>
+.container-summary {
+    .content {
+        color: #4A4A4A;
+        .content-title {
+            display: flex;
+            font-size: 32rpx;
+            font-weight: 700;
+            align-items: center;
+            justify-content: center;
+            margin-bottom: 62rpx;
+            image {
+                width: 48rpx;
+                height: 44rpx;
+                margin-right: 12rpx;
+            }
+        }
+        .content-list {
+            font-size: 32rpx;
+            font-weight: 400;
+        }
+        .list-subject { 
+            font-weight: 500;
+            margin-bottom: 20rpx;
+        }
+        .subject-detali {
+            font-size: 28rpx;
+            margin: 20rpx 0 60rpx 0;
+            display: flex;
+        }
+    }
+    .select-box {
+    	width: 100%;
+    
+    	.box {
+    		height: 95prx;
+    		line-height: 95rpx;
+    		text-align: center;
+    		font-size: 32rpx;
+    		border-bottom: 1rpx solid #EBEBEB;
+    	}
+    
+    	.box-bottom {
+    		border-bottom: none !important;
+    	}
+    }
+}
+
+</style>

+ 285 - 0
reportPages/reportSecretDetail/reportSecretDetail.vue

@@ -0,0 +1,285 @@
+<template>
+    <view class="container content-secret forbid-copy">
+        <block v-if="hasPermission==1 ||!hasPermission">
+        <view class="container-top" v-if="detali">
+            <view class="content-title">
+                {{detali.Title}}
+            </view>
+            <view class="content-time">
+                <text>{{detali.Department}}</text>
+                <text>{{detali.PublishDate}}</text>
+            </view>
+            <view class="content-statement">
+                <text>注:请务必阅读</text>
+                <text class="statement" @click="isShowStatement=true">免责声明 </text>
+            </view>
+            <view class="content-audio">
+                <view class="audio-img">
+                <image v-if="isPlay" @click="audiouspend" :src="require('../image/suspend_icon.png')"></image>
+                <image v-else  @click="audioPlay" :src="require('../image/play_icon.png')" mode=""></image>
+                </view>
+                <view class="audio-title">
+                    <text>{{detali.VideoName}}</text>
+                    <text>{{detali.VideoPlaySeconds}}</text>
+                </view>
+            </view>
+            <view v-if="detali.Abstract" class="content-abstract">
+                <text>摘要:</text>
+                <text>
+                    {{detali.Abstract}}
+                </text>
+            </view>
+            <view v-if="detali.ProductDescription&&isType==1" class="content-abstract">
+                <text>产品说明:</text>
+                <text>
+                    {{detali.ProductDescription}}
+                </text>
+            </view>
+            <view v-if="detali.UpdateDescription&&isType==1" class="content-abstract">
+                <text>变更说明:</text>
+                <text>
+                    {{detali.UpdateDescription}}
+                </text>
+            </view>
+            <view v-if="detali.FocusOn&&isType==1" class="content-focuson">
+                <text class="focuson">近期重点关注方向:</text>
+                <rich-text :nodes="detali.FocusOn"></rich-text>
+            </view>
+        </view>
+        <view class="container-text">
+            <researchSummary v-if="isType==1 ||isType==3" :dataList="dataList" />
+            <reportChoiceness v-if="isType==2" :dataListResearch="dataListResearch"/>
+        </view>
+        <statement :show="isShowStatement"/>
+        </block>
+        <view class="noauth-cont" v-else-if="hasPermission==3 || hasPermission==4">
+            <image src="https://hzstatic.hzinsights.com/cygx/czbk/noauth.png" class="noauth-ico"></image>
+            <block>
+            	<view class="tip">您暂无权限查看此文章内容,若想查看可以申请开通哦</view>
+            	<view class="btn-cont"  @click="applyAuth">
+                立即申请
+            	</view>	
+            </block>
+          <view class="btn-cont back-btn" @click="backIndex"> 返回首页	</view>
+        </view>
+    </view>
+</template>
+
+<script>
+    import statement from '@/components/statement.vue'
+    import researchSummary from './components/researchSummary.vue'
+    import reportChoiceness from './components/reportChoiceness.vue'
+    import {Reports} from '@/config/api.js'
+    let app = getApp()
+    export default {
+        data() {
+            return {
+                isShowStatement:false,
+                isPlay:false,
+                audioContext:'', //音频
+                isType:'',//类型
+                id:'',//
+                detali:'',//详情
+                dataList:[],//精选,上周 数组
+                dataListResearch:[],//本周数组
+                hasPermission:'',//权限判断
+                videoUrl:''
+                //bgAudioManager:''
+            }
+        },
+        methods: {
+            audioPlay(){
+                this.isPlay=true
+                app.globalData.bgAudioManager.title = this.detali.VideoName
+                app.globalData.bgAudioManager.src = this.videoUrl
+            },
+            audiouspend(){
+                this.isPlay=false
+                app.globalData.bgAudioManager.pause()
+            },
+          async  getDetilaiList(){
+                if(this.isType==1||this.isType==3){
+                    const res =  this.isType==1 ? await Reports.reportSelectionDetail({ArticleId:this.id})
+                                                : await Reports.minutesSummaryDetail({ ArticleId:this.id})
+                    if(res.Ret===200){
+                        this.detali = res.Data.Detail
+                        this.hasPermission=res.Data.HasPermission
+                        this.videoUrl=res.Data.Detail.VideoUrl
+                        this.dataList=res.Data.List
+                        if( app.globalData.bgAudioManager.src === this.videoUrl) {
+                            this.isPlay = true
+                        }
+                    }
+                }else {               
+                  const res =   await Reports.researchSummaryDetail({ArticleId:this.id})
+                     if(res.Ret===200){
+                         
+                         this.detali = res.Data.Detail
+                        this.hasPermission=res.Data.HasPermission
+                         this.dataListResearch=res.Data.List
+                         this.videoUrl=res.Data.Detail.VideoUrl
+                          if( app.globalData.bgAudioManager.src === this.videoUrl) {
+                              this.isPlay = true
+                          }
+                     }
+                }
+            },
+            /* 无权限申请开通权限 */
+            applyAuth() {
+            this.hasPermission === 4
+            	?  uni.navigateTo({
+            			url:"/pages/applyTrial/applyTrial"
+            		})
+            	: 	uni.showModal({
+            			title: '',
+            			content: '您已经提交过申请了,请耐心等待',
+            			showCancel:false,
+            			confirmColor:'#365595',
+            			success: function (res) {
+                             uni.navigateBack({
+                             	fail(){
+                             		uni.switchTab({
+                             			url:'/pages/index/index'
+                             		})
+                             	}
+                             })
+            			}
+            		});
+            },
+            // 返回首頁
+            backIndex() {
+            	uni.switchTab({
+            		url:'/pages/index/index'
+            	})
+            },
+        },
+        components:{
+            statement,
+            researchSummary,
+            reportChoiceness
+        },
+        onLoad(option) {
+            this.isType=option.type
+            this.id=Number(option.id) ||''
+            uni.setNavigationBarTitle({
+                title:this.isType==1 ? '报告精选' : this.isType==2 ? '本周研究汇总' : '上周纪要汇总'
+            })
+            
+                app.globalData.bgAudioManager.onEnded(res=>{
+                this.isPlay=true
+            })
+          },
+    onShow() {
+              this.$store.dispatch('checkHandle').then(res => {
+                  	app.globalData.isAuth = res.IsAuth;
+                  	app.globalData.isBind = res.IsBind;
+                  	if((!res.IsAuth) && (!res.IsBind)) { //已授权已绑定            
+                  		 this.getDetilaiList()
+                           
+                  	}else if(res.IsAuth) { //未授权
+                  		uni.navigateTo({
+                  			url:'/pages/authGuide/authGuide'
+                  		})
+                  	}else if(res.IsBind && !res.IsAuth){ //已授权未绑定
+                  		uni.navigateTo({
+                  			url:'/pages/login/login'
+                  		})
+                  	}
+                  })	
+              
+          },
+          onUnload(){
+          },
+        /**
+        * 用户点击分享
+        */
+        onShareAppMessage: function (res) {
+        	return {
+        		title: this.detali.Title,
+        		path: '/reportPages/reportSecretDetail/reportSecretDetail?type=' + this.isType + '&id='+this.id,
+        		success: (res)=> {
+        		},
+        		fail: (err)=> {
+        		}
+        	}
+        },
+    }
+</script>
+
+<style lang="scss" scoped>
+.content-secret {
+    @import '../jurisdiction.scss';
+    padding:10rpx 34rpx  34rpx;
+    .container-top {
+          font-size: 28rpx;
+        .content-title {
+            color: #4A4A4A;
+            font-size: 34rpx;
+            font-weight: bold;
+        }
+        .content-time {
+            margin:24rpx 0  34rpx 0;
+            display: flex;
+            justify-content: space-between;
+            color: #333333;
+        }
+        .content-statement {
+            display: flex;
+            color: #707070;      
+            .statement {
+                margin-left: 10rpx;
+                color: #3385FF;
+            }
+        }
+        .content-audio {
+            margin: 60rpx 0;
+            width: 682rpx;
+            align-items: center;
+            background: #FFFFFF;
+            box-shadow: 0rpx 0rpx 12rpx rgba(33, 74, 135, 0.16);
+            opacity: 1;
+            border-radius: 16rpx;
+            display: flex;
+            padding: 24rpx 21rpx 18rpx;
+           .audio-img{
+               width: 154rpx;
+               height: 154rpx;
+               margin-right: 20rpx;
+               image {
+                   width: 154rpx;
+                    height: 154rpx;
+                }
+           }   
+           .audio-title {
+                font-size: 28rpx;
+                color:#333;
+                :first-child{
+                    width: 450rpx;
+                    overflow: hidden;
+                    text-overflow:ellipsis;
+                    white-space: nowrap;
+                    margin-bottom:30rpx ;
+                    font-size: 32rpx
+                }
+            }
+        }
+        .content-abstract {
+            margin-bottom: 30rpx;
+            font-size: 32rpx;
+            color: #4A4A4A;
+            :first-child{
+                float:left;
+                font-weight: 700;
+            }
+        }
+        .content-focuson {
+            font-size: 32rpx !important;
+            margin-bottom: 30rpx;
+            color: #4A4A4A;
+            .focuson {
+                 font-weight: 700;
+            }
+        }
+    }
+}
+</style>

+ 273 - 0
reportPages/roadEssence/roadEssence.vue

@@ -0,0 +1,273 @@
+<template>
+    <view class="container content-road forbid-copy">
+        <block v-if='haveAuth===1'>
+        <view class="container-top">
+            <view class="content-title">
+                {{detali.Title}}
+            </view>
+            <view class="content-time">
+                <text>{{detali.Department}}</text>
+                <text>{{detali.PublishDate}}</text>
+            </view>
+            <view class="content-statement">
+                <text>注:请务必阅读</text>
+                <text class="statement" @click="isShowStatement=true">免责声明 </text>
+            </view>
+            <view class="content-audio">
+                <view class="audio-img">
+                    <image v-if="isPlay" @click="audiouspend" :src="require('../image/suspend_icon.png')"></image>
+                    <image v-else @click="audioPlay" :src="require('../image/play_icon.png')" mode=""></image>
+                </view>
+                <view class="audio-title">
+                    <text>{{detali.VideoName}}</text>
+                    <text>{{detali.VideoPlaySeconds}}</text>
+                </view>
+            </view>
+            <view  class="content-abstract">
+                <text>摘要:</text>
+                <text>
+                    {{detali.Abstract}}
+                </text>
+            </view>
+           <view class="content-boby">
+                <!-- <rich-text :nodes="detali.Body"></rich-text> -->
+                  <mp-html :content="detali.Body"/>
+           </view>
+        </view>
+        <view class="content-link" v-if="detali.ReportLink" @click="goDetali">
+            查看深度报告
+        </view>
+        <statement :show="isShowStatement"/>
+        </block>
+        <view class="noauth-cont" v-else-if="haveAuth===3||haveAuth===4">
+        	<image src="https://hzstatic.hzinsights.com/cygx/czbk/noauth.png" class="noauth-ico"></image>
+        	<block>
+        		<view class="tip">您暂无权限查看内容,若想查看可以申请开通哦</view>
+        		<view class="btn-cont"  @click="applyAuth">
+                立即申请
+        		</view>	
+        	</block>    	
+        	<view class="btn-cont back-btn" @click="backIndex">返回首页</view>
+        </view>
+    </view>
+   
+</template>
+
+<script>
+    import { Reports,User} from '@/config/api.js'
+    import statement from '@/components/statement.vue'
+    let app = getApp()
+    export default {
+        data() {
+            return {
+                 id: '',//
+                 detali:'',//详情
+                 audioContext:'', //音频
+                 isPlay:false, //mp3 播放的图片
+                 isShowStatement:false ,//免责声明隐现
+                 haveAuth:'',//权限判断
+                 videoUrl:''
+            }
+        },
+        methods: {
+            async getDetail() {
+                const res = await Reports.roadshowEssence({
+                    ArticleId: this.id
+                })
+                if(res.Ret===200){
+                    this.detali=res.Data.Detail
+                    this.haveAuth=res.Data.HasPermission
+                    this.videoUrl= res.Data.Detail.VideoUrl
+                    if( app.globalData.bgAudioManager.src === this.videoUrl) {
+                        this.isPlay = true
+                    }
+                }
+            },
+            goDetali(){
+                uni.navigateTo({
+                    url:'/pages/reportDetail/reportDetail?id='+this.detali.ReportLink
+                })
+            },
+            /* 无权限申请开通权限 */
+            applyAuth() {
+                this.haveAuth === 4
+            	?  uni.navigateTo({
+            			url:"/pages/applyTrial/applyTrial"
+            		})
+            	: 	uni.showModal({
+            			title: '',
+            			content: '您已经提交过申请了,请耐心等待',
+            			showCancel:false,
+            			confirmColor:'#365595',
+            			success: function (res) {
+                         uni.navigateBack({
+                         	fail(){
+                         		uni.switchTab({
+                         			url:'/pages/index/index'
+                         		})
+                         	}
+                         })
+            			}
+            		});
+            },
+            // 返回首頁
+            backIndex() {
+            	uni.switchTab({
+            		url:'/pages/index/index'
+            	})
+            },
+            audioPlay(){
+                this.isPlay=true
+                app.globalData.bgAudioManager.title = this.detali.VideoName
+                app.globalData.bgAudioManager.src = this.videoUrl
+            },
+            audiouspend(){
+                this.isPlay=false
+                 app.globalData.bgAudioManager.pause()
+            },
+            
+        },
+        components:{
+            statement
+        },
+        onLoad(option) {
+            this.id = Number(option.id) ||''
+            app.globalData.bgAudioManager.onEnded(res=>{
+                this.isPlay=true
+            }
+            },
+        onShow() {
+            this.$store.dispatch('checkHandle').then(res => {
+                	app.globalData.isAuth = res.IsAuth;
+                	app.globalData.isBind = res.IsBind;
+                	if((!res.IsAuth) && (!res.IsBind)) { //已授权已绑定            
+                		
+                		this.getDetail()
+                        this.audioContext = uni.createInnerAudioContext()
+                        //音频播放错误事件
+                         this.audioContext.onError((res) => {
+                          console.log(res.errMsg);
+                          console.log(res.errCode);
+                        });
+                         //音频自然播放结束事件
+                        this.audioContext.onEnded(res=>{
+                            this.isPlay=true
+                        })
+                	}else if(res.IsAuth) { //未授权
+                		uni.navigateTo({
+                			url:'/pages/authGuide/authGuide'
+                		})
+                	}else if(res.IsBind && !res.IsAuth){ //已授权未绑定
+                		uni.navigateTo({
+                			url:'/pages/login/login'
+                		})
+                	}
+                })		        
+            
+        },
+        /**
+        * 用户点击分享
+        */
+        onShareAppMessage: function (res) {
+        	return {
+        		title: this.detali.Title,
+        		url:'reportPages/roadEssence/roadEssence?id='+this.id,
+        		success: (res)=> {
+        		},
+        		fail: (err)=> {
+        		}
+        	}
+        },
+    }
+</script>
+
+<style lang="scss" scoped> 
+.content-road {
+    padding:10rpx 34rpx  34rpx;
+    .container-top {
+          font-size: 28rpx;
+        .content-title {
+            color: #4A4A4A;
+            font-size: 34rpx;
+            font-weight: bold;
+        }
+        .content-time {
+            margin:24rpx 0  34rpx 0;
+            display: flex;
+            justify-content: space-between;
+            color: #333333;
+        }
+        .content-statement {
+            display: flex;
+            color: #707070;      
+            .statement {
+                margin-left: 10rpx;
+                color: #3385FF;
+            }
+        }
+        .content-audio {
+            margin: 60rpx 0;
+            width: 682rpx;
+            align-items: center;
+            background: #FFFFFF;
+            box-shadow: 0rpx 0rpx 12rpx rgba(33, 74, 135, 0.16);
+            opacity: 1;
+            border-radius: 16rpx;
+            display: flex;
+            padding: 24rpx 21rpx 18rpx;
+           .audio-img{
+               width: 154rpx;
+               height: 154rpx;
+               margin-right: 20rpx;
+               image {
+                   width: 154rpx;
+                    height: 154rpx;
+                }
+           }   
+           .audio-title {
+                font-size: 28rpx;
+                color:#333;
+                :first-child{
+                    width: 450rpx;
+                    overflow: hidden;
+                    text-overflow:ellipsis;
+                    white-space: nowrap;
+                    margin-bottom:30rpx ;
+                    font-size: 32rpx
+                }
+            }
+        }
+        .content-abstract {
+            margin-bottom: 30rpx;
+            font-size: 32rpx;
+            color: #4A4A4A;
+            :first-child{
+                float:left;
+                font-weight: 700;
+            }
+        }
+        .content-boby {
+            font-size: 32rpx;
+            image,img {
+                width: 100%;
+            }
+            
+        }
+    }
+    .content-link {
+        width: 368rpx;
+        height: 80rpx;
+        border: 2rpx solid #2C83FF;
+        opacity: 1;
+        border-radius: 4rpx;
+        line-height:76rpx;
+        text-align: center;
+        color: #2C83FF;
+        font-size: 32rpx;
+        box-sizing: border-box;
+        margin: 100rpx auto;
+    }
+@import '../jurisdiction.scss';
+}
+
+</style>

+ 148 - 0
reportPages/secretDetails/secretDetails.vue

@@ -0,0 +1,148 @@
+<template>
+    <view class="container container-secret">
+        <view class="collect-ul" v-if="haveData">
+            <view class="collect-ltem" v-for="(item,index) in collectList" :key="index" @click="goDetail(item,index)">
+                <view class="item-left">
+                    <text class="title text_twoLine">{{item.Title}}
+                        <text class="reg-text" v-if="item.IsRed"></text>
+                    </text>
+                    <view class="abstract">{{item.Abstract}}</view>
+                    <view class="desc">
+                        <text class="publishDate">{{item.PublishDate}}</text>
+                    </view>
+
+                </view>
+                <u-icon name="arrow-right" color="#BDBDBD" size="34"></u-icon>
+            </view>
+            <u-loadmore :status="status" icon-type="flower" :load-text="loadText" margin-top="20" v-if="totalPage>1" />
+        </view>
+        <view class="nodata" v-else>
+            <image src="@/static/img/nodata.png" mode="" class="nodata_ico"></image>
+            <text>暂时没有报告的内容</text>
+        </view>
+    </view>
+</template>
+
+<script>
+    import {  Reports} from '@/config/api.js'
+    import {   Throttle} from '@/config/util.js'
+    let app = getApp()
+    export default {
+        data() {
+            return {
+                isType: '',
+                refresh: false, //正在下拉
+                page_no: 1,
+                pageSize: 10,
+                collectList: [],
+                haveData: true,
+                totalPage:'',
+                status: 'loadmore',
+                loadText: {
+                    loadmore: '上拉加载更多',
+                    loading: '加载中',
+                    nomore: '已经到底了'
+                },
+            }
+        },
+        methods: {
+            async getList() {
+                const res = await Reports.reportListByType({
+                    PageSize: this.pageSize,
+                    CurrentIndex: this.page_no,
+                    ReportType: this.isType
+                })
+                if (res.Ret == 200) {
+                    this.status = this.page_no < res.Data.Paging.Pages ? 'loadmore' : 'nomore';
+                    this.totalPage = res.Data.Paging.Pages; //总页数
+                    if (this.page_no === 1) {
+                        this.collectList = res.Data.List || [];
+                        this.haveData = this.collectList.length ? true : false
+                        if (this.refresh) {
+                            uni.stopPullDownRefresh();
+                            this.refresh = false;
+                        }
+                    } else {
+                        this.collectList = this.collectList.concat(res.Data.List)
+                    }
+                }
+                console.log(res);
+            },
+            goDetail(item,index){
+                /* 无需授权且已绑定 检验是或否有权限 */
+                this.collectList[index].IsRed=false
+                this.$store.dispatch('checkHandle').then(res => {
+                	app.globalData.isAuth = res.IsAuth;
+                	app.globalData.isBind = res.IsBind;
+                	if((!res.IsAuth) && (!res.IsBind)) { // 已授权已绑定
+                		uni.navigateTo({
+                			url:'/reportPages/reportSecretDetail/reportSecretDetail?type=' + this.isType + '&id='+item.ArticleId
+                		});
+                	}else if(res.IsAuth) { //未授权
+                		uni.navigateTo({
+                			url:'/pages/authGuide/authGuide'
+                		})
+                	}else if(res.IsBind && !res.IsAuth){ //已授权未绑定
+                		uni.navigateTo({
+                			url:'/pages/login/login'
+                		})
+                	}
+                })
+                
+            }
+        },
+        onLoad(option) {
+            this.$store.dispatch("checkHandle", {
+                type: 'load',
+                val: option
+            }).then(res => {
+                this.isType = option.type
+                this.isType == 1 ? uni.hideShareMenu() : ''
+                uni.setNavigationBarTitle({
+                    title:this.isType==1 ? '报告精选' : this.isType==2 ? '本周研究汇总' : '上周纪要汇总'
+                })
+                
+                this.getList()
+            })
+
+        },
+        /* 触底 */
+        onReachBottom: Throttle(function() {
+            if (this.status === 'nomore') return;
+            this.status = 'loading';
+            this.page_no++;
+            this.getList()
+        }),
+        /* 下拉刷新 */
+        onPullDownRefresh: Throttle(function() {
+            this.page_no = 1;
+            this.refresh = true;
+            this.getList()
+        }),
+         onShareAppMessage(res){
+             return {
+                title:  this.isType==2 ? '本周研究汇总' : '上周纪要汇总',
+                path: '/reportPages/secretDetails/secretDetails?type='+this.isType
+            }
+         }
+
+    }
+</script>
+
+<style lang="scss" scoped>
+    @import '../index.scss';
+    .container-secret {
+         background-color: #f6f6f6;
+         .title {
+              color: #333333 !important;
+              font-size: 30rpx !important;
+              font-weight: 400 !important;
+         }
+         .abstract {
+             margin:20rpx 0 0 30rpx;
+             color: #666666;
+             font-size: 28rpx;
+            font-weight: 400 !important;
+         }
+    }
+</style>

二進制
static/img/act_search.png


二進制
static/img/advice_ico.png


二進制
static/img/auth_bg.png


二進制
static/img/card_default.png


二進制
static/img/guide-2.png


二進制
static/img/guide-3.png


二進制
static/img/home_share.png


二進制
static/img/noauth.png


二進制
static/img/success_ico.png


+ 160 - 0
uni_modules/mp-html/README.md

@@ -0,0 +1,160 @@
+## 功能介绍
+- 全端支持(含 `v3、NVUE`)
+- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
+- 支持丰富的事件效果(自动预览图片、链接处理等)
+- 支持设置占位图(加载中、出错时、预览时)
+- 支持锚点跳转、长按复制等丰富功能
+- 支持大部分 *html* 实体
+- 丰富的插件(关键词搜索、内容 **编辑** 等)
+- 效率高、容错性强且轻量化
+
+查看 [功能介绍](https://jin-yufeng.gitee.io/mp-html/#/overview/feature) 了解更多
+
+## 使用方法
+- 源码方式  
+  1. 点击上方的使用 `HBuilder X` 导入插件或将下载的插件包拷贝到项目根目录下  
+     由于插件市场的 **非 uni_modules 版本** 无法更新,若需使用请从 [github](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 或 [gitee](https://gitee.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 获取最新版本
+  2. 在需要使用页面的 `(n)vue` 文件中添加  
+     ```html
+     <mp-html :content="html" />
+     ```
+     ```javascript
+     import mpHtml from '@/components/mp-html/mp-html'
+     export default {
+       // HBuilderX 2.5.5+ 可以通过 easycom 自动引入
+       components: {
+         mpHtml
+       },
+       data() {
+         return {
+           html: '<div>Hello World!</div>'
+         }
+       }
+     }
+     ```
+
+- npm 方式  
+  1. 在项目根目录下执行  
+     ```bash
+     npm install mp-html
+     ```
+  2. 在需要使用页面的 `(n)vue` 文件中添加  
+     ```html
+     <mp-html :content="html" />
+     ```
+     ```javascript
+     import mpHtml from 'mp-html/dist/uni-app/components/mp-html/mp-html'
+     export default {
+       // 不可省略
+       components: {
+         mpHtml
+       },
+       data() {
+         return {
+           html: '<div>Hello World!</div>'
+         }
+       }
+     }
+     ```
+  
+  使用 *cli* 方式运行的项目,通过 *npm* 方式引入时,需要在 *vue.config.js* 中配置 *transpileDependencies*,详情可见 [#330](https://github.com/jin-yufeng/mp-html/issues/330#issuecomment-913617687)  
+  如果在 **nvue** 中使用还要将 `dist/uni-app/static` 目录下的内容拷贝到项目的 `static` 目录下,否则无法运行  
+
+查看 [快速开始](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart) 了解更多
+
+## 组件属性
+
+| 属性 | 类型 | 默认值 | 说明 |
+|:---:|:---:|:---:|---|
+| container-style | String |  | 容器的样式([2.1.0+](https://jin-yufeng.gitee.io/mp-html/#/changelog/changelog#v210)) |
+| content | String |  | 用于渲染的 html 字符串 |
+| copy-link | Boolean | true | 是否允许外部链接被点击时自动复制 |
+| domain | String |  | 主域名(用于链接拼接) |
+| error-img | String |  | 图片出错时的占位图链接 |
+| lazy-load | Boolean | false | 是否开启图片懒加载 |
+| loading-img | String |  | 图片加载过程中的占位图链接 |
+| pause-video | Boolean | true | 是否在播放一个视频时自动暂停其他视频 |
+| preview-img | Boolean | true | 是否允许图片被点击时自动预览 |
+| scroll-table | Boolean | false | 是否给每个表格添加一个滚动层使其能单独横向滚动 |
+| selectable | Boolean | false | 是否开启文本长按复制 |
+| set-title | Boolean | true | 是否将 title 标签的内容设置到页面标题 |
+| show-img-menu | Boolean | true | 是否允许图片被长按时显示菜单 |
+| tag-style | Object |  | 设置标签的默认样式 |
+| use-anchor | Boolean | false | 是否使用锚点链接 |
+
+查看 [属性](https://jin-yufeng.gitee.io/mp-html/#/basic/prop) 了解更多
+
+## 组件事件
+
+| 名称 | 触发时机 |
+|:---:|---|
+| load | dom 树加载完毕时 |
+| ready | 图片加载完毕时 |
+| error | 发生渲染错误时 |
+| imgtap | 图片被点击时 |
+| linktap | 链接被点击时 |
+
+查看 [事件](https://jin-yufeng.gitee.io/mp-html/#/basic/event) 了解更多
+
+## api
+组件实例上提供了一些 `api` 方法可供调用
+
+| 名称 | 作用 |
+|:---:|---|
+| in | 将锚点跳转的范围限定在一个 scroll-view 内 |
+| navigateTo | 锚点跳转 |
+| getText | 获取文本内容 |
+| getRect | 获取富文本内容的位置和大小 |
+| setContent | 设置富文本内容 |
+| imgList | 获取所有图片的数组 |
+
+查看 [api](https://jin-yufeng.gitee.io/mp-html/#/advanced/api) 了解更多
+
+## 插件扩展  
+除基本功能外,本组件还提供了丰富的扩展,可按照需要选用
+
+| 名称 | 作用 |
+|:---:|---|
+| audio | 音乐播放器 |
+| editable | 富文本编辑([示例项目](https://6874-html-foe72-1259071903.tcb.qcloud.la/editable.zip?sign=cc0017be203fb3dbca62d33a0c15792e&t=1608447445)) |
+| emoji | 解析 emoji |
+| highlight | 代码块高亮显示 |
+| markdown | 渲染 markdown |
+| search | 关键词搜索 |
+| style | 匹配 style 标签中的样式 |
+| txv-video | 使用腾讯视频 |
+| img-cache | 图片缓存 by [@PentaTea](https://github.com/PentaTea) |
+
+从插件市场导入的包中 **不含有** 扩展插件,需要使用插件参考以下方法:  
+1. 获取完整组件包  
+   ```bash
+   npm install mp-html
+   ```
+2. 编辑 `tools/config.js` 中的 `plugins` 项,选择需要的插件  
+3. 生成新的组件包  
+   在 `node_modules/mp-html` 目录下执行  
+   ```bash
+   npm install
+   npm run build:uni-app
+   ```
+4. 拷贝 `dist/uni-app` 中的内容到项目根目录  
+
+查看 [插件](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin) 了解更多
+
+## 示例体验
+![富文本插件](https://gitee.com/jin-yufeng/mp-html/raw/master/docs/assets/case/富文本插件.jpg)
+
+## 关于 nvue
+`nvue` 使用原生渲染,不支持部分 `css` 样式,为实现和 `html` 相同的效果,组件内部通过 `web-view` 进行渲染,性能上差于原生,根据 `weex` 官方建议,`web` 标签仅应用在非常规的降级场景。因此,如果通过原生的方式(如 `richtext`)能够满足需要,则不建议使用本组件,如果有较多的富文本内容,则可以直接使用 `vue` 页面  
+由于渲染方式与其他端不同,有以下限制:  
+1. 不支持 `lazy-load` 属性
+2. 视频不支持全屏播放
+
+纯 `nvue` 模式下,[此问题](https://ask.dcloud.net.cn/question/119678) 修复前,不支持通过 `uni_modules` 引入,需要本地引入(将 [dist/uni-app](https://github.com/jin-yufeng/mp-html/tree/master/dist/uni-app) 中的内容拷贝到项目根目录下)  
+
+## 问题反馈
+遇到问题时,请先查阅 [常见问题](https://jin-yufeng.gitee.io/mp-html/#/question/faq) 和 [issue](https://github.com/jin-yufeng/mp-html/issues) 中是否已有相同的问题  
+可通过 [issue](https://github.com/jin-yufeng/mp-html/issues/new/choose) 、插件问答或发送邮件到 [mp_html@126.com](mailto:mp_html@126.com) 提问,不建议在评论区提问(不方便回复)  
+提问请严格按照 [issue 模板](https://github.com/jin-yufeng/mp-html/issues/new/choose) ,描述清楚使用环境、`html` 内容或可复现的 `demo` 项目以及复现方式,对于 **描述不清**、**无法复现** 或重复的问题将不予回复  
+
+查看 [问题反馈](https://jin-yufeng.gitee.io/mp-html/#/question/feedback) 了解更多

+ 62 - 0
uni_modules/mp-html/changelog.md

@@ -0,0 +1,62 @@
+## v2.2.0(2021-10-12)
+1. `A` 增加 `customElements` 配置项,便于添加自定义功能性标签 [详细](https://github.com/jin-yufeng/mp-html/issues/350)
+2. `A` `editable` 插件增加切换音视频自动播放状态的功能 [详细](https://github.com/jin-yufeng/mp-html/pull/341) by [@leeseett](https://github.com/leeseett)
+3. `A` `editable` 插件删除媒体标签时触发 `remove` 事件,便于删除已上传的文件
+4. `U` `editable` 插件 `insertImg` 方法支持同时插入多张图片 [详细](https://github.com/jin-yufeng/mp-html/issues/342)
+5. `U` `editable` 插入图片和音视频时支持拼接 `domian` 主域名
+6. `F` 修复了内部链接参数中包含 `://` 时被认为是外部链接的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/356)
+7. `F` 修复了部分 `svg` 标签名或属性名大小写不正确时不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/351)
+8. `F` 修复了 `nvue` 页面运行到非 `app` 平台时可能样式错误的问题
+## v2.1.5(2021-08-13)
+1. `A` 增加支持标签的 `dir` 属性
+2. `F` 修复了 `ruby` 标签文字与拼音没有居中对齐的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/325)
+3. `F` 修复了音视频标签内有 `a` 标签时可能无法播放的问题
+4. `F` 修复了 `externStyle` 中的 `class` 名包含下划线或数字时可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+5. `F` 修复了 `h5` 端引入 `externStyle` 可能不生效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/326)
+## v2.1.4(2021-07-14)
+1. `F` 修复了 `rt` 标签无法设置样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/318)
+2. `F` 修复了表格中有单元格同时合并行和列时可能显示不正确的问题
+3. `F` 修复了 `app` 端无法关闭图片长按菜单的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/322)
+4. `F` 修复了 `editable` 插件只能添加图片链接不能修改的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/312) by [@leeseett](https://github.com/leeseett)
+## v2.1.3(2021-06-12)
+1. `A` `editable` 插件增加 `insertTable` 方法
+2. `U` `editable` 插件支持编辑表格中的空白单元格 [详细](https://github.com/jin-yufeng/mp-html/issues/310)
+3. `F` 修复了 `externStyle` 中使用伪类可能失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/298)
+4. `F` 修复了多个组件同时使用时 `tag-style` 属性时可能互相影响的问题 [详细](https://github.com/jin-yufeng/mp-html/pull/305) by [@woodguoyu](https://github.com/woodguoyu)
+5. `F` 修复了包含 `linearGradient` 的 `svg` 可能无法显示的问题
+6. `F` 修复了编译到头条小程序时可能报错的问题
+7. `F` 修复了 `nvue` 端不触发 `click` 事件的问题
+8. `F` 修复了 `editable` 插件尾部插入时无法撤销的问题
+9. `F` 修复了 `editable` 插件的 `insertHtml` 方法只能在末尾插入的问题
+10. `F` 修复了 `editable` 插件插入音频不显示的问题
+## v2.1.2(2021-04-24)
+1. `A` 增加了 [img-cache](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#img-cache) 插件,可以在 `app` 端缓存图片 [详细](https://github.com/jin-yufeng/mp-html/issues/292) by [@PentaTea](https://github.com/PentaTea)
+2. `U` 支持通过 `container-style` 属性设置 `white-space` 来保留连续空格和换行符 [详细](https://jin-yufeng.gitee.io/mp-html/#/question/faq#space)
+3. `U` 代码风格符合 [standard](https://standardjs.com) 标准
+4. `U` `editable` 插件编辑状态下支持预览视频 [详细](https://github.com/jin-yufeng/mp-html/issues/286)
+5. `F` 修复了 `svg` 标签内嵌 `svg` 时无法显示的问题
+6. `F` 修复了编译到支付宝和头条小程序时部分区域不可复制的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/291)
+## v2.1.1(2021-04-09)
+1. 修复了对 `p` 标签设置 `tag-style` 可能不生效的问题
+2. 修复了 `svg` 标签中的文本无法显示的问题
+3. 修复了使用 `editable` 插件编辑表格时可能报错的问题
+4. 修复了使用 `highlight` 插件运行到头条小程序时可能没有样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/280)
+5. 修复了使用 `editable` 插件 `editable` 属性为 `false` 时会报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/284)
+6. 修复了 `style` 插件连续子选择器失效的问题
+7. 修复了 `editable` 插件无法修改图片和字体大小的问题
+## v2.1.0.2(2021-03-21)
+修复了 `nvue` 端使用可能报错的问题
+## v2.1.0(2021-03-20)
+1. `A` 增加了 [container-style](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#container-style) 属性 [详细](https://gitee.com/jin-yufeng/mp-html/pulls/1)
+2. `A` 增加支持 `strike` 标签
+3. `A` `editable` 插件增加 `placeholder` 属性 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+4. `A` `editable` 插件增加 `insertHtml` 方法 [详细](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#editable)
+5. `U` 外部样式支持标签名选择器 [详细](https://jin-yufeng.gitee.io/mp-html/#/overview/quickstart#setting)
+6. `F` 修复了 `nvue` 端部分情况下可能不显示的问题
+## v2.0.5(2021-03-12)
+1. `U` [linktap](https://jin-yufeng.gitee.io/mp-html/#/basic/event#linktap) 事件增加返回内部文本内容 `innerText` [详细](https://github.com/jin-yufeng/mp-html/issues/271)
+2. `U` [selectable](https://jin-yufeng.gitee.io/mp-html/#/basic/prop#selectable) 属性设置为 `force` 时能够在微信 `iOS` 端生效(文本块会变成 `inline-block`) [详细](https://github.com/jin-yufeng/mp-html/issues/267)
+3. `F` 修复了部分情况下竖向无法滚动的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/182)
+4. `F` 修复了多次修改富文本数据时部分内容可能不显示的问题
+5. `F` 修复了 [腾讯视频](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#txv-video) 插件可能无法播放的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/265)
+6. `F` 修复了 [highlight](https://jin-yufeng.gitee.io/mp-html/#/advanced/plugin#highlight) 插件没有设置高亮语言时没有应用默认样式的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/276) by [@fuzui](https://github.com/fuzui)

+ 432 - 0
uni_modules/mp-html/components/mp-html/mp-html.vue

@@ -0,0 +1,432 @@
+<template>
+  <view id="_root" :class="(selectable?'_select ':'')+'_root'" :style="containerStyle">
+    <slot v-if="!nodes[0]" />
+    <!-- #ifndef APP-PLUS-NVUE -->
+    <node v-else :childs="nodes" :opts="[lazyLoad,loadingImg,errorImg,showImgMenu]" name="span" />
+    <!-- #endif -->
+    <!-- #ifdef APP-PLUS-NVUE -->
+    <web-view ref="web" src="/uni_modules/mp-html/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'" @onPostMessage="_onMessage" />
+    <!-- #endif -->
+  </view>
+</template>
+
+<script>
+/**
+ * mp-html v2.2.0
+ * @description 富文本组件
+ * @tutorial https://github.com/jin-yufeng/mp-html
+ * @property {String} container-style 容器的样式
+ * @property {String} content 用于渲染的 html 字符串
+ * @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
+ * @property {String} domain 主域名,用于拼接链接
+ * @property {String} error-img 图片出错时的占位图链接
+ * @property {Boolean} lazy-load 是否开启图片懒加载
+ * @property {string} loading-img 图片加载过程中的占位图链接
+ * @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
+ * @property {Boolean} preview-img 是否允许图片被点击时自动预览
+ * @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
+ * @property {Boolean | String} selectable 是否开启长按复制
+ * @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
+ * @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
+ * @property {Object} tag-style 标签的默认样式
+ * @property {Boolean | Number} use-anchor 是否使用锚点链接
+ * @event {Function} load dom 结构加载完毕时触发
+ * @event {Function} ready 所有图片加载完毕时触发
+ * @event {Function} imgTap 图片被点击时触发
+ * @event {Function} linkTap 链接被点击时触发
+ * @event {Function} error 媒体加载出错时触发
+ */
+// #ifndef APP-PLUS-NVUE
+import node from './node/node'
+// #endif
+const plugins=[]
+const Parser = require('./parser')
+// #ifdef APP-PLUS-NVUE
+const dom = weex.requireModule('dom')
+// #endif
+export default {
+  name: 'mp-html',
+  data () {
+    return {
+      nodes: [],
+      // #ifdef APP-PLUS-NVUE
+      height: 3
+      // #endif
+    }
+  },
+  props: {
+    containerStyle: {
+      type: String,
+      default: ''
+    },
+    content: String,
+    copyLink: {
+      type: [Boolean, String],
+      default: true
+    },
+    domain: String,
+    errorImg: {
+      type: String,
+      default: ''
+    },
+    lazyLoad: {
+      type: [Boolean, String],
+      default: false
+    },
+    loadingImg: {
+      type: String,
+      default: ''
+    },
+    pauseVideo: {
+      type: [Boolean, String],
+      default: true
+    },
+    previewImg: {
+      type: [Boolean, String],
+      default: true
+    },
+    scrollTable: [Boolean, String],
+    selectable: [Boolean, String],
+    setTitle: {
+      type: [Boolean, String],
+      default: true
+    },
+    showImgMenu: {
+      type: [Boolean, String],
+      default: true
+    },
+    tagStyle: Object,
+    useAnchor: [Boolean, Number]
+  },
+  // #ifndef APP-PLUS-NVUE
+  components: {
+    node
+  },
+  // #endif
+  watch: {
+    content (content) {
+      this.setContent(content)
+    }
+  },
+  created () {
+    this.plugins = []
+    for (let i = plugins.length; i--;) {
+      this.plugins.push(new plugins[i](this))
+    }
+  },
+  mounted () {
+    if (this.content && !this.nodes.length) {
+      this.setContent(this.content)
+    }
+  },
+  beforeDestroy () {
+    this._hook('onDetached')
+    clearInterval(this._timer)
+  },
+  methods: {
+    /**
+     * @description 将锚点跳转的范围限定在一个 scroll-view 内
+     * @param {Object} page scroll-view 所在页面的示例
+     * @param {String} selector scroll-view 的选择器
+     * @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
+     */
+    in (page, selector, scrollTop) {
+      // #ifndef APP-PLUS-NVUE
+      if (page && selector && scrollTop) {
+        this._in = {
+          page,
+          selector,
+          scrollTop
+        }
+      }
+      // #endif
+    },
+
+    /**
+     * @description 锚点跳转
+     * @param {String} id 要跳转的锚点 id
+     * @param {Number} offset 跳转位置的偏移量
+     * @returns {Promise}
+     */
+    navigateTo (id, offset) {
+      return new Promise((resolve, reject) => {
+        if (!this.useAnchor) {
+          reject(Error('Anchor is disabled'))
+          return
+        }
+        offset = offset || parseInt(this.useAnchor) || 0
+        // #ifdef APP-PLUS-NVUE
+        if (!id) {
+          dom.scrollToElement(this.$refs.web, {
+            offset
+          })
+          resolve()
+        } else {
+          this._navigateTo = {
+            resolve,
+            reject,
+            offset
+          }
+          this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
+        }
+        // #endif
+        // #ifndef APP-PLUS-NVUE
+        let deep = ' '
+        // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
+        deep = '>>>'
+        // #endif
+        const selector = uni.createSelectorQuery()
+          // #ifndef MP-ALIPAY
+          .in(this._in ? this._in.page : this)
+          // #endif
+          .select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
+        if (this._in) {
+          selector.select(this._in.selector).scrollOffset()
+            .select(this._in.selector).boundingClientRect()
+        } else {
+          // 获取 scroll-view 的位置和滚动距离
+          selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
+        }
+        selector.exec(res => {
+          if (!res[0]) {
+            reject(Error('Label not found'))
+            return
+          }
+          const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
+          if (this._in) {
+            // scroll-view 跳转
+            this._in.page[this._in.scrollTop] = scrollTop
+          } else {
+            // 页面跳转
+            uni.pageScrollTo({
+              scrollTop,
+              duration: 300
+            })
+          }
+          resolve()
+        })
+        // #endif
+      })
+    },
+
+    /**
+     * @description 获取文本内容
+     * @return {String}
+     */
+    getText (nodes) {
+      let text = '';
+      (function traversal (nodes) {
+        for (let i = 0; i < nodes.length; i++) {
+          const node = nodes[i]
+          if (node.type === 'text') {
+            text += node.text.replace(/&amp;/g, '&')
+          } else if (node.name === 'br') {
+            text += '\n'
+          } else {
+            // 块级标签前后加换行
+            const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
+            if (isBlock && text && text[text.length - 1] !== '\n') {
+              text += '\n'
+            }
+            // 递归获取子节点的文本
+            if (node.children) {
+              traversal(node.children)
+            }
+            if (isBlock && text[text.length - 1] !== '\n') {
+              text += '\n'
+            } else if (node.name === 'td' || node.name === 'th') {
+              text += '\t'
+            }
+          }
+        }
+      })(nodes || this.nodes)
+      return text
+    },
+
+    /**
+     * @description 获取内容大小和位置
+     * @return {Promise}
+     */
+    getRect () {
+      return new Promise((resolve, reject) => {
+        uni.createSelectorQuery()
+          // #ifndef MP-ALIPAY
+          .in(this)
+          // #endif
+          .select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
+      })
+    },
+
+    /**
+     * @description 设置内容
+     * @param {String} content html 内容
+     * @param {Boolean} append 是否在尾部追加
+     */
+    setContent (content, append) {
+      if (!append || !this.imgList) {
+        this.imgList = []
+      }
+      const nodes = new Parser(this).parse(content)
+      // #ifdef APP-PLUS-NVUE
+      if (this._ready) {
+        this._set(nodes, append)
+      }
+      // #endif
+      this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
+
+      // #ifndef APP-PLUS-NVUE
+      this._videos = []
+      this.$nextTick(() => {
+        this._hook('onLoad')
+        this.$emit('load')
+      })
+
+      // 等待图片加载完毕
+      let height
+      clearInterval(this._timer)
+      this._timer = setInterval(() => {
+        this.getRect().then(rect => {
+          // 350ms 总高度无变化就触发 ready 事件
+          if (rect.height === height) {
+            this.$emit('ready', rect)
+            clearInterval(this._timer)
+          }
+          height = rect.height
+        }).catch(() => { })
+      }, 350)
+      // #endif
+    },
+
+    /**
+     * @description 调用插件钩子函数
+     */
+    _hook (name) {
+      for (let i = plugins.length; i--;) {
+        if (this.plugins[i][name]) {
+          this.plugins[i][name]()
+        }
+      }
+    },
+
+    // #ifdef APP-PLUS-NVUE
+    /**
+     * @description 设置内容
+     */
+    _set (nodes, append) {
+      this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes) + ',' + JSON.stringify([this.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
+    },
+
+    /**
+     * @description 接收到 web-view 消息
+     */
+    _onMessage (e) {
+      const message = e.detail.data[0]
+      switch (message.action) {
+        // web-view 初始化完毕
+        case 'onJSBridgeReady':
+          this._ready = true
+          if (this.nodes) {
+            this._set(this.nodes)
+          }
+          break
+        // 内容 dom 加载完毕
+        case 'onLoad':
+          this.height = message.height
+          this._hook('onLoad')
+          this.$emit('load')
+          break
+        // 所有图片加载完毕
+        case 'onReady':
+          this.getRect().then(res => {
+            this.$emit('ready', res)
+          }).catch(() => { })
+          break
+        // 总高度发生变化
+        case 'onHeightChange':
+          this.height = message.height
+          break
+        // 图片点击
+        case 'onImgTap':
+          this.$emit('imgtap', message.attrs)
+          if (this.previewImg) {
+            uni.previewImage({
+              current: parseInt(message.attrs.i),
+              urls: this.imgList
+            })
+          }
+          break
+        // 链接点击
+        case 'onLinkTap': {
+          const href = message.attrs.href
+          this.$emit('linktap', message.attrs)
+          if (href) {
+            // 锚点跳转
+            if (href[0] === '#') {
+              if (this.useAnchor) {
+                dom.scrollToElement(this.$refs.web, {
+                  offset: message.offset
+                })
+              }
+            } else if (href.includes('://')) {
+              // 打开外链
+              if (this.copyLink) {
+                plus.runtime.openWeb(href)
+              }
+            } else {
+              uni.navigateTo({
+                url: href,
+                fail () {
+                  uni.switchTab({
+                    url: href
+                  })
+                }
+              })
+            }
+          }
+          break
+        }
+        // 获取到锚点的偏移量
+        case 'getOffset':
+          if (typeof message.offset === 'number') {
+            dom.scrollToElement(this.$refs.web, {
+              offset: message.offset + this._navigateTo.offset
+            })
+            this._navigateTo.resolve()
+          } else {
+            this._navigateTo.reject(Error('Label not found'))
+          }
+          break
+        // 点击
+        case 'onClick':
+          this.$emit('tap')
+          this.$emit('click')
+          break
+        // 出错
+        case 'onError':
+          this.$emit('error', {
+            source: message.source,
+            attrs: message.attrs
+          })
+      }
+    }
+    // #endif
+  }
+}
+</script>
+
+<style>
+/* #ifndef APP-PLUS-NVUE */
+/* 根节点样式 */
+._root {
+  padding: 1px 0;
+  overflow-x: auto;
+  overflow-y: hidden;
+  -webkit-overflow-scrolling: touch;
+}
+
+/* 长按复制 */
+._select {
+  user-select: text;
+}
+/* #endif */
+</style>

+ 524 - 0
uni_modules/mp-html/components/mp-html/node/node.vue

@@ -0,0 +1,524 @@
+<template>
+  <view :id="attrs.id" :class="'_block _'+name+' '+attrs.class" :style="attrs.style">
+    <block v-for="(n, i) in childs" v-bind:key="i">
+      <!-- 图片 -->
+      <!-- 占位图 -->
+      <image v-if="n.name==='img'&&((opts[1]&&!ctrl[i])||ctrl[i]<0)" class="_img" :style="n.attrs.style" :src="ctrl[i]<0?opts[2]:opts[1]" mode="widthFix" />
+      <!-- 显示图片 -->
+      <!-- #ifdef H5 || APP-PLUS -->
+      <img v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap"/>
+      <!-- #endif -->
+      <!-- #ifndef H5 || APP-PLUS -->
+      <image v-if="n.name==='img'" :id="n.attrs.id" :class="'_img '+n.attrs.class" :style="(ctrl[i]===-1?'display:none;':'')+'width:'+(ctrl[i]||1)+'px;height:1px;'+n.attrs.style" :src="n.attrs.src" :mode="n.h?'':'widthFix'" :lazy-load="opts[0]" :webp="n.webp" :show-menu-by-longpress="opts[3]&&!n.attrs.ignore" :image-menu-prevent="!opts[3]||n.attrs.ignore" :data-i="i" @load="imgLoad" @error="mediaError" @tap.stop="imgTap" @longpress="imgLongTap" />
+      <!-- #endif -->
+      <!-- 文本 -->
+      <!-- #ifndef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
+      <text v-else-if="n.text" :user-select="n.us" decode>{{n.text}}</text>
+      <!-- #endif -->
+      <text v-else-if="n.name==='br'">\n</text>
+      <!-- 链接 -->
+      <view v-else-if="n.name==='a'" :id="n.attrs.id" :class="(n.attrs.href?'_a ':'')+n.attrs.class" hover-class="_hover" :style="'display:inline;'+n.attrs.style" :data-i="i" @tap.stop="linkTap">
+        <node name="span" :childs="n.children" :opts="opts" style="display:inherit" />
+      </view>
+      <!-- 视频 -->
+      <!-- #ifdef APP-PLUS -->
+      <view v-else-if="n.html" :id="n.attrs.id" :class="'_video '+n.attrs.class" :style="n.attrs.style" v-html="n.html" />
+      <!-- #endif -->
+      <!-- #ifndef APP-PLUS -->
+      <video v-else-if="n.name==='video'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :autoplay="n.attrs.autoplay" :controls="n.attrs.controls" :loop="n.attrs.loop" :muted="n.attrs.muted" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
+      <!-- #endif -->
+      <!-- #ifdef H5 || APP-PLUS -->
+      <iframe v-else-if="n.name==='iframe'" :style="n.attrs.style" :allowfullscreen="n.attrs.allowfullscreen" :frameborder="n.attrs.frameborder" :src="n.attrs.src" />
+      <embed v-else-if="n.name==='embed'" :style="n.attrs.style" :src="n.attrs.src" />
+      <!-- #endif -->
+      <!-- #ifndef MP-TOUTIAO -->
+      <!-- 音频 -->
+      <audio v-else-if="n.name==='audio'" :id="n.attrs.id" :class="n.attrs.class" :style="n.attrs.style" :author="n.attrs.author" :controls="n.attrs.controls" :loop="n.attrs.loop" :name="n.attrs.name" :poster="n.attrs.poster" :src="n.src[ctrl[i]||0]" :data-i="i" @play="play" @error="mediaError" />
+      <!-- #endif -->
+      <view v-else-if="(n.name==='table'&&n.c)||n.name==='li'" :id="n.attrs.id" :class="'_'+n.name+' '+n.attrs.class" :style="n.attrs.style">
+        <node v-if="n.name==='li'" :childs="n.children" :opts="opts" />
+        <view v-else v-for="(tbody, x) in n.children" v-bind:key="x" :class="'_'+tbody.name+' '+tbody.attrs.class" :style="tbody.attrs.style">
+          <node v-if="tbody.name==='td'||tbody.name==='th'" :childs="tbody.children" :opts="opts" />
+          <block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
+            <view v-if="tr.name==='td'||tr.name==='th'" :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
+              <node :childs="tr.children" :opts="opts" />
+            </view>
+            <view v-else :class="'_'+tr.name+' '+tr.attrs.class" :style="tr.attrs.style">
+              <view v-for="(td, z) in tr.children" v-bind:key="z" :class="'_'+td.name+' '+td.attrs.class" :style="td.attrs.style">
+                <node :childs="td.children" :opts="opts" />
+              </view>
+            </view>
+          </block>
+        </view>
+      </view>
+      
+      <!-- 富文本 -->
+      <!-- #ifdef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
+      <rich-text v-else-if="handler.use(n)" :id="n.attrs.id" :style="n.f" :nodes="[n]" />
+      <!-- #endif -->
+      <!-- #ifndef H5 || MP-WEIXIN || MP-QQ || APP-PLUS || MP-360 -->
+      <rich-text v-else-if="!n.c" :id="n.attrs.id" :style="n.f+';display:inline'" :preview="false" :nodes="[n]" />
+      <!-- #endif -->
+      <!-- 继续递归 -->
+      <view v-else-if="n.c===2" :id="n.attrs.id" :class="'_block _'+n.name+' '+n.attrs.class" :style="n.f+';'+n.attrs.style">
+        <node v-for="(n2, j) in n.children" v-bind:key="j" :style="n2.f" :name="n2.name" :attrs="n2.attrs" :childs="n2.children" :opts="opts" />
+      </view>
+      <node v-else :style="n.f" :name="n.name" :attrs="n.attrs" :childs="n.children" :opts="opts" />
+    </block>
+  </view>
+</template>
+<script module="handler" lang="wxs">
+// 行内标签列表
+var inlineTags = {
+  abbr: true,
+  b: true,
+  big: true,
+  code: true,
+  del: true,
+  em: true,
+  i: true,
+  ins: true,
+  label: true,
+  q: true,
+  small: true,
+  span: true,
+  strong: true,
+  sub: true,
+  sup: true
+}
+/**
+ * @description 是否使用 rich-text 显示剩余内容
+ */
+module.exports = {
+  use: function (item) {
+    if (item.c) return false
+    // 微信和 QQ 的 rich-text inline 布局无效
+    return !inlineTags[item.name] && (item.attrs.style || '').indexOf('display:inline') == -1
+  }
+}
+</script>
+<script>
+
+import node from './node'
+export default {
+  name: 'node',
+  options: {
+    // #ifdef MP-WEIXIN
+    virtualHost: true,
+    // #endif
+    // #ifdef MP-TOUTIAO
+    addGlobalClass: false
+    // #endif
+  },
+  data () {
+    return {
+      ctrl: {}
+    }
+  },
+  props: {
+    name: String,
+    attrs: {
+      type: Object,
+      default () {
+        return {}
+      }
+    },
+    childs: Array,
+    opts: Array
+  },
+  components: {
+
+    node
+  },
+  mounted () {
+    this.$nextTick(() => {
+      for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root.$parent);
+    })
+    // #ifdef H5 || APP-PLUS
+    if (this.opts[0]) {
+      let i
+      for (i = this.childs.length; i--;) {
+        if (this.childs[i].name === 'img') break
+      }
+      if (i !== -1) {
+        this.observer = uni.createIntersectionObserver(this).relativeToViewport({
+          top: 500,
+          bottom: 500
+        })
+        this.observer.observe('._img', res => {
+          if (res.intersectionRatio) {
+            this.$set(this.ctrl, 'load', 1)
+            this.observer.disconnect()
+          }
+        })
+      }
+    }
+    // #endif
+  },
+  beforeDestroy () {
+    // #ifdef H5 || APP-PLUS
+    if (this.observer) {
+      this.observer.disconnect()
+    }
+    // #endif
+  },
+  methods:{
+    // #ifdef MP-WEIXIN
+    toJSON () { },
+    // #endif
+    /**
+     * @description 播放视频事件
+     * @param {Event} e
+     */
+    play (e) {
+      // #ifndef APP-PLUS
+      if (this.root.pauseVideo) {
+        let flag = false; const id = e.target.id
+        for (let i = this.root._videos.length; i--;) {
+          if (this.root._videos[i].id === id) {
+            flag = true
+          } else {
+            this.root._videos[i].pause() // 自动暂停其他视频
+          }
+        }
+        // 将自己加入列表
+        if (!flag) {
+          const ctx = uni.createVideoContext(id
+            // #ifndef MP-BAIDU
+            , this
+            // #endif
+          )
+          ctx.id = id
+          this.root._videos.push(ctx)
+        }
+      }
+      // #endif
+    },
+
+    /**
+     * @description 图片点击事件
+     * @param {Event} e
+     */
+    imgTap (e) {
+      const node = this.childs[e.currentTarget.dataset.i]
+      if (node.a) {
+        this.linkTap(node.a)
+        return
+      }
+      if (node.attrs.ignore) return
+      // #ifdef H5 || APP-PLUS
+      node.attrs.src = node.attrs.src || node.attrs['data-src']
+      // #endif
+      this.root.$emit('imgtap', node.attrs)
+      // 自动预览图片
+      if (this.root.previewImg) {
+        uni.previewImage({
+          current: parseInt(node.attrs.i),
+          urls: this.root.imgList
+        })
+      }
+    },
+
+    /**
+     * @description 图片长按
+     */
+    imgLongTap (e) {
+      // #ifdef APP-PLUS
+      const attrs = this.childs[e.currentTarget.dataset.i].attrs
+      if (this.opts[3] && !attrs.ignore) {
+        uni.showActionSheet({
+          itemList: ['保存图片'],
+          success: () => {
+            const save = path => {
+              uni.saveImageToPhotosAlbum({
+                filePath: path,
+                success () {
+                  uni.showToast({
+                    title: '保存成功'
+                  })
+                }
+              })
+            }
+            if (this.root.imgList[attrs.i].startsWith('http')) {
+              uni.downloadFile({
+                url: this.root.imgList[attrs.i],
+                success: res => save(res.tempFilePath)
+              })
+            } else {
+              save(this.root.imgList[attrs.i])
+            }
+          }
+        })
+      }
+      // #endif
+    },
+
+    /**
+     * @description 图片加载完成事件
+     * @param {Event} e
+     */
+    imgLoad (e) {
+      const i = e.currentTarget.dataset.i
+      /* #ifndef H5 || APP-PLUS */
+      if (!this.childs[i].w) {
+        // 设置原宽度
+        this.$set(this.ctrl, i, e.detail.width)
+      } else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
+        // 加载完毕,取消加载中占位图
+        this.$set(this.ctrl, i, 1)
+      }
+    },
+
+    /**
+     * @description 链接点击事件
+     * @param {Event} e
+     */
+    linkTap (e) {
+      const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
+      const attrs = node.attrs || e
+      const href = attrs.href
+      this.root.$emit('linktap', Object.assign({
+        innerText: this.root.getText(node.children || []) // 链接内的文本内容
+      }, attrs))
+      if (href) {
+        if (href[0] === '#') {
+          // 跳转锚点
+          this.root.navigateTo(href.substring(1)).catch(() => { })
+        } else if (href.split('?')[0].includes('://')) {
+          // 复制外部链接
+          if (this.root.copyLink) {
+            // #ifdef H5
+            window.open(href)
+            // #endif
+            // #ifdef MP
+            uni.setClipboardData({
+              data: href,
+              success: () =>
+                uni.showToast({
+                  title: '链接已复制'
+                })
+            })
+            // #endif
+            // #ifdef APP-PLUS
+            plus.runtime.openWeb(href)
+            // #endif
+          }
+        } else {
+          // 跳转页面
+          uni.navigateTo({
+            url: href,
+            fail () {
+              uni.switchTab({
+                url: href,
+                fail () { }
+              })
+            }
+          })
+        }
+      }
+    },
+
+    /**
+     * @description 错误事件
+     * @param {Event} e
+     */
+    mediaError (e) {
+      const i = e.currentTarget.dataset.i
+      const node = this.childs[i]
+      // 加载其他源
+      if (node.name === 'video' || node.name === 'audio') {
+        let index = (this.ctrl[i] || 0) + 1
+        if (index > node.src.length) {
+          index = 0
+        }
+        if (index < node.src.length) {
+          this.$set(this.ctrl, i, index)
+          return
+        }
+      } else if (node.name === 'img' && this.opts[2]) {
+        // 显示错误占位图
+        this.$set(this.ctrl, i, -1)
+      }
+      if (this.root) {
+        this.root.$emit('error', {
+          source: node.name,
+          attrs: node.attrs,
+          errMsg: e.detail.errMsg
+        })
+      }
+    }
+  }
+}
+</script>
+<style>
+/* a 标签默认效果 */
+._a {
+  padding: 1.5px 0 1.5px 0;
+  color: #366092;
+  word-break: break-all;
+}
+
+/* a 标签点击态效果 */
+._hover {
+  text-decoration: underline;
+  opacity: 0.7;
+}
+
+/* 图片默认效果 */
+._img {
+  max-width: 100%;
+  -webkit-touch-callout: none;
+}
+
+/* 内部样式 */
+
+._block {
+  display: block;
+}
+
+._b,
+._strong {
+  font-weight: bold;
+}
+
+._code {
+  font-family: monospace;
+}
+
+._del {
+  text-decoration: line-through;
+}
+
+._em,
+._i {
+  font-style: italic;
+}
+
+._h1 {
+  font-size: 2em;
+}
+
+._h2 {
+  font-size: 1.5em;
+}
+
+._h3 {
+  font-size: 1.17em;
+}
+
+._h5 {
+  font-size: 0.83em;
+}
+
+._h6 {
+  font-size: 0.67em;
+}
+
+._h1,
+._h2,
+._h3,
+._h4,
+._h5,
+._h6 {
+  display: block;
+  font-weight: bold;
+}
+
+._image {
+  height: 1px;
+}
+
+._ins {
+  text-decoration: underline;
+}
+
+._li {
+  display: list-item;
+}
+
+._ol {
+  list-style-type: decimal;
+}
+
+._ol,
+._ul {
+  display: block;
+  padding-left: 40px;
+  margin: 1em 0;
+}
+
+._q::before {
+  content: '"';
+}
+
+._q::after {
+  content: '"';
+}
+
+._sub {
+  font-size: smaller;
+  vertical-align: sub;
+}
+
+._sup {
+  font-size: smaller;
+  vertical-align: super;
+}
+
+._thead,
+._tbody,
+._tfoot {
+  display: table-row-group;
+}
+
+._tr {
+  display: table-row;
+}
+
+._td,
+._th {
+  display: table-cell;
+  vertical-align: middle;
+}
+
+._th {
+  font-weight: bold;
+  text-align: center;
+}
+
+._ul {
+  list-style-type: disc;
+}
+
+._ul ._ul {
+  margin: 0;
+  list-style-type: circle;
+}
+
+._ul ._ul ._ul {
+  list-style-type: square;
+}
+
+._abbr,
+._b,
+._code,
+._del,
+._em,
+._i,
+._ins,
+._label,
+._q,
+._span,
+._strong,
+._sub,
+._sup {
+  display: inline;
+}
+
+/* #ifdef APP-PLUS */
+._video {
+  width: 300px;
+  height: 225px;
+}
+/* #endif */
+</style>

+ 1223 - 0
uni_modules/mp-html/components/mp-html/parser.js

@@ -0,0 +1,1223 @@
+/**
+ * @fileoverview html 解析器
+ */
+
+// 配置
+const config = {
+  // 信任的标签(保持标签名不变)
+  trustTags: makeMap('a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,ruby,rt,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,ul,video'),
+
+  // 块级标签(转为 div,其他的非信任标签转为 span)
+  blockTags: makeMap('address,article,aside,body,caption,center,cite,footer,header,html,nav,pre,section'),
+
+  // 要移除的标签
+  ignoreTags: makeMap('area,base,canvas,embed,frame,head,iframe,input,link,map,meta,param,rp,script,source,style,textarea,title,track,wbr'),
+
+  // 自闭合的标签
+  voidTags: makeMap('area,base,br,col,circle,ellipse,embed,frame,hr,img,input,line,link,meta,param,path,polygon,rect,source,track,use,wbr'),
+
+  // html 实体
+  entities: {
+    lt: '<',
+    gt: '>',
+    quot: '"',
+    apos: "'",
+    ensp: '\u2002',
+    emsp: '\u2003',
+    nbsp: '\xA0',
+    semi: ';',
+    ndash: '–',
+    mdash: '—',
+    middot: '·',
+    lsquo: '‘',
+    rsquo: '’',
+    ldquo: '“',
+    rdquo: '”',
+    bull: '•',
+    hellip: '…'
+  },
+
+  // 默认的标签样式
+  tagStyle: {
+    // #ifndef APP-PLUS-NVUE
+    address: 'font-style:italic',
+    big: 'display:inline;font-size:1.2em',
+    caption: 'display:table-caption;text-align:center',
+    center: 'text-align:center',
+    cite: 'font-style:italic',
+    dd: 'margin-left:40px',
+    mark: 'background-color:yellow',
+    pre: 'font-family:monospace;white-space:pre',
+    s: 'text-decoration:line-through',
+    small: 'display:inline;font-size:0.8em',
+    strike: 'text-decoration:line-through',
+    u: 'text-decoration:underline'
+    // #endif
+  },
+
+  // svg 大小写对照表
+  svgDict: {
+    animatetransform: 'animateTransform',
+    lineargradient: 'linearGradient',
+    viewbox: 'viewBox',
+    attributename: 'attributeName',
+    repeatcount: 'repeatCount',
+    repeatdur: 'repeatDur'
+  }
+}
+const tagSelector={}
+const {
+  windowWidth,
+  // #ifdef MP-WEIXIN
+  system
+  // #endif
+} = uni.getSystemInfoSync()
+const blankChar = makeMap(' ,\r,\n,\t,\f')
+let idIndex = 0
+
+// #ifdef H5 || APP-PLUS
+config.ignoreTags.iframe = undefined
+config.trustTags.iframe = true
+config.ignoreTags.embed = undefined
+config.trustTags.embed = true
+// #endif
+// #ifdef APP-PLUS-NVUE
+config.ignoreTags.source = undefined
+config.ignoreTags.style = undefined
+// #endif
+
+/**
+ * @description 创建 map
+ * @param {String} str 逗号分隔
+ */
+function makeMap (str) {
+  const map = Object.create(null)
+  const list = str.split(',')
+  for (let i = list.length; i--;) {
+    map[list[i]] = true
+  }
+  return map
+}
+
+/**
+ * @description 解码 html 实体
+ * @param {String} str 要解码的字符串
+ * @param {Boolean} amp 要不要解码 &amp;
+ * @returns {String} 解码后的字符串
+ */
+function decodeEntity (str, amp) {
+  let i = str.indexOf('&')
+  while (i !== -1) {
+    const j = str.indexOf(';', i + 3)
+    let code
+    if (j === -1) break
+    if (str[i + 1] === '#') {
+      // &#123; 形式的实体
+      code = parseInt((str[i + 2] === 'x' ? '0' : '') + str.substring(i + 2, j))
+      if (!isNaN(code)) {
+        str = str.substr(0, i) + String.fromCharCode(code) + str.substr(j + 1)
+      }
+    } else {
+      // &nbsp; 形式的实体
+      code = str.substring(i + 1, j)
+      if (config.entities[code] || (code === 'amp' && amp)) {
+        str = str.substr(0, i) + (config.entities[code] || '&') + str.substr(j + 1)
+      }
+    }
+    i = str.indexOf('&', i + 1)
+  }
+  return str
+}
+
+/**
+ * @description html 解析器
+ * @param {Object} vm 组件实例
+ */
+function Parser (vm) {
+  this.options = vm || {}
+  this.tagStyle = Object.assign({}, config.tagStyle, this.options.tagStyle)
+  this.imgList = vm.imgList || []
+  this.plugins = vm.plugins || []
+  this.attrs = Object.create(null)
+  this.stack = []
+  this.nodes = []
+  this.pre = (this.options.containerStyle || '').includes('white-space') && this.options.containerStyle.includes('pre') ? 2 : 0
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Parser.prototype.parse = function (content) {
+  // 插件处理
+  for (let i = this.plugins.length; i--;) {
+    if (this.plugins[i].onUpdate) {
+      content = this.plugins[i].onUpdate(content, config) || content
+    }
+  }
+
+  new Lexer(this).parse(content)
+  // 出栈未闭合的标签
+  while (this.stack.length) {
+    this.popNode()
+  }
+  return this.nodes
+}
+
+/**
+ * @description 将标签暴露出来(不被 rich-text 包含)
+ */
+Parser.prototype.expose = function () {
+  // #ifndef APP-PLUS-NVUE
+  for (let i = this.stack.length; i--;) {
+    const item = this.stack[i]
+    if (item.c || item.name === 'a' || item.name === 'video' || item.name === 'audio') return
+    item.c = 1
+  }
+  // #endif
+}
+
+/**
+ * @description 处理插件
+ * @param {Object} node 要处理的标签
+ * @returns {Boolean} 是否要移除此标签
+ */
+Parser.prototype.hook = function (node) {
+  for (let i = this.plugins.length; i--;) {
+    if (this.plugins[i].onParse && this.plugins[i].onParse(node, this) === false) {
+      return false
+    }
+  }
+  return true
+}
+
+/**
+ * @description 将链接拼接上主域名
+ * @param {String} url 需要拼接的链接
+ * @returns {String} 拼接后的链接
+ */
+Parser.prototype.getUrl = function (url) {
+  const domain = this.options.domain
+  if (url[0] === '/') {
+    if (url[1] === '/') {
+      // // 开头的补充协议名
+      url = (domain ? domain.split('://')[0] : 'http') + ':' + url
+    } else if (domain) {
+      // 否则补充整个域名
+      url = domain + url
+    }
+  } else if (domain && !url.includes('data:') && !url.includes('://')) {
+    url = domain + '/' + url
+  }
+  return url
+}
+
+/**
+ * @description 解析样式表
+ * @param {Object} node 标签
+ * @returns {Object}
+ */
+Parser.prototype.parseStyle = function (node) {
+  const attrs = node.attrs
+  const list = (this.tagStyle[node.name] || '').split(';').concat((attrs.style || '').split(';'))
+  const styleObj = {}
+  let tmp = ''
+
+  if (attrs.id && !this.xml) {
+    // 暴露锚点
+    if (this.options.useAnchor) {
+      this.expose()
+    } else if (node.name !== 'img' && node.name !== 'a' && node.name !== 'video' && node.name !== 'audio') {
+      attrs.id = undefined
+    }
+  }
+
+  // 转换 width 和 height 属性
+  if (attrs.width) {
+    styleObj.width = parseFloat(attrs.width) + (attrs.width.includes('%') ? '%' : 'px')
+    attrs.width = undefined
+  }
+  if (attrs.height) {
+    styleObj.height = parseFloat(attrs.height) + (attrs.height.includes('%') ? '%' : 'px')
+    attrs.height = undefined
+  }
+
+  for (let i = 0, len = list.length; i < len; i++) {
+    const info = list[i].split(':')
+    if (info.length < 2) continue
+    const key = info.shift().trim().toLowerCase()
+    let value = info.join(':').trim()
+    if ((value[0] === '-' && value.lastIndexOf('-') > 0) || value.includes('safe')) {
+      // 兼容性的 css 不压缩
+      tmp += `;${key}:${value}`
+    } else if (!styleObj[key] || value.includes('import') || !styleObj[key].includes('import')) {
+      // 重复的样式进行覆盖
+      if (value.includes('url')) {
+        // 填充链接
+        let j = value.indexOf('(') + 1
+        if (j) {
+          while (value[j] === '"' || value[j] === "'" || blankChar[value[j]]) {
+            j++
+          }
+          value = value.substr(0, j) + this.getUrl(value.substr(j))
+        }
+      } else if (value.includes('rpx')) {
+        // 转换 rpx(rich-text 内部不支持 rpx)
+        value = value.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * windowWidth / 750 + 'px')
+      }
+      styleObj[key] = value
+    }
+  }
+
+  node.attrs.style = tmp
+  return styleObj
+}
+
+/**
+ * @description 解析到标签名
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onTagName = function (name) {
+  this.tagName = this.xml ? name : name.toLowerCase()
+  if (this.tagName === 'svg') {
+    this.xml = (this.xml || 0) + 1 // svg 标签内大小写敏感
+  }
+}
+
+/**
+ * @description 解析到属性名
+ * @param {String} name 属性名
+ * @private
+ */
+Parser.prototype.onAttrName = function (name) {
+  name = this.xml ? name : name.toLowerCase()
+  if (name.substr(0, 5) === 'data-') {
+    if (name === 'data-src' && !this.attrs.src) {
+      // data-src 自动转为 src
+      this.attrName = 'src'
+    } else if (this.tagName === 'img' || this.tagName === 'a') {
+      // a 和 img 标签保留 data- 的属性,可以在 imgtap 和 linktap 事件中使用
+      this.attrName = name
+    } else {
+      // 剩余的移除以减小大小
+      this.attrName = undefined
+    }
+  } else {
+    this.attrName = name
+    this.attrs[name] = 'T' // boolean 型属性缺省设置
+  }
+}
+
+/**
+ * @description 解析到属性值
+ * @param {String} val 属性值
+ * @private
+ */
+Parser.prototype.onAttrVal = function (val) {
+  const name = this.attrName || ''
+  if (name === 'style' || name === 'href') {
+    // 部分属性进行实体解码
+    this.attrs[name] = decodeEntity(val, true)
+  } else if (name.includes('src')) {
+    // 拼接主域名
+    this.attrs[name] = this.getUrl(decodeEntity(val, true))
+  } else if (name) {
+    this.attrs[name] = val
+  }
+}
+
+/**
+ * @description 解析到标签开始
+ * @param {Boolean} selfClose 是否有自闭合标识 />
+ * @private
+ */
+Parser.prototype.onOpenTag = function (selfClose) {
+  // 拼装 node
+  const node = Object.create(null)
+  node.name = this.tagName
+  node.attrs = this.attrs
+  // 避免因为自动 diff 使得 type 被设置为 null 导致部分内容不显示
+  if (this.options.nodes.length) {
+    node.type = 'node'
+  }
+  this.attrs = Object.create(null)
+
+  const attrs = node.attrs
+  const parent = this.stack[this.stack.length - 1]
+  const siblings = parent ? parent.children : this.nodes
+  const close = this.xml ? selfClose : config.voidTags[node.name]
+
+  // 替换标签名选择器
+  if (tagSelector[node.name]) {
+    attrs.class = tagSelector[node.name] + (attrs.class ? ' ' + attrs.class : '')
+  }
+
+  // 转换 embed 标签
+  if (node.name === 'embed') {
+    // #ifndef H5 || APP-PLUS
+    const src = attrs.src || ''
+    // 按照后缀名和 type 将 embed 转为 video 或 audio
+    if (src.includes('.mp4') || src.includes('.3gp') || src.includes('.m3u8') || (attrs.type || '').includes('video')) {
+      node.name = 'video'
+    } else if (src.includes('.mp3') || src.includes('.wav') || src.includes('.aac') || src.includes('.m4a') || (attrs.type || '').includes('audio')) {
+      node.name = 'audio'
+    }
+    if (attrs.autostart) {
+      attrs.autoplay = 'T'
+    }
+    attrs.controls = 'T'
+    // #endif
+    // #ifdef H5 || APP-PLUS
+    this.expose()
+    // #endif
+  }
+
+  // #ifndef APP-PLUS-NVUE
+  // 处理音视频
+  if (node.name === 'video' || node.name === 'audio') {
+    // 设置 id 以便获取 context
+    if (node.name === 'video' && !attrs.id) {
+      attrs.id = 'v' + idIndex++
+    }
+    // 没有设置 controls 也没有设置 autoplay 的自动设置 controls
+    if (!attrs.controls && !attrs.autoplay) {
+      attrs.controls = 'T'
+    }
+    // 用数组存储所有可用的 source
+    node.src = []
+    if (attrs.src) {
+      node.src.push(attrs.src)
+      attrs.src = undefined
+    }
+    this.expose()
+  }
+  // #endif
+
+  // 处理自闭合标签
+  if (close) {
+    if (!this.hook(node) || config.ignoreTags[node.name]) {
+      // 通过 base 标签设置主域名
+      if (node.name === 'base' && !this.options.domain) {
+        this.options.domain = attrs.href
+      } /* #ifndef APP-PLUS-NVUE */ else if (node.name === 'source' && parent && (parent.name === 'video' || parent.name === 'audio') && attrs.src) {
+        // 设置 source 标签(仅父节点为 video 或 audio 时有效)
+        parent.src.push(attrs.src)
+      } /* #endif */
+      return
+    }
+
+    // 解析 style
+    const styleObj = this.parseStyle(node)
+
+    // 处理图片
+    if (node.name === 'img') {
+      if (attrs.src) {
+        // 标记 webp
+        if (attrs.src.includes('webp')) {
+          node.webp = 'T'
+        }
+        // data url 图片如果没有设置 original-src 默认为不可预览的小图片
+        if (attrs.src.includes('data:') && !attrs['original-src']) {
+          attrs.ignore = 'T'
+        }
+        if (!attrs.ignore || node.webp || attrs.src.includes('cloud://')) {
+          for (let i = this.stack.length; i--;) {
+            const item = this.stack[i]
+            if (item.name === 'a') {
+              node.a = item.attrs
+              break
+            }
+            // #ifndef H5 || APP-PLUS
+            const style = item.attrs.style || ''
+            if (style.includes('flex:') && !style.includes('flex:0') && !style.includes('flex: 0') && (!styleObj.width || !styleObj.width.includes('%'))) {
+              styleObj.width = '100% !important'
+              styleObj.height = ''
+              for (let j = i + 1; j < this.stack.length; j++) {
+                this.stack[j].attrs.style = (this.stack[j].attrs.style || '').replace('inline-', '')
+              }
+            } else if (style.includes('flex') && styleObj.width === '100%') {
+              for (let j = i + 1; j < this.stack.length; j++) {
+                const style = this.stack[j].attrs.style || ''
+                if (!style.includes(';width') && !style.includes(' width') && style.indexOf('width') !== 0) {
+                  styleObj.width = ''
+                  break
+                }
+              }
+            } else if (style.includes('inline-block')) {
+              if (styleObj.width && styleObj.width[styleObj.width.length - 1] === '%') {
+                item.attrs.style += ';max-width:' + styleObj.width
+                styleObj.width = ''
+              } else {
+                item.attrs.style += ';max-width:100%'
+              }
+            }
+            // #endif
+            item.c = 1
+          }
+          attrs.i = this.imgList.length.toString()
+          let src = attrs['original-src'] || attrs.src
+          // #ifndef H5 || MP-ALIPAY || APP-PLUS || MP-360
+          if (this.imgList.includes(src)) {
+            // 如果有重复的链接则对域名进行随机大小写变换避免预览时错位
+            let i = src.indexOf('://')
+            if (i !== -1) {
+              i += 3
+              let newSrc = src.substr(0, i)
+              for (; i < src.length; i++) {
+                if (src[i] === '/') break
+                newSrc += Math.random() > 0.5 ? src[i].toUpperCase() : src[i]
+              }
+              newSrc += src.substr(i)
+              src = newSrc
+            }
+          }
+          // #endif
+          this.imgList.push(src)
+          // #ifdef H5 || APP-PLUS
+          if (this.options.lazyLoad) {
+            attrs['data-src'] = attrs.src
+            attrs.src = undefined
+          }
+          // #endif
+        }
+      }
+      if (styleObj.display === 'inline') {
+        styleObj.display = ''
+      }
+      // #ifndef APP-PLUS-NVUE
+      if (attrs.ignore) {
+        styleObj['max-width'] = styleObj['max-width'] || '100%'
+        attrs.style += ';-webkit-touch-callout:none'
+      }
+      // #endif
+      // 设置的宽度超出屏幕,为避免变形,高度转为自动
+      if (parseInt(styleObj.width) > windowWidth) {
+        styleObj.height = undefined
+      }
+      // 记录是否设置了宽高
+      if (styleObj.width) {
+        if (styleObj.width.includes('auto')) {
+          styleObj.width = ''
+        } else {
+          node.w = 'T'
+          if (styleObj.height && !styleObj.height.includes('auto')) {
+            node.h = 'T'
+          }
+        }
+      }
+    } else if (node.name === 'svg') {
+      siblings.push(node)
+      this.stack.push(node)
+      this.popNode()
+      return
+    }
+    for (const key in styleObj) {
+      if (styleObj[key]) {
+        attrs.style += `;${key}:${styleObj[key].replace(' !important', '')}`
+      }
+    }
+    attrs.style = attrs.style.substr(1) || undefined
+  } else {
+    if ((node.name === 'pre' || ((attrs.style || '').includes('white-space') && attrs.style.includes('pre'))) && this.pre !== 2) {
+      this.pre = node.pre = 1
+    }
+    node.children = []
+    this.stack.push(node)
+  }
+
+  // 加入节点树
+  siblings.push(node)
+}
+
+/**
+ * @description 解析到标签结束
+ * @param {String} name 标签名
+ * @private
+ */
+Parser.prototype.onCloseTag = function (name) {
+  // 依次出栈到匹配为止
+  name = this.xml ? name : name.toLowerCase()
+  let i
+  for (i = this.stack.length; i--;) {
+    if (this.stack[i].name === name) break
+  }
+  if (i !== -1) {
+    while (this.stack.length > i) {
+      this.popNode()
+    }
+  } else if (name === 'p' || name === 'br') {
+    const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+    siblings.push({
+      name,
+      attrs: {
+        class: tagSelector[name],
+        style: this.tagStyle[name]
+      }
+    })
+  }
+}
+
+/**
+ * @description 处理标签出栈
+ * @private
+ */
+Parser.prototype.popNode = function () {
+  const node = this.stack.pop()
+  let attrs = node.attrs
+  const children = node.children
+  const parent = this.stack[this.stack.length - 1]
+  const siblings = parent ? parent.children : this.nodes
+
+  if (!this.hook(node) || config.ignoreTags[node.name]) {
+    // 获取标题
+    if (node.name === 'title' && children.length && children[0].type === 'text' && this.options.setTitle) {
+      uni.setNavigationBarTitle({
+        title: children[0].text
+      })
+    }
+    siblings.pop()
+    return
+  }
+
+  if (node.pre && this.pre !== 2) {
+    // 是否合并空白符标识
+    this.pre = node.pre = undefined
+    for (let i = this.stack.length; i--;) {
+      if (this.stack[i].pre) {
+        this.pre = 1
+      }
+    }
+  }
+
+  const styleObj = {}
+
+  // 转换 svg
+  if (node.name === 'svg') {
+    if (this.xml > 1) {
+      // 多层 svg 嵌套
+      this.xml--
+      return
+    }
+    // #ifdef APP-PLUS-NVUE
+    (function traversal (node) {
+      if (node.name) {
+        // 调整 svg 的大小写
+        node.name = config.svgDict[node.name] || node.name
+        for (const item in node.attrs) {
+          if (config.svgDict[item]) {
+            node.attrs[config.svgDict[item]] = node.attrs[item]
+            node.attrs[item] = undefined
+          }
+        }
+        for (let i = 0; i < (node.children || []).length; i++) {
+          traversal(node.children[i])
+        }
+      }
+    })(node)
+    // #endif
+    // #ifndef APP-PLUS-NVUE
+    let src = ''
+    const style = attrs.style
+    attrs.style = ''
+    attrs.xmlns = 'http://www.w3.org/2000/svg';
+    (function traversal (node) {
+      if (node.type === 'text') {
+        src += node.text
+        return
+      }
+      const name = config.svgDict[node.name] || node.name
+      src += '<' + name
+      for (const item in node.attrs) {
+        const val = node.attrs[item]
+        if (val) {
+          src += ` ${config.svgDict[item] || item}="${val}"`
+        }
+      }
+      if (!node.children) {
+        src += '/>'
+      } else {
+        src += '>'
+        for (let i = 0; i < node.children.length; i++) {
+          traversal(node.children[i])
+        }
+        src += '</' + name + '>'
+      }
+    })(node)
+    node.name = 'img'
+    node.attrs = {
+      src: 'data:image/svg+xml;utf8,' + src.replace(/#/g, '%23'),
+      style,
+      ignore: 'T'
+    }
+    node.children = undefined
+    // #endif
+    this.xml = false
+    return
+  }
+
+  // #ifndef APP-PLUS-NVUE
+  // 转换 align 属性
+  if (attrs.align) {
+    if (node.name === 'table') {
+      if (attrs.align === 'center') {
+        styleObj['margin-inline-start'] = styleObj['margin-inline-end'] = 'auto'
+      } else {
+        styleObj.float = attrs.align
+      }
+    } else {
+      styleObj['text-align'] = attrs.align
+    }
+    attrs.align = undefined
+  }
+
+  // 转换 dir 属性
+  if (attrs.dir) {
+    styleObj.direction = attrs.dir
+    attrs.dir = undefined
+  }
+
+  // 转换 font 标签的属性
+  if (node.name === 'font') {
+    if (attrs.color) {
+      styleObj.color = attrs.color
+      attrs.color = undefined
+    }
+    if (attrs.face) {
+      styleObj['font-family'] = attrs.face
+      attrs.face = undefined
+    }
+    if (attrs.size) {
+      let size = parseInt(attrs.size)
+      if (!isNaN(size)) {
+        if (size < 1) {
+          size = 1
+        } else if (size > 7) {
+          size = 7
+        }
+        styleObj['font-size'] = ['xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large'][size - 1]
+      }
+      attrs.size = undefined
+    }
+  }
+  // #endif
+
+  // 一些编辑器的自带 class
+  if ((attrs.class || '').includes('align-center')) {
+    styleObj['text-align'] = 'center'
+  }
+
+  Object.assign(styleObj, this.parseStyle(node))
+
+  if (node.name !== 'table' && parseInt(styleObj.width) > windowWidth) {
+    styleObj['max-width'] = '100%'
+    styleObj['box-sizing'] = 'border-box'
+  }
+
+  // #ifndef APP-PLUS-NVUE
+  if (config.blockTags[node.name]) {
+    node.name = 'div'
+  } else if (!config.trustTags[node.name] && !this.xml) {
+    // 未知标签转为 span,避免无法显示
+    node.name = 'span'
+  }
+
+  if (node.name === 'a' || node.name === 'ad'
+    // #ifdef H5 || APP-PLUS
+    || node.name === 'iframe' // eslint-disable-line
+    // #endif
+  ) {
+    this.expose()
+  } /* #ifdef APP-PLUS */ else if (node.name === 'video') {
+    let str = '<video style="width:100%;height:100%"'
+    for (const item in attrs) {
+      if (attrs[item]) {
+        str += ' ' + item + '="' + attrs[item] + '"'
+      }
+    }
+    if (this.options.pauseVideo) {
+      str += ' onplay="for(var e=document.getElementsByTagName(\'video\'),t=0;t<e.length;t++)e[t]!=this&&e[t].pause()"'
+    }
+    str += '>'
+    for (let i = 0; i < node.src.length; i++) {
+      str += '<source src="' + node.src[i] + '">'
+    }
+    str += '</video>'
+    node.html = str
+  } /* #endif */ else if ((node.name === 'ul' || node.name === 'ol') && node.c) {
+    // 列表处理
+    const types = {
+      a: 'lower-alpha',
+      A: 'upper-alpha',
+      i: 'lower-roman',
+      I: 'upper-roman'
+    }
+    if (types[attrs.type]) {
+      attrs.style += ';list-style-type:' + types[attrs.type]
+      attrs.type = undefined
+    }
+    for (let i = children.length; i--;) {
+      if (children[i].name === 'li') {
+        children[i].c = 1
+      }
+    }
+  } else if (node.name === 'table') {
+    // 表格处理
+    // cellpadding、cellspacing、border 这几个常用表格属性需要通过转换实现
+    let padding = parseFloat(attrs.cellpadding)
+    let spacing = parseFloat(attrs.cellspacing)
+    const border = parseFloat(attrs.border)
+    if (node.c) {
+      // padding 和 spacing 默认 2
+      if (isNaN(padding)) {
+        padding = 2
+      }
+      if (isNaN(spacing)) {
+        spacing = 2
+      }
+    }
+    if (border) {
+      attrs.style += ';border:' + border + 'px solid gray'
+    }
+    if (node.flag && node.c) {
+      // 有 colspan 或 rowspan 且含有链接的表格通过 grid 布局实现
+      styleObj.display = 'grid'
+      if (spacing) {
+        styleObj['grid-gap'] = spacing + 'px'
+        styleObj.padding = spacing + 'px'
+      } else if (border) {
+        // 无间隔的情况下避免边框重叠
+        attrs.style += ';border-left:0;border-top:0'
+      }
+
+      const width = [] // 表格的列宽
+      const trList = [] // tr 列表
+      const cells = [] // 保存新的单元格
+      const map = {}; // 被合并单元格占用的格子
+
+      (function traversal (nodes) {
+        for (let i = 0; i < nodes.length; i++) {
+          if (nodes[i].name === 'tr') {
+            trList.push(nodes[i])
+          } else {
+            traversal(nodes[i].children || [])
+          }
+        }
+      })(children)
+
+      for (let row = 1; row <= trList.length; row++) {
+        let col = 1
+        for (let j = 0; j < trList[row - 1].children.length; j++, col++) {
+          const td = trList[row - 1].children[j]
+          if (td.name === 'td' || td.name === 'th') {
+            // 这个格子被上面的单元格占用,则列号++
+            while (map[row + '.' + col]) {
+              col++
+            }
+            let style = td.attrs.style || ''
+            const start = style.indexOf('width') ? style.indexOf(';width') : 0
+            // 提取出 td 的宽度
+            if (start !== -1) {
+              let end = style.indexOf(';', start + 6)
+              if (end === -1) {
+                end = style.length
+              }
+              if (!td.attrs.colspan) {
+                width[col] = style.substring(start ? start + 7 : 6, end)
+              }
+              style = style.substr(0, start) + style.substr(end)
+            }
+            style += (border ? `;border:${border}px solid gray` + (spacing ? '' : ';border-right:0;border-bottom:0') : '') + (padding ? `;padding:${padding}px` : '')
+            // 处理列合并
+            if (td.attrs.colspan) {
+              style += `;grid-column-start:${col};grid-column-end:${col + parseInt(td.attrs.colspan)}`
+              if (!td.attrs.rowspan) {
+                style += `;grid-row-start:${row};grid-row-end:${row + 1}`
+              }
+              col += parseInt(td.attrs.colspan) - 1
+            }
+            // 处理行合并
+            if (td.attrs.rowspan) {
+              style += `;grid-row-start:${row};grid-row-end:${row + parseInt(td.attrs.rowspan)}`
+              if (!td.attrs.colspan) {
+                style += `;grid-column-start:${col};grid-column-end:${col + 1}`
+              }
+              // 记录下方单元格被占用
+              for (let rowspan = 1; rowspan < td.attrs.rowspan; rowspan++) {
+                for (let colspan = 0; colspan < (td.attrs.colspan || 1); colspan++) {
+                  map[(row + rowspan) + '.' + (col - colspan)] = 1
+                }
+              }
+            }
+            if (style) {
+              td.attrs.style = style
+            }
+            cells.push(td)
+          }
+        }
+        if (row === 1) {
+          let temp = ''
+          for (let i = 1; i < col; i++) {
+            temp += (width[i] ? width[i] : 'auto') + ' '
+          }
+          styleObj['grid-template-columns'] = temp
+        }
+      }
+      node.children = cells
+    } else {
+      // 没有使用合并单元格的表格通过 table 布局实现
+      if (node.c) {
+        styleObj.display = 'table'
+      }
+      if (!isNaN(spacing)) {
+        styleObj['border-spacing'] = spacing + 'px'
+      }
+      if (border || padding) {
+        // 遍历
+        (function traversal (nodes) {
+          for (let i = 0; i < nodes.length; i++) {
+            const td = nodes[i]
+            if (td.name === 'th' || td.name === 'td') {
+              if (border) {
+                td.attrs.style = `border:${border}px solid gray;${td.attrs.style || ''}`
+              }
+              if (padding) {
+                td.attrs.style = `padding:${padding}px;${td.attrs.style || ''}`
+              }
+            } else if (td.children) {
+              traversal(td.children)
+            }
+          }
+        })(children)
+      }
+    }
+    // 给表格添加一个单独的横向滚动层
+    if (this.options.scrollTable && !(attrs.style || '').includes('inline')) {
+      const table = Object.assign({}, node)
+      node.name = 'div'
+      node.attrs = {
+        style: 'overflow:auto'
+      }
+      node.children = [table]
+      attrs = table.attrs
+    }
+  } else if ((node.name === 'td' || node.name === 'th') && (attrs.colspan || attrs.rowspan)) {
+    for (let i = this.stack.length; i--;) {
+      if (this.stack[i].name === 'table') {
+        this.stack[i].flag = 1 // 指示含有合并单元格
+        break
+      }
+    }
+  } else if (node.name === 'ruby') {
+    // 转换 ruby
+    node.name = 'span'
+    for (let i = 0; i < children.length - 1; i++) {
+      if (children[i].type === 'text' && children[i + 1].name === 'rt') {
+        children[i] = {
+          name: 'div',
+          attrs: {
+            style: 'display:inline-block;text-align:center'
+          },
+          children: [{
+            name: 'div',
+            attrs: {
+              style: 'font-size:50%;' + (children[i + 1].attrs.style || '')
+            },
+            children: children[i + 1].children
+          }, children[i]]
+        }
+        children.splice(i + 1, 1)
+      }
+    }
+  } else if (node.c) {
+    node.c = 2
+    for (let i = node.children.length; i--;) {
+      if (!node.children[i].c || node.children[i].name === 'table') {
+        node.c = 1
+      }
+    }
+  }
+
+  if ((styleObj.display || '').includes('flex') && !node.c) {
+    for (let i = children.length; i--;) {
+      const item = children[i]
+      if (item.f) {
+        item.attrs.style = (item.attrs.style || '') + item.f
+        item.f = undefined
+      }
+    }
+  }
+  // flex 布局时部分样式需要提取到 rich-text 外层
+  const flex = parent && (parent.attrs.style || '').includes('flex')
+    // #ifdef MP-WEIXIN
+    // 检查基础库版本 virtualHost 是否可用
+    && !(node.c && wx.getNFCAdapter) // eslint-disable-line
+    // #endif
+    // #ifndef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
+    && !node.c // eslint-disable-line
+  // #endif
+  if (flex) {
+    node.f = ';max-width:100%'
+  }
+  // #endif
+
+  for (const key in styleObj) {
+    if (styleObj[key]) {
+      const val = `;${key}:${styleObj[key].replace(' !important', '')}`
+      /* #ifndef APP-PLUS-NVUE */
+      if (flex && ((key.includes('flex') && key !== 'flex-direction') || key === 'align-self' || styleObj[key][0] === '-' || (key === 'width' && val.includes('%')))) {
+        node.f += val
+        if (key === 'width') {
+          attrs.style += ';width:100%'
+        }
+      } else /* #endif */ {
+        attrs.style += val
+      }
+    }
+  }
+  attrs.style = attrs.style.substr(1) || undefined
+}
+
+/**
+ * @description 解析到文本
+ * @param {String} text 文本内容
+ */
+Parser.prototype.onText = function (text) {
+  if (!this.pre) {
+    // 合并空白符
+    let trim = ''
+    let flag
+    for (let i = 0, len = text.length; i < len; i++) {
+      if (!blankChar[text[i]]) {
+        trim += text[i]
+      } else {
+        if (trim[trim.length - 1] !== ' ') {
+          trim += ' '
+        }
+        if (text[i] === '\n' && !flag) {
+          flag = true
+        }
+      }
+    }
+    // 去除含有换行符的空串
+    if (trim === ' ' && flag) return
+    text = trim
+  }
+  const node = Object.create(null)
+  node.type = 'text'
+  node.text = decodeEntity(text)
+  if (this.hook(node)) {
+    // #ifdef MP-WEIXIN
+    if (this.options.selectable === 'force' && system.includes('iOS')) {
+      this.expose()
+      node.us = 'T'
+    }
+    // #endif
+    const siblings = this.stack.length ? this.stack[this.stack.length - 1].children : this.nodes
+    siblings.push(node)
+  }
+}
+
+/**
+ * @description html 词法分析器
+ * @param {Object} handler 高层处理器
+ */
+function Lexer (handler) {
+  this.handler = handler
+}
+
+/**
+ * @description 执行解析
+ * @param {String} content 要解析的文本
+ */
+Lexer.prototype.parse = function (content) {
+  this.content = content || ''
+  this.i = 0 // 标记解析位置
+  this.start = 0 // 标记一个单词的开始位置
+  this.state = this.text // 当前状态
+  for (let len = this.content.length; this.i !== -1 && this.i < len;) {
+    this.state()
+  }
+}
+
+/**
+ * @description 检查标签是否闭合
+ * @param {String} method 如果闭合要进行的操作
+ * @returns {Boolean} 是否闭合
+ * @private
+ */
+Lexer.prototype.checkClose = function (method) {
+  const selfClose = this.content[this.i] === '/'
+  if (this.content[this.i] === '>' || (selfClose && this.content[this.i + 1] === '>')) {
+    if (method) {
+      this.handler[method](this.content.substring(this.start, this.i))
+    }
+    this.i += selfClose ? 2 : 1
+    this.start = this.i
+    this.handler.onOpenTag(selfClose)
+    if (this.handler.tagName === 'script') {
+      this.i = this.content.indexOf('</', this.i)
+      if (this.i !== -1) {
+        this.i += 2
+        this.start = this.i
+      }
+      this.state = this.endTag
+    } else {
+      this.state = this.text
+    }
+    return true
+  }
+  return false
+}
+
+/**
+ * @description 文本状态
+ * @private
+ */
+Lexer.prototype.text = function () {
+  this.i = this.content.indexOf('<', this.i) // 查找最近的标签
+  if (this.i === -1) {
+    // 没有标签了
+    if (this.start < this.content.length) {
+      this.handler.onText(this.content.substring(this.start, this.content.length))
+    }
+    return
+  }
+  const c = this.content[this.i + 1]
+  if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+    // 标签开头
+    if (this.start !== this.i) {
+      this.handler.onText(this.content.substring(this.start, this.i))
+    }
+    this.start = ++this.i
+    this.state = this.tagName
+  } else if (c === '/' || c === '!' || c === '?') {
+    if (this.start !== this.i) {
+      this.handler.onText(this.content.substring(this.start, this.i))
+    }
+    const next = this.content[this.i + 2]
+    if (c === '/' && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
+      // 标签结尾
+      this.i += 2
+      this.start = this.i
+      this.state = this.endTag
+      return
+    }
+    // 处理注释
+    let end = '-->'
+    if (c !== '!' || this.content[this.i + 2] !== '-' || this.content[this.i + 3] !== '-') {
+      end = '>'
+    }
+    this.i = this.content.indexOf(end, this.i)
+    if (this.i !== -1) {
+      this.i += end.length
+      this.start = this.i
+    }
+  } else {
+    this.i++
+  }
+}
+
+/**
+ * @description 标签名状态
+ * @private
+ */
+Lexer.prototype.tagName = function () {
+  if (blankChar[this.content[this.i]]) {
+    // 解析到标签名
+    this.handler.onTagName(this.content.substring(this.start, this.i))
+    while (blankChar[this.content[++this.i]]);
+    if (this.i < this.content.length && !this.checkClose()) {
+      this.start = this.i
+      this.state = this.attrName
+    }
+  } else if (!this.checkClose('onTagName')) {
+    this.i++
+  }
+}
+
+/**
+ * @description 属性名状态
+ * @private
+ */
+Lexer.prototype.attrName = function () {
+  let c = this.content[this.i]
+  if (blankChar[c] || c === '=') {
+    // 解析到属性名
+    this.handler.onAttrName(this.content.substring(this.start, this.i))
+    let needVal = c === '='
+    const len = this.content.length
+    while (++this.i < len) {
+      c = this.content[this.i]
+      if (!blankChar[c]) {
+        if (this.checkClose()) return
+        if (needVal) {
+          // 等号后遇到第一个非空字符
+          this.start = this.i
+          this.state = this.attrVal
+          return
+        }
+        if (this.content[this.i] === '=') {
+          needVal = true
+        } else {
+          this.start = this.i
+          this.state = this.attrName
+          return
+        }
+      }
+    }
+  } else if (!this.checkClose('onAttrName')) {
+    this.i++
+  }
+}
+
+/**
+ * @description 属性值状态
+ * @private
+ */
+Lexer.prototype.attrVal = function () {
+  const c = this.content[this.i]
+  const len = this.content.length
+  if (c === '"' || c === "'") {
+    // 有冒号的属性
+    this.start = ++this.i
+    this.i = this.content.indexOf(c, this.i)
+    if (this.i === -1) return
+    this.handler.onAttrVal(this.content.substring(this.start, this.i))
+  } else {
+    // 没有冒号的属性
+    for (; this.i < len; this.i++) {
+      if (blankChar[this.content[this.i]]) {
+        this.handler.onAttrVal(this.content.substring(this.start, this.i))
+        break
+      } else if (this.checkClose('onAttrVal')) return
+    }
+  }
+  while (blankChar[this.content[++this.i]]);
+  if (this.i < len && !this.checkClose()) {
+    this.start = this.i
+    this.state = this.attrName
+  }
+}
+
+/**
+ * @description 结束标签状态
+ * @returns {String} 结束的标签名
+ * @private
+ */
+Lexer.prototype.endTag = function () {
+  const c = this.content[this.i]
+  if (blankChar[c] || c === '>' || c === '/') {
+    this.handler.onCloseTag(this.content.substring(this.start, this.i))
+    if (c !== '>') {
+      this.i = this.content.indexOf('>', this.i)
+      if (this.i === -1) return
+    }
+    this.start = ++this.i
+    this.state = this.text
+  } else {
+    this.i++
+  }
+}
+
+module.exports = Parser

+ 79 - 0
uni_modules/mp-html/package.json

@@ -0,0 +1,79 @@
+{
+    "id": "mp-html",
+    "displayName": "mp-html 富文本组件【全端支持,可编辑】",
+    "version": "v2.2.0",
+    "description": "一个强大的富文本组件,高效轻量,功能丰富",
+    "keywords": [
+        "富文本",
+        "编辑器",
+        "html",
+        "rich-text",
+        "editor"
+    ],
+    "repository": "https://github.com/jin-yufeng/mp-html",
+    "dcloudext": {
+        "category": [
+            "前端组件",
+            "通用组件"
+        ],
+        "sale": {
+            "regular": {
+                "price": "0.00"
+            },
+            "sourcecode": {
+                "price": "0.00"
+            }
+        },
+        "contact": {
+            "qq": ""
+        },
+        "declaration": {
+            "ads": "无",
+            "data": "无",
+            "permissions": "无"
+        },
+        "npmurl": "https://www.npmjs.com/package/mp-html"
+    },
+    "uni_modules": {
+        "platforms": {
+            "cloud": {
+                "tcb": "y",
+                "aliyun": "y"
+            },
+            "client": {
+                "App": {
+                    "app-vue": "y",
+                    "app-nvue": "y"
+                },
+                "H5-mobile": {
+                    "Safari": "y",
+                    "Android Browser": "y",
+                    "微信浏览器(Android)": "y",
+                    "QQ浏览器(Android)": "y"
+                },
+                "H5-pc": {
+                    "Chrome": "y",
+                    "IE": "u",
+                    "Edge": "y",
+                    "Firefox": "y",
+                    "Safari": "y"
+                },
+                "小程序": {
+                    "微信": "y",
+                    "阿里": "y",
+                    "百度": "y",
+                    "字节跳动": "y",
+                    "QQ": "y"
+                },
+                "快应用": {
+                    "华为": "y",
+                    "联盟": "y"
+                },
+                "Vue": {
+                    "vue2": "y",
+                    "vue3": "u"
+                }
+            }
+        }
+    }
+}

文件差異過大導致無法顯示
+ 0 - 0
uni_modules/mp-html/static/app-plus/mp-html/js/handler.js


文件差異過大導致無法顯示
+ 0 - 0
uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js


+ 1 - 0
uni_modules/mp-html/static/app-plus/mp-html/local.html

@@ -0,0 +1 @@
+<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}@keyframes show{0%{opacity:0}100%{opacity:1}}</style></head><body><div id="content"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>

部分文件因文件數量過多而無法顯示