Kaynağa Gözat

Merge branch 'master' of http://git.cc-lotus.info/pointToNetwork/point-app

zs 2 yıl önce
ebeveyn
işleme
056d6dd2fd

+ 27 - 0
components/u-parse/components/wxParseAudio.vue

@@ -0,0 +1,27 @@
+<template>
+  <!--增加audio标签支持-->
+  <audio
+    :id="node.attr.id"
+    :class="node.classStr"
+    :style="node.styleStr"
+    :src="node.attr.src"
+    :loop="node.attr.loop"
+    :poster="node.attr.poster"
+    :name="node.attr.name"
+    :author="node.attr.author"
+    controls></audio>
+</template>
+
+<script>
+export default {
+  name: 'wxParseAudio',
+  props: {
+    node: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+};
+</script>

+ 86 - 0
components/u-parse/components/wxParseImg.vue

@@ -0,0 +1,86 @@
+<template>
+  <image
+    :mode="node.attr.mode"
+    :lazy-load="node.attr.lazyLoad"
+    :class="node.classStr"
+    :style="newStyleStr || node.styleStr"
+    :data-src="node.attr.src"
+    :src="node.attr.src"
+    @tap="wxParseImgTap"
+    @load="wxParseImgLoad"
+    />
+</template>
+
+<script>
+export default {
+  name: 'wxParseImg',
+  data() {
+    return {
+      newStyleStr: '',
+      preview: true,
+    };
+  },
+  props: {
+    node: {
+      type: Object,
+      default() {
+        return {};
+      },
+    },
+  },
+  methods: {
+    wxParseImgTap(e) {
+      if (!this.preview) return;
+      const { src } = e.currentTarget.dataset;
+      if (!src) return;
+      let parent = this.$parent;
+      while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
+      	parent = parent.$parent;
+      }
+      parent.preview(src, e);
+    },
+    // 图片视觉宽高计算函数区
+    wxParseImgLoad(e) {
+      const { src } = e.currentTarget.dataset;
+      if (!src) return;
+      const { width, height } = e.mp.detail;
+      const recal = this.wxAutoImageCal(width, height);
+      const { imageheight, imageWidth } = recal;
+      const { padding, mode } = this.node.attr;
+      const { styleStr } = this.node;
+      const imageHeightStyle = mode === 'widthFix' ? '' : `height: ${imageheight}px;`;
+      this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px; padding: 0 ${+padding}px;`;
+    },
+    // 计算视觉优先的图片宽高
+    wxAutoImageCal(originalWidth, originalHeight) {
+      // 获取图片的原始长宽
+      const { padding } = this.node.attr;
+      const windowWidth = this.node.$screen.width - (2 * padding);
+      const results = {};
+
+      if (originalWidth < 60 || originalHeight < 60) {
+        const { src } = this.node.attr;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.removeImageUrl(src);
+        this.preview = false;
+      }
+
+      // 判断按照那种方式进行缩放
+      if (originalWidth > windowWidth) {
+        // 在图片width大于手机屏幕width时候
+        results.imageWidth = windowWidth;
+        results.imageheight = windowWidth * (originalHeight / originalWidth);
+      } else {
+        // 否则展示原来的数据
+        results.imageWidth = originalWidth;
+        results.imageheight = originalHeight;
+      }
+
+      return results;
+    },
+  },
+};
+</script>

+ 107 - 0
components/u-parse/components/wxParseTemplate0.vue

@@ -0,0 +1,107 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--table类型-->
+			<block v-else-if="node.tag == 'table'">
+				<view :class="node.classStr" class="table" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate1';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate0',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;// TODO currentTarget才有dataset
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {// TODO 遍历获取父节点执行方法
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 99 - 0
components/u-parse/components/wxParseTemplate1.vue

@@ -0,0 +1,99 @@
+<template>
+	<view :class="(node.tag == 'li' ? node.classStr : (node.node==='text'?'text':''))">
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<!-- <view :class="node.classStr" :style="node.styleStr"> -->
+				<view :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate2';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate1',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 97 - 0
components/u-parse/components/wxParseTemplate10.vue

@@ -0,0 +1,97 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate11';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate10',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 87 - 0
components/u-parse/components/wxParseTemplate11.vue

@@ -0,0 +1,87 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<!--button类型-->
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					{{node.text}}
+				</view>
+			</block>
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate11',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate2.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate3';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate2',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate3.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate4';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate3',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate4.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate5';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate4',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate5.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate6';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate5',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate6.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate7';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate6',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate7.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate8';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate7',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate8.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate9';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate8',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 98 - 0
components/u-parse/components/wxParseTemplate9.vue

@@ -0,0 +1,98 @@
+<template>
+	<view>
+		<!--判断是否是标签节点-->
+		<block v-if="node.node == 'element'">
+			<block v-if="node.tag == 'button'">
+				<button type="default" size="mini">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</button>
+			</block>
+
+			<!--li类型-->
+			<block v-else-if="node.tag == 'li'">
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--video类型-->
+			<block v-else-if="node.tag == 'video'">
+				<wx-parse-video :node="node" />
+			</block>
+
+			<!--audio类型-->
+			<block v-else-if="node.tag == 'audio'">
+				<wx-parse-audio :node="node" />
+			</block>
+
+			<!--img类型-->
+			<block v-else-if="node.tag == 'img'">
+				<wx-parse-img :node="node" />
+			</block>
+
+			<!--a类型-->
+			<block v-else-if="node.tag == 'a'">
+				<view @click="wxParseATap" :class="node.classStr" :data-href="node.attr.href" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+			<!--br类型-->
+			<block v-else-if="node.tag == 'br'">
+				<text>\n</text>
+			</block>
+
+			<!--其他标签-->
+			<block v-else>
+				<view :class="node.classStr" :style="node.styleStr">
+					<block v-for="(node, index) of node.nodes" :key="index">
+						<wx-parse-template :node="node" />
+					</block>
+				</view>
+			</block>
+
+		</block>
+
+		<!--判断是否是文本节点-->
+		<block v-else-if="node.node == 'text'">{{node.text}}</block>
+	</view>
+</template>
+
+<script>
+	import wxParseTemplate from './wxParseTemplate10';
+	import wxParseImg from './wxParseImg';
+	import wxParseVideo from './wxParseVideo';
+	import wxParseAudio from './wxParseAudio';
+
+	export default {
+		name: 'wxParseTemplate9',
+		props: {
+			node: {},
+		},
+		components: {
+			wxParseTemplate,
+			wxParseImg,
+			wxParseVideo,
+			wxParseAudio,
+		},
+		methods: {
+			wxParseATap(e) {
+				const {
+					href
+				} = e.currentTarget.dataset;
+				if (!href) return;
+				let parent = this.$parent;
+				while(!parent.preview || typeof parent.preview !== 'function') {
+					parent = parent.$parent;
+				}
+				parent.navigate(href, e);
+			},
+		},
+	};
+</script>

+ 15 - 0
components/u-parse/components/wxParseVideo.vue

@@ -0,0 +1,15 @@
+<template>
+  <!--增加video标签支持,并循环添加-->
+  <view :class="node.classStr" :style="node.styleStr">
+    <video :class="node.classStr" class="video-video" :src="node.attr.src"></video>
+  </view>
+</template>
+
+<script>
+export default {
+  name: 'wxParseVideo',
+  props: {
+    node: {},
+  },
+};
+</script>

+ 261 - 0
components/u-parse/libs/html2json.js

@@ -0,0 +1,261 @@
+/**
+ * html2Json 改造来自: https://github.com/Jxck/html2json
+ *
+ *
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+import wxDiscode from './wxDiscode';
+import HTMLParser from './htmlparser';
+
+function makeMap(str) {
+  const obj = {};
+  const items = str.split(',');
+  for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
+  return obj;
+}
+
+// Block Elements - HTML 5
+const block = makeMap('br,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
+
+// Inline Elements - HTML 5
+const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
+
+function removeDOCTYPE(html) {
+  const isDocument = /<body.*>([^]*)<\/body>/.test(html);
+  return isDocument ? RegExp.$1 : html;
+}
+
+function trimHtml(html) {
+  return html
+    .replace(/<!--.*?-->/gi, '')
+    .replace(/\/\*.*?\*\//gi, '')
+    .replace(/[ ]+</gi, '<')
+    .replace(/<script[^]*<\/script>/gi, '')
+    .replace(/<style[^]*<\/style>/gi, '');
+}
+
+function getScreenInfo() {
+  const screen = {};
+  wx.getSystemInfo({
+    success: (res) => {
+      screen.width = res.windowWidth;
+      screen.height = res.windowHeight;
+    },
+  });
+  return screen;
+}
+
+function html2json(html, customHandler, imageProp, host) {
+  // 处理字符串
+  html = removeDOCTYPE(html);
+  html = trimHtml(html);
+  html = wxDiscode.strDiscode(html);
+  // 生成node节点
+  const bufArray = [];
+  const results = {
+    nodes: [],
+    imageUrls: [],
+  };
+
+	const screen = getScreenInfo();
+  function Node(tag) {
+    this.node = 'element';
+    this.tag = tag;
+		
+		this.$screen = screen;
+  }
+
+  HTMLParser(html, {
+    start(tag, attrs, unary) {
+      // node for this element
+      const node = new Node(tag);
+
+      if (bufArray.length !== 0) {
+        const parent = bufArray[0];
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+      }
+
+      if (block[tag]) {
+        node.tagType = 'block';
+      } else if (inline[tag]) {
+        node.tagType = 'inline';
+      } else if (closeSelf[tag]) {
+        node.tagType = 'closeSelf';
+      }
+
+      node.attr = attrs.reduce((pre, attr) => {
+        const { name } = attr;
+        let { value } = attr;
+        if (name === 'class') {
+          node.classStr = value;
+        }
+        // has multi attibutes
+        // make it array of attribute
+        if (name === 'style') {
+          node.styleStr = value;
+        }
+        if (value.match(/ /)) {
+          value = value.split(' ');
+        }
+
+        // if attr already exists
+        // merge it
+        if (pre[name]) {
+          if (Array.isArray(pre[name])) {
+            // already array, push to last
+            pre[name].push(value);
+          } else {
+            // single value, make it array
+            pre[name] = [pre[name], value];
+          }
+        } else {
+          // not exist, put it
+          pre[name] = value;
+        }
+
+        return pre;
+      }, {});
+
+      // 优化样式相关属性
+      if (node.classStr) {
+        node.classStr += ` ${node.tag}`;
+      } else {
+        node.classStr = node.tag;
+      }
+      if (node.tagType === 'inline') {
+        node.classStr += ' inline';
+      }
+
+      // 对img添加额外数据
+      if (node.tag === 'img') {
+        let imgUrl = node.attr.src;
+        imgUrl = wxDiscode.urlToHttpUrl(imgUrl, imageProp.domain);
+        Object.assign(node.attr, imageProp, {
+          src: imgUrl || '',
+        });
+        if (imgUrl) {
+          results.imageUrls.push(imgUrl);
+        }
+      }
+
+      // 处理a标签属性
+      if (node.tag === 'a') {
+        node.attr.href = node.attr.href || '';
+      }
+
+      // 处理font标签样式属性
+      if (node.tag === 'font') {
+        const fontSize = [
+          'x-small',
+          'small',
+          'medium',
+          'large',
+          'x-large',
+          'xx-large',
+          '-webkit-xxx-large',
+        ];
+        const styleAttrs = {
+          color: 'color',
+          face: 'font-family',
+          size: 'font-size',
+        };
+        if (!node.styleStr) node.styleStr = '';
+        Object.keys(styleAttrs).forEach((key) => {
+          if (node.attr[key]) {
+            const value = key === 'size' ? fontSize[node.attr[key] - 1] : node.attr[key];
+            node.styleStr += `${styleAttrs[key]}: ${value};`;
+          }
+        });
+      }
+
+      // 临时记录source资源
+      if (node.tag === 'source') {
+        results.source = node.attr.src;
+      }
+
+      if (customHandler.start) {
+        customHandler.start(node, results);
+      }
+
+      if (unary) {
+        // if this tag doesn't have end tag
+        // like <img src="hoge.png"/>
+        // add to parents
+        const parent = bufArray[0] || results;
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      } else {
+        bufArray.unshift(node);
+      }
+    },
+    end(tag) {
+      // merge into parent tag
+      const node = bufArray.shift();
+      if (node.tag !== tag) {
+        console.error('invalid state: mismatch end tag');
+      }
+
+      // 当有缓存source资源时于于video补上src资源
+      if (node.tag === 'video' && results.source) {
+        node.attr.src = results.source;
+        delete results.source;
+      }
+
+      if (customHandler.end) {
+        customHandler.end(node, results);
+      }
+
+      if (bufArray.length === 0) {
+        results.nodes.push(node);
+      } else {
+        const parent = bufArray[0];
+        if (!parent.nodes) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      }
+    },
+    chars(text) {
+      if (!text.trim()) return;
+
+      const node = {
+        node: 'text',
+        text,
+      };
+
+      if (customHandler.chars) {
+        customHandler.chars(node, results);
+      }
+
+      if (bufArray.length === 0) {
+        results.nodes.push(node);
+      } else {
+        const parent = bufArray[0];
+        if (parent.nodes === undefined) {
+          parent.nodes = [];
+        }
+        parent.nodes.push(node);
+      }
+    },
+  });
+
+  return results;
+}
+
+export default html2json;

+ 156 - 0
components/u-parse/libs/htmlparser.js

@@ -0,0 +1,156 @@
+/**
+ *
+ * htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
+ *
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *               垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+// Regular Expressions for parsing tags and attributes
+
+const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
+const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
+const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
+
+function makeMap(str) {
+  const obj = {};
+  const items = str.split(',');
+  for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
+  return obj;
+}
+
+// Empty Elements - HTML 5
+const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
+
+// Block Elements - HTML 5
+const block = makeMap('address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
+
+// Inline Elements - HTML 5
+const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
+
+// Elements that you can, intentionally, leave open
+// (and which close themselves)
+const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
+
+// Attributes that have their values filled in disabled="disabled"
+const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
+
+function HTMLParser(html, handler) {
+  let index;
+  let chars;
+  let match;
+  let last = html;
+  const stack = [];
+
+  stack.last = () => stack[stack.length - 1];
+
+  function parseEndTag(tag, tagName) {
+    // If no tag name is provided, clean shop
+    let pos;
+    if (!tagName) {
+      pos = 0;
+    } else {
+      // Find the closest opened tag of the same type
+      tagName = tagName.toLowerCase();
+      for (pos = stack.length - 1; pos >= 0; pos -= 1) {
+        if (stack[pos] === tagName) break;
+      }
+    }
+    if (pos >= 0) {
+      // Close all the open elements, up the stack
+      for (let i = stack.length - 1; i >= pos; i -= 1) {
+        if (handler.end) handler.end(stack[i]);
+      }
+
+      // Remove the open elements from the stack
+      stack.length = pos;
+    }
+  }
+
+  function parseStartTag(tag, tagName, rest, unary) {
+    tagName = tagName.toLowerCase();
+
+    if (block[tagName]) {
+      while (stack.last() && inline[stack.last()]) {
+        parseEndTag('', stack.last());
+      }
+    }
+
+    if (closeSelf[tagName] && stack.last() === tagName) {
+      parseEndTag('', tagName);
+    }
+
+    unary = empty[tagName] || !!unary;
+
+    if (!unary) stack.push(tagName);
+
+    if (handler.start) {
+      const attrs = [];
+
+      rest.replace(attr, function genAttr(matches, name) {
+        const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
+
+        attrs.push({
+          name,
+          value,
+          escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
+        });
+      });
+
+      if (handler.start) {
+        handler.start(tagName, attrs, unary);
+      }
+    }
+  }
+
+  while (html) {
+    chars = true;
+
+    if (html.indexOf('</') === 0) {
+      match = html.match(endTag);
+
+      if (match) {
+        html = html.substring(match[0].length);
+        match[0].replace(endTag, parseEndTag);
+        chars = false;
+      }
+
+      // start tag
+    } else if (html.indexOf('<') === 0) {
+      match = html.match(startTag);
+
+      if (match) {
+        html = html.substring(match[0].length);
+        match[0].replace(startTag, parseStartTag);
+        chars = false;
+      }
+    }
+
+    if (chars) {
+      index = html.indexOf('<');
+      let text = '';
+      while (index === 0) {
+        text += '<';
+        html = html.substring(1);
+        index = html.indexOf('<');
+      }
+      text += index < 0 ? html : html.substring(0, index);
+      html = index < 0 ? '' : html.substring(index);
+
+      if (handler.chars) handler.chars(text);
+    }
+
+    if (html === last) throw new Error(`Parse Error: ${html}`);
+    last = html;
+  }
+
+  // Clean up any remaining tags
+  parseEndTag();
+}
+
+export default HTMLParser;

+ 195 - 0
components/u-parse/libs/wxDiscode.js

@@ -0,0 +1,195 @@
+// HTML 支持的数学符号
+function strNumDiscode(str) {
+  str = str.replace(/&forall;/g, '∀');
+  str = str.replace(/&part;/g, '∂');
+  str = str.replace(/&exist;/g, '∃');
+  str = str.replace(/&empty;/g, '∅');
+  str = str.replace(/&nabla;/g, '∇');
+  str = str.replace(/&isin;/g, '∈');
+  str = str.replace(/&notin;/g, '∉');
+  str = str.replace(/&ni;/g, '∋');
+  str = str.replace(/&prod;/g, '∏');
+  str = str.replace(/&sum;/g, '∑');
+  str = str.replace(/&minus;/g, '−');
+  str = str.replace(/&lowast;/g, '∗');
+  str = str.replace(/&radic;/g, '√');
+  str = str.replace(/&prop;/g, '∝');
+  str = str.replace(/&infin;/g, '∞');
+  str = str.replace(/&ang;/g, '∠');
+  str = str.replace(/&and;/g, '∧');
+  str = str.replace(/&or;/g, '∨');
+  str = str.replace(/&cap;/g, '∩');
+  str = str.replace(/&cup;/g, '∪');
+  str = str.replace(/&int;/g, '∫');
+  str = str.replace(/&there4;/g, '∴');
+  str = str.replace(/&sim;/g, '∼');
+  str = str.replace(/&cong;/g, '≅');
+  str = str.replace(/&asymp;/g, '≈');
+  str = str.replace(/&ne;/g, '≠');
+  str = str.replace(/&le;/g, '≤');
+  str = str.replace(/&ge;/g, '≥');
+  str = str.replace(/&sub;/g, '⊂');
+  str = str.replace(/&sup;/g, '⊃');
+  str = str.replace(/&nsub;/g, '⊄');
+  str = str.replace(/&sube;/g, '⊆');
+  str = str.replace(/&supe;/g, '⊇');
+  str = str.replace(/&oplus;/g, '⊕');
+  str = str.replace(/&otimes;/g, '⊗');
+  str = str.replace(/&perp;/g, '⊥');
+  str = str.replace(/&sdot;/g, '⋅');
+  return str;
+}
+
+// HTML 支持的希腊字母
+function strGreeceDiscode(str) {
+  str = str.replace(/&Alpha;/g, 'Α');
+  str = str.replace(/&Beta;/g, 'Β');
+  str = str.replace(/&Gamma;/g, 'Γ');
+  str = str.replace(/&Delta;/g, 'Δ');
+  str = str.replace(/&Epsilon;/g, 'Ε');
+  str = str.replace(/&Zeta;/g, 'Ζ');
+  str = str.replace(/&Eta;/g, 'Η');
+  str = str.replace(/&Theta;/g, 'Θ');
+  str = str.replace(/&Iota;/g, 'Ι');
+  str = str.replace(/&Kappa;/g, 'Κ');
+  str = str.replace(/&Lambda;/g, 'Λ');
+  str = str.replace(/&Mu;/g, 'Μ');
+  str = str.replace(/&Nu;/g, 'Ν');
+  str = str.replace(/&Xi;/g, 'Ν');
+  str = str.replace(/&Omicron;/g, 'Ο');
+  str = str.replace(/&Pi;/g, 'Π');
+  str = str.replace(/&Rho;/g, 'Ρ');
+  str = str.replace(/&Sigma;/g, 'Σ');
+  str = str.replace(/&Tau;/g, 'Τ');
+  str = str.replace(/&Upsilon;/g, 'Υ');
+  str = str.replace(/&Phi;/g, 'Φ');
+  str = str.replace(/&Chi;/g, 'Χ');
+  str = str.replace(/&Psi;/g, 'Ψ');
+  str = str.replace(/&Omega;/g, 'Ω');
+
+  str = str.replace(/&alpha;/g, 'α');
+  str = str.replace(/&beta;/g, 'β');
+  str = str.replace(/&gamma;/g, 'γ');
+  str = str.replace(/&delta;/g, 'δ');
+  str = str.replace(/&epsilon;/g, 'ε');
+  str = str.replace(/&zeta;/g, 'ζ');
+  str = str.replace(/&eta;/g, 'η');
+  str = str.replace(/&theta;/g, 'θ');
+  str = str.replace(/&iota;/g, 'ι');
+  str = str.replace(/&kappa;/g, 'κ');
+  str = str.replace(/&lambda;/g, 'λ');
+  str = str.replace(/&mu;/g, 'μ');
+  str = str.replace(/&nu;/g, 'ν');
+  str = str.replace(/&xi;/g, 'ξ');
+  str = str.replace(/&omicron;/g, 'ο');
+  str = str.replace(/&pi;/g, 'π');
+  str = str.replace(/&rho;/g, 'ρ');
+  str = str.replace(/&sigmaf;/g, 'ς');
+  str = str.replace(/&sigma;/g, 'σ');
+  str = str.replace(/&tau;/g, 'τ');
+  str = str.replace(/&upsilon;/g, 'υ');
+  str = str.replace(/&phi;/g, 'φ');
+  str = str.replace(/&chi;/g, 'χ');
+  str = str.replace(/&psi;/g, 'ψ');
+  str = str.replace(/&omega;/g, 'ω');
+  str = str.replace(/&thetasym;/g, 'ϑ');
+  str = str.replace(/&upsih;/g, 'ϒ');
+  str = str.replace(/&piv;/g, 'ϖ');
+  str = str.replace(/&middot;/g, '·');
+  return str;
+}
+
+function strcharacterDiscode(str) {
+  // 加入常用解析
+  str = str.replace(/&nbsp;/g, ' ');
+  str = str.replace(/&ensp;/g, ' ');
+  str = str.replace(/&emsp;/g, ' ');
+  str = str.replace(/&quot;/g, "'");
+  str = str.replace(/&amp;/g, '&');
+  str = str.replace(/&lt;/g, '<');
+  str = str.replace(/&gt;/g, '>');
+  str = str.replace(/&#8226;/g, '•');
+
+  return str;
+}
+
+// HTML 支持的其他实体
+function strOtherDiscode(str) {
+  str = str.replace(/&OElig;/g, 'Œ');
+  str = str.replace(/&oelig;/g, 'œ');
+  str = str.replace(/&Scaron;/g, 'Š');
+  str = str.replace(/&scaron;/g, 'š');
+  str = str.replace(/&Yuml;/g, 'Ÿ');
+  str = str.replace(/&fnof;/g, 'ƒ');
+  str = str.replace(/&circ;/g, 'ˆ');
+  str = str.replace(/&tilde;/g, '˜');
+  str = str.replace(/&ensp;/g, '');
+  str = str.replace(/&emsp;/g, '');
+  str = str.replace(/&thinsp;/g, '');
+  str = str.replace(/&zwnj;/g, '');
+  str = str.replace(/&zwj;/g, '');
+  str = str.replace(/&lrm;/g, '');
+  str = str.replace(/&rlm;/g, '');
+  str = str.replace(/&ndash;/g, '–');
+  str = str.replace(/&mdash;/g, '—');
+  str = str.replace(/&lsquo;/g, '‘');
+  str = str.replace(/&rsquo;/g, '’');
+  str = str.replace(/&sbquo;/g, '‚');
+  str = str.replace(/&ldquo;/g, '“');
+  str = str.replace(/&rdquo;/g, '”');
+  str = str.replace(/&bdquo;/g, '„');
+  str = str.replace(/&dagger;/g, '†');
+  str = str.replace(/&Dagger;/g, '‡');
+  str = str.replace(/&bull;/g, '•');
+  str = str.replace(/&hellip;/g, '…');
+  str = str.replace(/&permil;/g, '‰');
+  str = str.replace(/&prime;/g, '′');
+  str = str.replace(/&Prime;/g, '″');
+  str = str.replace(/&lsaquo;/g, '‹');
+  str = str.replace(/&rsaquo;/g, '›');
+  str = str.replace(/&oline;/g, '‾');
+  str = str.replace(/&euro;/g, '€');
+  str = str.replace(/&trade;/g, '™');
+
+  str = str.replace(/&larr;/g, '←');
+  str = str.replace(/&uarr;/g, '↑');
+  str = str.replace(/&rarr;/g, '→');
+  str = str.replace(/&darr;/g, '↓');
+  str = str.replace(/&harr;/g, '↔');
+  str = str.replace(/&crarr;/g, '↵');
+  str = str.replace(/&lceil;/g, '⌈');
+  str = str.replace(/&rceil;/g, '⌉');
+
+  str = str.replace(/&lfloor;/g, '⌊');
+  str = str.replace(/&rfloor;/g, '⌋');
+  str = str.replace(/&loz;/g, '◊');
+  str = str.replace(/&spades;/g, '♠');
+  str = str.replace(/&clubs;/g, '♣');
+  str = str.replace(/&hearts;/g, '♥');
+
+  str = str.replace(/&diams;/g, '♦');
+  str = str.replace(/&#39;/g, "'");
+  return str;
+}
+
+function strDiscode(str) {
+  str = strNumDiscode(str);
+  str = strGreeceDiscode(str);
+  str = strcharacterDiscode(str);
+  str = strOtherDiscode(str);
+  return str;
+}
+
+function urlToHttpUrl(url, domain) {
+  if (/^\/\//.test(url)) {
+    return `https:${url}`;
+  } else if (/^\//.test(url)) {
+    return `https://${domain}${url}`;
+  }
+  return url;
+}
+
+export default {
+  strDiscode,
+  urlToHttpUrl,
+};

+ 232 - 0
components/u-parse/u-parse.css

@@ -0,0 +1,232 @@
+/**
+ * author: Di (微信小程序开发工程师)
+ * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
+ *         垂直微信小程序开发交流社区
+ *
+ * github地址: https://github.com/icindy/wxParse
+ *
+ * for: 微信小程序富文本解析
+ * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
+ */
+
+.wxParse {
+  width: 100%;
+  font-family: Helvetica, sans-serif;
+  font-size: 30upx;
+  color: #666;
+  line-height: 1.8;
+}
+
+.wxParse view {
+  word-break: hyphenate;
+}
+
+.wxParse .inline {
+  display: inline;
+  margin: 0;
+  padding: 0;
+}
+
+.wxParse .div {
+  margin: 0;
+  padding: 0;
+}
+
+.wxParse .h1 .text {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+.wxParse .h2 .text {
+  font-size: 1.5em;
+  margin: 0.83em 0;
+}
+.wxParse .h3 .text {
+  font-size: 1.17em;
+  margin: 1em 0;
+}
+.wxParse .h4 .text {
+  margin: 1.33em 0;
+}
+.wxParse .h5 .text {
+  font-size: 0.83em;
+  margin: 1.67em 0;
+}
+.wxParse .h6 .text {
+  font-size: 0.67em;
+  margin: 2.33em 0;
+}
+
+.wxParse .h1 .text,
+.wxParse .h2 .text,
+.wxParse .h3 .text,
+.wxParse .h4 .text,
+.wxParse .h5 .text,
+.wxParse .h6 .text,
+.wxParse .b,
+.wxParse .strong {
+  font-weight: bolder;
+}
+
+
+.wxParse .p {
+  margin: 1em 0;
+}
+
+.wxParse .i,
+.wxParse .cite,
+.wxParse .em,
+.wxParse .var,
+.wxParse .address {
+  font-style: italic;
+}
+
+.wxParse .pre,
+.wxParse .tt,
+.wxParse .code,
+.wxParse .kbd,
+.wxParse .samp {
+  font-family: monospace;
+}
+.wxParse .pre {
+  overflow: auto;
+  background: #f5f5f5;
+  padding: 16upx;
+  white-space: pre;
+  margin: 1em 0upx;
+}
+.wxParse .code {
+  display: inline;
+  background: #f5f5f5;
+}
+
+.wxParse .big {
+  font-size: 1.17em;
+}
+
+.wxParse .small,
+.wxParse .sub,
+.wxParse .sup {
+  font-size: 0.83em;
+}
+
+.wxParse .sub {
+  vertical-align: sub;
+}
+.wxParse .sup {
+  vertical-align: super;
+}
+
+.wxParse .s,
+.wxParse .strike,
+.wxParse .del {
+  text-decoration: line-through;
+}
+
+.wxParse .strong,
+.wxParse .s {
+  display: inline;
+}
+
+.wxParse .a {
+  color: deepskyblue;
+}
+
+.wxParse .video {
+  text-align: center;
+  margin: 22upx 0;
+}
+
+.wxParse .video-video {
+  width: 100%;
+}
+
+.wxParse .img {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  max-width: 100%;
+  overflow: hidden;
+}
+
+.wxParse .blockquote {
+  margin: 10upx 0;
+  padding: 22upx 0 22upx 22upx;
+  font-family: Courier, Calibri, "宋体";
+  background: #f5f5f5;
+  border-left: 6upx solid #dbdbdb;
+}
+.wxParse .blockquote .p {
+  margin: 0;
+}
+
+.wxParse .ul, .wxParse .ol {
+  display: block;
+  margin: 1em 0;
+  padding-left: 33upx;
+}
+.wxParse .ol {
+  list-style-type: disc;
+}
+.wxParse .ol {
+  list-style-type: decimal;
+}
+.wxParse .ol>weixin-parse-template,.wxParse .ul>weixin-parse-template {
+  display: list-item;
+  align-items: baseline;
+  text-align: match-parent;
+}
+
+.wxParse .ol>.li,.wxParse .ul>.li {
+  display: list-item;
+  align-items: baseline;
+  text-align: match-parent;
+}
+.wxParse .ul .ul, .wxParse .ol .ul {
+  list-style-type: circle;
+}
+.wxParse .ol .ol .ul, .wxParse .ol .ul .ul, .wxParse .ul .ol .ul, .wxParse .ul .ul .ul {
+    list-style-type: square;
+}
+
+.wxParse .u {
+  text-decoration: underline;
+}
+.wxParse .hide {
+  display: none;
+}
+.wxParse .del {
+  display: inline;
+}
+.wxParse .figure {
+  overflow: hidden;
+}
+
+.wxParse .table {
+  width: 100%;
+}
+.wxParse .thead, .wxParse .tfoot, .wxParse .tr {
+  display: flex;
+  flex-direction: row;
+}
+.wxParse .tr {
+  width:100%;
+  display: flex;
+  border-right: 2upx solid #e0e0e0;
+  border-bottom: 2upx solid #e0e0e0;
+}
+.wxParse .th,
+.wxParse .td {
+  display: flex;
+  width: 1276upx;
+  overflow: auto;
+  flex: 1;
+  padding: 11upx;
+  border-left: 2upx solid #e0e0e0;
+}
+.wxParse .td:last {
+  border-top: 2upx solid #e0e0e0;
+}
+.wxParse .th {
+  background: #f0f0f0;
+  border-top: 2upx solid #e0e0e0;
+}

+ 117 - 0
components/u-parse/u-parse.vue

@@ -0,0 +1,117 @@
+<!--**
+ * forked from:https://github.com/F-loat/mpvue-wxParse
+ *
+ * github地址: https://github.com/dcloudio/uParse
+ *
+ * for: uni-app框架下 富文本解析
+ */-->
+
+<template>
+<!--基础元素-->
+<div class="wxParse" :class="className" v-if="!loading">
+  <block v-for="(node,index) of nodes" :key="index">
+    <wxParseTemplate :node="node" />
+  </block>
+</div>
+</template>
+
+<script>
+import HtmlToJson from './libs/html2json';
+import wxParseTemplate from './components/wxParseTemplate0';
+
+export default {
+  name: 'wxParse',
+  props: {
+    loading: {
+      type: Boolean,
+      default: false,
+    },
+    className: {
+      type: String,
+      default: '',
+    },
+    content: {
+      type: String,
+      default: '',
+    },
+    noData: {
+      type: String,
+      default: '<div style="color: red;">数据不能为空</div>',
+    },
+    startHandler: {
+      type: Function,
+      default() {
+        return (node) => {
+          node.attr.class = null;
+          node.attr.style = null;
+        };
+      },
+    },
+    endHandler: {
+      type: Function,
+      default: null,
+    },
+    charsHandler: {
+      type: Function,
+      default: null,
+    },
+    imageProp: {
+      type: Object,
+      default() {
+        return {
+          mode: 'aspectFit',
+          padding: 0,
+          lazyLoad: false,
+          domain: '',
+        };
+      },
+    },
+  },
+  components: {
+    wxParseTemplate,
+  },
+  data() {
+    return {
+      imageUrls: [],
+    };
+  },
+  computed: {
+    nodes() {
+      const {
+        content,
+        noData,
+        imageProp,
+        startHandler,
+        endHandler,
+        charsHandler,
+      } = this;
+      const parseData = content || noData;
+      const customHandler = {
+        start: startHandler,
+        end: endHandler,
+        chars: charsHandler,
+      };
+      const results = HtmlToJson(parseData, customHandler, imageProp, this);
+      this.imageUrls = results.imageUrls;
+      return results.nodes;
+    },
+  },
+  methods: {
+    navigate(href, $event) {
+      this.$emit('navigate', href, $event);
+    },
+    preview(src, $event) {
+      if (!this.imageUrls.length) return;
+      wx.previewImage({
+        current: src,
+        urls: this.imageUrls,
+      });
+      this.$emit('preview', src, $event);
+    },
+    removeImageUrl(src) {
+      const { imageUrls } = this;
+      imageUrls.splice(imageUrls.indexOf(src), 1);
+    },
+  },
+};
+</script>

+ 17 - 15
pagesHome/order/detail.vue

@@ -2,12 +2,10 @@
 	<mobile-frame>
 		<view class="main">
 			<view class="onemain">
-				<scroll-view scroll-y="true" class="scroll-view" scroll-with-animation :scroll-into-view="topItem"
-					@scroll="handleScroll">
+				<scroll-view scroll-y="true" class="scroll-view" scroll-with-animation :scroll-into-view="topItem" @scroll="handleScroll">
 					<view class="list-scroll-view" id="top">
 						<view class="one">
-							<swiper class="swiper" circular :indicator-dots="true" indicator-color="#ffffff"
-								indicator-active-color="#FB1438" :autoplay="true" :interval="3000" :duration="1000">
+							<swiper class="swiper" circular :indicator-dots="true" indicator-color="#ffffff" indicator-active-color="#FB1438" :autoplay="true" :interval="3000" :duration="1000">
 								<swiper-item class="list" v-for="(item,index) in bannerList" :key="index">
 									<image class="image" :src="item.url" mode="">
 									</image>
@@ -66,15 +64,14 @@
 						</view>
 						<view class="five">
 							<view class="five_1">
-								<rich-text :nodes="info.brief"></rich-text>
+								<u-parse :content="info.brief"></u-parse>
 							</view>
 						</view>
 					</view>
 				</scroll-view>
 			</view>
 			<view class="foot">
-				<uni-goods-nav :options="options" :button-group="buttonGroup" @click="onClick"
-					@buttonClick="buttonClick" />
+				<uni-goods-nav :options="options" :button-group="buttonGroup" @click="onClick" @buttonClick="buttonClick" />
 			</view>
 		</view>
 		<view class="collect">
@@ -96,8 +93,7 @@
 		<uni-popup ref="popup" background-color="#fff" type="bottom">
 			<view class="content">
 				<view class="one">
-					<image class="image" v-if="specsInfo.file&&specsInfo.file.length>0"
-						:src="specsInfo.file&&specsInfo.file.length>0?specsInfo.file[0].url:''"></image>
+					<image class="image" v-if="specsInfo.file&&specsInfo.file.length>0" :src="specsInfo.file&&specsInfo.file.length>0?specsInfo.file[0].url:''"></image>
 					<image class="image" v-else :src="info.file&&info.file.length>0?info.file[0].url:''"></image>
 					<view class="other">
 						<view class="money">
@@ -115,16 +111,14 @@
 				<view class="two">
 					<view class="two_1">规格</view>
 					<view class="two_2">
-						<text v-for="(item,index) in specs" :key="index" @click="toStyle(item,index)"
-							:class="{ 'style': isActive==index}">{{item.name}}
+						<text v-for="(item,index) in specs" :key="index" @click="toStyle(item,index)" :class="{ 'style': isActive==index}">{{item.name}}
 						</text>
 					</view>
 				</view>
 				<view class="thr">
 					<text>数量</text>
 					<view class="count">
-						<uni-number-box :min="1" :max="specsInfo.num" :disabled="disabled" v-model="num"
-							@change="toCount">
+						<uni-number-box :min="1" :max="specsInfo.num" :disabled="disabled" v-model="num" @change="toCount">
 						</uni-number-box>
 					</view>
 					<text>库存{{specsInfo.num||0}}</text>
@@ -133,8 +127,7 @@
 					<text @click="toBuy(type)" :class="{ 'button': specsInfo._id&&specsInfo.can_group=='0'&&type=='1'}">
 						{{type=='0'?'加入购物车':'立即购买'}}
 					</text>
-					<text v-if="specsInfo._id&&specsInfo.can_group=='0'&&type=='1'" @click="toGroup"
-						class="button2">参团</text>
+					<text v-if="specsInfo._id&&specsInfo.can_group=='0'&&type=='1'" @click="toGroup" class="button2">参团</text>
 				</view>
 			</view>
 		</uni-popup>
@@ -142,7 +135,11 @@
 </template>
 
 <script>
+	import uParse from '@/components/u-parse/u-parse.vue'
 	export default {
+		components: {
+			uParse
+		},
 		data() {
 			return {
 				barList: [{
@@ -676,6 +673,11 @@
 
 				.five_1 {
 					background-color: var(--mainColor);
+					padding: 2vw;
+
+					image {
+						width: 100% !important;
+					}
 				}
 			}
 		}

+ 26 - 16
pagesHome/shop/index.vue

@@ -96,12 +96,12 @@
 								服务
 							</view>
 						</view>
-						<view class="second_2">
-							<view class="second_2_bor">
-								<uqrcode class="qrcode" ref="uqrcode" canvas-id="qrcode" :value="uqrcodeInfo" :size="160" :options="{ margin:10 }"></uqrcode>
-							</view>
-							<view class="txt">
-								店铺二维码
+						<view class="qrcode_1">
+							<view class="qrcode_1_1">
+								<uqrcode ref="uqrcode" canvas-id="qrcode" :value="uqrcodeInfo" :options="{ margin:10 }"></uqrcode>
+								<view class="txt">
+									店铺二维码
+								</view>
 							</view>
 						</view>
 					</view>
@@ -763,22 +763,32 @@
 						}
 					}
 
-					.second_2 {
+					.qrcode_1 {
 						display: flex;
 						justify-content: center;
-						flex-direction: column;
-						margin: 15vw 25vw 0 25vw;
 						text-align: center;
-						background: #b2b2b2;
-						padding: 3vw;
-						border-radius: 5px;
+						margin: 5vw 0;
+
+						.qrcode_1_1 {
+							padding: 2vw;
+							background: red;
 
-						.txt {
-							color: #fff;
-							font-size: 14px;
-							margin: 2vw 0;
+							.uqrcode {
+								width: 216px !important;
+								height: 216px !important;
+							}
+
+							// canvas {
+							// 	width: 180px !important;
+							// 	height: 180px !important;
+							// }
+
+							.txt {
+								margin: 2vw 0 0 0;
+							}
 						}
 					}
+
 				}
 			}
 

+ 50 - 46
pagesRest/article/index.vue

@@ -1,55 +1,59 @@
 <template>
-	<mobile-frame>
-		<view class="main">
-			<view class="one">
-				<rich-text :nodes="info.content"></rich-text>
-			</view>
-		</view>
-	</mobile-frame>
+  <mobile-frame>
+    <view class="main">
+      <view class="one">
+        <u-parse :content="info.content"></u-parse>
+      </view>
+    </view>
+  </mobile-frame>
 </template>
 
 <script>
-	export default {
-		data() {
-			return {
-				id: '',
-				info: {}
-			};
-		},
-		onLoad: function(e) {
-			const that = this;
-			that.$set(that, `id`, e.id || '')
-		},
-		onShow: function() {
-			const that = this;
-			that.search();
-		},
-		methods: {
-			async search() {
-				const that = this;
-				const res = await that.$api(`/banner/${that.id}`, 'GET');
-				if (res.errcode == '0') {
-					that.$set(that, `info`, res.data)
-				} else {
-					uni.showToast({
-						title: res.errmsg,
-						icon: 'none'
-					})
-				}
-			}
-		}
-	}
+import uParse from "@/components/u-parse/u-parse.vue";
+export default {
+  components: {
+    uParse,
+  },
+  data() {
+    return {
+      id: "",
+      info: {},
+    };
+  },
+  onLoad: function (e) {
+    const that = this;
+    that.$set(that, `id`, e.id || "");
+  },
+  onShow: function () {
+    const that = this;
+    that.search();
+  },
+  methods: {
+    async search() {
+      const that = this;
+      const res = await that.$api(`/banner/${that.id}`, "GET");
+      if (res.errcode == "0") {
+        that.$set(that, `info`, res.data);
+      } else {
+        uni.showToast({
+          title: res.errmsg,
+          icon: "none",
+        });
+      }
+    },
+  },
+};
 </script>
 
 <style lang="scss">
-	.main {
-		display: flex;
-		flex-direction: column;
-		width: 100vw;
-		height: 100vh;
+.main {
+  display: flex;
+  flex-direction: column;
+  width: 100vw;
+  height: 100vh;
 
-		.one {
-			padding: 2vw;
-		}
-	}
+  .one {
+    padding: 2vw;
+  }
+}
 </style>