Initial commit
This commit is contained in:
120
components/AreaPicker/areaCode.js
Normal file
120
components/AreaPicker/areaCode.js
Normal file
@@ -0,0 +1,120 @@
|
||||
export const areaCode = [
|
||||
{ label: "中国", value: "86" },
|
||||
{ label: "马来西亚", value: "60" },
|
||||
{ label: "印度尼西亚", value: "62" },
|
||||
{ label: "菲律宾", value: "63" },
|
||||
{ label: "新加坡", value: "65" },
|
||||
{ label: "泰国", value: "66" },
|
||||
{ label: "文莱", value: "673" },
|
||||
{ label: "日本", value: "81" },
|
||||
{ label: "韩国", value: "82" },
|
||||
{ label: "越南", value: "84" },
|
||||
{ label: "朝鲜", value: "850" },
|
||||
{ label: "香港(中国)", value: "852" },
|
||||
{ label: "澳门(中国)", value: "853" },
|
||||
{ label: "柬埔寨", value: "855" },
|
||||
{ label: "老挝", value: "856" },
|
||||
{ label: "台湾(中国)", value: "886" },
|
||||
{ label: "孟加拉国", value: "880" },
|
||||
{ label: "土耳其", value: "90" },
|
||||
{ label: "印度", value: "91" },
|
||||
{ label: "巴基斯坦", value: "92" },
|
||||
{ label: "阿富汗", value: "93" },
|
||||
{ label: "斯里兰卡", value: "94" },
|
||||
{ label: "缅甸", value: "95" },
|
||||
{ label: "马尔代夫", value: "960" },
|
||||
{ label: "黎巴嫩", value: "961" },
|
||||
{ label: "约旦", value: "962" },
|
||||
{ label: "叙利亚", value: "963" },
|
||||
{ label: "伊拉克", value: "964" },
|
||||
{ label: "科威特", value: "965" },
|
||||
{ label: "沙特阿拉伯", value: "966" },
|
||||
{ label: "阿曼", value: "968" },
|
||||
{ label: "以色列", value: "972" },
|
||||
{ label: "巴林", value: "973" },
|
||||
{ label: "卡塔尔", value: "974" },
|
||||
{ label: "不丹", value: "975" },
|
||||
{ label: "蒙古", value: "976" },
|
||||
{ label: "尼泊尔", value: "977" },
|
||||
{ label: "伊朗", value: "98" },
|
||||
{ label: "塞浦路斯", value: "357" },
|
||||
{ label: "巴勒斯坦", value: "970" },
|
||||
{ label: "阿联酋", value: "971" },
|
||||
{ label: "俄罗斯联邦", value: "7" },
|
||||
{ label: "希腊", value: "30" },
|
||||
{ label: "荷兰", value: "31" },
|
||||
{ label: "比利时", value: "32" },
|
||||
{ label: "法国", value: "33" },
|
||||
{ label: "西班牙", value: "34" },
|
||||
{ label: "直布罗陀", value: "350" },
|
||||
{ label: "葡萄牙", value: "351" },
|
||||
{ label: "卢森堡", value: "352" },
|
||||
{ label: "爱尔兰", value: "353" },
|
||||
{ label: "冰岛", value: "354" },
|
||||
{ label: "阿尔巴尼亚", value: "355" },
|
||||
{ label: "马耳他", value: "356" },
|
||||
{ label: "安道尔", value: "376" },
|
||||
{ label: "芬兰", value: "358" },
|
||||
{ label: "保加利亚", value: "359" },
|
||||
{ label: "匈牙利", value: "36" },
|
||||
{ label: "德国", value: "49" },
|
||||
{ label: "南斯拉夫", value: "381" },
|
||||
{ label: "意大利", value: "39" },
|
||||
{ label: "圣马力诺", value: "378" },
|
||||
{ label: "梵蒂冈", value: "3906698" },
|
||||
{ label: "罗马尼亚", value: "40" },
|
||||
{ label: "瑞士", value: "41" },
|
||||
{ label: "列支敦士登", value: "423" },
|
||||
{ label: "奥地利", value: "43" },
|
||||
{ label: "英国", value: "44" },
|
||||
{ label: "丹麦", value: "45" },
|
||||
{ label: "瑞典", value: "46" },
|
||||
{ label: "挪威", value: "47" },
|
||||
{ label: "波兰", value: "48" },
|
||||
{ label: "捷克", value: "420" },
|
||||
{ label: "斯洛伐克", value: "421" },
|
||||
{ label: "摩纳哥", value: "377" },
|
||||
{ label: "马其顿", value: "389" },
|
||||
{ label: "科罗地亚", value: "385" },
|
||||
{ label: "斯洛文尼亚", value: "386" },
|
||||
{ label: "波斯尼亚和塞哥维那", value: "387" },
|
||||
{ label: "亚美尼亚共和国", value: "374" },
|
||||
{ label: "白俄罗斯共和国", value: "375" },
|
||||
{ label: "格鲁吉亚共和国", value: "995" },
|
||||
{ label: "哈萨克斯坦共和国", value: "7" },
|
||||
{ label: "吉尔吉斯坦共和国", value: "996" },
|
||||
{ label: "乌兹别克斯坦共和国", value: "998" },
|
||||
{ label: "塔吉克斯坦共和国", value: "992" },
|
||||
{ label: "土库曼斯坦共和国", value: "993" },
|
||||
{ label: "乌克兰", value: "380" },
|
||||
{ label: "立陶宛", value: "370" },
|
||||
{ label: "拉脱维亚", value: "371" },
|
||||
{ label: "爱沙尼亚", value: "372" },
|
||||
{ label: "摩尔多瓦", value: "373" },
|
||||
{ label: "埃及", value: "20" },
|
||||
{ label: "摩洛哥", value: "212" },
|
||||
{ label: "阿尔及利亚", value: "213" },
|
||||
{ label: "突尼斯", value: "216" },
|
||||
{ label: "利比亚", value: "218" },
|
||||
{ label: "冈比亚", value: "220" },
|
||||
{ label: "塞内加尔", value: "221" },
|
||||
{ label: "毛里塔尼亚", value: "222" },
|
||||
{ label: "马里", value: "223" },
|
||||
{ label: "几内亚", value: "224" },
|
||||
{ label: "科特迪瓦", value: "225" },
|
||||
{ label: "布基拉法索", value: "226" },
|
||||
{ label: "尼日尔", value: "227" },
|
||||
{ label: "多哥", value: "228" },
|
||||
{ label: "贝宁", value: "229" },
|
||||
{ label: "毛里求斯", value: "230" },
|
||||
{ label: "利比里亚", value: "231" },
|
||||
{ label: "塞拉利昂", value: "232" },
|
||||
{ label: "加纳", value: "233" },
|
||||
{ label: "尼日利亚", value: "234" },
|
||||
{ label: "乍得", value: "235" },
|
||||
{ label: "中非", value: "236" },
|
||||
{ label: "喀麦隆", value: "237" },
|
||||
{ label: "佛得角", value: "238" },
|
||||
{ label: "圣多美", value: "239" },
|
||||
{ label: "普林西比", value: "239" },
|
||||
];
|
||||
44
components/AreaPicker/index.vue
Normal file
44
components/AreaPicker/index.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<u-picker
|
||||
:show="show"
|
||||
:defaultIndex="defaultIndex"
|
||||
:columns="columns"
|
||||
keyName="label"
|
||||
@cancel="cancel"
|
||||
@confirm="confirm"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { areaCode } from "./areaCode";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
defaultIndex: [0],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.show = true;
|
||||
},
|
||||
confirm({ value }) {
|
||||
const item = value[0];
|
||||
this.$emit("chooseArea", item.value);
|
||||
this.show = false;
|
||||
},
|
||||
cancel() {
|
||||
this.show = false;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
columns() {
|
||||
const list = areaCode.map((i) => {
|
||||
return { label: `${i.label} +${i.value}`, value: i.value };
|
||||
});
|
||||
return [list];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
59
components/ChooseIndexFooter/SelectedMember.vue
Normal file
59
components/ChooseIndexFooter/SelectedMember.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<view class="selected_item">
|
||||
<view class="left_info">
|
||||
<my-avatar
|
||||
:src="source.faceURL"
|
||||
:desc="source.nickname || source.showName"
|
||||
:isGroup="Boolean(source.groupID)"
|
||||
size="42"
|
||||
/>
|
||||
<text>{{ source.nickname || source.groupName || source.showName }}</text>
|
||||
</view>
|
||||
<view>
|
||||
<u-button @click="action" plain text="移除" type="primary" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MyAvatar from "@/components/MyAvatar/index.vue";
|
||||
export default {
|
||||
name: "",
|
||||
components: {
|
||||
MyAvatar,
|
||||
},
|
||||
props: {
|
||||
source: Object,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
action() {
|
||||
this.$emit("removeItem");
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.source);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.selected_item {
|
||||
@include btwBox();
|
||||
padding: 20rpx 0;
|
||||
|
||||
.left_info {
|
||||
@include vCenterBox();
|
||||
|
||||
.u-avatar {
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.u-button {
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
143
components/ChooseIndexFooter/index.vue
Normal file
143
components/ChooseIndexFooter/index.vue
Normal file
@@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<view class="member_checked_desc">
|
||||
<view @click="showSelected = true" class="left_info">
|
||||
<view class="select_num">
|
||||
<text class="text">{{ `已选择(${choosedData.length})` }}</text>
|
||||
<u-icon name="arrow-up" size="14" color="#007aff" />
|
||||
</view>
|
||||
<view class="select_list">{{ selectedStr }}</view>
|
||||
</view>
|
||||
<view class="">
|
||||
<u-button
|
||||
:loading="comfirmLoading"
|
||||
@click="clickComfirm"
|
||||
:disabled="choosedData.length === 0"
|
||||
type="primary"
|
||||
:text="
|
||||
isRemove
|
||||
? '移除'
|
||||
: `确定(${choosedData.length}${
|
||||
maxLength > 0 ? `/${maxLength}` : ``
|
||||
})`
|
||||
"
|
||||
/>
|
||||
<u-popup round="24" :show="showSelected" mode="bottom" @close="close">
|
||||
<view class="selected_container">
|
||||
<view class="top_desc">
|
||||
<text>{{ `已选择(${choosedData.length})` }}</text>
|
||||
<text @click="close" class="comfirm_text">确认</text>
|
||||
</view>
|
||||
<u-list class="selected_list">
|
||||
<u-list-item
|
||||
v-for="item in choosedData"
|
||||
:key="item.userID || item.groupID"
|
||||
>
|
||||
<selected-member @removeItem="removeItem(item)" :source="item" />
|
||||
</u-list-item>
|
||||
</u-list>
|
||||
</view>
|
||||
</u-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectedMember from "./SelectedMember.vue";
|
||||
export default {
|
||||
name: "ChooseIndexFooter",
|
||||
components: {
|
||||
SelectedMember,
|
||||
},
|
||||
props: {
|
||||
isRemove: Boolean,
|
||||
choosedData: Array,
|
||||
comfirmLoading: Boolean,
|
||||
maxLength: Number,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showSelected: false,
|
||||
showConfirmModal: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedStr() {
|
||||
return this.choosedData
|
||||
.map((item) => item.nickname || item.showName || item.groupName)
|
||||
.join("、");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.showSelected = false;
|
||||
},
|
||||
removeItem(item) {
|
||||
this.$emit("removeItem", item);
|
||||
},
|
||||
clickComfirm() {
|
||||
this.$emit("confirm");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.member_checked_desc {
|
||||
@include btwBox();
|
||||
background-color: #fff;
|
||||
align-items: flex-start;
|
||||
padding: 24rpx 44rpx 0;
|
||||
height: 60px;
|
||||
max-height: 60px;
|
||||
box-shadow: 0px -1px 4px 1px rgba(0, 0, 0, 0.04);
|
||||
|
||||
.left_info {
|
||||
@include colBox(false);
|
||||
|
||||
.select_num {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $uni-color-primary;
|
||||
}
|
||||
|
||||
.select_list {
|
||||
font-size: 24rpx;
|
||||
color: #8e9ab0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 50vw;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 30rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.u-button {
|
||||
background-color: #0089ff;
|
||||
height: 40px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.selected_container {
|
||||
padding: 44rpx;
|
||||
|
||||
.top_desc {
|
||||
@include btwBox();
|
||||
margin-bottom: 20rpx;
|
||||
|
||||
.comfirm_text {
|
||||
color: $uni-color-primary;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.selected_list {
|
||||
height: 60vh !important;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
91
components/ChooseIndexList/index.vue
Normal file
91
components/ChooseIndexList/index.vue
Normal file
@@ -0,0 +1,91 @@
|
||||
<template>
|
||||
<u-index-list
|
||||
@scrolltolower="scrolltolower"
|
||||
class="user_list"
|
||||
:style="{ height: height }"
|
||||
:index-list="indexList"
|
||||
>
|
||||
<template v-for="(item, index) in itemArr">
|
||||
<u-index-item :key="index">
|
||||
<u-index-anchor
|
||||
class="user_anchor"
|
||||
:text="indexList[index]"
|
||||
></u-index-anchor>
|
||||
<user-item
|
||||
@itemClick="itemClick"
|
||||
@updateCheck="updateCheck"
|
||||
:checked="checkedIDList.includes(cell.userID)"
|
||||
:disabled="disabledIDList.includes(cell.userID)"
|
||||
:checkVisible="showCheck"
|
||||
v-for="cell in item"
|
||||
:item="cell"
|
||||
:key="cell.userID"
|
||||
/>
|
||||
</u-index-item>
|
||||
</template>
|
||||
</u-index-list>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UserItem from "../UserItem/index.vue";
|
||||
export default {
|
||||
name: "ChooseIndexList",
|
||||
components: {
|
||||
UserItem,
|
||||
},
|
||||
props: {
|
||||
height: {
|
||||
type: String,
|
||||
default: "0px",
|
||||
},
|
||||
indexList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
itemArr: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
checkedIDList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
disabledIDList: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
showCheck: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
itemClick(item) {
|
||||
this.$emit("itemClick", item);
|
||||
},
|
||||
updateCheck(item) {
|
||||
this.$emit("updateCheck", item);
|
||||
},
|
||||
scrolltolower() {
|
||||
this.$emit("scrolltolower");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.user_list {
|
||||
flex: 1;
|
||||
/deep/uni-scroll-view {
|
||||
max-height: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.user_anchor {
|
||||
background-color: #f8f8f8 !important;
|
||||
border: none !important;
|
||||
}
|
||||
</style>
|
||||
92
components/CustomNavBar/index.vue
Normal file
92
components/CustomNavBar/index.vue
Normal file
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<u-navbar :title="title" placeholder class="custom_nav_bar">
|
||||
<template slot="left">
|
||||
<slot name="left">
|
||||
<view class="u-nav-slot">
|
||||
<img
|
||||
@click="leftClick"
|
||||
class="back_icon"
|
||||
width="12"
|
||||
height="20"
|
||||
src="static/images/common_left_arrow.png"
|
||||
alt=""
|
||||
srcset=""
|
||||
/>
|
||||
</view>
|
||||
</slot>
|
||||
</template>
|
||||
|
||||
<template slot="center">
|
||||
<slot name="center"></slot>
|
||||
</template>
|
||||
|
||||
<template slot="right">
|
||||
<slot name="more">
|
||||
<view @click="rightClick" v-if="more" class="u-nav-slot">
|
||||
<u-icon
|
||||
class="more_dot"
|
||||
name="more-dot-fill"
|
||||
size="23"
|
||||
color="#0C1C33"
|
||||
></u-icon>
|
||||
</view>
|
||||
</slot>
|
||||
</template>
|
||||
</u-navbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "",
|
||||
components: {},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
more: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
route: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
leftClick() {
|
||||
if (this.route) {
|
||||
uni.navigateBack();
|
||||
}
|
||||
this.$emit("leftClick");
|
||||
},
|
||||
rightClick() {
|
||||
this.$emit("rightClick");
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.custom_nav_bar {
|
||||
/deep/ .u-navbar__content__left {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/deep/ .u-navbar__content__right {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.back_icon {
|
||||
padding: 24rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.more_dot {
|
||||
padding: 24rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
94
components/MyAvatar/index.vue
Normal file
94
components/MyAvatar/index.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<u-avatar
|
||||
@longpress="longpress"
|
||||
@click="click"
|
||||
@onError="errorHandle"
|
||||
:src="getAvatarUrl"
|
||||
:text="avatarText"
|
||||
bgColor="#0089FF"
|
||||
:defaultUrl="getDdefaultUrl"
|
||||
:shape="shape"
|
||||
:size="size"
|
||||
mode="aspectFill"
|
||||
font-size="14"
|
||||
>
|
||||
</u-avatar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import defaultGroupIcon from "static/images/contact_my_group.png";
|
||||
import defaultNotifyIcon from "static/images/default_notify_icon.png";
|
||||
export default {
|
||||
name: "MyAvatar",
|
||||
props: {
|
||||
src: String,
|
||||
shape: {
|
||||
type: String,
|
||||
default: "square",
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: "40",
|
||||
},
|
||||
isGroup: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isNotify: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
desc: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatarText: undefined,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
getAvatarUrl() {
|
||||
if (this.src) {
|
||||
return this.src;
|
||||
}
|
||||
if (this.isGroup) {
|
||||
return defaultGroupIcon;
|
||||
}
|
||||
if (this.isNotify) {
|
||||
return defaultNotifyIcon;
|
||||
}
|
||||
this.avatarText = this.desc ? this.desc.slice(0, 1) : "未知";
|
||||
return "";
|
||||
},
|
||||
getDdefaultUrl() {
|
||||
return this.isGroup ? defaultGroupIcon : undefined;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
errorHandle() {
|
||||
this.avatarText = this.desc ? this.desc.slice(0, 1) : "未知";
|
||||
},
|
||||
redirectShow() {
|
||||
if (this.avatarText) {
|
||||
this.avatarText = undefined;
|
||||
}
|
||||
},
|
||||
click() {
|
||||
this.$emit("click");
|
||||
},
|
||||
longpress() {
|
||||
this.$emit("longpress");
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
src() {
|
||||
this.redirectShow();
|
||||
},
|
||||
desc() {
|
||||
this.redirectShow();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
84
components/SettingItem/index.vue
Normal file
84
components/SettingItem/index.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<view
|
||||
@click="onClick"
|
||||
class="setting_item"
|
||||
:class="{ setting_item_border: border }"
|
||||
>
|
||||
<text :style="{ color: danger ? '#FF381F' : '$uni-text-color' }">{{
|
||||
title
|
||||
}}</text>
|
||||
<u-switch
|
||||
:loading="loading"
|
||||
@change="onChange"
|
||||
:asyncChange="true"
|
||||
v-if="is_switch"
|
||||
size="20"
|
||||
:value="switchValue"
|
||||
/>
|
||||
<view v-else class="setting_right">
|
||||
<slot></slot>
|
||||
<u-icon v-if="arrow" name="arrow-right" color="#999" size="18" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "",
|
||||
components: {},
|
||||
props: {
|
||||
title: String,
|
||||
danger: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
is_switch: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
switchValue: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
border: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
arrow: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
onClick() {
|
||||
this.$emit("click");
|
||||
},
|
||||
onChange(value) {
|
||||
this.$emit("switch", value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.setting_item {
|
||||
@include btwBox();
|
||||
padding: 24rpx 36rpx;
|
||||
color: $uni-text-color;
|
||||
|
||||
.setting_right {
|
||||
@include vCenterBox();
|
||||
}
|
||||
|
||||
&_border {
|
||||
border-bottom: 1px solid rgba(153, 153, 153, 0.2);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
149
components/UserItem/index.vue
Normal file
149
components/UserItem/index.vue
Normal file
@@ -0,0 +1,149 @@
|
||||
<template>
|
||||
<view @click="clickItem" class="user_item">
|
||||
<view
|
||||
v-if="checkVisible"
|
||||
class="check_wrap"
|
||||
:class="{ check_wrap_active: checked, check_wrap_disabled: disabled }"
|
||||
>
|
||||
<u-icon v-show="checked" name="checkbox-mark" size="12" color="#fff" />
|
||||
</view>
|
||||
|
||||
<my-avatar
|
||||
:src="item.faceURL"
|
||||
:desc="item.remark || item.nickname || item.showName"
|
||||
:isGroup="item.groupName !== undefined || isGroupConversation"
|
||||
size="42"
|
||||
/>
|
||||
<view class="user_item_details">
|
||||
<text class="user_name">{{
|
||||
item.remark || item.nickname || item.groupName || item.showName
|
||||
}}</text>
|
||||
<text v-if="item.roleLevel === 100" class="user_role">群主</text>
|
||||
<text v-if="item.roleLevel === 60" class="user_role admin_role"
|
||||
>管理员</text
|
||||
>
|
||||
<!-- <view class="bottom_line" /> -->
|
||||
</view>
|
||||
|
||||
<slot name="action"></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MyAvatar from "@/components/MyAvatar/index.vue";
|
||||
import { SessionType } from "openim-uniapp-polyfill";
|
||||
export default {
|
||||
name: "UserItem",
|
||||
components: {
|
||||
MyAvatar,
|
||||
},
|
||||
props: {
|
||||
checkVisible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
item: Object,
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
isGroupConversation() {
|
||||
return this.item.conversationType === SessionType.WorkingGroup;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
clickItem() {
|
||||
if (!this.disabled) {
|
||||
this.$emit(this.checkVisible ? "updateCheck" : "itemClick", this.item);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user_item {
|
||||
@include vCenterBox();
|
||||
padding: 24rpx 44rpx;
|
||||
color: $uni-text-color;
|
||||
position: relative;
|
||||
|
||||
.check_wrap {
|
||||
@include centerBox();
|
||||
box-sizing: border-box;
|
||||
width: 40rpx;
|
||||
min-width: 40rpx;
|
||||
height: 40rpx;
|
||||
min-height: 40rpx;
|
||||
border: 2px solid #979797;
|
||||
border-radius: 50%;
|
||||
margin-top: 16rpx;
|
||||
margin-right: 24rpx;
|
||||
|
||||
&_active {
|
||||
background-color: #1d6bed;
|
||||
border: none;
|
||||
}
|
||||
|
||||
&_disabled {
|
||||
background-color: #c8c9cc;
|
||||
}
|
||||
}
|
||||
|
||||
&_details {
|
||||
@include vCenterBox();
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-left: 24rpx;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
.bottom_line {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: #f0f0f0;
|
||||
position: absolute;
|
||||
bottom: -44rpx;
|
||||
}
|
||||
|
||||
.user_name {
|
||||
@include nomalEllipsis();
|
||||
max-width: 60%;
|
||||
color: $uni-text-color;
|
||||
}
|
||||
|
||||
.user_role {
|
||||
font-size: 34rpx;
|
||||
// background-color: #f4da9a;
|
||||
// color: #FF8C00;
|
||||
padding: 8rpx 24rpx;
|
||||
border-radius: 24rpx;
|
||||
margin-left: 24rpx;
|
||||
color: $u-tips-color;
|
||||
}
|
||||
|
||||
.admin_role {
|
||||
color: $u-tips-color;
|
||||
// background-color: #A2C9F8;
|
||||
// color: #2691ED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.u-list-item:last-child {
|
||||
.bottom_line {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
29
components/gaoyia-parse/components/wxParseAudio.vue
Normal file
29
components/gaoyia-parse/components/wxParseAudio.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<!-- '<audio/>' 组件不再维护,建议使用能力更强的 'uni.createInnerAudioContext' 接口 有时间再改-->
|
||||
<!--增加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>
|
||||
95
components/gaoyia-parse/components/wxParseImg.vue
Normal file
95
components/gaoyia-parse/components/wxParseImg.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<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: false,
|
||||
};
|
||||
},
|
||||
inject: ["parseWidth"],
|
||||
mounted() {},
|
||||
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;
|
||||
let { width, height } = e.mp.detail;
|
||||
|
||||
const recal = this.wxAutoImageCal(width, height);
|
||||
|
||||
const { imageheight, imageWidth } = recal;
|
||||
const { padding, mode } = this.node.attr; //删除padding
|
||||
// const { 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;`; //删除padding
|
||||
// this.newStyleStr = `${styleStr}; ${imageHeightStyle}; width: ${imageWidth}px;`;
|
||||
},
|
||||
// 计算视觉优先的图片宽高
|
||||
wxAutoImageCal(originalWidth, originalHeight) {
|
||||
// 获取图片的原始长宽
|
||||
const windowWidth = this.parseWidth.value;
|
||||
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>
|
||||
59
components/gaoyia-parse/components/wxParseTable.vue
Normal file
59
components/gaoyia-parse/components/wxParseTable.vue
Normal file
@@ -0,0 +1,59 @@
|
||||
<template>
|
||||
<div class="tablebox">
|
||||
<rich-text
|
||||
:nodes="nodes"
|
||||
:class="node.classStr"
|
||||
:style="'user-select:' + parseSelect"
|
||||
></rich-text>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: "wxParseTable",
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
inject: ["parseSelect"],
|
||||
data() {
|
||||
return {
|
||||
nodes: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.nodes = this.loadNode([this.node]);
|
||||
},
|
||||
methods: {
|
||||
loadNode(node) {
|
||||
let obj = [];
|
||||
for (let children of node) {
|
||||
if (children.node == "element") {
|
||||
let t = {
|
||||
name: children.tag,
|
||||
attrs: {
|
||||
class: children.classStr,
|
||||
// style: children.styleStr,
|
||||
},
|
||||
children: children.nodes ? this.loadNode(children.nodes) : [],
|
||||
};
|
||||
|
||||
obj.push(t);
|
||||
} else if (children.node == "text") {
|
||||
obj.push({
|
||||
type: "text",
|
||||
text: children.text,
|
||||
});
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
@import url("../parse.css");
|
||||
</style>
|
||||
122
components/gaoyia-parse/components/wxParseTemplate0.vue
Normal file
122
components/gaoyia-parse/components/wxParseTemplate0.vue
Normal file
@@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifdef APP-PLUS | H5
|
||||
import wxParseTemplate from "./wxParseTemplate0";
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
import wxParseTemplate from "./wxParseTemplate1";
|
||||
// #endif
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
// #ifdef APP-PLUS | H5
|
||||
name: "wxParseTemplate",
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
name: "wxParseTemplate0",
|
||||
// #endif
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate1.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate1.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate2";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate1",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate10.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate10.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate11";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate10",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
121
components/gaoyia-parse/components/wxParseTemplate11.vue
Normal file
121
components/gaoyia-parse/components/wxParseTemplate11.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<rich-text
|
||||
:nodes="node"
|
||||
:class="node.classStr"
|
||||
:style="'user-select:' + parseSelect"
|
||||
></rich-text>
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
:class="node.classStr"
|
||||
:data-href="node.attr.href"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<rich-text
|
||||
:nodes="node"
|
||||
:class="node.classStr"
|
||||
:style="'user-select:' + parseSelect"
|
||||
></rich-text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<rich-text
|
||||
:nodes="node"
|
||||
:class="node.classStr"
|
||||
:style="'user-select:' + parseSelect"
|
||||
></rich-text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img :node="node" v-else-if="node.tag == 'img'" />
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :class="node.classStr" :style="node.styleStr">
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<rich-text
|
||||
:nodes="node"
|
||||
:class="node.classStr"
|
||||
:style="'user-select:' + parseSelect"
|
||||
></rich-text>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<!--判断是否是文本节点-->
|
||||
<block v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate11",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate2.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate2.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate3";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate2",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate3.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate3.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate4";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate3",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate4.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate4.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate5";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate4",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate5.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate5.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate6";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate5",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate6.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate6.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate7";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate6",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate7.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate7.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate8";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate7",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate8.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate8.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate9";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate8",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
111
components/gaoyia-parse/components/wxParseTemplate9.vue
Normal file
111
components/gaoyia-parse/components/wxParseTemplate9.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<!--判断是否是标签节点-->
|
||||
<block v-if="node.node == 'element'">
|
||||
<!--button类型-->
|
||||
<button
|
||||
v-if="node.tag == 'button'"
|
||||
type="default"
|
||||
size="mini"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<wx-parse-template :node="node" />
|
||||
</button>
|
||||
|
||||
<!--a类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'a'"
|
||||
@click="wxParseATap(node.attr, $event)"
|
||||
: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>
|
||||
|
||||
<!--li类型-->
|
||||
<view
|
||||
v-else-if="node.tag == 'li'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
>
|
||||
<block v-for="(node, index) of node.nodes" :key="index">
|
||||
<wx-parse-template :node="node" />
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<!--table类型-->
|
||||
<wx-parse-table
|
||||
v-else-if="node.tag == 'table'"
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
:node="node"
|
||||
/>
|
||||
|
||||
<!--br类型-->
|
||||
<!-- #ifndef H5 -->
|
||||
<text v-else-if="node.tag == 'br'">\n</text>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<br v-else-if="node.tag == 'br'" />
|
||||
<!-- #endif -->
|
||||
|
||||
<!--video类型-->
|
||||
<wx-parse-video :node="node" v-else-if="node.tag == 'video'" />
|
||||
|
||||
<!--audio类型-->
|
||||
<wx-parse-audio :node="node" v-else-if="node.tag == 'audio'" />
|
||||
|
||||
<!--img类型-->
|
||||
<wx-parse-img
|
||||
:node="node"
|
||||
v-else-if="node.tag == 'img'"
|
||||
:style="node.styleStr"
|
||||
/>
|
||||
|
||||
<!--其他标签-->
|
||||
<view v-else :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 v-else-if="node.node == 'text'">{{ node.text }}</block>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import wxParseTemplate from "./wxParseTemplate10";
|
||||
import wxParseImg from "./wxParseImg";
|
||||
import wxParseVideo from "./wxParseVideo";
|
||||
import wxParseAudio from "./wxParseAudio";
|
||||
import wxParseTable from "./wxParseTable";
|
||||
|
||||
export default {
|
||||
name: "wxParseTemplate9",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
components: {
|
||||
wxParseTemplate,
|
||||
wxParseImg,
|
||||
wxParseVideo,
|
||||
wxParseAudio,
|
||||
wxParseTable,
|
||||
},
|
||||
methods: {
|
||||
wxParseATap(attr, 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, attr);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
20
components/gaoyia-parse/components/wxParseVideo.vue
Normal file
20
components/gaoyia-parse/components/wxParseVideo.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<!--增加video标签支持,并循环添加-->
|
||||
<view :class="node.classStr" :style="node.styleStr">
|
||||
<video
|
||||
:class="node.classStr"
|
||||
:style="node.styleStr"
|
||||
class="video-video"
|
||||
:src="node.attr.src"
|
||||
></video>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "wxParseVideo",
|
||||
props: {
|
||||
node: {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
266
components/gaoyia-parse/libs/html2json.js
Normal file
266
components/gaoyia-parse/libs/html2json.js
Normal file
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* 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;
|
||||
170
components/gaoyia-parse/libs/htmlparser.js
Normal file
170
components/gaoyia-parse/libs/htmlparser.js
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
*
|
||||
* 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;
|
||||
227
components/gaoyia-parse/libs/wxDiscode.js
Normal file
227
components/gaoyia-parse/libs/wxDiscode.js
Normal file
@@ -0,0 +1,227 @@
|
||||
// HTML 支持的数学符号
|
||||
function strNumDiscode(str) {
|
||||
str = str.replace(/∀|∀|∀/g, "∀");
|
||||
str = str.replace(/∂|∂|∂/g, "∂");
|
||||
str = str.replace(/∃|∃|∃/g, "∃");
|
||||
str = str.replace(/∅|∅|∅/g, "∅");
|
||||
str = str.replace(/∇|∇|∇/g, "∇");
|
||||
str = str.replace(/∈|∈|∈/g, "∈");
|
||||
str = str.replace(/∉|∉|∉/g, "∉");
|
||||
str = str.replace(/∋|∋|∋/g, "∋");
|
||||
str = str.replace(/∏|∏|∏/g, "∏");
|
||||
str = str.replace(/∑|∑|∑/g, "∑");
|
||||
str = str.replace(/−|−|−/g, "−");
|
||||
str = str.replace(/∗|∗|∗/g, "∗");
|
||||
str = str.replace(/√|√|√/g, "√");
|
||||
str = str.replace(/∝|∝|∝/g, "∝");
|
||||
str = str.replace(/∞|∞|∞/g, "∞");
|
||||
str = str.replace(/∠|∠|∠/g, "∠");
|
||||
str = str.replace(/∧|∧|∧/g, "∧");
|
||||
str = str.replace(/∨|∨|∨/g, "∨");
|
||||
str = str.replace(/∩|∩|∩/g, "∩");
|
||||
str = str.replace(/∪|∪|∪/g, "∪");
|
||||
str = str.replace(/∫|∫|∫/g, "∫");
|
||||
str = str.replace(/∴|∴|∴/g, "∴");
|
||||
str = str.replace(/∼|∼|∼/g, "∼");
|
||||
str = str.replace(/≅|≅|≅/g, "≅");
|
||||
str = str.replace(/≈|≈|≈/g, "≈");
|
||||
str = str.replace(/≠|≠|≠/g, "≠");
|
||||
str = str.replace(/≤|≤|≤/g, "≤");
|
||||
str = str.replace(/≥|≥|≥/g, "≥");
|
||||
str = str.replace(/⊂|⊂|⊂/g, "⊂");
|
||||
str = str.replace(/⊃|⊃|⊃/g, "⊃");
|
||||
str = str.replace(/⊄|⊄|⊄/g, "⊄");
|
||||
str = str.replace(/⊆|⊆|⊆/g, "⊆");
|
||||
str = str.replace(/⊇|⊇|⊇/g, "⊇");
|
||||
str = str.replace(/⊕|⊕|⊕/g, "⊕");
|
||||
str = str.replace(/⊗|⊗|⊗/g, "⊗");
|
||||
str = str.replace(/⊥|⊥|⊥/g, "⊥");
|
||||
str = str.replace(/⋅|⋅|⋅/g, "⋅");
|
||||
return str;
|
||||
}
|
||||
|
||||
// HTML 支持的希腊字母
|
||||
function strGreeceDiscode(str) {
|
||||
str = str.replace(/Α|Α|Α/g, "Α");
|
||||
str = str.replace(/Β|Β|Β/g, "Β");
|
||||
str = str.replace(/Γ|Γ|Γ/g, "Γ");
|
||||
str = str.replace(/Δ|Δ|Δ/g, "Δ");
|
||||
str = str.replace(/Ε|Ε|Ε/g, "Ε");
|
||||
str = str.replace(/Ζ|Ζ|Ζ/g, "Ζ");
|
||||
str = str.replace(/Η|Η|Η/g, "Η");
|
||||
str = str.replace(/Θ|Θ|Θ/g, "Θ");
|
||||
str = str.replace(/Ι|Ι|Ι/g, "Ι");
|
||||
str = str.replace(/Κ|Κ|Κ/g, "Κ");
|
||||
str = str.replace(/Λ|Λ|Λ/g, "Λ");
|
||||
str = str.replace(/Μ|Μ|Μ/g, "Μ");
|
||||
str = str.replace(/Ν|Ν|Ν/g, "Ν");
|
||||
str = str.replace(/Ξ|Ν|Ν/g, "Ν");
|
||||
str = str.replace(/Ο|Ο|Ο/g, "Ο");
|
||||
str = str.replace(/Π|Π|Π/g, "Π");
|
||||
str = str.replace(/Ρ|Ρ|Ρ/g, "Ρ");
|
||||
str = str.replace(/Σ|Σ|Σ/g, "Σ");
|
||||
str = str.replace(/Τ|Τ|Τ/g, "Τ");
|
||||
str = str.replace(/Υ|Υ|Υ/g, "Υ");
|
||||
str = str.replace(/Φ|Φ|Φ/g, "Φ");
|
||||
str = str.replace(/Χ|Χ|Χ/g, "Χ");
|
||||
str = str.replace(/Ψ|Ψ|Ψ/g, "Ψ");
|
||||
str = str.replace(/Ω|Ω|Ω/g, "Ω");
|
||||
|
||||
str = str.replace(/α|α|α/g, "α");
|
||||
str = str.replace(/β|β|β/g, "β");
|
||||
str = str.replace(/γ|γ|γ/g, "γ");
|
||||
str = str.replace(/δ|δ|δ/g, "δ");
|
||||
str = str.replace(/ε|ε|ε/g, "ε");
|
||||
str = str.replace(/ζ|ζ|ζ/g, "ζ");
|
||||
str = str.replace(/η|η|η/g, "η");
|
||||
str = str.replace(/θ|θ|θ/g, "θ");
|
||||
str = str.replace(/ι|ι|ι/g, "ι");
|
||||
str = str.replace(/κ|κ|κ/g, "κ");
|
||||
str = str.replace(/λ|λ|λ/g, "λ");
|
||||
str = str.replace(/μ|μ|μ/g, "μ");
|
||||
str = str.replace(/ν|ν|ν/g, "ν");
|
||||
str = str.replace(/ξ|ξ|ξ/g, "ξ");
|
||||
str = str.replace(/ο|ο|ο/g, "ο");
|
||||
str = str.replace(/π|π|π/g, "π");
|
||||
str = str.replace(/ρ|ρ|ρ/g, "ρ");
|
||||
str = str.replace(/ς|ς|ς/g, "ς");
|
||||
str = str.replace(/σ|σ|σ/g, "σ");
|
||||
str = str.replace(/τ|τ|τ/g, "τ");
|
||||
str = str.replace(/υ|υ|υ/g, "υ");
|
||||
str = str.replace(/φ|φ|φ/g, "φ");
|
||||
str = str.replace(/χ|χ|χ/g, "χ");
|
||||
str = str.replace(/ψ|ψ|ψ/g, "ψ");
|
||||
str = str.replace(/ω|ω|ω/g, "ω");
|
||||
str = str.replace(/ϑ|ϑ|ϑ/g, "ϑ");
|
||||
str = str.replace(/ϒ|ϒ|ϒ/g, "ϒ");
|
||||
str = str.replace(/ϖ|ϖ|ϖ/g, "ϖ");
|
||||
str = str.replace(/·|·|·/g, "·");
|
||||
return str;
|
||||
}
|
||||
|
||||
function strcharacterDiscode(str) {
|
||||
// 加入常用解析
|
||||
|
||||
// str = str.replace(/ | | /g, " ");
|
||||
// str = str.replace(/ | | /g, ' ');
|
||||
// str = str.replace(/ | /g, '<span class=\'spaceshow\'> </span>');
|
||||
// str = str.replace(/ | | /g, ' ');
|
||||
// str = str.replace(/"|"|"/g, "\"");
|
||||
// str = str.replace(/'|'|'/g, "'");
|
||||
// str = str.replace(/´|´|´/g, "´");
|
||||
// str = str.replace(/×|×|×/g, "×");
|
||||
// str = str.replace(/÷|÷|÷/g, "÷");
|
||||
// str = str.replace(/&|&|&/g, '&');
|
||||
// str = str.replace(/<|<|</g, '<');
|
||||
// str = str.replace(/>|>|>/g, '>');
|
||||
|
||||
str = str.replace(/ | | /g, "<span class='spaceshow'> </span>");
|
||||
str = str.replace(
|
||||
/ | | /g,
|
||||
"<span class='spaceshow'> </span>",
|
||||
);
|
||||
str = str.replace(/ | /g, "<span class='spaceshow'> </span>");
|
||||
str = str.replace(
|
||||
/ | | /g,
|
||||
"<span class='spaceshow'> </span>",
|
||||
);
|
||||
str = str.replace(/"|"|"/g, '"');
|
||||
str = str.replace(/"|'|'/g, "'");
|
||||
str = str.replace(/´|´|´/g, "´");
|
||||
str = str.replace(/×|×|×/g, "×");
|
||||
str = str.replace(/÷|÷|÷/g, "÷");
|
||||
str = str.replace(/&|&|&/g, "&");
|
||||
str = str.replace(/<|<|</g, "<");
|
||||
str = str.replace(/>|>|>/g, ">");
|
||||
return str;
|
||||
}
|
||||
|
||||
// HTML 支持的其他实体
|
||||
function strOtherDiscode(str) {
|
||||
str = str.replace(/Œ|Œ|Œ/g, "Œ");
|
||||
str = str.replace(/œ|œ|œ/g, "œ");
|
||||
str = str.replace(/Š|Š|Š/g, "Š");
|
||||
str = str.replace(/š|š|š/g, "š");
|
||||
str = str.replace(/Ÿ|Ÿ|Ÿ/g, "Ÿ");
|
||||
str = str.replace(/ƒ|ƒ|ƒ/g, "ƒ");
|
||||
str = str.replace(/ˆ|ˆ|ˆ/g, "ˆ");
|
||||
str = str.replace(/˜|˜|˜/g, "˜");
|
||||
str = str.replace(
|
||||
/ |$#8201;| /g,
|
||||
"<span class='spaceshow'> </span>",
|
||||
);
|
||||
str = str.replace(
|
||||
/‌|‌|‌/g,
|
||||
"<span class='spaceshow'></span>",
|
||||
);
|
||||
str = str.replace(
|
||||
/‍|$#8205;|‍/g,
|
||||
"<span class='spaceshow'></span>",
|
||||
);
|
||||
str = str.replace(
|
||||
/‎|$#8206;|‎/g,
|
||||
"<span class='spaceshow'></span>",
|
||||
);
|
||||
str = str.replace(
|
||||
/‏|‏|‏/g,
|
||||
"<span class='spaceshow'></span>",
|
||||
);
|
||||
str = str.replace(/–|–|–/g, "–");
|
||||
str = str.replace(/—|—|—/g, "—");
|
||||
str = str.replace(/‘|‘|‘/g, "‘");
|
||||
str = str.replace(/’|’|’/g, "’");
|
||||
str = str.replace(/‚|‚|‚/g, "‚");
|
||||
str = str.replace(/“|“|“/g, "“");
|
||||
str = str.replace(/”|”|”/g, "”");
|
||||
str = str.replace(/„|„|„/g, "„");
|
||||
str = str.replace(/†|†|†/g, "†");
|
||||
str = str.replace(/‡|‡|‡/g, "‡");
|
||||
str = str.replace(/•|•|•/g, "•");
|
||||
str = str.replace(/…|…|…/g, "…");
|
||||
str = str.replace(/‰|‰|‰/g, "‰");
|
||||
str = str.replace(/′|′|′/g, "′");
|
||||
str = str.replace(/″|″|″/g, "″");
|
||||
str = str.replace(/‹|‹|‹/g, "‹");
|
||||
str = str.replace(/›|›|›/g, "›");
|
||||
str = str.replace(/‾|‾|‾/g, "‾");
|
||||
str = str.replace(/€|€|€/g, "€");
|
||||
str = str.replace(/™|™|™/g, "™");
|
||||
str = str.replace(/←|←|←/g, "←");
|
||||
str = str.replace(/↑|↑|↑/g, "↑");
|
||||
str = str.replace(/→|→|→/g, "→");
|
||||
str = str.replace(/↓|↓|↓/g, "↓");
|
||||
str = str.replace(/↔|↔|↔/g, "↔");
|
||||
str = str.replace(/↵|↵|↵/g, "↵");
|
||||
str = str.replace(/⌈|⌈|⌈/g, "⌈");
|
||||
str = str.replace(/⌉|⌉|⌉/g, "⌉");
|
||||
str = str.replace(/⌊|⌊|⌊/g, "⌊");
|
||||
str = str.replace(/⌋|⌋|⌋/g, "⌋");
|
||||
str = str.replace(/◊|◊|◊/g, "◊");
|
||||
str = str.replace(/♠|♠|♠/g, "♠");
|
||||
str = str.replace(/♣|♣|♣/g, "♣");
|
||||
str = str.replace(/♥|♥|♥/g, "♥");
|
||||
str = str.replace(/♦|♦|♦/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,
|
||||
};
|
||||
271
components/gaoyia-parse/parse.css
Normal file
271
components/gaoyia-parse/parse.css
Normal file
@@ -0,0 +1,271 @@
|
||||
/**
|
||||
* 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 '/static/wxParse.css';
|
||||
*/
|
||||
.wxParse {
|
||||
user-select: none;
|
||||
width: 100%;
|
||||
font-family: Helvetica, "PingFangSC", "Microsoft Yahei", "微软雅黑", Arial,
|
||||
sans-serif;
|
||||
color: #0c1c33;
|
||||
line-height: 1.5;
|
||||
font-size: 1em;
|
||||
text-align: justify; /* //左右两端对齐 */
|
||||
}
|
||||
.wxParse view,
|
||||
.wxParse uni-view {
|
||||
word-break: break-word;
|
||||
}
|
||||
.wxParse .p {
|
||||
padding-bottom: 0.5em;
|
||||
clear: both;
|
||||
/* letter-spacing: 0;//字间距 */
|
||||
}
|
||||
.wxParse .inline {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.wxParse .div {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.wxParse .h1 {
|
||||
font-size: 2em;
|
||||
line-height: 1.2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
.wxParse .h2 {
|
||||
font-size: 1.5em;
|
||||
margin: 0.83em 0;
|
||||
}
|
||||
.wxParse .h3 {
|
||||
font-size: 1.17em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
.wxParse .h4 {
|
||||
margin: 1.33em 0;
|
||||
}
|
||||
.wxParse .h5 {
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
.wxParse .h6 {
|
||||
font-size: 0.83em;
|
||||
margin: 1.67em 0;
|
||||
}
|
||||
|
||||
.wxParse .h1,
|
||||
.wxParse .h2,
|
||||
.wxParse .h3,
|
||||
.wxParse .h4,
|
||||
.wxParse .h5,
|
||||
.wxParse .h6,
|
||||
.wxParse .b,
|
||||
.wxParse .strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
.wxParse .i,
|
||||
.wxParse .cite,
|
||||
.wxParse .em,
|
||||
.wxParse .var,
|
||||
.wxParse .address {
|
||||
font-style: italic;
|
||||
}
|
||||
.wxParse .spaceshow {
|
||||
white-space: pre;
|
||||
}
|
||||
.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;
|
||||
font-size: 24upx;
|
||||
}
|
||||
.wxParse .code {
|
||||
overflow: auto;
|
||||
padding: 16upx;
|
||||
white-space: pre;
|
||||
margin: 1em 0upx;
|
||||
background: #f5f5f5;
|
||||
font-size: 24upx;
|
||||
}
|
||||
|
||||
.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 .text,
|
||||
.wxParse .span,
|
||||
.wxParse .s {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.wxParse .a {
|
||||
color: deepskyblue;
|
||||
}
|
||||
|
||||
.wxParse .video {
|
||||
text-align: center;
|
||||
margin: 22upx 0;
|
||||
}
|
||||
|
||||
.wxParse .video-video {
|
||||
width: 100%;
|
||||
}
|
||||
.wxParse .uni-image {
|
||||
max-width: 100%;
|
||||
}
|
||||
.wxParse .img {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
margin-bottom: 0em; /* //与p标签底部padding同时修改 */
|
||||
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: 2em;
|
||||
}
|
||||
.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 .tablebox {
|
||||
overflow: auto;
|
||||
background-color: #f5f5f5;
|
||||
background: #f5f5f5;
|
||||
font-size: 13px;
|
||||
padding: 8px;
|
||||
}
|
||||
.wxParse .table .table,
|
||||
.wxParse .table {
|
||||
border-collapse: collapse;
|
||||
box-sizing: border-box;
|
||||
/* 内边框 */
|
||||
/* width: 100%; */
|
||||
overflow: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
.wxParse .tbody {
|
||||
border-collapse: collapse;
|
||||
box-sizing: border-box;
|
||||
/* 内边框 */
|
||||
border: 1px solid #dadada;
|
||||
}
|
||||
.wxParse .table .thead,
|
||||
.wxParse .table .tfoot,
|
||||
.wxParse .table .th {
|
||||
border-collapse: collapse;
|
||||
box-sizing: border-box;
|
||||
background: #ececec;
|
||||
font-weight: 40;
|
||||
}
|
||||
.wxParse .table .tr {
|
||||
border-collapse: collapse;
|
||||
box-sizing: border-box;
|
||||
/* border: 2px solid #F0AD4E; */
|
||||
overflow: auto;
|
||||
}
|
||||
.wxParse .table .th,
|
||||
.wxParse .table .td {
|
||||
border-collapse: collapse;
|
||||
box-sizing: border-box;
|
||||
border: 2upx solid #dadada;
|
||||
overflow: auto;
|
||||
}
|
||||
.wxParse .audio,
|
||||
.wxParse .uni-audio-default {
|
||||
display: block;
|
||||
}
|
||||
226
components/gaoyia-parse/parse.vue
Normal file
226
components/gaoyia-parse/parse.vue
Normal file
@@ -0,0 +1,226 @@
|
||||
<!--**
|
||||
* forked from:https://github.com/F-loat/mpvue-wxParse
|
||||
*
|
||||
* github地址: https://github.com/dcloudio/uParse
|
||||
*
|
||||
* for: uni-app框架下 富文本解析
|
||||
*
|
||||
* 优化 by gaoyia@qq.com https://github.com/gaoyia/parse
|
||||
*/-->
|
||||
|
||||
<template>
|
||||
<!--基础元素-->
|
||||
<div class="wxParse" :class="className" :style="'user-select:' + userSelect">
|
||||
<block v-for="(node, index) of nodes" :key="index" v-if="!loading">
|
||||
<wxParseTemplate :node="node" />
|
||||
</block>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import HtmlToJson from "./libs/html2json";
|
||||
import wxParseTemplate from "./components/wxParseTemplate0";
|
||||
|
||||
export default {
|
||||
name: "wxParse",
|
||||
props: {
|
||||
// user-select:none;
|
||||
userSelect: {
|
||||
type: String,
|
||||
default: "text", //none |text| all | element
|
||||
},
|
||||
imgOptions: {
|
||||
type: [Object, Boolean],
|
||||
default: function () {
|
||||
return {
|
||||
loop: false,
|
||||
indicator: "number",
|
||||
longPressActions: false,
|
||||
// longPressActions: {
|
||||
// itemList: ['发送给朋友', '保存图片', '收藏'],
|
||||
// success: function (res) {
|
||||
// console.log('选中了第' + (res.tapIndex + 1) + '个按钮');
|
||||
// },
|
||||
// fail: function (res) {
|
||||
// console.log(res.errMsg);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
};
|
||||
},
|
||||
},
|
||||
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 {
|
||||
nodes: {},
|
||||
imageUrls: [],
|
||||
wxParseWidth: {
|
||||
value: 0,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
mounted() {
|
||||
this.setHtml();
|
||||
},
|
||||
methods: {
|
||||
setHtml() {
|
||||
this.getWidth().then((data) => {
|
||||
this.wxParseWidth.value = data;
|
||||
});
|
||||
let {
|
||||
content,
|
||||
noData,
|
||||
imageProp,
|
||||
startHandler,
|
||||
endHandler,
|
||||
charsHandler,
|
||||
} = this;
|
||||
let parseData = content || noData;
|
||||
let customHandler = {
|
||||
start: startHandler,
|
||||
end: endHandler,
|
||||
chars: charsHandler,
|
||||
};
|
||||
let results = HtmlToJson(parseData, customHandler, imageProp, this);
|
||||
|
||||
this.imageUrls = results.imageUrls;
|
||||
// this.nodes = results.nodes;
|
||||
|
||||
this.nodes = [];
|
||||
results.nodes.forEach((item) => {
|
||||
setTimeout(() => {
|
||||
this.nodes.push(item);
|
||||
}, 0);
|
||||
});
|
||||
},
|
||||
getWidth() {
|
||||
return new Promise((res, rej) => {
|
||||
// #ifndef MP-ALIPAY || MP-BAIDU
|
||||
uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select(".wxParse")
|
||||
.fields(
|
||||
{
|
||||
size: true,
|
||||
scrollOffset: true,
|
||||
},
|
||||
(data) => {
|
||||
res(data.width);
|
||||
},
|
||||
)
|
||||
.exec();
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU
|
||||
const query = swan.createSelectorQuery();
|
||||
query.select(".wxParse").boundingClientRect();
|
||||
query.exec((obj) => {
|
||||
const rect = obj[0];
|
||||
if (rect) {
|
||||
res(rect.width);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
my.createSelectorQuery()
|
||||
.select(".wxParse")
|
||||
.boundingClientRect()
|
||||
.exec((ret) => {
|
||||
res(ret[0].width);
|
||||
});
|
||||
// #endif
|
||||
});
|
||||
},
|
||||
navigate(href, $event, attr) {
|
||||
console.log(href, attr);
|
||||
this.$emit("navigate", href, $event);
|
||||
},
|
||||
preview(src, $event) {
|
||||
// if (!this.imageUrls.length || typeof this.imgOptions === 'boolean') {
|
||||
// } else {
|
||||
// uni.previewImage({
|
||||
// current: src,
|
||||
// urls: this.imageUrls,
|
||||
// loop: this.imgOptions.loop,
|
||||
// indicator: this.imgOptions.indicator,
|
||||
// longPressActions: this.imgOptions.longPressActions
|
||||
// });
|
||||
// }
|
||||
// this.$emit('preview', src, $event);
|
||||
},
|
||||
removeImageUrl(src) {
|
||||
const { imageUrls } = this;
|
||||
imageUrls.splice(imageUrls.indexOf(src), 1);
|
||||
},
|
||||
},
|
||||
// 父组件中提供
|
||||
provide() {
|
||||
return {
|
||||
parseWidth: this.wxParseWidth,
|
||||
parseSelect: this.userSelect,
|
||||
// 提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
content() {
|
||||
this.setHtml();
|
||||
},
|
||||
// content: {
|
||||
// handler: function(newVal, oldVal) {
|
||||
// if (newVal !== oldVal) {
|
||||
//
|
||||
// }
|
||||
// },
|
||||
// deep: true
|
||||
// }
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user