Browse Source

冲突解决

hbchen 2 years ago
parent
commit
47b53b109f
47 changed files with 1842 additions and 2683 deletions
  1. 8 0
      api/common.js
  2. 23 0
      api/sandTable.js
  3. 9 2
      api/user.js
  4. 24 0
      api/video.js
  5. 120 0
      components/searchBox/searchBox.vue
  6. 6 6
      custom-tab-bar/index.wxml
  7. 1 1
      mixin/index.js
  8. 1 1
      mixin/questionMixin.js
  9. 1 1
      pages-applyPermission/applyPermission.vue
  10. 1 1
      pages-question/answerDetail.vue
  11. 1 1
      pages-question/answerList.vue
  12. 3 2
      pages-report/reportDetail.vue
  13. 769 0
      pages-sandTable/sandTable.vue
  14. 46 19
      pages.json
  15. 3 0
      pages/pc.vue
  16. 62 0
      pages/pricedriven/pricedriven.vue
  17. 15 2
      pages/question/question.vue
  18. 92 26
      pages/report/report.vue
  19. 392 0
      pages/video/videoList.vue
  20. 238 0
      pages/video/videoSearch.vue
  21. BIN
      static/arrow-right.png
  22. BIN
      static/buy.png
  23. BIN
      static/classify.png
  24. BIN
      static/filter-icon.png
  25. BIN
      static/sandTable/fullScreen.png
  26. BIN
      static/sandTable/sandTable-share.png
  27. BIN
      static/sandTable/sandTable_filtration.png
  28. BIN
      static/search-del.png
  29. BIN
      static/search-icon-s.png
  30. BIN
      static/search-icon.png
  31. BIN
      static/share-icon.png
  32. BIN
      static/tabbar/price-s.png
  33. BIN
      static/tabbar/price.png
  34. BIN
      static/tabbar/video-s.png
  35. BIN
      static/tabbar/video.png
  36. BIN
      static/video-play-btn.png
  37. 0 182
      uni_modules/mp-html/README.md
  38. 0 75
      uni_modules/mp-html/changelog.md
  39. 0 458
      uni_modules/mp-html/components/mp-html/mp-html.vue
  40. 0 536
      uni_modules/mp-html/components/mp-html/node/node.vue
  41. 0 1260
      uni_modules/mp-html/components/mp-html/parser.js
  42. 0 79
      uni_modules/mp-html/package.json
  43. 0 0
      uni_modules/mp-html/static/app-plus/mp-html/js/handler.js
  44. 0 0
      uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
  45. 0 1
      uni_modules/mp-html/static/app-plus/mp-html/local.html
  46. 26 29
      utils/config.js
  47. 1 1
      utils/request.js

+ 8 - 0
api/common.js

@@ -39,6 +39,7 @@ export const apiGetWechatPhone=params=>{
  *                    special_column_list(专栏列表) special_column_detail(专栏详情)
  *                    report_list(报告列表) report_detail(报告详情)
  *                    chart_list(图库列表) chart_detail(图库详情)
+ * 					  sandbox_list(沙盘列表) sandbox_detail(沙盘详情)
  * @param version 
  * @param pars 生成海报需要的页面参数
  */
@@ -52,4 +53,11 @@ export const apiGetPoster=params=>{
  */
 export const apiGetSceneToParams=params=>{
     return httpGet('/public/get_suncode_scene',params)
+}
+
+/**
+ * 获取标签树
+ */
+export const apiGetTagTree = params=>{
+    return httpGet('/public/get_variety_tag_tree',params)
 }

+ 23 - 0
api/sandTable.js

@@ -0,0 +1,23 @@
+// 活动模块
+
+import { httpGet, httpPost } from "@/utils/request.js";
+
+/**
+ * 沙盘图列表
+ * @param keyword 沙盘图名称
+ * @param chart_permission_id 分类ID
+ * @param is_high_light 是否高亮搜索词 true | false
+ * @param current_index
+ * @param page_size
+ */
+export const apiSandTableList = (params) => {
+    return httpGet("/sandbox/list", params);
+};
+
+/**
+ * 沙盘图详情
+ * @param sandbox_id 沙盘ID
+ */
+export const apiSandTableDetail = (params) => {
+    return httpGet("/sandbox/detail", params);
+};

+ 9 - 2
api/user.js

@@ -9,6 +9,13 @@ export const apiWechatLogin=params=>{
 	return httpGet('/wechat/login',params)
 }
 
+/**
+ * 顶部tab
+ */
+export const apiHomeTab = () => {
+	return httpGet('/user/get_top_tab')
+}
+
 /**
  * 获取用户tabbar权限
  */
@@ -41,8 +48,8 @@ export const apiUserLogin=params=>{
  * @param company_name 公司名
  * @param permission 选择的权限
  * @param real_name 姓名
- * @param source 来源:我的1、活动2、图库3、研报4
- * @param source_agent 来源平台:1:小程序、2:pc
+ * @param source 来源:我的1、活动2、图库3、研报4、沙盘推演7
+ * @param source_agent 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:官网web(pc)
  * @param from_page 来源页面: '活动列表'、'活动详情'等
  */
 export const apiApplyPermission=params=>{

+ 24 - 0
api/video.js

@@ -0,0 +1,24 @@
+// 视频模块
+
+import { httpGet, httpPost } from "@/utils/request.js";
+
+/**
+ * 视频列表
+ * @param page_index
+ * @param page_size
+ * @param keywords
+ * @param video_id
+ * @param chart_permission_id
+ */
+export const apiVideoList=params=>{
+    return httpGet('/community/video/list',params)
+}
+
+/**
+ * 视频播放埋点
+ * @param video_id
+ * @param source_agent 来源平台:1:小程序、2:小程序(pc)、3:公众号、4:官网web(pc)
+ */
+export const apiVideoPlayLog=params=>{
+    return httpPost('/community/video/play_log',{...params,source_agent:1})
+}

+ 120 - 0
components/searchBox/searchBox.vue

@@ -0,0 +1,120 @@
+<template>
+    <view :class="['flex search-box',isFocus||searchVal?'search-focus':'']">
+        <image 
+            class="search-icon" 
+            :src="isFocus||searchVal?'../../static/search-icon-s.png':'../../static/search-icon.png'" 
+            mode="aspectFill"
+        />
+        <input 
+            type="text" 
+            :maxlength="-1"
+            v-model="searchVal" 
+            :placeholder="placeholder" 
+            :focus="isFocus" 
+            @focus="handelFocus"
+            @blur="handelBlur"
+            @confirm="handleSearch"
+            @input="handleInput"
+            confirm-type="search"
+            :disabled="disabled"
+        />
+        <image 
+            class="search-clear" 
+            src="../../static/search-del.png" 
+            mode="aspectFill"
+            v-if="searchVal"
+            @click="handleClearSearch"
+        />
+        <view class="right-btn" v-if="hasRightBtn&&searchVal" @click="handleSearch">搜索</view>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        hasRightBtn:{
+            type:Boolean,
+            default:true
+        },
+        placeholder:{
+            type:String,
+            default:'请输入搜索关键词'
+        },
+        focus:{
+            type:Boolean,
+            default:false
+        },
+        disabled:{
+            type:Boolean,
+            default:false
+        }
+    },
+    data () {
+        return {
+            searchVal:'',
+            isFocus:this.focus
+        }
+    },
+    methods: {
+        handleClearSearch(){
+            this.searchVal=''
+            this.$emit('change',this.searchVal)
+            this.$emit('search')
+        },
+
+        handleInput(){
+            this.$emit('change',this.searchVal)
+        },
+
+        handelFocus(){
+            this.isFocus=true
+        },
+
+        handelBlur(){
+            this.isFocus=false
+        },
+
+        handleSearch(){
+            this.$emit('search')
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.search-box{
+    border: 1px solid #E5E5E5;
+    align-items: center;
+    background-color: #F6F6F6;
+    border-radius: 43rpx;
+    padding: 0 30rpx;
+    height: 70rpx;
+    .search-icon{
+        width: 48rpx;
+        height: 48rpx;
+        flex-shrink: 0;
+        margin-right: 5rpx;
+    }
+    input{
+        flex: 1;
+    }
+    .search-clear{
+        width: 40rpx;
+        height: 40rpx;
+        flex-shrink: 0;
+        margin-left: 5rpx;
+        margin-right: 20rpx;
+    }
+    .right-btn{
+        font-size: 28rpx;
+        color: #E3B377;
+        flex-shrink: 0;
+        border-left: 1px solid #999999;
+        padding-left: 20rpx;
+    }
+}
+.search-focus{
+    border-color: #E3B377;
+    background-color: #fff;
+}
+</style>

+ 6 - 6
custom-tab-bar/index.wxml

@@ -1,6 +1,6 @@
-<view class="tab-bar">
-  <view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-text="{{item.text}}" bindtap="switchTab">
-    <image class="icon" src="{{selected === item.pagePath ? item.selectedIconPath : item.iconPath}}"></image>
-    <view class="text" style="color: {{selected === item.pagePath ? selectedColor : color}}">{{item.text}}</view>
-  </view>
-</view>
+<cover-view class="tab-bar">
+  <cover-view wx:for="{{list}}" wx:key="index" class="tab-bar-item" data-path="{{item.pagePath}}" data-text="{{item.text}}" bindtap="switchTab">
+    <cover-image class="icon" src="{{selected === item.pagePath ? item.selectedIconPath : item.iconPath}}"></cover-image>
+    <cover-view class="text" style="color: {{selected === item.pagePath ? selectedColor : color}}">{{item.text}}</cover-view>
+  </cover-view>
+</cover-view>

+ 1 - 1
mixin/index.js

@@ -5,7 +5,7 @@ moment.locale('zh-cn');
 import {globalImgUrls} from "../utils/config"
 import store from '@/store'
 
-const tabbarPathList=['pages/activity/activity','pages/buy/buy','pages/chart/chart',/* 'pages/user/user', */'pages/report/report','pages/question/question']
+const tabbarPathList=['pages/activity/activity','pages/pricedriven/pricedriven','pages/video/videoList','pages/report/report','pages/question/question']
 
 module.exports = {
   watch: {

+ 1 - 1
mixin/questionMixin.js

@@ -179,7 +179,7 @@ export default {
                 page_index: this.page,
                 page_size: this.pageSize,
                 /* chart_permission_id: this.selectId === -1 ? '' : this.selectId, */
-                group_id: this.selectId === -1 ? '' : this.selectId,
+                variety_tag_id: this.selectId === -1 ? '' : this.selectId,
                 reply_status: status,
                 only_mine:onlyMine
             })

+ 1 - 1
pages-applyPermission/applyPermission.vue

@@ -78,7 +78,7 @@ export default {
                 tel: '',
                 permission: '',
             },
-            source:"",//来源 1-我的 2-活动 3-图库 4-研报 5-问答
+            source:"",//来源 1-我的 2-活动 3-图库 4-研报 5-问答 6价格驱动
             from_page:''
         }
     },

+ 1 - 1
pages-question/answerDetail.vue

@@ -6,7 +6,7 @@
           <view class="question-info">
             <view style="flex: 1" class="question-title">
               <text class="item-label">{{
-                questionItem.research_group_second_name
+                questionItem.variety_tag_name
               }}</text>
               {{ questionItem.question_content }}
             </view>

+ 1 - 1
pages-question/answerList.vue

@@ -27,7 +27,7 @@
               <text
                 class="item-label"
                 v-if="(item.reply_status === 3 || item.replier_user_id == userInfo.user_id) && questionStatus!=2"
-                >{{ item.research_group_second_name }}</text
+                >{{ item.variety_tag_name }}</text
               >
               {{ item.question_content }}
             </view>

+ 3 - 2
pages-report/reportDetail.vue

@@ -1,5 +1,5 @@
 <template>
-    <web-view :src="url" @message="handleGetMessage"/></web-view>
+    <web-view :src="url" @message="handleGetMessage"></web-view>
 </template>
 
 <script>
@@ -19,7 +19,8 @@ export default {
     onShareAppMessage() {
         return {
             title:this.msgObj.title,
-            path:`/pages-report/reportDetail?reportId=${this.msgObj.reportId}`
+            path:`/pages-report/reportDetail?reportId=${this.msgObj.reportId}`,
+            imageUrl:this.msgObj.shareImg||''
         }
     },
     methods: {

+ 769 - 0
pages-sandTable/sandTable.vue

@@ -0,0 +1,769 @@
+<template>
+	<page-meta :page-style="'padding-bottom: 0;'+'overflow:'+((showFilter||show||showPoster)?'hidden':'visible')"/>
+	<view style="background-color: #F6F6F6;">
+		<!-- 没有权限 -->
+		<block v-if="noAuthor ==1 && isFinished">
+			<view class="sandTable-noAuthor">
+				<block v-if="!applyer.hasApply">
+					<image :src="globalImgUrls.sandBoxNoAuthor" mode="aspectFit"></image>
+					<text style="margin-top: 48rpx;">您暂无权限查看沙盘推演</text>
+					<text style="margin-top: 20rpx;">若想查看可以申请开通</text>
+					<button @click="toApply">立即申请</button>
+				</block>
+				<block v-else>
+					<image class="img-wait" :src="globalImgUrls.chartWait" mode="widthFix" 
+					style="width: 186rpx;margin-top: 200rpx;width: 186rpx;margin-bottom: 50rpx;"></image>
+					<text style="margin-bottom:15px">您已提交申请</text>
+					<text>请等待销售人员与您联系</text>
+				</block>
+			</view>
+		</block>
+		<block v-if="noAuthor ==2 && isFinished">
+			<view class="sandTable-noAuthor">
+				<image :src="globalImgUrls.sandBoxNoAuthor" mode="aspectFit"></image>
+				<text style="margin-top: 48rpx;">您暂无权限查看沙盘推演</text>
+				<text style="margin: 20rpx 0 6rpx 0;">若想查看请联系对口销售</text>
+				<view>
+					<text>{{salesData.name}}:</text><text class="sales-mobile" @click="callToSales">{{salesData.phone}}</text>
+				</view>
+			</view>
+		</block>
+		<!-- 有权限 -->
+		<view v-show="noAuthor ==0 && isFinished" style="padding-top: 156rpx;">
+			<view style="position: fixed;top: 0;width: 100vw;">
+				<view style="height: 2rpx;background-color: #F6F6F6;"></view>
+				  <view class="search-wrap">
+					  <van-search
+						  shape="round"
+						  placeholder="沙盘图名称搜索"
+						  clear-trigger="always"
+						  style="flex-grow: 1"
+						  :value="sandTableQuery.keyword"
+						  @change="searchValChange"
+						  @search="onSearch"
+						  @clear="onClearSearch"
+						  placeholderStyle="color: #999999;"
+					  />
+					  <view class="filtration-icon-zone" @click="showFilter=true">
+						<image
+						  src="../static/sandTable/sandTable_filtration.png"
+						  mode="widthFix"
+						  class="menu-icon"/>
+						<text>筛选</text>
+					  </view>
+				  </view>
+			</view>
+			<!-- 无数据 -->
+			<view class="sandTable-noData" v-if="!list">
+				<image :src="globalImgUrls.sandBoxNoAuthor" mode="aspectFit"></image>
+				<text >暂无数据</text>
+			</view>
+			<view class="sandTable-list" v-else>
+				<view class="sandTable-box" v-for="(item,index) in list" :key="item.sandbox_id">
+					<view class="sandTable-box-top">
+						<view class="sandTable-box-topL">
+							<view class="sandTable-tag">
+								{{item.chart_permission_name}}
+							</view>
+							<rich-text :nodes="item.name" class="sandTable-name"></rich-text>
+						</view>
+						<view class="sandTable-box-topR">
+							<image src="../static/sandTable/fullScreen.png" style="margin-right: 50rpx;" @click="previewImage(index)"></image>
+							<image src="../static/sandTable/sandTable-share.png" @click="generatePoster('detail',item)"></image>
+						</view>
+					</view>
+					<view class="sandTable-item" @click="previewImage(index)">
+						<image :src="item.pic_url" mode="aspectFit"></image>
+<!-- 						<view class="sandTable-item-origin">
+							来源:弘则研究
+						</view> -->
+					</view>
+				</view>
+				<view v-if="list.length==total && list.length>0" class="bottom_text">已经到底了</view>
+			</view>
+		</view>
+	</view>
+	<!-- 筛选弹窗 -->
+	<van-popup :show="showFilter" round position="bottom" @close="showFilter = false" z-index="99999" :safe-area-inset-bottom="true" >
+		<view class="filter-container">
+			<view class="filter-container-header">
+				<text>全部筛选</text>
+				<text style="color: #E3B377;" @click="showFilter=false">取消</text>
+			</view>
+			<view class="list-box">
+				<van-collapse accordion @change="selectFisrtClassify" :value="selectedFirstId" :border="false">
+					<van-collapse-item
+						:title="item.classify_name" 
+						:name='item.id' 
+						:border="false"
+						v-for="item in classfyList"
+						:key="item.id"
+					>
+						<van-row gutter="5">
+							<van-col 
+								:span="_item.chart_permission_name.length>7?16:8" 
+								v-for="_item in item.list" 
+								:key="_item.chart_permission_id"
+							>
+								<text 
+									:class="['list-item',_item.chart_permission_id==selectedSecondId&&'list-item-active']" 
+									@click="handleSelectPerItem(_item)"
+								>{{_item.chart_permission_name}}</text>
+							</van-col>
+						</van-row>
+					</van-collapse-item>
+				</van-collapse>
+			</view>
+		</view>
+	</van-popup>
+	<!-- 分享按钮 -->
+	<image @click="generatePoster('list')" class="share-icon" src="@/static/share-poster-icon.png" mode="aspectFill" v-if="noAuthor==0&&isFinished"/>
+	<!-- 生成海报弹窗  -->
+	<div class="share-poster-wrap" @touchmove.prevent>
+		<div class="poster-mask" v-if="show||showPoster" @click="showPoster=false" @touchmove.prevent></div>
+        <div class="loading-box" v-if="show">
+            <img class="load-img" src="../static/loading.png"/>
+            <div>海报生成中...</div>
+        </div>
+		<img v-if="showPoster" class="poster-img" mode="widthFix" :src="posterImg" show-menu-by-longpress />
+	</div>
+
+</template>
+
+<script>
+	import {apiSandTableList,apiSandTableDetail} from "../api/sandTable.js"
+	import {apiReportIndexPageAuthList} from "../api/report.js"
+	import {apiGetPoster,apiGetSceneToParams} from "../api/common.js"
+	import {apiApplyPermission} from "../api/user.js"
+	export default {
+		data() {
+			return {
+				sandTableQuery:{
+					page_size: 20,
+					curr_page: 1,
+					keyword:'' ,
+					chart_permission_id: 0,
+					is_high_light:false // 是否高亮
+				},
+				total:0,
+				isRequseting:false,
+				showFilter:false,
+				list:[],
+				classfyList:[],
+				selectedFirstId:0,
+				selectedSecondId:0,
+				// 是否显示过全部加载弹窗
+				haveShowToast:false,
+				showPoster:false,
+				show:false,
+				// 是否跳转到申请结果页面
+				haveGoToResult:false,
+				// 是否请求完成
+				isFinished:false,
+				posterImg:'',
+				// 没有权限  1:立即申请 2:联系销售
+				noAuthor:0,
+				// 销售信息
+				salesData:{
+					phone:'',
+					name:''
+				},
+				// 申请权限时的用户信息
+				applyer:{
+					name:'',
+					company:'',
+					// 是否已经申请
+					hasApply:false,
+					// 状态
+					status:''
+				}
+			}
+		},
+		onLoad(options) {
+			this.init(options)
+		},
+		onShow(options) {
+			// 预览图片结束时,会触发onShow,切回竖屏
+			uni.setPageOrientation({orientation : "portrait"})
+			if(this.haveGoToResult){
+				//从申请结果页面回来 
+				this.getSandBoxList()
+				this.haveGoToResult=false
+			}
+		},
+		// 小程序自带分享
+		onShareAppMessage() {
+			let {keyword,chart_permission_id,is_high_light} = this.sandTableQuery
+		    return {
+		        title:'沙盘推演',
+				path:`/pages-sandTable/sandTable?keyword=${keyword}&chart_permission_id=${chart_permission_id}`+
+				`&is_high_light=${is_high_light}&firstClassifyId=${this.selectedFirstId}`
+		    }
+		},
+		onPullDownRefresh() {
+			this.sandTableQuery.curr_page=1
+			this.sandTableQuery.chart_permission_id = this.selectedSecondId = this.selectedFirstId=0
+			this.sandTableQuery.keyword=''
+			this.is_high_light=false
+			this.haveShowToast=false
+			this.getSandBoxList('stopPullDown')
+			this.getClassifyList()
+		},
+		onReachBottom() {
+			if(this.isRequseting) return 
+			if(this.list.length>=this.total && this.total!=0){
+				// if(this.haveShowToast) return
+				// // 只显示一次
+				// this.haveShowToast = true
+				// uni.showToast({
+				// 	title:"没有了~",
+				// 	icon:'none'
+				// })
+				return
+			}
+			this.sandTableQuery.curr_page++
+			this.getSandBoxList()
+		},
+		methods: {
+			async init(options){
+				let obj={}
+				if(options.scene){
+					let res = await apiGetSceneToParams({scene_key:options.scene})
+					if(res.code==200){
+						obj=JSON.parse(res.data)
+					}
+				}
+				// 有sandbox_id 说明是单个分享进来的
+				if(obj.sandbox_id){
+					this.selectedFirstId = obj.firstClassifyId || 0
+					this.selectedSecondId = obj.chart_permission_id || 0
+					this.getSandBoxDetail(obj.sandbox_id)
+				}else{
+					this.sandTableQuery.keyword = obj.keyword || ""
+					this.selectedFirstId = obj.firstClassifyId || 0
+					this.sandTableQuery.chart_permission_id = this.selectedSecondId = obj.chart_permission_id || 0
+					this.sandTableQuery.is_high_light = obj.is_high_light || false
+					this.getSandBoxList()
+				}
+				this.getClassifyList()
+			},
+			// 获取沙盘图数据
+			getSandBoxList(option){
+				this.isRequseting=true
+				apiSandTableList(this.sandTableQuery).then(({data:{list,paging,type,name,mobile,customer_info},code})=>{
+					if(option == 'stopPullDown'){
+						uni.stopPullDownRefresh()
+					}
+					// 403 没有权限
+					if(code==403){
+						this.applyer.name = customer_info.name
+						this.applyer.company = customer_info.company_name
+						this.applyer.hasApply = customer_info.has_apply
+						this.applyer.status = customer_info.status
+						if(type == 'apply'){
+							// 申请
+							this.noAuthor =1
+						}else{
+							// 联系销售
+							this.noAuthor =2
+							this.salesData.name=name
+							this.salesData.phone=mobile
+						}
+						return 
+					}
+					if(this.sandTableQuery.curr_page==1){
+						this.list = list
+						this.total = paging.totals
+					}else{
+						this.list = [...this.list,...list]
+					}
+					this.noAuthor=0
+				})
+				.finally(res=>{
+					this.isRequseting=false
+					this.isFinished=true
+					this.showFilter=false
+				})
+			},
+			getSandBoxDetail(sandbox_id){
+				this.isRequseting=true
+				apiSandTableDetail({sandbox_id}).then(({data,code})=>{
+					if(code==403){
+						this.applyer.name = data.customer_info.name
+						this.applyer.company = data.customer_info.company_name
+						this.applyer.hasApply = data.customer_info.has_apply
+						this.applyer.status = data.customer_info.status
+						if(data.type == 'apply'){
+							// 申请
+							this.noAuthor =1
+						}else{
+							// 联系销售
+							this.noAuthor =2
+							this.salesData.name=data.name
+							this.salesData.phone=data.mobile
+						}
+						return 
+					}
+					this.list= [data]
+					this.noAuthor=0
+				})
+				.finally(res=>{
+					this.isRequseting=false
+					this.isFinished=true
+					this.showFilter=false
+				})
+			},
+			// 获取分类数据
+			getClassifyList(){
+				apiReportIndexPageAuthList().then(({data:{permission_list}})=>{
+					// 过滤掉'更多报告' 和 没有权限的分类
+					this.classfyList = permission_list.filter(item => item.sort!=100000)
+					this.classfyList.forEach(item=>{
+						item.list=item.list.filter(it=>it.auth_ok)
+					})
+					this.classfyList=this.classfyList.filter(item=>item.list.length!=0)
+				})
+			},
+			// 权限申请
+			toApply(type=''){
+				if(type=='auto'){
+					apiApplyPermission({
+						company_name:this.applyer.company,
+						real_name:this.applyer.name,
+						source:7,
+						from_page:'沙盘推演',
+					}).then(res=>{
+						console.log('自动申请成功');
+					})
+				}else{
+					if(this.applyer.status==='流失'){
+						apiApplyPermission({
+							company_name:this.applyer.company,
+							real_name:this.applyer.name,
+							source:7,
+							from_page:'沙盘推演',
+						}).then(res=>{
+							this.haveGoToResult=true
+							uni.navigateTo({url:'/pages-applyPermission/applyResult'})
+						})
+					}else{
+						uni.navigateTo({ url: '/pages-applyPermission/applyPermission?source=7&from_page=沙盘推演' })
+					}
+				}
+			},
+			// 联系销售申请权限
+			callToSales(){
+				if(!this.applyer.hasApply){
+				    this.toApply('auto')
+				}
+				uni.makePhoneCall({
+				    phoneNumber: this.salesData.phone,
+				    success: (result) => {},
+				    fail: (error) => {}
+				})
+			},
+			// 搜索内容变化
+			searchValChange(e){
+			  this.sandTableQuery.keyword=e.detail
+			  // this.sandTableQuery.is_high_light = true
+			  // this.getSandBoxList()
+			},
+			// 清除搜索内容
+			onClearSearch(){
+				this.sandTableQuery={
+					page_size: 20,
+					curr_page: 1,
+					keyword:'' ,
+					chart_permission_id: 0,
+					is_high_light:false
+				}
+				this.selectedFirstId = this.selectedSecondId = 0
+				this.haveShowToast=false
+				this.getSandBoxList()
+			},
+			// 确认搜索
+			onSearch(){
+			  this.sandTableQuery.chart_permission_id= this.selectedFirstId = this.selectedSecondId = 0
+			  this.sandTableQuery.is_high_light = true
+			  this.haveShowToast=false
+			  this.getSandBoxList()
+			},
+			// 选中一级分类
+			selectFisrtClassify(e){
+				this.selectedFirstId = e.detail
+			},
+			handleSelectPerItem(item){
+				if(this.selectedSecondId==item.chart_permission_id){
+				    this.sandTableQuery.chart_permission_id=this.selectedSecondId=0
+				}else{
+				    this.sandTableQuery.chart_permission_id=this.selectedSecondId=item.chart_permission_id
+				}
+				this.sandTableQuery.curr_page=1
+				uni.pageScrollTo({
+					scrollTop:0,
+					duration:300
+				})
+				this.showFilter=false
+				this.getSandBoxList()
+			},
+			// 预览图片
+			previewImage(index){
+				// 先切换横屏才预览图片 ,预览图片开启之后 切换不了横屏
+				uni.setPageOrientation({orientation : "landscape"}).finally(()=>{
+					// 在回调函数中 用setTimeout将预览图片的任务 再往后排 不然可能会切换失败
+					setTimeout(()=>{
+						uni.previewImage({
+							urls:this.list.map(item=> item.pic_url),
+							current:index,
+							showmenu:false
+						})
+					},10)
+				})
+			},
+			// 生成海报
+			generatePoster(type,item=''){
+				this.handleCreatePoster(type,item)
+			},
+			async handleCreatePoster(type,item){
+			    this.show=true
+				let code_scene_json = {},source='',parsJson={},code_scene=''
+				if(type == 'detail'){
+					// 分享单个
+					let {chart_permission_id} = item
+					let first_permission_id = 0
+					// 通过分享的沙盘图的二级分类Id,找到对应的一级Id
+					U:for (let item of this.classfyList) {
+						for (let it of item.list) {
+							if(it.chart_permission_id == chart_permission_id){
+								first_permission_id = item.id
+								break U
+							}
+						}
+					}
+					code_scene_json={
+						sandbox_id:item.sandbox_id,
+						chart_permission_id,
+						firstClassifyId:first_permission_id
+					}
+					code_scene=JSON.stringify(code_scene_json)
+					source = 'sandbox_detail'
+					parsJson = {title_1:item.name,img_1:item.pic_url}
+				}else{
+					// 分享列表
+					let {keyword,chart_permission_id,is_high_light} = this.sandTableQuery
+					let firstImageUrl,secondImageUrl;
+					if(!this.list || !this.list[0]){
+						// 分享的列表页一条数据也没有 使用两个默认的沙盘图地址
+						firstImageUrl = this.globalImgUrls.sandBoxShareDefault1
+						secondImageUrl = this.globalImgUrls.sandBoxShareDefault2
+					}else if(!this.list[1]){
+						// 分享的列表页只有一条数据 第二个图片使用默认的沙盘图地址
+						firstImageUrl = this.list[0].pic_url
+						secondImageUrl = this.globalImgUrls.sandBoxShareDefault1
+					}else{
+						// 列表页有数据
+						firstImageUrl = this.list[0].pic_url
+						secondImageUrl = this.list[1].pic_url
+					}
+					code_scene_json={
+						keyword,
+						chart_permission_id,
+						is_high_light,
+						firstClassifyId:this.selectedFirstId
+					}
+					code_scene=JSON.stringify(code_scene_json)
+					source = 'sandbox_list'
+					parsJson = {title_1:'沙盘推演',img_1:firstImageUrl,img_2:secondImageUrl}
+				}
+			    const res=await apiGetPoster({
+			        code_page:'pages-sandTable/sandTable',
+			        code_scene,
+			        source,
+			        pars:JSON.stringify(parsJson),
+					version:'7.0'
+			    })
+			    if(res.code==200){
+			        this.posterImg=res.data
+			        this.show=false
+			        this.showPoster=true
+			    }else{
+			        this.show=false 
+			    }
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page{
+		padding-bottom: 0;
+		// 无权限
+		.sandTable-noAuthor{
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			height: 100vh;
+			image{
+				margin-top: 180rpx;
+			}
+			text{
+				font-family: 'PingFang SC';
+				font-style: normal;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #999999;
+			}
+			.sales-mobile{
+				color: #E3B377;
+			}
+			button{
+				background: #E6B77D;
+				border-radius: 4px;
+				width: 634rpx;
+				height: 80rpx;
+				margin-top: 108rpx;
+				font-family: 'PingFang SC';
+				font-style: normal;
+				font-weight: 500;
+				font-size: 32rpx;
+				color: #FFFFFF;
+			}
+		}
+		// 搜索区域
+		.search-wrap{
+			display: flex;
+			background-color: white;
+			padding: 20rpx 34rpx 20rpx 10rpx;
+			height: 156rpx;
+			align-items: center;
+			.filtration-icon-zone{
+				display: flex;
+				align-items: center;
+				image{
+					width: 52rpx;
+					height: 52rpx;
+				}
+				text{
+					font-family: 'PingFang SC';
+					font-style: normal;
+					font-weight: 400;
+					font-size: 32rpx;
+					color: #E3B377;
+				}
+			}
+		}
+		// 列表区域 无数据
+		.sandTable-noData{
+			display: flex;
+			flex-direction: column;
+			align-items: center;
+			height: calc(100vh - 158rpx);
+			image{
+				margin-top: 180rpx;
+			}
+			text{
+				margin-top: 48rpx;
+				font-family: 'PingFang SC';
+				font-style: normal;
+				font-weight: 400;
+				font-size: 28rpx;
+				color: #999999;
+			}
+		}
+		// 列表区域
+		.sandTable-box{
+			padding: 24rpx 34rpx 40rpx 34rpx;
+			background-color: white;
+			margin-top: 10rpx;
+			.sandTable-box-top{
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				margin-bottom: 32rpx;
+				.sandTable-box-topL{
+					display: flex;
+					align-items: center;
+					.sandTable-tag{
+						margin-right: 20rpx;
+						padding: 4rpx 22rpx;
+						background: #333333;
+						border-radius: 8rpx 8rpx 8rpx 8rpx;
+						font-size: 24rpx;
+						font-family: PingFang SC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #E4B478;
+						display: flex;
+						align-items: center;
+						justify-content: center;
+					}
+					.sandTable-name{
+						font-size: 32rpx;
+						font-family: PingFang SC-Medium, PingFang SC;
+						font-weight: 500;
+						color: #333333;
+						max-width: 390rpx;
+					}
+				}
+				.sandTable-box-topR{
+					display: flex;
+					align-items: center;
+					image{
+						width: 32rpx;
+						height: 32rpx;
+					}
+				}
+			}
+			.sandTable-item{
+				border: 2rpx solid #C4C4C4;
+				image{
+					width: 100%;
+					height: 480rpx;
+				}
+				.sandTable-item-origin{
+					text-align: right;
+					padding:0 24rpx 20rpx 0 ;
+					font-size: 20rpx;
+					font-family: PingFang SC-Regular, PingFang SC;
+					font-weight: 400;
+					color: #666666;
+				}
+			}
+		}
+		.bottom_text{
+			display: flex;
+			justify-content: center;
+			height: 60rpx;
+			color: gray;
+			font-size: 32rpx;
+		}
+		// 过滤弹窗
+		.filter-container{
+			height: 700rpx;
+			width: 100vw;
+			position: relative;
+			.filter-container-header{
+				padding: 54rpx 34rpx 20rpx 34rpx;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				text{
+					font-size: 32rpx;
+					font-family: PingFang SC-Medium, PingFang SC;
+					font-weight: 500;
+					color: #000000;
+				}
+			}
+			.list-box{
+			    min-height: 30vh;
+			    max-height: 60vh;
+			    .list-item{
+			        display: block;
+			        margin: 10rpx;
+			        height: 76rpx;
+			        line-height: 76rpx;
+			        color: #000;
+			        background: #F6F6F6;
+			        border-radius: 4px 4px 4px 4px;
+			        text-align: center;
+			    }
+			    .list-item-active{
+			        background-color: #FAEEDE;
+			    }
+			}
+			button{
+				position: absolute;
+				bottom: 0;
+				height: 80rpx;
+				width: 100vw;
+				border-radius: 0;
+				background-color: #E6B77D;
+				font-size: 32rpx;
+				font-family: PingFang SC-Medium, PingFang SC;
+				font-weight: 500;
+				color: #FFFFFF;
+			}
+		}
+		// 分享海报
+		.share-poster-wrap{
+		    .poster-mask{
+		        position: fixed;
+		        left: 0;
+		        top: 0;
+		        right: 0;
+		        bottom: 0;
+		        background: rgba(0, 0, 0, 0.4);
+		        z-index: 998;
+		    }
+		    .loading-box{
+		        background-color: #fff;
+		        position: fixed;
+		        left: 50%;
+		        top: 50%;
+		        z-index: 999;
+		        transform: translate(-50%,-50%);
+		        width: 417rpx;
+		        height: 261rpx;
+		        text-align: center;
+		        padding-top: 80rpx;
+		        font-size: 32rpx;
+		        font-weight: bold;
+		        .load-img{
+		            width: 91rpx;
+		            height: 91rpx;
+		            animation: circle 1s linear infinite;
+		        }
+		        @keyframes circle {
+		            0%{
+		                transform: rotateZ(0);
+		            }
+		            100%{
+		                transform: rotateZ(360deg);
+		            }
+		        }
+		    }
+		    .poster-img{
+		        width: 90vw;
+		        display: block;
+		        position: fixed;
+		        left: 50%;
+		        top: 50%;
+		        z-index: 999;
+		        transform: translate(-50%,-50%);
+		        border-radius: 16rpx;
+		    }
+		}
+		// 分享图标
+		.share-icon{
+			position: fixed;
+			bottom: 100rpx;
+			right: 34rpx;
+			z-index: 50;
+			width: 76rpx;
+			height: 76rpx;
+		}
+	
+	}
+
+</style>
+<style scoped>
+ /deep/ .van-search__content{background-color:#F6F6F6;
+border: 2px solid #E5E5E5;box-sizing: border-box;}
+</style>
+<style lang='scss'>
+.filter-container{
+    .list-box{
+        .van-cell__title, .van-cell__value{
+            flex: none !important;
+        }
+        .van-cell:after{
+            border: none !important;
+        }
+        .van-cell__title{
+            font-size: 14px;
+        }
+        .van-hairline--top:after{
+            border-top-width: 0 !important;
+        }
+    }
+}
+</style>

+ 46 - 19
pages.json

@@ -4,6 +4,7 @@
 			"path": "pages/report/report",
 			"style": {
 				"navigationBarTitleText": "FICC研报",
+				"navigationStyle": "custom",
 				"enablePullDownRefresh": true
 			}
 		},
@@ -17,7 +18,7 @@
 		{
 			"path": "pages/chart/chart",
 			"style": {
-				"navigationBarTitleText": "ETA图库",
+				"navigationBarTitleText": "图库",
 				"enablePullDownRefresh": true
 			}
 		},
@@ -52,6 +53,25 @@
 			"style":{
 				"navigationBarTitleText": ""
 			}
+		},
+		{
+			"path": "pages/pricedriven/pricedriven",
+			"style":{
+				"navigationBarTitleText":"价格驱动"
+			}
+		},
+		{
+			"path": "pages/video/videoList",
+			"style": {
+				"navigationBarTitleText": "视频社区",
+				"enablePullDownRefresh": true
+			}
+		},
+		{
+			"path": "pages/video/videoSearch",
+			"style": {
+				"navigationBarTitleText": "视频社区"
+			}
 		}
 	],
 	"subPackages":[
@@ -238,6 +258,19 @@
 					}
 				}
 			]
+		},
+		// 沙盘图
+		{
+			"root": "pages-sandTable",
+			"pages": [
+				{
+					"path": "sandTable",
+					"style":{
+						"navigationBarTitleText": "沙盘推演",
+						"enablePullDownRefresh": true
+					}
+				}
+			]
 		}
 	],
 		
@@ -248,21 +281,21 @@
 		"list": [
 			{
 				"pagePath": "pages/report/report",
-				"text": "报告",
+				"text": "首页",
 				"iconPath": "./static/tabbar/report.png",
 				"selectedIconPath": "./static/tabbar/report-s.png"
 			},
 			{
-				"pagePath": "pages/buy/buy",
-				"text": "已购",
-				"iconPath": "./static/tabbar/buy.png",
-				"selectedIconPath": "./static/tabbar/buy-s.png"
+				"pagePath": "pages/pricedriven/pricedriven",
+				"text": "价格驱动",
+				"iconPath": "./static/tabbar/price.png",
+				"selectedIconPath": "./static/tabbar/price-s.png"
 			},
 			{
-				"pagePath": "pages/chart/chart",
-				"text": "图库",
-				"iconPath": "./static/tabbar/chart.png",
-				"selectedIconPath": "./static/tabbar/chart-s.png"
+				"pagePath": "pages/video/videoList",
+				"text": "视频社区",
+				"iconPath": "./static/tabbar/video.png",
+				"selectedIconPath": "./static/tabbar/video-s.png"
 			},
 			{
 				"pagePath": "pages/activity/activity",
@@ -270,12 +303,6 @@
 				"iconPath": "./static/tabbar/activity.png",
 				"selectedIconPath": "./static/tabbar/activity-s.png"
 			},
-			/* {
-				"pagePath": "pages/user/user",
-				"text": "我的",
-				"iconPath": "./static/tabbar/user.png",
-				"selectedIconPath": "./static/tabbar/user-s.png"
-			}, */
 			{
 				"pagePath": "pages/question/question",
 				"text": "问答",
@@ -302,16 +329,16 @@
 			"van-icon": "/wxcomponents/vant/icon/index",
 			"van-radio": "/wxcomponents/vant/radio/index",
 			"van-tab": "/wxcomponents/vant/tab/index",
-  		"van-tabs": "/wxcomponents/vant/tabs/index",
+  			"van-tabs": "/wxcomponents/vant/tabs/index",
 			"van-count-down": "/wxcomponents/vant/count-down/index",
 			"van-empty": "/wxcomponents/vant/empty/index",
 			"van-checkbox": "/wxcomponents/vant/checkbox/index",
 			"van-transition": "/wxcomponents/vant/transition/index",
 			"van-collapse": "/wxcomponents/vant/collapse/index",
-  		"van-collapse-item": "/wxcomponents/vant/collapse-item/index",
+  			"van-collapse-item": "/wxcomponents/vant/collapse-item/index",
 			"van-tag": "/wxcomponents/vant/tag/index",
 			"van-row": "/wxcomponents/vant/row/index",
-  		"van-col": "/wxcomponents/vant/col/index",
+  			"van-col": "/wxcomponents/vant/col/index",
 			"van-progress": "/wxcomponents/vant/progress/index",
 			"van-dialog": "/wxcomponents/vant/dialog/index"
 		}

+ 3 - 0
pages/pc.vue

@@ -8,6 +8,7 @@
 import {pcBaseUrl} from '../utils/config'
 const mapObj=new Map([
     ['pages/activity/activity','/activity/list'],
+	 ['pages/pricedriven/pricedriven','/pricedriven'],
     ['pages-activity/detail','/activity/detail'],
     ['pages/report/report','/report/index'],
     ['pages-report/classify','/report/classify'],
@@ -16,6 +17,8 @@ const mapObj=new Map([
     ['pages-report/chapterDetail','/report/chapterdetail'],
     ['pages-report/specialColumn/list','/report/specialcolumnlist'],
     ['pages-report/specialColumn/detail','/report/specialcolumndetail'],
+    ['pages/video/videoList','/video/list'],
+	['pages-sandTable/sandTable','/sandBox/list']
 ])//map映射小程序页面路径对应h5页面路径
 import {apiUserInfo} from '@/api/user'
 import {apiGetSceneToParams} from '@/api/common'

+ 62 - 0
pages/pricedriven/pricedriven.vue

@@ -0,0 +1,62 @@
+<template>
+    <web-view :src="url" @message="handleGetMessage"/></web-view>
+</template>
+
+<script>
+import {h5BaseUrl} from '@/utils/config'
+import {apiGetSceneToParams} from '@/api/common'
+export default {
+    data () {
+        return {
+            url:'',
+            msgObj:{},
+						options: {}
+        }
+    },
+    onLoad(options) {
+			this.options = options;
+        
+    },
+	 onShow() {
+			this.init(this.options)
+	 },
+      onHide() {
+         this.options = {}
+     },
+    onShareAppMessage() {
+        return {
+            title:this.msgObj.title,
+            path:`/pages/pricedriven/pricedriven?default_classify_first=${this.msgObj.default_classify_first}&default_classify_sub=${this.msgObj.default_classify_sub}`
+        }
+    },
+    methods: {
+        async init(options){
+            console.log('options',options);
+            if(options.scene){
+                const res=await apiGetSceneToParams({scene_key:options.scene})
+                if(res.code==200){
+                    console.log(res);
+                    const obj=JSON.parse(res.data)
+                    console.log(obj);
+                    options.default_classify_first=obj.default_classify_first
+						  options.default_classify_sub = obj.default_classify_sub
+                    console.log(options);
+                }
+            }
+
+            let default_classify_first=options.default_classify_first || ''
+						let default_classify_sub=options.default_classify_sub || ''
+						let timestamp = new Date().getTime();
+            const token=this.$store.state.user.token
+            this.url=`${h5BaseUrl}/hzyb/pricedriven/detail?default_classify_first=${default_classify_first}&default_classify_sub=${default_classify_sub}&token=${token}&timestamp=${timestamp}#wechat_redirect`
+        },
+
+        handleGetMessage(e){
+            const data=e.detail.data[e.detail.data.length-1]
+            console.log('h5传来的数据',data);
+            this.msgObj=data
+        }
+    }
+    
+}
+</script>

+ 15 - 2
pages/question/question.vue

@@ -39,7 +39,7 @@
 				<view class="question-item" v-for="item in questionList" :key="item.community_question_id">
 					<view class="question-info">
 						<view style="flex:1;" class="question-title">
-							<text class="item-label">{{item.research_group_second_name}}</text>
+							<text class="item-label">{{item.variety_tag_name}}</text>
 							<!-- <text class="item-title"> -->{{ item.question_content }}<!-- </text> -->
 						</view>	
 						<view class="item-answer">
@@ -135,6 +135,7 @@
 <script>
 import mixin from "../../mixin/questionMixin";
 import {apiOptionGroupList,apiBarTotal} from '@/api/question'
+import {apiGetTagTree} from '@/api/common'
 export default {
 	mixins: [mixin],
 	data() {
@@ -201,9 +202,21 @@ export default {
 		},
 		//获取筛选列表
 		async getOptionList(){
-			const res = await apiOptionGroupList()
+		/* 	const res = await apiOptionGroupList()
 			if(res.code===200){
 				this.optionList = res.data
+			} */
+			const res = await apiGetTagTree()
+			if(res.code===200){
+				const result = res.data
+				this.optionList = result.map((item)=>{
+					let obj = {}
+					obj.research_group_name = item.classify_name
+					obj.children = item.tags.map((i)=>{
+						return {research_group_id:i.tag_id,research_group_name:i.tag_name}
+					})
+					return obj
+				})
 			}
 		},	
 		//点击筛选

+ 92 - 26
pages/report/report.vue

@@ -2,36 +2,35 @@
   <view class="report-page">
     <view class="top-sticky" style="background: #fff">
     <!-- 导航 -->
-    <!-- <view class="nav-bar-wrap" :style="{height:navBarStyle.height,paddingTop:navBarStyle.paddingTop,paddingBottom:navBarStyle.paddingBottom}">
+    <view class="nav-bar-wrap" :style="{height:navBarStyle.height,paddingTop:navBarStyle.paddingTop,paddingBottom:navBarStyle.paddingBottom}">
       <view class="content">
+		  <view class="avatar" @click="goUser">
+			<image style="width:100%;height:100%;border-radius: 50%" :src="userInfo.head_img_url" mode="aspectFill"/>
+		  </view>
         <van-icon custom-class="search-icon" name="search" size="24px" @click="goSearch" />
         <view class="text">FICC研报</view>
       </view>
-    </view> -->
+    </view>
+	
+	<!-- card -->
+	<view class="tab-card">
+		<view 
+			class="card-item" 
+			v-for="(tab,index) in tabCards" 
+			:key="index" 
+			@click="linkPage(tab)"
+		>
+			<image :src="tab.icon" mode="aspectFill" class="card-ico"/>
+			<view class="title">{{tab.tab}}</view>
+		</view>
+	</view>
+	
     <!-- 分类 -->
     <view class="type-wrap">
-      <view style="display:flex;align-items: center;margin-bottom: 20rpx;">
-        <view class="avatar" @click="goUser">
-          <image style="width:100%;height:100%" :src="userInfo.head_img_url" mode="aspectFill"/>
-        </view>
-        <view style="flex:1" @click="goSearch">
-          <van-search
-                shape="round"
-                disabled
-                placeholder="请输入报告标题或关键字"
-            />
-        </view>
-        
-      </view>
       <view class="flex first-type-box">
-        <view class="item" v-for="(item,index) in topFirstList" :key="item.classify_name" @click="handleClickTopFirst(item,index)">
-          <image :src="selectTopFirstId==item.classify_name?item.select_icon_url:item.icon_url" mode="aspectFill"/>
+        <view :class="['item',{ act: selectTopFirstId==item.classify_name }]" v-for="(item,index) in topFirstList" :key="item.classify_name" @click="handleClickTopFirst(item,index)">
           <view>{{item.classify_name}}</view>
         </view>
-        <!-- <view class="item" @click="goClassify">
-          <image src="@/static/report-menu.png" mode="aspectFill"/>
-          <view>查看更多</view>
-        </view> -->
       </view>
       <view class="flex sub-type-box">
         <view 
@@ -88,6 +87,7 @@
 const moment=require('@/utils/moment-with-locales.min')
 moment.locale('zh-cn');
 import {apiReportIndexPageAuthList,apiReportIndexPageList} from '@/api/report'
+import { apiHomeTab } from '@/api/user.js';
 export default {
   filters: {
     getListTime(e){
@@ -115,12 +115,21 @@ export default {
       dateArr:[],
       page:1,
       pageSize:20,
-      finished:false
+      finished:false,
+	  
+		tabPathMap: new Map([
+			['report','/pages-report/classify'],
+			['chart','/pages/chart/chart'],
+			['buy','/pages/buy/buy'],
+			['sandbox','/pages-sandTable/sandTable'],
+		]),
+		tabCards: []
     }
   },
   onLoad(){ 
     this.initNavBar()
     this.getTopAuthList()
+	 this.getTopTab();
   },
   onShow() {
     uni.getSystemInfo({
@@ -167,10 +176,18 @@ export default {
       if(res.code===200){
         this.authData.isBuy=res.data.check_flag
         this.authData.contactInfo=res.data.contact_info
-        this.topFirstList=res.data.permission_list
+        this.topFirstList=res.data.permission_list.slice(0,4)
         this.handleClickTopFirst(this.topFirstList[0],0)
       }
     },
+	 
+	/* 顶部tab */
+	 async getTopTab() {
+		const { code,data } = await apiHomeTab()
+		
+		if(code !== 200) return
+		this.tabCards = data;
+	 },
 
     //点击顶部一级分类
     handleClickTopFirst(item,index){
@@ -244,6 +261,18 @@ export default {
       }
     },
 
+	//跳转
+	linkPage({mark}) {
+		const url = this.tabPathMap.get(mark);
+		uni.navigateTo({ url,
+			fail () {
+			   uni.switchTab({
+				  url,
+			   })
+		   } 
+		})
+	},
+	
     // 跳转分类
     goClassify(){
       uni.navigateTo({ url: '/pages-report/classify' })
@@ -260,7 +289,7 @@ export default {
         url: '/pages/user/user',
         fail () {
           uni.switchTab({
-            url:'/pages/user/user'
+            url:'/pages/user/user',
           })
         }
       })
@@ -308,10 +337,19 @@ export default {
     height: 100%;
     .search-icon{
       position: absolute;
-      left: 34rpx;
+      left: 134rpx;
       top: 50%;
       transform: translateY(-50%);
     }
+	.avatar {
+		width: 60rpx;
+		height: 60rpx;
+		border-radius: 50%;
+		position: absolute;
+		left: 34rpx;
+		top: 50%;
+		transform: translateY(-50%);
+	}
   }
   
 }
@@ -363,13 +401,18 @@ movable-area{
     height:78rpx;
     border-radius: 50%;
     overflow: hidden;
-    margin-right: 15rpx;
+    margin-right: 30rpx;
   }
   .first-type-box{
     justify-content: space-between;
     .item{
+		 min-width: 120rpx;
       flex-shrink: 0;
       text-align: center;
+		padding: 16rpx 0;
+		text-align: center;
+		background-color: #F5F5F5;
+		border-radius: 8rpx;
       font-size: $global-font-size-sm;
       image{
         width: 100rpx;
@@ -378,6 +421,10 @@ movable-area{
         margin: 0 auto 15rpx auto;
       }
     }
+	 .act {
+		background: #FDF8F2;
+		color: #E3B377;
+	 }
   }
   .sub-type-box{
     margin-top: 40rpx;
@@ -494,4 +541,23 @@ movable-area{
   z-index: 50;
 }
 
+.tab-card {
+	display: flex;
+	padding:  40rpx 34rpx 20rpx;
+	align-items: center;
+	justify-content: space-around;
+	.card-item {
+		margin-right: 40rpx;
+		&:last-child { margin-right: 0; }
+		.card-ico {
+			width: 100rpx;
+			height: 100rpx;
+			display: block;
+		}
+		.title {
+			text-align: center;
+		}
+	}
+}
+
 </style>

+ 392 - 0
pages/video/videoList.vue

@@ -0,0 +1,392 @@
+<template>
+    <view class="video-list-page">
+        <van-sticky style="background: #fff">
+            <view class="flex search-wrap">
+                <view @click="goSearchPage" style="flex:1;margin-right:30rpx" >
+                    <searchBox 
+                        placeholder="关键字搜索" 
+                        :hasRightBtn="false" 
+                        :disabled="true"
+                    ></searchBox>
+                </view>
+                <view class="flex" @click="showFilter=true">
+                    <image style="width:50rpx;height:50rpx" src="@/static/filter-icon.png" mode="aspectFill"/>
+                    <text style="color:#E3B377;font-size:32rpx">筛选</text>
+                </view>
+            </view>
+        </van-sticky>
+        <view class="empty-box" v-if="list.length==0&&finished">
+            <image
+                :src="globalImgUrls.activityNoAuth"
+                mode="widthFix"
+            />
+            <view>暂无数据</view>
+        </view>
+        <view class="list-wrap">
+            <view class="item" v-for="item in list" :key="item.community_video_id">
+                <view class="title-box">
+                    <text class="tag">{{item.variety_tag_name}}</text>
+                    <text class="title">{{item.title}}</text>
+                </view>
+                <button 
+                    class="share-btn" 
+                    open-type="share" 
+                    :data-item="item">
+                    <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
+                </button>
+                <video
+                    autoplay
+                    object-fit="contain"
+                    show-mute-btn
+                    :poster="item.cover_img_url"
+                    :src="item.video_url"
+                    enable-play-gesture
+                    :id="item.community_video_id"
+                    @ended="curVideoId=0"
+                    v-if="item.community_video_id==curVideoId"
+                ></video>
+                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
+                <view class="time">发布时间:{{item.publish_time}}</view>
+            </view>
+        </view>
+
+        <!-- 筛选 -->
+        <van-popup 
+            :show="showFilter" 
+            position="bottom" 
+            :safe-area-inset-bottom="true" 
+            round 
+            @close="showFilter=false"
+        >
+            <view class="filter-wrap">
+                <view class="flex top">
+                    <text style="color:#000">全部筛选</text>
+                    <text style="color:#E3B377" @click="showFilter=false">取消</text>
+                </view>
+                <view class="list-box">
+                    <van-collapse accordion @change="change" :value="active" :border="false">
+                        <van-collapse-item 
+                            :title="item.ClassifyName" 
+                            :name='item.ClassifyName' 
+                            :border="false"
+                            v-for="item in options"
+                            :key="item.ClassifyName"
+                        >
+                            <van-row gutter="5">
+                                <van-col 
+                                    :span="_item.PermissionName.length>7?16:8" 
+                                    v-for="_item in item.Items" 
+                                    :key="_item.PermissionId"
+                                >
+                                    <text 
+                                        :class="['list-item',_item.PermissionId==selectPerId&&'list-item-active']" 
+                                        @click="handleSelectPerItem(_item)"
+                                    >{{_item.PermissionName}}</text>
+                                </van-col>
+                            </van-row>
+                        </van-collapse-item>
+                    </van-collapse>
+                </view>
+            </view>
+        </van-popup>
+    </view>
+    
+</template>
+<script>
+import {apiVideoList,apiVideoPlayLog} from '@/api/video'
+import {apiOptionList} from '@/api/question'
+import {apiGetSceneToParams,apiGetTagTree} from '@/api/common'
+export default {
+    data() {
+        return {
+            showFilter:false,
+            active:'',
+            options:[],
+            selectPerId:0,
+
+            videoId:0,
+            page:1,
+            pageSize:10,
+            finished:false,
+            list:[],
+
+            curVideoId:0,
+        }
+    },
+    onLoad(options){
+        this.init(options)
+        this.getPermissionList()
+    },
+    onHide(){
+        this.showFilter=false
+        this.curVideoId=0
+    },
+    onShareAppMessage({from,target}) {
+        console.log(from,target);
+        let path='/pages/video/videoList?videoId=0'
+        let title='FICC视频社区'
+        let imageUrl=''
+        if(from=='button'){
+            title=`${target.dataset.item.chart_permission_name}:${target.dataset.item.title}`
+            path=`/pages/video/videoList?videoId=${target.dataset.item.community_video_id}`
+            imageUrl=target.dataset.item.cover_img_url
+        }
+        return {
+            title:title,
+            path:path,
+            imageUrl:imageUrl
+        }
+    },
+    onPullDownRefresh(){
+        this.videoId=0
+        this.selectPerId=0
+        this.page=1
+        this.list=[]
+        this.finished=false
+        this.getList()
+        setTimeout(() => {
+            uni.stopPullDownRefresh()
+        }, 1500)
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    methods: {
+        async init(options){
+            if(options.scene){
+                const resScene=await apiGetSceneToParams({scene_key:options.scene})
+                if(resScene.code===200){
+                    const obj=JSON.parse(resScene.data)
+                    this.videoId=obj.videoId||0
+                }
+            }else{
+                this.videoId=options.videoId||0
+            }
+            this.getList()
+        },
+
+        goSearchPage(){
+            uni.navigateTo({
+                url: '/pages/video/videoSearch',
+            });
+        },
+
+        change(e){
+            this.active=e.detail
+        },
+
+        //点击分类某项
+        handleSelectPerItem(item){
+            if(this.selectPerId==item.PermissionId){
+                this.selectPerId=0
+            }else{
+                this.selectPerId=item.PermissionId
+            }
+            
+            this.videoId=0//重置掉分享进入的状态
+            this.curVideoId=0
+            this.page=1
+            this.list=[]
+            this.finished=false
+            this.getList()
+            this.showFilter=false
+        },
+
+        async getList(){
+            const res=await apiVideoList({
+                page_index:Number(this.page),
+                page_size:Number(this.pageSize),
+                video_id:Number(this.videoId),
+                variety_tag_id:Number(this.selectPerId)
+            })
+            if(res.code===200){
+                let arr=res.data||[]
+                this.list=[...this.list,...arr]
+                if(arr.length===0){
+                    this.finished=true
+                }
+            }
+        },
+
+        //获取筛选项
+        async getPermissionList(){
+            /* const res=await apiOptionList()
+            if(res.code===200){
+                this.options=res.data
+            } */
+            const res=await apiGetTagTree()
+            if(res.code===200){
+                const result = res.data||[];
+                this.options = result.map(item=>{
+                    let obj = {};
+                    obj.ClassifyName = item.classify_name;
+                    obj.Items = item.tags.map(_item=>{
+                        return {PermissionId:_item.tag_id,PermissionName:_item.tag_name,PriceDrivenState:_item.price_driven_state};
+                    })
+                    return obj;
+                })
+            }
+        },
+
+        handelClickPlay(item){
+            this.curVideoId=item.community_video_id
+            // 记录播放
+            apiVideoPlayLog({video_id:Number(item.community_video_id)}).then(res=>{
+                if(res.code===200){
+                    console.log('视频埋点成功');
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style lang='scss'>
+.search-wrap .van-search{
+    padding: 0 !important;
+}
+
+.video-list-page{
+    .filter-wrap{
+        .van-cell__title, .van-cell__value{
+            flex: none !important;
+        }
+        .van-cell:after{
+            border: none !important;
+        }
+        .van-cell__title{
+            font-size: 14px;
+        }
+        .van-hairline--top:after{
+            border-top-width: 0 !important;
+        }
+    }
+}
+</style>
+<style lang="scss" scoped>
+.video-list-page{
+    .search-wrap {
+        background-color: #fff;
+        padding: 30rpx 34rpx;
+        align-items: center;
+        .menu-icon{
+            width: 52rpx;
+            height: 40rpx;
+            display: block;
+            flex-shrink: 0;
+            margin-left: 30rpx;
+        }
+    } 
+    
+    .list-wrap{
+        .item{
+            border-top: 10rpx solid #f9f9f9;
+            padding: 30rpx 34rpx;
+            position: relative;
+            .title-box{
+                padding-right: 40rpx;
+            }
+            .share-btn{
+                position: absolute;
+                top: 34rpx;
+                right: 34rpx;
+                background-color: transparent;
+                width: 36rpx;
+                height: 36rpx;
+                line-height: 1;
+                padding: 0;
+                &::after{
+                    border: none;
+                }
+            }
+            .share-img{
+                width: 32.5rpx;
+                height: 32rpx;
+            }
+            .tag{
+                color: #E4B478;
+                background-color: #333;
+                padding: 5rpx 20rpx;
+                border-radius: 20rpx;
+                font-size: 24rpx;
+                margin-right: 26rpx;
+            }
+            .title{
+                font-size: 32rpx;
+                color: #000;
+            }
+            video{
+                width: 100%;
+                height: 400rpx;
+                margin: 30rpx 0 20rpx 0;
+                border-radius: 20rpx;
+            }
+            .poster{
+                width: 100%;
+                height: 400rpx;
+                margin: 30rpx 0 20rpx 0;
+                border-radius: 20rpx;
+                position: relative;
+                &::after{
+                    content:'';
+                    display: block;
+                    position: absolute;
+                    width: 120rpx;
+                    height: 120rpx;
+                    top: 50%;
+                    left: 50%;
+                    transform: translate(-50%,-50%);
+                    background-image: url('@/static/video-play-btn.png');
+                    background-size: cover;
+                }
+            }
+            .time{
+                font-size: 28rpx;
+                color: #999;
+            }
+        }
+    }
+
+    .empty-box{
+        text-align: center;
+        font-size: 32rpx;
+        color: #999;
+        padding-top: 150rpx;
+        image{
+            width: 80vw;
+            margin-bottom: 57rpx;
+        }
+    }
+}
+
+.filter-wrap{
+    background-color: #fff;
+    padding-top: 53rpx;
+    padding-bottom: 100rpx;
+    .top{
+        font-size: 32rpx;
+        justify-content: space-between;
+        margin-bottom: 40rpx;
+        padding: 0 34rpx;
+    }
+    .list-box{
+        min-height: 30vh;
+        max-height: 60vh;
+        .list-item{
+            display: block;
+            margin: 10rpx;
+            height: 76rpx;
+            line-height: 76rpx;
+            color: #000;
+            background: #F6F6F6;
+            border-radius: 4px 4px 4px 4px;
+            text-align: center;
+        }
+        .list-item-active{
+            background-color: #FAEEDE;
+        }
+    }
+}
+</style>

+ 238 - 0
pages/video/videoSearch.vue

@@ -0,0 +1,238 @@
+<template>
+    <view class="video-search-page">
+        <van-sticky style="background: #fff">
+            <view style="padding:30rpx 34rpx">
+            <searchBox 
+                :focus="focus" 
+                placeholder="关键字搜索" 
+                @change="onChange"
+                @search="onSearch"
+            ></searchBox>
+            </view>
+        </van-sticky>
+        <view class="empty-box" v-if="list.length==0&&finished">
+            <image
+                :src="globalImgUrls.activityNoAuth"
+                mode="widthFix"
+            />
+            <view>暂无数据,试试别的搜索词吧~</view>
+        </view>
+        <view class="list-wrap">
+            <view class="item" v-for="item in list" :key="item.community_video_id">
+                <view class="title-box">
+                    <text class="tag">{{item.chart_permission_name}}</text>
+                    <text class="title">{{item.title}}</text>
+                </view>
+                <button 
+                    class="share-btn" 
+                    open-type="share" 
+                    :data-item="item">
+                    <image class="share-img" src="@/static/share-icon.png" mode="aspectFill"/>
+                </button>
+                <video
+                    autoplay
+                    object-fit="contain"
+                    show-mute-btn
+                    :poster="item.cover_img_url"
+                    :src="item.video_url"
+                    enable-play-gesture
+                    :id="item.community_video_id"
+                    v-if="item.community_video_id==curVideoId"
+                ></video>
+                <image @click="handelClickPlay(item)" v-else class="poster" :src="item.cover_img_url" mode="aspectFill" lazy-load/>
+                <view class="time">发布时间:{{item.publish_time}}</view>
+            </view>
+        </view>
+    </view>
+</template>
+
+<script>
+import searchBox from '@/components/searchBox/searchBox.vue'
+import {apiVideoList,apiVideoPlayLog} from '@/api/video'
+export default {
+    components: {
+        searchBox
+    },
+    data() {
+        return {
+            searchVal:'',
+            focus:true,
+            list:[],
+            finished:false,
+            page:1,
+            pageSize:10,
+
+            curVideoId:0,
+        }
+    },
+    onReachBottom() {
+        if(this.finished) return
+        this.page++
+        this.getList()
+    },
+    onShareAppMessage({from,target}) {
+        console.log(from,target);
+        let path='/pages/video/videoList?videoId=0'
+        let title='FICC视频社区'
+        let imageUrl=''
+        if(from=='button'){
+            title=target.dataset.item.title
+            path=`/pages/video/videoList?videoId=${target.dataset.item.community_video_id}`
+            imageUrl=target.dataset.item.cover_img_url
+        }
+        return {
+            title:title,
+            path:path,
+            imageUrl:imageUrl
+        }
+    },
+    methods: {
+        onChange(e){
+            this.searchVal=e
+        },
+
+        async onSearch(){
+            this.finished=false
+            this.page=1
+            this.list=[]
+            if(!this.searchVal){
+                this.finished=true
+                return
+            }
+            this.getList()
+        },
+
+        async getList(){
+            this.curVideoId=0
+            const res=await apiVideoList({
+                page_index:Number(this.page),
+                page_size:Number(this.pageSize),
+                keywords:this.searchVal
+            })
+            if(res.code===200){
+                let arr=res.data||[]
+                this.list=[...this.list,...arr]
+                if(arr.length===0){
+                    this.finished=true
+                }
+            }
+        },
+
+        handelClickPlay(item){
+            this.curVideoId=item.community_video_id
+            // 记录播放
+            apiVideoPlayLog({video_id:Number(item.community_video_id)}).then(res=>{
+                if(res.code===200){
+                    console.log('视频埋点成功');
+                }
+            })
+        }
+    },
+}
+</script>
+
+<style>
+.van-sticky-wrap--fixed{
+  background-color: #fff;
+}
+page{
+    padding-bottom: 0;
+}
+</style>
+
+<style lang="scss" scoped>
+.video-search-page{
+    .search-wrap {
+        background-color: #fff;
+        padding: 30rpx 34rpx;
+        align-items: center;
+        .menu-icon{
+            width: 52rpx;
+            height: 40rpx;
+            display: block;
+            flex-shrink: 0;
+            margin-left: 30rpx;
+        }
+    } 
+    
+    .list-wrap{
+        .item{
+            border-top: 10rpx solid #f9f9f9;
+            padding: 30rpx 34rpx;
+            position: relative;
+            .title-box{
+                padding-right: 40rpx;
+            }
+            .share-btn{
+                position: absolute;
+                top: 34rpx;
+                right: 34rpx;
+                background-color: transparent;
+                width: 32rpx;
+                height: 32rpx;
+                line-height: 1;
+                padding: 0;
+                &::after{
+                    border: none;
+                }
+            }
+            .share-img{
+                width: 32rpx;
+                height: 32rpx;
+            }
+            .tag{
+                color: #E4B478;
+                background-color: #333;
+                padding: 5rpx 20rpx;
+                border-radius: 20rpx;
+                font-size: 24rpx;
+                margin-right: 26rpx;
+            }
+            .title{
+                font-size: 32rpx;
+                color: #000;
+            }
+            video{
+                width: 100%;
+                height: 400rpx;
+                margin: 30rpx 0 20rpx 0;
+                border-radius: 20rpx;
+            }
+            .poster{
+                width: 100%;
+                height: 400rpx;
+                margin: 30rpx 0 20rpx 0;
+                border-radius: 20rpx;
+                position: relative;
+                &::after{
+                    content:'';
+                    display: block;
+                    position: absolute;
+                    width: 120rpx;
+                    height: 120rpx;
+                    top: 50%;
+                    left: 50%;
+                    transform: translate(-50%,-50%);
+                    background-image: url('@/static/video-play-btn.png');
+                    background-size: cover;
+                }
+            }
+            .time{
+                font-size: 28rpx;
+                color: #999;
+            }
+        }
+    }
+
+    .empty-box{
+        text-align: center;
+        font-size: 32rpx;
+        color: #999;
+        padding-top: 150rpx;
+        image{
+            width: 80vw;
+            margin-bottom: 57rpx;
+        }
+    }
+}
+</style>

BIN
static/arrow-right.png


BIN
static/buy.png


BIN
static/classify.png


BIN
static/filter-icon.png


BIN
static/sandTable/fullScreen.png


BIN
static/sandTable/sandTable-share.png


BIN
static/sandTable/sandTable_filtration.png


BIN
static/search-del.png


BIN
static/search-icon-s.png


BIN
static/search-icon.png


BIN
static/share-icon.png


BIN
static/tabbar/price-s.png


BIN
static/tabbar/price.png


BIN
static/tabbar/video-s.png


BIN
static/tabbar/video.png


BIN
static/video-play-btn.png


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

@@ -1,182 +0,0 @@
-## 功能介绍
-- 全端支持(含 `v3、NVUE`)
-- 支持丰富的标签(包括 `table`、`video`、`svg` 等)
-- 支持丰富的事件效果(自动预览图片、链接处理等)
-- 支持设置占位图(加载中、出错时、预览时)
-- 支持锚点跳转、长按复制等丰富功能
-- 支持大部分 *html* 实体
-- 丰富的插件(关键词搜索、内容 **编辑** 等)
-- 效率高、容错性强且轻量化
-
-查看 [功能介绍](https://jin-yufeng.gitee.io/mp-html/#/overview/feature) 了解更多
-
-## 使用方法
-- `uni_modules` 方式  
-  1. 点击右上角的 `使用 HBuilder X 导入插件` 按钮直接导入项目或点击 `下载插件 ZIP` 按钮下载插件包并解压到项目的 `uni_modules/mp-html` 目录下  
-  2. 在需要使用页面的 `(n)vue` 文件中添加  
-     ```html
-     <!-- 不需要引入,可直接使用 -->
-     <mp-html :content="html" />
-     ```
-     ```javascript
-     export default {
-       data() {
-         return {
-           html: '<div>Hello World!</div>'
-         }
-       }
-     }
-     ```
-  3. 需要更新版本时在 `HBuilder X` 中右键 `uni_modules/mp-html` 目录选择 `从插件市场更新` 即可  
-
-- 源码方式  
-  1. 从 [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) 下载源码  
-     插件市场的 **非 uni_modules 版本** 无法更新,不建议从插件市场获取  
-  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>'
-         }
-       }
-     }
-     ```
-  3. 需要更新版本时执行以下命令即可  
-     ```bash
-     npm update mp-html
-     ```
-  
-  使用 *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) 了解更多

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

@@ -1,75 +0,0 @@
-## v2.2.2(2022-02-26)
-1. `A` 增加了 [pauseMedia](https://jin-yufeng.gitee.io/mp-html/#/advanced/api#pauseMedia) 的 `api`,可用于暂停播放音视频 [详细](https://github.com/jin-yufeng/mp-html/issues/317)
-2. `U` 优化了长内容的加载速度  
-3. `U` 适配 `vue3` [#389](https://github.com/jin-yufeng/mp-html/issues/389)、[#398](https://github.com/jin-yufeng/mp-html/pull/398) by [@zhouhuafei](https://github.com/zhouhuafei)、[#400](https://github.com/jin-yufeng/mp-html/issues/400)
-4. `F` 修复了小程序端图片高度设置为百分比时可能不显示的问题
-5. `F` 修复了 `highlight` 插件部分情况下可能显示不完整的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/403)
-## v2.2.1(2021-12-24)
-1. `A` `editable` 插件增加上下移动标签功能
-2. `U` `editable` 插件支持在文本中间光标处插入内容
-3. `F` 修复了 `nvue` 端设置 `margin` 后可能导致高度不正确的问题
-4. `F` 修复了 `highlight` 插件使用压缩版的 `prism.css` 可能导致背景失效的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/367)
-5. `F` 修复了编辑状态下使用 `emoji` 插件内容为空时可能报错的问题 [详细](https://github.com/jin-yufeng/mp-html/issues/371)
-6. `F` 修复了使用 `editable` 插件后将 `selectable` 属性设置为 `force` 不生效的问题
-## 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)

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

@@ -1,458 +0,0 @@
-<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.2
- * @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
-import Parser from './parser'
-const plugins=[]
-// #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: {
-      type: String,
-      default: ''
-    },
-    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]
-  },
-  // #ifdef VUE3
-  emits: ['load', 'ready', 'imgtap', 'linktap', 'error'],
-  // #endif
-  // #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 暂停播放媒体
-     */
-    pauseMedia () {
-      for (let i = (this._videos || []).length; i--;) {
-        this._videos[i].pause()
-      }
-      // #ifdef APP-PLUS
-      const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
-      // #ifndef APP-PLUS-NVUE
-      let page = this.$parent
-      while (!page.$scope) page = page.$parent
-      page.$scope.$getAppWebview().evalJS(command)
-      // #endif
-      // #ifdef APP-PLUS-NVUE
-      this.$refs.web.evalJs(command)
-      // #endif
-      // #endif
-    },
-
-    /**
-     * @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>

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

@@ -1,536 +0,0 @@
-<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 && VUE2) -->
-      <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 -->
-      <!-- #ifdef APP-PLUS && VUE3 -->
-      <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;'+n.attrs.style" :src="n.attrs.src||(ctrl.load?n.attrs['data-src']:'')" :mode="n.h?'':'widthFix'" :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 || ((H5 || APP-PLUS) && VUE3) -->
-      <!-- 音频 -->
-      <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) && VUE2) -->
-      <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) && VUE2) -->
-      <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
-  },
-  // #ifndef H5 && VUE3
-  components: {
-
-    node
-  },
-  // #endif
-  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 && VUE2) */
-      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') {
-        // #ifdef H5 && VUE3
-        if (this.opts[0] && !this.ctrl.load) return
-        // #endif
-        // 显示错误占位图
-        if (this.opts[2]) {
-          this.$set(this.ctrl, i, -1)
-        }
-      }
-      if (this.root) {
-        this.root.$emit('error', {
-          source: node.name,
-          attrs: node.attrs,
-          // #ifndef H5 && VUE3
-          errMsg: e.detail.errMsg
-          // #endif
-        })
-      }
-    }
-  }
-}
-</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>

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

@@ -1,1260 +0,0 @@
-/**
- * @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'),
-
-  // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
-  // 行内标签
-  inlineTags: makeMap('abbr,b,big,code,del,em,i,ins,label,q,small,span,strong,sub,sup'),
-  // #endif
-
-  // 要移除的标签
-  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 (!isNaN(parseInt(styleObj.height)) && (!styleObj.height.includes('%') || (parent && (parent.attrs.style || '').includes('height')))) {
-            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'] = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', 'xxx-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--;) {
-      const child = node.children[i]
-      // #ifdef (MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE3
-      if (child.name && (config.inlineTags[child.name] || (child.attrs.style || '').includes('inline'))) {
-        child.c = 1
-      }
-      // #endif
-      if (!child.c || child.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%'
-  }
-
-  // 优化长内容加载速度
-  if (children.length >= 50 && node.c && !(styleObj.display || '').includes('flex')) {
-    let i = children.length - 1
-    for (let j = i; j >= -1; j--) {
-      // 合并多个块级标签
-      if (j === -1 || children[j].c || !children[j].name || (children[j].name !== 'div' && children[j].name !== 'p' && children[j].name[0] !== 'h') || (children[j].attrs.style || '').includes('inline')) {
-        if (i - j >= 5) {
-          children.splice(j + 1, i - j, {
-            name: 'div',
-            attrs: {},
-            children: node.children.slice(j + 1, i + 1)
-          })
-        }
-        i = j - 1
-      }
-    }
-  }
-  // #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
-  // #ifdef (MP-WEIXIN || MP-QQ) && VUE3
-  if (!attrs.style) {
-    delete attrs.style
-  }
-  // #endif
-}
-
-/**
- * @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'
-  // #ifdef (MP-BAIDU || MP-ALIPAY || MP-TOUTIAO) && VUE3
-  node.attrs = {}
-  // #endif
-  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++
-  }
-}
-
-export default Parser

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

@@ -1,79 +0,0 @@
-{
-    "id": "mp-html",
-    "displayName": "mp-html 富文本组件【全端支持,可编辑】",
-    "version": "v2.2.2",
-    "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": "y"
-                }
-            }
-        }
-    }
-}

File diff suppressed because it is too large
+ 0 - 0
uni_modules/mp-html/static/app-plus/mp-html/js/handler.js


File diff suppressed because it is too large
+ 0 - 0
uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js


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

@@ -1 +0,0 @@
-<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}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>

+ 26 - 29
utils/config.js

@@ -8,6 +8,7 @@ let pcBaseUrl=''//pc页面根路径
 if(env.envVersion==='develop'){//开发
     baseApiUrl='http://8.136.199.33:8612/api'
     h5BaseUrl='http://xcxh5test.hzinsights.com/xcx_h5'
+	 // h5BaseUrl='http://192.168.77.17:3000/xcx_h5'
     pcBaseUrl='https://ybpctest.hzinsights.com'
 }else if(env.envVersion==='trial'){//体验版
     baseApiUrl='http://8.136.199.33:8612/api'
@@ -31,6 +32,9 @@ const globalImgUrls={
     defaultAvatar:'https://hzstatic.hzinsights.com/static/icon/hzyb/default_avatar.png',
     ficcServiceImg:'https://hzstatic.hzinsights.com/static/icon/hzyb/ficc_service.png',//ficc服务banner图
     ficcServicePage:'https://hzstatic.hzinsights.com/static/icon/hzyb/ficc_service_page.png',//ficc服务介绍图
+	sandBoxNoAuthor:'https://hzstatic.hzinsights.com/static/icon/hzyb/sandbox_no_author.png', //沙盘无权限 无数据
+	sandBoxShareDefault1:'https://hzstatic.hzinsights.com/static/images/yb/sandbox_20220705160455.png', //沙盘分享时 默认图片1
+	sandBoxShareDefault2:'https://hzstatic.hzinsights.com/static/images/yb/sandbox_20220705160533.png', //沙盘分享时 默认图片2
 }
 
 // 默认tabbar数据
@@ -38,45 +42,38 @@ const defaultTabBarListConfig=[
     {
         key: "report",
         pagePath: "pages/report/report",
-        text: "报告",
+        text: "首页",
         iconPath: "../static/tabbar/report.png",
         selectedIconPath: "../static/tabbar/report-s.png",
     },
+	{
+		key: 'pricedriven',
+		pagePath: "pages/pricedriven/pricedriven",
+		text: "价格驱动",
+		iconPath: "../static/tabbar/price.png",
+		selectedIconPath: "../static/tabbar/price-s.png"
+	},
     {
-        key: "buy",
-        pagePath: "pages/buy/buy",
-        text: "已购",
-        iconPath: "../static/tabbar/buy.png",
-        selectedIconPath: "../static/tabbar/buy-s.png",
+        key: "video",
+        pagePath: "pages/video/videoList",
+        text: "视频社区",
+        iconPath: "../static/tabbar/video.png",
+        selectedIconPath: "../static/tabbar/video-s.png",
     },
-    {
-        key: "chart",
-        pagePath: "pages/chart/chart",
-        text: "ETA图库",
-        iconPath: "../static/tabbar/chart.png",
-        selectedIconPath: "../static/tabbar/chart-s.png",
-    },
-    {
-        key: "activity",
-        pagePath: "pages/activity/activity",
-        text: "活动",
-        iconPath: "../static/tabbar/activity.png",
-        selectedIconPath: "../static/tabbar/activity-s.png",
-    },
-   /*  {
-        key: "user",
-        pagePath: "pages/user/user",
-        text: "我的",
-        iconPath: "../static/tabbar/user.png",
-        selectedIconPath: "../static/tabbar/user-s.png",
-    }, */
     {
         key: "question",
         pagePath: "pages/question/question",
         text: "问答",
         iconPath: "../static/tabbar/question.png",
-        selectedIconPath: "../static/tabbar/question-s.png"
-    }
+        selectedIconPath: "../static/tabbar/question-s.png",
+    },
+	 {
+	     key: "activity",
+	     pagePath: "pages/activity/activity",
+	     text: "活动",
+	     iconPath: "../static/tabbar/activity.png",
+	     selectedIconPath: "../static/tabbar/activity-s.png",
+	 },
 ]
 
 

+ 1 - 1
utils/request.js

@@ -95,7 +95,7 @@ const http=(url,params,method)=>{
 			method:method,
 			header:{
 				Authorization:store.state.user.token,
-				version:'yb5.0'
+				version:'yb7.0'
 			},
 			success(e) {
 				// 接口404

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