智慧保安互联网APP
zengh
2021-07-09 1a36fef1028f1bb7a7c9c9476011bc8289e0bf03
初版集成
3 files modified
41 files added
5519 ■■■■■ changed files
App.vue 60 ●●●●● patch | view | raw | blame | history
components/contacts/contacts.vue 236 ●●●●● patch | view | raw | blame | history
components/e-picker/e-picker.js 1 ●●●● patch | view | raw | blame | history
components/e-picker/e-picker.vue 138 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseAudio.vue 28 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseImg.vue 94 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTable.vue 56 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate0.vue 116 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate1.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate10.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate11.vue 105 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate2.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate3.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate4.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate5.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate6.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate7.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate8.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseTemplate9.vue 107 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseVideo.vue 55 ●●●●● patch | view | raw | blame | history
components/feng-parse/components/wxParseVideo1.vue 25 ●●●●● patch | view | raw | blame | history
components/feng-parse/libs/html2json.js 308 ●●●●● patch | view | raw | blame | history
components/feng-parse/libs/htmlparser.js 156 ●●●●● patch | view | raw | blame | history
components/feng-parse/libs/wxDiscode.js 209 ●●●●● patch | view | raw | blame | history
components/feng-parse/parse.css 258 ●●●●● patch | view | raw | blame | history
components/feng-parse/parse.vue 237 ●●●●● patch | view | raw | blame | history
components/nav-bar-top/nav-bar-top.vue 72 ●●●●● patch | view | raw | blame | history
components/outAdmin/uni-Popup.vue 121 ●●●●● patch | view | raw | blame | history
components/pColumn/pColumn.vue 275 ●●●●● patch | view | raw | blame | history
components/seeImges/seeImges.vue 169 ●●●●● patch | view | raw | blame | history
components/squareBut/squareBut.vue 61 ●●●●● patch | view | raw | blame | history
components/submit/emoji/emoji.vue 75 ●●●●● patch | view | raw | blame | history
components/submit/submit.vue 447 ●●●●● patch | view | raw | blame | history
components/uni-load-more/uni-load-more.vue 362 ●●●●● patch | view | raw | blame | history
components/uni-nav-bar/uni-nav-bar.vue 251 ●●●●● patch | view | raw | blame | history
components/uni-nav-bar/uni-status-bar.vue 25 ●●●●● patch | view | raw | blame | history
package.json 24 ●●●●● patch | view | raw | blame | history
pages/login/login-account.vue 208 ●●●● patch | view | raw | blame | history
router/router.js 38 ●●●●● patch | view | raw | blame | history
static/lib/axios.js 3 ●●●●● patch | view | raw | blame | history
static/lib/wxStorage.js 27 ●●●●● patch | view | raw | blame | history
store/actions.js 90 ●●●●● patch | view | raw | blame | history
store/index.js 65 ●●●●● patch | view | raw | blame | history
store/mutations.js 54 ●●●●● patch | view | raw | blame | history
App.vue
@@ -1,19 +1,67 @@
<script>
    import WxStorage from "./static/lib/wxStorage.js" //微信Storage
    export default {
        onLaunch: function() {
            console.log('App Launch')
        data() {
            return {
                login: '',
            }
        },
        onShow: function() {
            console.log('App Show')
        methods: {
            judgeAdmin() {
                var scss = this.$route.path == "/pages/loging/loging";
                wx.getSystemInfo({
                    success(res) {
                        console.log(res)
                    }
                })
                console.log(this.$store.state.logPath, 'scss')
                if (scss) {
                    return
                }
                this.login = WxStorage.get("init");
                // console.log(this.login, 'login')
                if (this.login == "false") {
                    wx.navigateTo({
                        url: 'pages/loging/loging?id=1',
                    })
                }
            }
        },
        watch: {},
        mounted() {},
        onLaunch: function() { //初始化完成时触发(全局只触发一次)
            if (WxStorage.get("init") == '') {
                WxStorage.set("init", 'false');
                console.log('第一次进入')
            }
            // this.judgeAdmin();
        },
        onShow: function() { //当 uni-app 启动,或从后台进入前台显示 //监听用户进入小程序
            // console.log('App Show')
            // this.judgeAdmin();
        },
        onHide: function() {
            console.log('App Hide')
            // console.log('App Hide')
        }
    }
</script>
<style lang="scss">
    // @import '@smallwei/avue/lib/index.css';
    /*uview全局样式*/
    @import "uview-ui/index.scss";
    /*app全局样式*/
    @import 'static/style/app.scss';
</style>
    uni-page-wrapper {
        width: 100%;
        height: 100%;
    }
    uni-page-body {
        width: 100%;
        height: 100%;
    }
    /*每个页面公共css */
</style>
components/contacts/contacts.vue
New file
@@ -0,0 +1,236 @@
<template>
    <view class="pColumn" >
        <view class="inPColumn" v-if="fromW == 0">
            <view class="left" @click="chating">
                <view class="top">
                    <view class="userImg">
                        <img class="img" :src=Pdata.avatar>
                    </view>
                    <view class="t-type">{{Pdata.recipientName}}</view>
                    <view class="t-id">{{Pdata.postTime}}</view>
                </view>
                <view class="bottom">{{Pdata.postMessage}}</view>
            </view>
        </view>
        <view class="inPColumn" v-if="fromW == 1">
            <view class="left" @click="QZchating">
                <view class="top">
                    <view class="userImg">
                        <img class="img" :src=Pdata.avatar>
                    </view>
                    <view class="t-type">{{Pdata.GroupName}}</view>
                    <!-- <view class="t-id">{{Pdata.postTime}}</view> -->
                </view>
                <view class="bottom">{{Pdata.GroupContent}}</view>
            </view>
        </view>
        <view class="inPColumn" v-if="fromW == 2">
            <view class="left" @click="TXLchating">
                <view class="top">
                    <view class="userImg">
                        <img class="img" :src=Pdata.avatar>
                    </view>
                    <view class="t-type">{{Pdata.realName}}</view>
                    <!-- <view class="t-id">{{Pdata.postTime}}</view> -->
                </view>
                <view class="bottom">电话:{{Pdata.phone}}</view>
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        props: ['fromW', 'Pdata'],
        data() {
            return {
                popuShow: false,
                bmainb: ''
            }
        },
        methods: {
            beginObj() {
                this.bmainb = '3rem';
                //#ifdef MP-WEIXIN
                this.bmainb = '0';
                //#endif
            },
            chating(){
                //发起聊天
                var datas = this.Pdata;
                //alert(datas.name)
                uni.navigateTo({
                    url: '/pages/groupChat/chating?chatID=' + datas.recipientId.toString()
                });
            },
            QZchating(){
                //发起聊天
                var datas = this.Pdata;
                //alert(datas.name)
                uni.navigateTo({
                    url: '/pages/groupChat/chatingQZ?chatID=' + datas.id.toString()
                });
            },
            TXLchating(){
                //发起聊天
                var datas = this.Pdata;
                //alert(datas.name)
                uni.navigateTo({
                    url: '/pages/groupChat/chating?chatID=' + datas.id.toString()
                });
            },
            onClose() { //触摸遮罩事件
                this.setData({
                    popuShow: false
                });
            },
        },
        mounted() {
            this.beginObj();
        }
    }
</script>
<style lang="scss" scoped>
    /* components/pColumn/pColumn.wxss */
    .pColumn,
    .inPColumn,
    .left,
    .right,
    .top {
        display: flex;
    }
    .userImg {
        // border: 1px solid #007AFF;
        .img {
            width: 100rpx;
            height: 100rpx;
            border-radius: 100rpx;
            // border: 1px solid #007AFF;
        }
    }
    .pColumn {
        width: 100%;
        align-items: center;
        justify-content: center;
        padding-top: 0.5rem;
        .inPColumn {
            margin: 0.2rem 0 0.4rem 0;
            width: 95%;
            height: 4rem;
            border-bottom: 1px rgb(207, 207, 207) solid;
            align-items: center;
            justify-content: space-between;
            .left {
                width: 80%;
                /* border: 1px rgb(114, 250, 159) solid; */
                flex-direction: column;
                .top {
                    .t-type {
                        padding-left: 0.7rem;
                        font-size: 1.1rem;
                        color: #000000;
                    }
                    .t-id {
                        color: #8b8b8b;
                        font-size: 0.8rem;
                        line-height: 1.6rem;
                        position: absolute;
                        right: 1.2rem;
                    }
                }
                .bottom {
                    color: #8b8b8b;
                    font-size: 0.9rem;
                    position: relative;
                    bottom: 1rem;
                    left: 4rem;
                }
            }
            .right {
                width: 20%;
                /* border: 1px rgb(143, 114, 250) solid; */
                justify-content: space-around;
                /* align-items: center; */
                .butPopup {
                    z-index: 4;
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba($color: #000000, $alpha: 0.5);
                    .b-main {
                        position: absolute;
                        z-index: 2;
                        // bottom: 3rem;//小程序不兼容
                        width: 100%;
                        // border: 1px solid #007AFF;
                        border-radius: 1.5rem;
                        background-color: #fff;
                        // height: 20rem;
                        .b-m-title {
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            width: 100%;
                            height: 2.8rem;
                        }
                        .b-m-Y,
                        .b-m-N {
                            color: #fff;
                            border-radius: 0;
                        }
                        .b-m-Y {
                            background-color: #07C160 !important;
                        }
                        .b-m-Y-hove {
                            background-color: #048c44 !important;
                        }
                        .b-m-N {
                            background-color: #FF976A !important;
                        }
                        .b-m-N-hove {
                            background-color: #e1855d !important;
                        }
                    }
                }
            }
        }
    }
    // .buttitle {
    //     display: flex;
    //     align-items: center;
    //     justify-content: center;
    //     width: 100%;
    //     height: 2.8rem;
    // }
    // .popups {
    //     width: 100%;
    //     padding-bottom: 0 !important;
    //     /* border: 1px solid seagreen; */
    // }
</style>
components/e-picker/e-picker.js
New file
@@ -0,0 +1 @@
"use strict";function getDayArr(e,t){for(var r=e%4==0&&e%100!=0&&e%400!=0,a=[31,r?29:28,31,30,31,30,31,31,30,31,30,31],n=[],o=0;o<a[t-1];o++)n.push(fmt(o+1)+"日");return n}function getArr(e){var t=[],r=1,a=13,n="月";e>2&&(r=0,3==e&&(a=24,n="时"),e>3&&(a=60,4==e&&(n="分"),5==e&&(n="秒")));for(var o=r;o<a;o++)t.push(fmt(o)+n);return t}function fmt(e){return e>9?e:"0"+e}function checkShowValue(e,t){if("date"!=e&&"dateTime"!=e&&"time"!=e)throw Error("mode无"+e+"该选项配置");if("date"==e&&10!=t.length||"time"==e&&8!=t.length||"dateTime"==e&&19!=t.length)throw Error("'showValue'有误,请根据当前mode 正确设置格式")}function getDateTimeValue(e,t){var r=fmt(parseInt(e[0])),a=fmt(parseInt(e[1])),n=fmt(parseInt(e[2])),o=fmt(parseInt(e[3])),m=fmt(parseInt(e[4])),u=fmt(parseInt(e[5]));return"date"==t?r+"-"+a+"-"+n:"dateTime"==t?r+"-"+a+"-"+n+" "+o+":"+m+":"+u:r+":"+a+":"+n}function getLocalTime(e){var t=new Date;switch(e){case"dateTime":return t.getFullYear()+"-"+fmt(t.getMonth()+1)+"-"+fmt(t.getDate())+" "+fmt(t.getHours())+":"+fmt(t.getMinutes())+":"+fmt(t.getSeconds());case"time":return fmt(t.getHours())+":"+fmt(t.getMinutes())+":"+fmt(t.getSeconds());default:return t.getFullYear()+"-"+fmt(t.getMonth()+1)+"-"+fmt(t.getDate())}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getDayArr=getDayArr,exports.getArr=getArr,exports.checkShowValue=checkShowValue,exports.getDateTimeValue=getDateTimeValue,exports.getLocalTime=getLocalTime;
components/e-picker/e-picker.vue
New file
@@ -0,0 +1,138 @@
<template>
    <picker mode="multiSelector" :range="range" :value="value" @change="change" @columnchange="columnchange">
        <slot></slot>
    </picker>
</template>
<script>
    import * as utils from "./e-picker.js";
    let defaultValue;
    export default {
        data() {
            return {
                range: [],
                value: []
            };
        },
        props: {
            mode: {
                type: String,
                default: "date"
            },
            showValue: String,
            startYear: {
                type: [Number, String],
                default: 1949
            },
            endYear: {
                type: [String, Number],
                default: new Date().getFullYear()
            }
        },
        watch: {
            showValue(v) {
                this.init()
            }
        },
        created() {
            this.init();
        },
        methods: {
            init() {
                this.range = [];
                this.value = [];
                let l;
                defaultValue = utils.getLocalTime(this.mode)
                if (this.showValue) {
                    defaultValue = this.showValue
                }
                utils.checkShowValue(this.mode, defaultValue);
                this.mode == "dateTime" ? (l = 6) : (l = 3);
                for (let i = 0; i < l; i++) {
                    this.range.push([]);
                    this.value.push(0);
                    this.setColumns(i);
                }
            },
            setColumns(index) {
                const m = this.mode;
                if (m != "time") {
                    const showYear = defaultValue.substring(0, 4),
                        showMonth = defaultValue.substring(5, 7),
                        showDay = defaultValue.substring(8, 10);
                    switch (index) {
                        case 0:
                            const s = +this.startYear,
                                e = +this.endYear;
                            for (let i = s; i < e + 1; i++) {
                                this.range[index].push(i + "年");
                            }
                            this.value[index] = this.range[index].indexOf(showYear + "年");
                            break;
                        case 1:
                            this.range[index] = utils.getArr(1);
                            this.value[index] = this.range[index].indexOf(showMonth + "月");
                            break;
                        case 2:
                            this.range[index] = utils.getDayArr(+showYear, +showMonth);
                            this.value[index] = this.range[index].indexOf(showDay + "日");
                            break;
                        case 3:
                            const show_h = defaultValue.substring(11, 13);
                            this.range[index] = utils.getArr(3);
                            this.value[index] = this.range[index].indexOf(show_h + "时");
                            break;
                        case 4:
                            const show_m = defaultValue.substring(14, 16);
                            this.range[index] = utils.getArr(4);
                            this.value[index] = this.range[index].indexOf(show_m + "分");
                            break;
                        case 5:
                            const show_s = defaultValue.substring(17, 19);
                            this.range[index] = utils.getArr(5);
                            this.value[index] = this.range[index].indexOf(show_s + "秒");
                            break;
                    }
                } else {
                    switch (index) {
                        case 0:
                            const show_h = defaultValue.substring(0, 2);
                            this.range[index] = utils.getArr(3);
                            this.value[index] = this.range[index].indexOf(show_h + "时");
                            break;
                        case 1:
                            const show_m = defaultValue.substring(3, 5);
                            this.range[index] = utils.getArr(4);
                            this.value[index] = this.range[index].indexOf(show_m + "分");
                            break;
                        case 2:
                            const show_s = defaultValue.substring(6, 8);
                            this.range[index] = utils.getArr(5);
                            this.value[index] = this.range[index].indexOf(show_s + "秒");
                            break;
                    }
                }
                this.$forceUpdate()
            },
            columnchange(e) {
                if (this.mode == "time") return;
                const column = e.detail.column,
                    value = e.detail.value;
                if (column == 1 || !column) {
                    this.value[column] = value;
                }
                const y = parseInt(this.range[0][this.value[0]]),
                    m = parseInt(this.range[1][this.value[1]]);
                this.range[2] = utils.getDayArr(y, m);
                this.$forceUpdate()
            },
            change(e) {
                const value = e.detail.value;
                const timeArr = value.map((v, i) => {
                    return this.range[i][v];
                });
                this.$emit("change", utils.getDateTimeValue(timeArr, this.mode));
            }
        }
    };
</script>
components/feng-parse/components/wxParseAudio.vue
New file
@@ -0,0 +1,28 @@
<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>
components/feng-parse/components/wxParseImg.vue
New file
@@ -0,0 +1,94 @@
<template>
    <image
        mode="widthFix"
        :lazy-load="node.attr.lazyLoad"
        :class="node.classStr"
        :style="newStyleStr || node.styleStr"
        :data-src="node.attr.src"
        :src="node.attr.src"
        @tap="wxParseImgTap"
        @load="wxParseImgLoad"
    />
</template>
<script>
export default {
    name: 'wxParseImg',
    data() {
        return {
            newStyleStr: '',
            preview: true
        };
    },
    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;`;
            if(!styleStr) 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>
components/feng-parse/components/wxParseTable.vue
New file
@@ -0,0 +1,56 @@
<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) {
            console.log(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>
components/feng-parse/components/wxParseTemplate0.vue
New file
@@ -0,0 +1,116 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate1.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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 -->
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--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>
components/feng-parse/components/wxParseTemplate10.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate11.vue
New file
@@ -0,0 +1,105 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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">
                <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'"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate2.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate3.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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 -->
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--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>
components/feng-parse/components/wxParseTemplate4.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate5.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate6.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate7.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate8.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseTemplate9.vue
New file
@@ -0,0 +1,107 @@
<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" style="display: inline; border-bottom: 1px solid #555555;">
            <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"/>
        <!--strong标签-->
        <view v-else-if="node.tag == 'strong'" :class="node.classStr" :style="node.styleStr" style="font-weight: 700;display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--span标签-->
        <view v-else-if="node.tag == 'span'" :class="node.classStr"  :style="node.styleStr" style="display: inline;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--em标签-->
        <view v-else-if="node.tag == 'em'" :class="node.classStr"  :style="node.styleStr" style="display: inline;font-style: italic;">
            <block v-for="(node, index) of node.nodes" :key="index">
                <wx-parse-template :node="node"/>
            </block>
        </view>
        <!--其他标签-->
        <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>
components/feng-parse/components/wxParseVideo.vue
New file
@@ -0,0 +1,55 @@
<template>
    <!-- 这个模板用来解决原生video总是浮在最上层的问题,使用view替换video,播放是再替换回,监听一个事件,用来被遮盖时做替换video -->
  <!--增加video标签支持,并循环添加-->
  <view @click="play">
      <view v-if="!playState" :class="node.classStr" :style="node.styleStr" style="display: inline-block;margin: auto;max-width: 100%;" class="video-video">
          <view style="display: flex;width: 100%;height:100%;flex-direction: row; justify-content: center;align-items: center;">
              <image src="https://gwbj.tongwenkeji.com/html/static/play.png" style="width: 20%;" mode="widthFix"></image>
          </view>
      </view>
      <video
      :autoplay="false"
      :class="node.classStr"
      :style="node.styleStr"
      class="video-video"
      v-if="playState"
      :src="node.attr.src"></video>
  </view>
</template>
<script>
export default {
  name: 'wxParseVideo',
  props: {
    node: {},
  },
  data(){
      return{
          playState:true,
          videoStyle:'width: 100%;'
      }
  },
  methods:{
      play(){
          console.log('点击了video 播放')
          //显示播放器并播放播放器
          this.playState = !this.playState
      }
  },
  mounted() {
      //捕获侧滑菜单的遮盖行为,隐藏video
      uni.$on('slideMenuShow',e=>{
        console.log('捕获事件:'+e)
        if(e == 'show' && this.playState){
            //正在播放则停止
            this.playState = false
        }
    })
  }
};
</script>
<style>
    .video-video{background: #000000;}
</style>
components/feng-parse/components/wxParseVideo1.vue
New file
@@ -0,0 +1,25 @@
<template>
    <!-- 这个模板用来渲染原生video -->
  <!--增加video标签支持,并循环添加-->
  <view style="max-width: 100%;">
    <video
    :autoplay="playState"
    :class="node.classStr"
    :style="node.styleStr"
    class="video-video"
    v-if="playState"
    :src="node.attr.src"></video>
  </view>
</template>
<script>
export default {
  name: 'wxParseVideo',
  props: {
    node: {},
  }
};
</script>
<style>
    .video-video{z-index: 1;}
</style>
components/feng-parse/libs/html2json.js
New file
@@ -0,0 +1,308 @@
/**
 * 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 || '';
            }
            //处理table
            if (node.tag === 'table' || node.tag === 'tr' || node.tag === 'td') {
                node.styleStr = ""
                if (node.attr.width) {
                    node.styleStr += "width:" + node.attr.width + 'px;'
                    if (node.attr.width > node.$screen.width) {
                        //等比缩放height
                        if (node.attr.height) {
                            node.attr.height = (node.$screen.width * node.attr.height) / node.attr.width
                        }
                    }
                }
                if (node.attr.height) {
                    node.styleStr += "height:" + node.attr.height + 'px;'
                }
            }
            //处理video
            if (node.tag === 'video') {
                node.styleStr = ""
                if (node.attr.width) {
                    node.styleStr += "width:" + node.attr.width + 'px;'
                    if (node.attr.width > node.$screen.width) {
                        //等比缩放height
                        if (node.attr.height) {
                            node.attr.height = (node.$screen.width * node.attr.height) / node.attr.width
                        }
                    }
                }
                if (node.attr.height) {
                    node.styleStr += "height:" + node.attr.height + 'px;'
                }
            }
            // 处理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;
            }
            //#ifndef MP-BAIDU
            if (customHandler.start) {
                customHandler.start(node, results);
            }
            //#endif
            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;
            }
            //#ifndef MP-BAIDU
            if (customHandler && customHandler.end) {
                customHandler.end(node, results);
            }
            //#endif
            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,
            };
            //#ifndef MP-BAIDU
            if (customHandler.chars) {
                customHandler.chars(node, results);
            }
            //#endif
            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;
components/feng-parse/libs/htmlparser.js
New file
@@ -0,0 +1,156 @@
/**
 *
 * htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
 *
 * author: Di (微信小程序开发工程师)
 * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
 *               垂直微信小程序开发交流社区
 *
 * github地址: https://github.com/icindy/wxParse
 *
 * for: 微信小程序富文本解析
 * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
 */
// Regular Expressions for parsing tags and attributes
const startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z0-9_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
const endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
const attr = /([a-zA-Z0-9_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
function makeMap(str) {
  const obj = {};
  const items = str.split(',');
  for (let i = 0; i < items.length; i += 1) obj[items[i]] = true;
  return obj;
}
// Empty Elements - HTML 5
const empty = makeMap('area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr');
// Block Elements - HTML 5
const block = makeMap('address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video');
// Inline Elements - HTML 5
const inline = makeMap('a,abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var');
// Elements that you can, intentionally, leave open
// (and which close themselves)
const closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr');
// Attributes that have their values filled in disabled="disabled"
const fillAttrs = makeMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected');
function HTMLParser(html, handler) {
  let index;
  let chars;
  let match;
  let last = html;
  const stack = [];
  stack.last = () => stack[stack.length - 1];
  function parseEndTag(tag, tagName) {
    // If no tag name is provided, clean shop
    let pos;
    if (!tagName) {
      pos = 0;
    } else {
      // Find the closest opened tag of the same type
      tagName = tagName.toLowerCase();
      for (pos = stack.length - 1; pos >= 0; pos -= 1) {
        if (stack[pos] === tagName) break;
      }
    }
    if (pos >= 0) {
      // Close all the open elements, up the stack
      for (let i = stack.length - 1; i >= pos; i -= 1) {
        if (handler.end) handler.end(stack[i]);
      }
      // Remove the open elements from the stack
      stack.length = pos;
    }
  }
  function parseStartTag(tag, tagName, rest, unary) {
    tagName = tagName.toLowerCase();
    if (block[tagName]) {
      while (stack.last() && inline[stack.last()]) {
        parseEndTag('', stack.last());
      }
    }
    if (closeSelf[tagName] && stack.last() === tagName) {
      parseEndTag('', tagName);
    }
    unary = empty[tagName] || !!unary;
    if (!unary) stack.push(tagName);
    if (handler.start) {
      const attrs = [];
      rest.replace(attr, function genAttr(matches, name) {
        const value = arguments[2] || arguments[3] || arguments[4] || (fillAttrs[name] ? name : '');
        attrs.push({
          name,
          value,
          escaped: value.replace(/(^|[^\\])"/g, '$1\\"'), // "
        });
      });
      if (handler.start) {
        handler.start(tagName, attrs, unary);
      }
    }
  }
  while (html) {
    chars = true;
    if (html.indexOf('</') === 0) {
      match = html.match(endTag);
      if (match) {
        html = html.substring(match[0].length);
        match[0].replace(endTag, parseEndTag);
        chars = false;
      }
      // start tag
    } else if (html.indexOf('<') === 0) {
      match = html.match(startTag);
      if (match) {
        html = html.substring(match[0].length);
        match[0].replace(startTag, parseStartTag);
        chars = false;
      }
    }
    if (chars) {
      index = html.indexOf('<');
      let text = '';
      while (index === 0) {
        text += '<';
        html = html.substring(1);
        index = html.indexOf('<');
      }
      text += index < 0 ? html : html.substring(0, index);
      html = index < 0 ? '' : html.substring(index);
      if (handler.chars) handler.chars(text);
    }
    if (html === last) throw new Error(`Parse Error: ${html}`);
    last = html;
  }
  // Clean up any remaining tags
  parseEndTag();
}
export default HTMLParser;
components/feng-parse/libs/wxDiscode.js
New file
@@ -0,0 +1,209 @@
// HTML 支持的数学符号
function strNumDiscode(str) {
str = str.replace(/&forall;|&#8704;|&#x2200;/g, '∀');
str = str.replace(/&part;|&#8706;|&#x2202;/g, '∂');
str = str.replace(/&exist;|&#8707;|&#x2203;/g, '∃');
str = str.replace(/&empty;|&#8709;|&#x2205;/g, '∅');
str = str.replace(/&nabla;|&#8711;|&#x2207;/g, '∇');
str = str.replace(/&isin;|&#8712;|&#x2208;/g, '∈');
str = str.replace(/&notin;|&#8713;|&#x2209;/g, '∉');
str = str.replace(/&ni;|&#8715;|&#x220b;/g, '∋');
str = str.replace(/&prod;|&#8719;|&#x220f;/g, '∏');
str = str.replace(/&sum;|&#8721;|&#x2211;/g, '∑');
str = str.replace(/&minus;|&#8722;|&#x2212;/g, '−');
str = str.replace(/&lowast;|&#8727;|&#x2217;/g, '∗');
str = str.replace(/&radic;|&#8730;|&#x221a;/g, '√');
str = str.replace(/&prop;|&#8733;|&#x221d;/g, '∝');
str = str.replace(/&infin;|&#8734;|&#x221e;/g, '∞');
str = str.replace(/&ang;|&#8736;|&#x2220;/g, '∠');
str = str.replace(/&and;|&#8743;|&#x2227;/g, '∧');
str = str.replace(/&or;|&#8744;|&#x2228;/g, '∨');
str = str.replace(/&cap;|&#8745;|&#x2229;/g, '∩');
str = str.replace(/&cup;|&#8746;|&#x222a;/g, '∪');
str = str.replace(/&int;|&#8747;|&#x222b;/g, '∫');
str = str.replace(/&there4;|&#8756;|&#x2234;/g, '∴');
str = str.replace(/&sim;|&#8764;|&#x223c;/g, '∼');
str = str.replace(/&cong;|&#8773;|&#x2245;/g, '≅');
str = str.replace(/&asymp;|&#8776;|&#x2248;/g, '≈');
str = str.replace(/&ne;|&#8800;|&#x2260;/g, '≠');
str = str.replace(/&le;|&#8804;|&#x2264;/g, '≤');
str = str.replace(/&ge;|&#8805;|&#x2265;/g, '≥');
str = str.replace(/&sub;|&#8834;|&#x2282;/g, '⊂');
str = str.replace(/&sup;|&#8835;|&#x2283;/g, '⊃');
str = str.replace(/&nsub;|&#8836;|&#x2284;/g, '⊄');
str = str.replace(/&sube;|&#8838;|&#x2286;/g, '⊆');
str = str.replace(/&supe;|&#8839;|&#x2287;/g, '⊇');
str = str.replace(/&oplus;|&#8853;|&#x2295;/g, '⊕');
str = str.replace(/&otimes;|&#8855;|&#x2297;/g, '⊗');
str = str.replace(/&perp;|&#8869;|&#x22a5;/g, '⊥');
str = str.replace(/&sdot;|&#8901;|&#x22c5;/g, '⋅');
return str;
}
// HTML 支持的希腊字母
function strGreeceDiscode(str) {
str = str.replace(/&Alpha;|&#913;|&#x391;/g, 'Α');
str = str.replace(/&Beta;|&#914;|&#x392;/g, 'Β');
str = str.replace(/&Gamma;|&#915;|&#x393;/g, 'Γ');
str = str.replace(/&Delta;|&#916;|&#x394;/g, 'Δ');
str = str.replace(/&Epsilon;|&#917;|&#x395;/g, 'Ε');
str = str.replace(/&Zeta;|&#918;|&#x396;/g, 'Ζ');
str = str.replace(/&Eta;|&#919;|&#x397;/g, 'Η');
str = str.replace(/&Theta;|&#920;|&#x398;/g, 'Θ');
str = str.replace(/&Iota;|&#921;|&#x399;/g, 'Ι');
str = str.replace(/&Kappa;|&#922;|&#x39a;/g, 'Κ');
str = str.replace(/&Lambda;|&#923;|&#x39b;/g, 'Λ');
str = str.replace(/&Mu;|&#924;|&#x39c;/g, 'Μ');
str = str.replace(/&Nu;|&#925;|&#x39d;/g, 'Ν');
str = str.replace(/&Xi;|&#925;|&#x39d;/g, 'Ν');
str = str.replace(/&Omicron;|&#927;|&#x39f;/g, 'Ο');
str = str.replace(/&Pi;|&#928;|&#x3a0;/g, 'Π');
str = str.replace(/&Rho;|&#929;|&#x3a1;/g, 'Ρ');
str = str.replace(/&Sigma;|&#931;|&#x3a3;/g, 'Σ');
str = str.replace(/&Tau;|&#932;|&#x3a4;/g, 'Τ');
str = str.replace(/&Upsilon;|&#933;|&#x3a5;/g, 'Υ');
str = str.replace(/&Phi;|&#934;|&#x3a6;/g, 'Φ');
str = str.replace(/&Chi;|&#935;|&#x3a7;/g, 'Χ');
str = str.replace(/&Psi;|&#936;|&#x3a8;/g, 'Ψ');
str = str.replace(/&Omega;|&#937;|&#x3a9;/g, 'Ω');
str = str.replace(/&alpha;|&#945;|&#x3b1;/g, 'α');
str = str.replace(/&beta;|&#946;|&#x3b2;/g, 'β');
str = str.replace(/&gamma;|&#947;|&#x3b3;/g, 'γ');
str = str.replace(/&delta;|&#948;|&#x3b4;/g, 'δ');
str = str.replace(/&epsilon;|&#949;|&#x3b5;/g, 'ε');
str = str.replace(/&zeta;|&#950;|&#x3b6;/g, 'ζ');
str = str.replace(/&eta;|&#951;|&#x3b7;/g, 'η');
str = str.replace(/&theta;|&#952;|&#x3b8;/g, 'θ');
str = str.replace(/&iota;|&#953;|&#x3b9;/g, 'ι');
str = str.replace(/&kappa;|&#954;|&#x3ba;/g, 'κ');
str = str.replace(/&lambda;|&#955;|&#x3bb;/g, 'λ');
str = str.replace(/&mu;|&#956;|&#x3bc;/g, 'μ');
str = str.replace(/&nu;|&#957;|&#x3bd;/g, 'ν');
str = str.replace(/&xi;|&#958;|&#x3be;/g, 'ξ');
str = str.replace(/&omicron;|&#959;|&#x3bf;/g, 'ο');
str = str.replace(/&pi;|&#960;|&#x3c0;/g, 'π');
str = str.replace(/&rho;|&#961;|&#x3c1;/g, 'ρ');
str = str.replace(/&sigmaf;|&#962;|&#x3c2;/g, 'ς');
str = str.replace(/&sigma;|&#963;|&#x3c3;/g, 'σ');
str = str.replace(/&tau;|&#964;|&#x3c4;/g, 'τ');
str = str.replace(/&upsilon;|&#965;|&#x3c5;/g, 'υ');
str = str.replace(/&phi;|&#966;|&#x3c6;/g, 'φ');
str = str.replace(/&chi;|&#967;|&#x3c7;/g, 'χ');
str = str.replace(/&psi;|&#968;|&#x3c8;/g, 'ψ');
str = str.replace(/&omega;|&#969;|&#x3c9;/g, 'ω');
str = str.replace(/&thetasym;|&#977;|&#x3d1;/g, 'ϑ');
str = str.replace(/&upsih;|&#978;|&#x3d2;/g, 'ϒ');
str = str.replace(/&piv;|&#982;|&#x3d6;/g, 'ϖ');
str = str.replace(/&middot;|&#183;|&#xb7;/g, '·');
return str;
}
function strcharacterDiscode(str) {
// 加入常用解析
str = str.replace(/&nbsp;|&#32;|&#x20;/g, "&nbsp;");
str = str.replace(/&ensp;|&#8194;|&#x2002;/g, '&ensp;');
str = str.replace(/&#12288;|&#x3000;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&emsp;|&#8195;|&#x2003;/g, '&emsp;');
str = str.replace(/&quot;|&#34;|&#x22;/g, "\"");
str = str.replace(/&apos;|&#39;|&#x27;/g, "&apos;");
str = str.replace(/&acute;|&#180;|&#xB4;/g, "´");
str = str.replace(/&times;|&#215;|&#xD7;/g, "×");
str = str.replace(/&divide;|&#247;|&#xF7;/g, "÷");
str = str.replace(/&amp;|&#38;|&#x26;/g, '&amp;');
str = str.replace(/&lt;|&#60;|&#x3c;/g, '&lt;');
str = str.replace(/&gt;|&#62;|&#x3e;/g, '&gt;');
str = str.replace(/&nbsp;|&#32;|&#x20;/g, "<span class='spaceshow'> </span>");
str = str.replace(/&ensp;|&#8194;|&#x2002;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&#12288;|&#x3000;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&emsp;|&#8195;|&#x2003;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&quot;|&#34;|&#x22;/g, "\"");
str = str.replace(/&quot;|&#39;|&#x27;/g, "'");
str = str.replace(/&acute;|&#180;|&#xB4;/g, "´");
str = str.replace(/&times;|&#215;|&#xD7;/g, "×");
str = str.replace(/&divide;|&#247;|&#xF7;/g, "÷");
str = str.replace(/&amp;|&#38;|&#x26;/g, '&');
str = str.replace(/&lt;|&#60;|&#x3c;/g, '<');
str = str.replace(/&gt;|&#62;|&#x3e;/g, '>');
return str;
}
// HTML 支持的其他实体
function strOtherDiscode(str) {
str = str.replace(/&OElig;|&#338;|&#x152;/g, 'Œ');
str = str.replace(/&oelig;|&#339;|&#x153;/g, 'œ');
str = str.replace(/&Scaron;|&#352;|&#x160;/g, 'Š');
str = str.replace(/&scaron;|&#353;|&#x161;/g, 'š');
str = str.replace(/&Yuml;|&#376;|&#x178;/g, 'Ÿ');
str = str.replace(/&fnof;|&#402;|&#x192;/g, 'ƒ');
str = str.replace(/&circ;|&#710;|&#x2c6;/g, 'ˆ');
str = str.replace(/&tilde;|&#732;|&#x2dc;/g, '˜');
str = str.replace(/&thinsp;|$#8201;|&#x2009;/g, '<span class=\'spaceshow\'> </span>');
str = str.replace(/&zwnj;|&#8204;|&#x200C;/g, '<span class=\'spaceshow\'>‌</span>');
str = str.replace(/&zwj;|$#8205;|&#x200D;/g, '<span class=\'spaceshow\'>‍</span>');
str = str.replace(/&lrm;|$#8206;|&#x200E;/g, '<span class=\'spaceshow\'>‎</span>');
str = str.replace(/&rlm;|&#8207;|&#x200F;/g, '<span class=\'spaceshow\'>‏</span>');
str = str.replace(/&ndash;|&#8211;|&#x2013;/g, '–');
str = str.replace(/&mdash;|&#8212;|&#x2014;/g, '—');
str = str.replace(/&lsquo;|&#8216;|&#x2018;/g, '‘');
str = str.replace(/&rsquo;|&#8217;|&#x2019;/g, '’');
str = str.replace(/&sbquo;|&#8218;|&#x201a;/g, '‚');
str = str.replace(/&ldquo;|&#8220;|&#x201c;/g, '“');
str = str.replace(/&rdquo;|&#8221;|&#x201d;/g, '”');
str = str.replace(/&bdquo;|&#8222;|&#x201e;/g, '„');
str = str.replace(/&dagger;|&#8224;|&#x2020;/g, '†');
str = str.replace(/&Dagger;|&#8225;|&#x2021;/g, '‡');
str = str.replace(/&bull;|&#8226;|&#x2022;/g, '•');
str = str.replace(/&hellip;|&#8230;|&#x2026;/g, '…');
str = str.replace(/&permil;|&#8240;|&#x2030;/g, '‰');
str = str.replace(/&prime;|&#8242;|&#x2032;/g, '′');
str = str.replace(/&Prime;|&#8243;|&#x2033;/g, '″');
str = str.replace(/&lsaquo;|&#8249;|&#x2039;/g, '‹');
str = str.replace(/&rsaquo;|&#8250;|&#x203a;/g, '›');
str = str.replace(/&oline;|&#8254;|&#x203e;/g, '‾');
str = str.replace(/&euro;|&#8364;|&#x20ac;/g, '€');
str = str.replace(/&trade;|&#8482;|&#x2122;/g, '™');
str = str.replace(/&larr;|&#8592;|&#x2190;/g, '←');
str = str.replace(/&uarr;|&#8593;|&#x2191;/g, '↑');
str = str.replace(/&rarr;|&#8594;|&#x2192;/g, '→');
str = str.replace(/&darr;|&#8595;|&#x2193;/g, '↓');
str = str.replace(/&harr;|&#8596;|&#x2194;/g, '↔');
str = str.replace(/&crarr;|&#8629;|&#x21b5;/g, '↵');
str = str.replace(/&lceil;|&#8968;|&#x2308;/g, '⌈');
str = str.replace(/&rceil;|&#8969;|&#x2309;/g, '⌉');
str = str.replace(/&lfloor;|&#8970;|&#x230a;/g, '⌊');
str = str.replace(/&rfloor;|&#8971;|&#x230b;/g, '⌋');
str = str.replace(/&loz;|&#9674;|&#x25ca;/g, '◊');
str = str.replace(/&spades;|&#9824;|&#x2660;/g, '♠');
str = str.replace(/&clubs;|&#9827;|&#x2663;/g, '♣');
str = str.replace(/&hearts;|&#9829;|&#x2665;/g, '♥');
str = str.replace(/&diams;|&#9830;|&#x2666;/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,
};
components/feng-parse/parse.css
New file
@@ -0,0 +1,258 @@
/**
 * 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: #333;
    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;
}
components/feng-parse/parse.vue
New file
@@ -0,0 +1,237 @@
<!--**
 * forked from:https://github.com/F-loat/mpvue-wxParse
 *
 * github地址: https://github.com/dcloudio/uParse
 *
 * for: uni-app框架下 富文本解析
 *
 * 优化 by zhiqiang.feng@qq.com
 */-->
<template>
    <!--基础元素-->
    <view class="wxParse" :class="className" :style="'user-select:' + userSelect">
        <block v-for="(node, index) of nodes" :key="index" v-if="!loading">
            <wxParseTemplate :node="node" />
        </block>
    </view>
</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: ''
            },
            startHandler: {
                type: Function,
                default () {
                    return node => {
                        node.attr.class = null;
                        node.attr.style = null;
                    };
                }
            },
            endHandler: {
                type: Function,
                default() {
                    return node => {
                        node = node
                    };
                }
            },
            charsHandler: {
                type: Function,
                default() {
                    return node => {
                        node = node
                    };
                }
            },
            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(() => {
                        if(item.node){
                            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(val){
                this.setHtml()
            }
            // content: {
            //     handler: function(newVal, oldVal) {
            //         if (newVal !== oldVal) {
            //
            //         }
            //     },
            //     deep: true
            // }
        }
    };
</script>
components/nav-bar-top/nav-bar-top.vue
New file
@@ -0,0 +1,72 @@
<template name="navBarTop">
    <!-- 自定义顶部导航栏 -->
    <!-- <view class="nav-bar-top" @click="gotoMyself()">
        <view class="nav-bar-top-left">
            <image :src="navBarImage" />
        </view>
        <view class="nav-bar-top-title">我要查</view>
    </view> -->
    <uni-nav-bar class="uni-nav-bar-info" :fixed="true"  :status-bar="true" >
        <view class="title" slot="default">{{title}}</view>
        <view slot="left" class="uni-nav-bar-left" @click="gotoMyself()">
            <image :src="avatarImage"></image>
        </view>
    </uni-nav-bar>
</template>
<script>
    import uniNavBar from '../../components/uni-nav-bar/uni-nav-bar.vue'
    export default{
        props:['title'],
        components:{uniNavBar},
        name:"navBarTop",
        data(){
            // console.log(title);
            return{
                avatarImage:this.$store.state.avatar,
            }
        },
        methods:{
            //跳转至我的页面
            gotoMyself(){
                uni.navigateTo({
                    url:'../myself/myself'
                    // animationType: 'pop-in',
                    // animationDuration: 200
                })
                // uni.navigateBack({
                //     delta:1,
                //     animationType:'pop-out',
                //     animationDuration:200
                // });
            }
        }
    }
</script>
<style lang="scss">
    .uni-nav-bar-info {
        // font-weight: 550;
        .title{
            position: fixed;
            right: 45%;
            font-weight: 550;
        }
        .uni-nav-bar-left{
            display: flex;
            justify-items: center;
            image{
                // background-color: #00BFFF;
                margin-left: 1rem;
                width: 1.8rem;
                height: 1.8rem;
                border-radius: 100px;
            }
        }
    }
</style>
components/outAdmin/uni-Popup.vue
New file
@@ -0,0 +1,121 @@
<template>
    <view>
        <view class="show-box-bg wx-login-box" @tap.self="$emit('cancel')">
            <view class="conten">
                <view class="titl">
                    {{ textmsg.title }}
                </view>
                <view class="text">
                    {{ textmsg.content }}
                </view>
                <view class="text" style="margin-bottom: 50rpx;">
                    {{ textmsg.contentTwo || '' }}
                </view>
                <view class="btn-box">
                    <view class="cancel" @tap="$emit('cancel')">
                        {{ textmsg.cancel }}
                    </view>
                    <view class="confirm" @tap="$emit('confirm',textmsg.type)">
                        {{ textmsg.confirm }}
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        props:['textmsg'],
        data() {
            return {
            }
        },
        methods:{
            operation(e){
                let type = e
                this.$emit('operation',type);
            },
        }
    }
</script>
<style scoped lang="scss">
    .wx-login-box {
        width: 100%;
        position: fixed;
        top: 0;
        left: 0;
        height: 100%;
        background-color: rgba(0, 0, 0, 0.6);
        z-index: 901;
        .conten {
            width: 78%;
            // height: 400upx;
            background-color: #ffffff;
            z-index: 1000;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            border-radius: 14upx;
            overflow: hidden;
            .titl {
                width: 90%;
                height: 110rpx;
                font-size: 40rpx;
                padding: 0 5%;
                color: #000000;
                text-align: center;
                line-height: 140rpx;
            }
            .text {
                width: 90%;
                font-size: 28rpx;
                color: #000000;
                padding: 0 5%;
                text-align: center;
            }
            .memberY {
                width: 90%;
                font-size: 28rpx;
                color: #07c1ea;
                padding: 0 5%;
                text-align: center;
            }
            .memberB {
                width: 90%;
                font-size: 28rpx;
                color: #007AFF;
                padding: 0 5%;
                text-align: center;
            }
            .btn-box {
                width: 100%;
                height: 90rpx;
                display: flex;
                border-top: 2rpx solid #969696;
                .cancel {
                    width: 50%;
                    height: 100%;
                    font-size: 40rpx;
                    color: #999;
                    text-align: center;
                    line-height: 89rpx;
                    border-right: 2rpx solid #969696;
                }
                .confirm {
                    width: 50%;
                    height: 100%;
                    font-size: 40rpx;
                    color: #07c1ea;
                    text-align: center;
                    line-height: 99rpx;
                }
            }
        }
    }
</style>
components/pColumn/pColumn.vue
New file
@@ -0,0 +1,275 @@
<template>
    <view class="pColumn">
        <view class="inPColumn">
            <view class="left">
                <view class="top">
                    <view class="t-type">{{Pdata.alarmType}} </view>
                    <view class="t-id"> 警单编号:{{Pdata.id}}</view>
                </view>
                <view class="image-time">
                    <image src="../../static/images/pColumn/alarm.png"></image>
                    <view class="t-time"> {{Pdata.alarmTime}}</view>
                </view>
                <view class="image-place">
                    <image src="../../static/images/pColumn/position-bule.png"></image>
                    <view class="place">{{Pdata.place}}</view>
                </view>
            </view>
            <view class="right">
                <button type="default" @click="PClick">{{fromW == 0?'详情':fromW == 1?'接受':""}}</button>
                <view class="butPopup" v-show="popuShow">
                    <view class="b-main" :style="{bottom: bmainb}">
                        <view class="b-m-title">
                            是否接该任务
                        </view>
                        <button class="b-m-Y" hover-class='b-m-Y-hove' type="default" @click="popupBY">接受</button>
                        <button class="b-m-N" hover-class='b-m-N-hove' type="default" @click="popupBN">取消</button>
                    </view>
                </view>
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        props: ['fromW', 'Pdata'],
        data() {
            return {
                popuShow: false,
                bmainb: ''
            }
        },
        methods: {
            beginObj() {
                this.bmainb = '3rem';
                //#ifdef MP-WEIXIN
                this.bmainb = '0';
                //#endif
            },
            receives() {
                var url = this.$store.state.piAPI + "/alarm/alarm/APP-setAlarm",
                    Pid = this.Pdata.id,
                    id = this.$store.state.puserID, //警察id
                    name = this.$store.state.puserName, //警察id
                    data = {
                        id: Pid,
                        securityId: id,
                        alarmPeople: name
                    },
                    that = this;
                // console.log(data);
                wx.request({
                    url: url,
                    data: data,
                    header: {
                        "content-type": "application/x-www-form-urlencoded"
                    },
                    method: 'POST',
                    success(res) {
                        // console.log(res.data.msg);
                    }
                })
            },
            PClick(val) {
                if (this.fromW == 0) { //打开详情页面
                    // wx.navigateTo({url: '/pages/map/map'});
                    var datas = this.Pdata;
                    datas.state = 0;
                    datas.dtype = 0;
                    datas.size = 300;
                    // console.log(datas)
                    var data = [datas]; //传给地图的参数
                    wx.navigateTo({
                        url: '/pages/map/map?data=' + JSON.stringify(data)
                    });
                } else if (this.fromW == 1) { //打开提交弹窗
                    this.popuShow = true;
                }
            },
            onClose() { //触摸遮罩事件
                this.setData({
                    popuShow: false
                });
            },
            popupBY() {
                this.receives();
                // console.log('接收成功');
                this.$emit('refreshTask', this.fromW)
                // this.triggerEvent('myevent', this.data.fromW);
                this.popuShow = false;
            },
            popupBN() {
                // console.log('接收取消');
                this.popuShow = false;
            }
        },
        mounted() {
            this.beginObj();
        }
    }
</script>
<style lang="scss" scoped>
    /* components/pColumn/pColumn.wxss */
    .pColumn,
    .inPColumn,
    .left,
    .right,
    .image-time,
    .image-place,
    .top {
        display: flex;
    }
    .pColumn {
        width: 100%;
        align-items: center;
        justify-content: center;
        padding-top: 0.8rem;
        .inPColumn {
            // background-color: #00BFFF;
            margin: 0.2rem 0 0.4rem 0;
            width: 95%;
            height: 5rem;
            border-bottom: 1px rgb(207, 207, 207) solid;
            align-items: center;
            justify-content: space-between;
            .left {
                width: 80%;
                /* border: 1px rgb(114, 250, 159) solid; */
                flex-direction: column;
                .top {
                    .t-type {
                        font-size: 1.1rem;
                        color: #ff0000;
                        letter-spacing: 1px;
                    }
                    .t-id {
                        color: #00aaff;
                        font-size: 0.8rem;
                        line-height: 1.6rem;
                        position: relative;
                        left: 0.7rem;
                    }
                }
                .image-time{
                    align-items: center;
                    height: 30px;
                    image{
                        width: 35rpx;
                        height: 35rpx;
                    }
                    .t-time{
                        font-size: 0.8rem;
                        color: #808080;
                        height: 20rpx;
                        line-height: 20rpx;
                        margin-left: 15rpx;
                    }
                }
                .image-place{
                    align-items: center;
                    height: 20px;
                    image{
                        width: 35rpx;
                        height: 35rpx;
                    }
                    .place {
                        font-size: 0.8rem;
                        margin-left: 15rpx;
                        color: #808080;
                        height: 20rpx;
                        line-height: 20rpx;
                    }
                }
            }
            .right {
                width: 20%;
                /* border: 1px rgb(143, 114, 250) solid; */
                justify-content: space-around;
                /* align-items: center; */
                .butPopup {
                    z-index: 4;
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background-color: rgba($color: #000000, $alpha: 0.5);
                    .b-main {
                        position: absolute;
                        z-index: 2;
                        // bottom: 3rem;//小程序不兼容
                        width: 100%;
                        // border: 1px solid #007AFF;
                        border-radius: 1.5rem;
                        background-color: #fff;
                        // height: 20rem;
                        .b-m-title {
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            width: 100%;
                            height: 2.8rem;
                        }
                        .b-m-Y,
                        .b-m-N {
                            color: #fff;
                            border-radius: 0;
                        }
                        .b-m-Y {
                            background-color: #07C160 !important;
                        }
                        .b-m-Y-hove {
                            background-color: #048c44 !important;
                        }
                        .b-m-N {
                            background-color: #FF976A !important;
                        }
                        .b-m-N-hove {
                            background-color: #e1855d !important;
                        }
                    }
                }
            }
        }
    }
    // .buttitle {
    //     display: flex;
    //     align-items: center;
    //     justify-content: center;
    //     width: 100%;
    //     height: 2.8rem;
    // }
    // .popups {
    //     width: 100%;
    //     padding-bottom: 0 !important;
    //     /* border: 1px solid seagreen; */
    // }
</style>
components/seeImges/seeImges.vue
New file
@@ -0,0 +1,169 @@
<template>
    <view class="seeImgs" v-if="imgs.length != 0 || videos.length != 0 ">
        <view class="imgs" v-for="(item, index) in imgs" :key="index" v-if="type == 'imgs'">
            <image :src="item.src" mode="scaleToFill" @click="previewImage(index)"></image>
            <view class="close" @click="delelteImg(index)">
                X
            </view>
        </view>
        <view class="videos" v-for="(item, index) in videos" :key="index" v-if="type == 'videos'">
            <!-- <image :src="item.src" mode="scaleToFill" @click="previewImage(index)"></image> -->
            <video :src="item.src" controls></video>
            <view class="close" @click="deleltevideo(index)">
                X
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        props: ['imgs', 'videos', 'type'],
        // props: [{
        //     imgs:{
        //         type: Array,
        //         default: []
        //     },
        //     videos:{
        //         type: Object,
        //         default: []
        //     },
        //     type:{
        //         type: String,
        //         default: null
        //     },
        // }],
        data() {
            return {
            }
        },
        methods: {
            //图片删除
            delelteImg(index) {
                var that = this;
                wx.showModal({
                    title: '提示',
                    content: '确定要删除该照片吗?',
                    cancelText: '取消',
                    confirmText: '确定',
                    success: res => {
                        if (res.confirm) {
                            // console.log(index)
                            // that.imgs.splice(index, 1);
                            that.$emit('del', index);
                        }
                    }
                });
            },
            //图片预览
            previewImage(index) {
                let photoList = this.imgs.map(item => {
                    return item.src;
                });
                // console.log(index)
                // console.log(photoList)
                wx.previewImage({
                    current: photoList[index],
                    urls: photoList
                });
            },
            //视频删除
            deleltevideo(index) {
                var that = this;
                wx.showModal({
                    title: '提示',
                    content: '确定要删除该视频吗?',
                    cancelText: '取消',
                    confirmText: '确定',
                    success: res => {
                        if (res.confirm) {
                            // console.log(index)
                            // that.imgs.splice(index, 1);
                            that.$emit('del', index);
                        }
                    }
                });
            },
        }
    }
</script>
<style lang="scss" scoped>
    .seeImgs {
        width: 100%;
        height: 4.3rem;
        // border: 1px solid #0000FF;
        white-space: nowrap;
        box-sizing: border-box;
        overflow: auto;
        // display: flex;
        // align-items: center;
        // position: absolute;
        // right: 0;
        // z-index: 110;
        .imgs {
            display: inline-block;
            padding-top: 0.5rem;
            width: 4rem;
            height: 4rem;
            padding: 0 0.2rem 0 0.2rem;
            margin: 0 0.2rem 0 0.2rem;
            // border-right: 1px solid rgba($color: #000000, $alpha: 0.5);
            position: relative;
            // border: 1px solid #0000FF;
            top: 0.22rem;
            image {
                width: 100%;
                height: 100%;
            }
        }
        .videos {
            display: inline-block;
            padding-top: 0.5rem;
            width: 4rem;
            height: 4rem;
            padding: 0 0.2rem 0 0.2rem;
            margin: 0 0.2rem 0 0.2rem;
            // border-right: 1px solid rgba($color: #000000, $alpha: 0.5);
            position: relative;
            // border: 1px solid #0000FF;
            top: 0.22rem;
            video {
                width: 100%;
                height: 100%;
            }
        }
    }
    .close {
        background-color: #fff;
        width: 0.9rem;
        height: 0.9rem;
        text-align: center;
        line-height: 0.8rem;
        position: absolute;
        top: 0.1rem;
        right: 0.2rem;
        font-size: 0.5rem;
        color: red;
        border-radius: 1.5rem;
        border: 1px solid red;
        z-index: 111;
        &:hover {
            color: red;
            border: 1px solid red;
        }
    }
</style>
components/squareBut/squareBut.vue
New file
@@ -0,0 +1,61 @@
<template>
    <view class="squareBut">
        <view class="once" v-for="(item,index) in data" :key="index" @click="goHref(index)">
            <view class="imgs">
                <image :src="item.imgSrc" mode=""></image>
            </view>
            <view class="title">
                {{item.title}}
            </view>
        </view>
        <view style="clear:left"></view>
    </view>
</template>
<script>
    export default {
        props: ['data'],
        methods:{
            goHref(index){
                // console.log(this.data[index].goHref)
                wx.navigateTo({
                    url:this.data[index].goHref
                })
            }
        }
    }
</script>
<style lang="scss" scoped>
    .squareBut {
        width: 95%;
        margin: 0 auto;
        border: 1px solid rgba($color: #000000, $alpha: 0.03);
        border-radius: 1rem;
        .once {
            width: 6rem;
            height: 6rem;
            border-right: 1px solid rgba($color: #000000, $alpha: 0.3);
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
            border-radius: 1rem;
            box-shadow: 0.1rem 0.1rem 0.5rem 0.01rem #dadada;
            float: left;
            margin: 0.65rem;
            .imgs {
                width: 4rem;
                height: 4rem;
                image {
                    width: 100%;
                    height: 100%;
                }
            }
            .title {}
        }
    }
</style>
components/submit/emoji/emoji.vue
New file
@@ -0,0 +1,75 @@
<template>
    <view class="emoji"
                :style="{height:height + 'px'}">
        <view class="emoji-line"
                    v-for="(line, i) in emoji"
                    :key="i">
            <view class="emoji-line-item"
                        v-for="(item, index) in line"
                        :key="index"
                        @tap="clickEmoji(item)">
                {{ item }}
            </view>
        </view>
    </view>
</template>
<script>
    export default {
        props:{
            height: {
                type: Number,
                default: 260
            }
        },
        data() {
            return {
                emoji:[
                    ['😀', '😁', '😂', '🤣', '😃', '😅'],
                    ['😆', '😉', '😊', '😋', '😎', '😍'],
                    ['😘', '😗', '😙', '😚', '🙂', '🤗'],
                    ['🤔', '😐', '😑', '😶', '🙄', '😏'],
                    ['😣', '😥', '😮', '🤐', '😯', '😪'],
                    ['😫', '😴', '😌', '😛', '😜', '😝'],
                    ['🤤', '😓', '😔', '😕', '🙃', '🤑'],
                    ['😲', '🙁', '😖', '😞', '😟', '😤'],
                    ['😢', '😭', '😦', '😧', '😨', '😩'],
                    ['😬', '😱', '😳', '😵', '😳', '😵'],
                    ['💼', '🌂', '💍', '💄', '⛑', '🎓'],
                    ['👒', '🎩', '👑', '👢', '👡', '👠'],
                    ['👟', '👞', '👝', '👜', '👛', '👚'],
                    ['🍇', '🍈', '🍉', '🍊', '🍌', '🍒'],
                    ['☠', '🛀', '💣', '⏰', '🎎', '📻'],
                    ['💘', '❤', '💔', '💢', '💮', '🕜'],
                ]
            };
        },
        methods: {
            clickEmoji(e) {
                this.$emit('emotion', e)
            }
        }
    }
</script>
<style lang="scss">
    .emoji{
        width: 100%;
        padding: 16rpx 10rpx 180rpx 10rpx;
        box-sizing: border-box;
        overflow: hidden;
        overflow-y: auto;
        .emoji-line {
            display: flex;
            .emoji-line-item {
                flex: 1;
                text-align: center;
                font-size: 52rpx;
                line-height: 80rpx;
            }
        }
    }
</style>
components/submit/submit.vue
New file
@@ -0,0 +1,447 @@
<template>
    <view>
        <view class="submit">
            <view class="submit-chat">
                <view class="bt-img">
                    <image src="../../static/images/chatroom/voice.png"
                                 mode=""
                                 @tap="records"/>
                </view>
                <textarea auto-height="true"
                                    class="chat-send btn"
                                    :class="{displaynone: isrecord}"
                                    @input="inputs"
                                    v-model="msg"
                                    @focus="focus"/>
                <view class="record btn"
                            :class="{displaynone: !isrecord}"
                            @touchstart="touchstart"
                            @touchend="touchend"
                            @touchmove="touchmove"
                            >
                    按住说话
                </view>
                <view class="bt-img">
                    <image src="../../static/images/chatroom/emoji.png"
                                 mode=""
                                 @tap="emoji"/>
                </view>
                <view class="bt-img">
                    <image src="../../static/images/chatroom/add.png"
                                 mode=""
                                 @tap="more"/>
                </view>
            </view>
            <view class="emoji"
                        :class="{ displaynone: !isemoji }">
                <view class="emoji-send">
                    <view class="emoji-send-del"
                                @tap="emojiBack">
                                删除
                    </view>
                    <view class="emoji-send-bt"
                                @tap="emojiSend">
                                发送
                    </view>
                </view>
                <emoji @emotion="emotion"
                             :height="260" />
            </view>
            <view class="more"
                        :class="{ displaynone: !ismore }">
                <view class="more-list"
                            @tap="sendImg('album')">
                    <image src="../../static/images/chatroom/photo.png"/>
                    <text class="more-list-title">图片</text>
                </view>
                <view class="more-list"
                            @tap="sendImg('camera')">
                    <image src="../../static/images/chatroom/camera.png"/>
                    <text class="more-list-title">拍照</text>
                </view>
                <view class="more-list">
                    <image src="../../static/images/chatroom/file.png"/>
                    <text class="more-list-title">文件</text>
                </view>
                <view class="more-list"
                            @tap="chooseLocation()">
                    <image src="../../static/images/chatroom/location.png"/>
                    <text class="more-list-title">位置</text>
                </view>
                <view class="more-list">
                    <image src="../../static/images/chatroom/vedio.png"/>
                    <text class="more-list-title">视频</text>
                </view>
            </view>
        </view>
        <!-- 录制语音遮罩 -->
        <view class="voice-bg"
                    :class="{displaynone: !voicebg}">
            <view class="voice-bg-len">
                <view class="voice-bg-time"
                            :style="{width:vlength/0.6 + '%'}">
                    {{ vlength }} "
                </view>
            </view>
            <view class="voice-del">上滑取消取消录音</view>
        </view>
    </view>
</template>
<script>
    import emoji from './emoji/emoji.vue'
    const recorderManager = uni.getRecorderManager()
    export default {
        data() {
            return {
                isrecord: false,
                isemoji: false,
                ismore: false,
                voicebg: false,
                msg: '',
                timer: '',
                vlength: 0,
                pageY: 0,
            };
        },
        components:{
            emoji,
        },
        methods:{
            // 获取高度
            _getElementHeight() {
                const query = uni.createSelectorQuery().in(this);
                query.select('.submit').boundingClientRect(data => {
                    this.$emit('heights', data.height)
                }).exec();
            },
            // 点击切换音频
            records() {
                this.isrecord = !this.isrecord
                this.isemoji = false
                this.ismore = false
                setTimeout(() => {
                    this._getElementHeight()
                }, 10)
            },
            // 点击弹出表情
            emoji() {
                this.isemoji = !this.isemoji
                this.ismore = false
                this.isrecord = false
                setTimeout(() => {
                    this._getElementHeight()
                }, 10)
            },
            // 点击弹出更多
            more() {
                this.ismore = !this.ismore
                this.isemoji = false
                this.isrecord = false
                setTimeout(() => {
                    this._getElementHeight()
                }, 10)
            },
            // 接收表情
            emotion(e) {
                this.msg = this.msg + e
            },
            // 文字发送
            inputs(e) {
                let chatm = e.detail.value
                let pos = chatm.indexOf('\n')
                if(pos != -1 && chatm.length > 1) {
                    this.send(this.msg,0)
                }
                setTimeout(() => {
                    this._getElementHeight()
                },10)
            },
            // 输入框聚焦
            focus(){
                this.isemoji = false;
                this.ismore = false;
                setTimeout(() => {
                    this._getElementHeight()
                },10)
            },
            // 表情内发送
            emojiSend() {
                if(this.msg.length > 0) {
                    this.send(this.msg, 0)
                }
                setTimeout(() => {
                    this._getElementHeight()
                },10)
            },
            // 表情退格
            emojiBack() {
                if(this.msg.length > 0){
                    this.msg = this.msg.substring(0, this.msg.length-1)
                }
            },
            // 发送消息
            send(msg, type) {
                let data = {
                    message: msg,
                    types: type
                }
                this.$emit('inputs', data)
                setTimeout(() => {
                    this.msg = ''
                }, 0)
                setTimeout(() => {
                    this._getElementHeight()
                },10)
            },
            // 发送图片
            sendImg(e) {
                let count = 9;
                if(e == 'album') {
                    count = 9
                }else {
                    count = 1
                }
                uni.chooseImage({
                    count: count,
                    sizeType: ['original', 'comperssed'],
                    sourceType: [e],
                    success: (res) => {
                        const filePath = res.tempFilePaths
                        for (let i in filePath){
                            this.send(filePath[i], 1)
                        }
                    }
                })
                setTimeout(() => {
                    this._getElementHeight()
                },10)
            },
            // 音频处理
            touchstart(e) {
                // 此时的Y轴位置
                this.pageY = e.changedTouches[0].pageY
                let startIndex = 1
                this.voicebg = true
                this.timer = setInterval(() => {
                    this.vlength = startIndex
                    startIndex++
                    if(startIndex > 60) {
                        clearInterval(this.timer)
                        this.touchend();
                    }
                }, 1000)
                recorderManager.start()
            },
            touchend() {
                clearInterval(this.timer)
                recorderManager.stop()
                recorderManager.onStop((res) => {
                    let data = {
                        voice: res.tempFilePath,
                        time: this.vlength
                    }
                    if(this.voicebg){
                        this.send(data, 2);
                    }
                    this.vlength = 0
                    this.voicebg = false
                })
            },
            touchmove(e) {
                if(this.pageY - e.changedTouches[0].pageY > 200) {
                    this.voicebg = false
                }
            },
            // 定位
            chooseLocation() {
                uni.chooseLocation({
                    success: (res) => {
                        let data = {
                            name: res.name,
                            address: res.address,
                            latitude: res.latitude,
                            longitude: res.longitude
                        }
                        this.send(data, 3)
                        console.log('位置名称' + res.name)
                        console.log('详细地址' + res.address)
                        console.log('维度' + res.latitude)
                        console.log('经度' + res.longitude)
                    }
                })
            }
        }
    }
</script>
<style lang="scss">
    .submit {
        background-color: rgba(244, 244, 244, .96);
        border-top: 1px solid $uni-border-color;
        width: 100%;
        position: fixed;
        bottom: 0;
        left: 0;
        z-index: 1002;
        padding-bottom: env(safe-area-inset-bottom);
    }
    .submit-chat {
        width: 100%;
        display: flex;
        align-items: flex-end;
        box-sizing: border-box;
        padding: 14rpx 10rpx;
        image {
            width: 56rpx;
            height: 56rpx;
            margin: 0 10rpx;
            flex: auto;
        }
        .btn {
            flex: auto;
            background-color: #fff;
            border-radius: 10rpx;
            padding: 20rpx;
            max-height: 160rpx;
            margin: 0 10rpx;
        }
        .chat-send {
            line-height: 44rpx !important;
        }
        .record {
            text-align: center;
            font-size: $uni-font-size-lg;
            color: $uni-text-color-grey;
            font-weight: bold;
        }
    }
    .displaynone {
        display: none;
    }
    .emoji {
        width: 100%;
        height: 460rpx;
        background: rgba(236, 237, 238, 1);
        box-shadow: 0 -1rpx 0 0 rgba(0, 0, 0, 1);
        .emoji-send {
            width: 260rpx;
            height: 104rpx;
            background: rgba(236, 237, 238, .9);
            position: fixed;
            bottom: env(safe-area-inset-bottom);
            right: 0;
            padding-top: 24rpx;
            display: flex;
            .emoji-send-bt {
                flex: 1;
                height: 80rpx;
                margin: 0 32rpx 0 20rpx;
                background: rgba(255, 228, 49 ,1);
                border-radius: 240rpx;
                font-size: 32rpx;
                text-align: center;
                line-height: 80rpx;
                border-radius: 12rpx;
            }
            .emoji-send-del {
                flex: 1;
                height: 80rpx;
                background: #fff;
                border-radius: 240rpx;
                font-size: 32rpx;
                text-align: center;
                line-height: 80rpx;
                border-radius: 12rpx;
                margin-left: 24rpx;
            }
        }
    }
    .more {
        width: 100%;
        height: 436rpx;
        background: rgba(236, 237, 238, 1);
        box-shadow: rgba(0, 0, 0, .1);
        bottom: env(safe-area-inset-bottom);
        padding: 0 20rpx;
        box-sizing: border-box;
        .more-list {
            width: 25%;
            text-align: center;
            float: left;
            margin-top: 32rpx;
            image {
                width: 72rpx;
                height: 72rpx;
                padding: 24rpx;
                background: rgba(255, 255, 255, 1);
                border-radius: 24rpx;
            }
            .more-list-title {
                color: rgba(30, 40, 50, .5);
                line-height: 34rpx;
                font-size: 24rpx;
                display: block;
            }
        }
    }
    .voice-bg {
        height: 100%;
        width: 100%;
        background: rgba(0, 0, 0, .3);
        position: fixed;
        top: 0;
        bottom: 0;
        z-index: 1001;
        // position: relative;
        .voice-bg-len {
            height: 84rpx;
            width: 600rpx;
            position: absolute;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            margin: auto;
            background: rgba(255, 255, 255, .2);
            border-radius: 42rpx;
            text-align: center;
            .voice-bg-time {
                display: inline-block;
                line-height: 84rpx;
                background-color: $uni-color-primary;
                border-radius: 42rpx;
                min-width: 120rpx;
            }
        }
        .voice-del {
            position: absolute;
            bottom: 148rpx;
            margin-bottom: env(safe-area-inset-bottom);
            width: 100%;
            text-align: center;
             color: #fff;
             font-size: $uni-font-size-base;
        }
    }
</style>
components/uni-load-more/uni-load-more.vue
New file
@@ -0,0 +1,362 @@
<template>
    <view class="uni-load-more" @click="onClick">
        <!-- #ifdef APP-NVUE -->
        <loading-indicator v-if="!webviewHide && status === 'loading' && showIcon" :style="{color: color,width:iconSize+'px',height:iconSize+'px'}" :animating="true" class="uni-load-more__img uni-load-more__img--nvue"></loading-indicator>
        <!-- #endif -->
        <!-- #ifdef H5 -->
        <svg width="24" height="24" viewBox="25 25 50 50" v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
        :style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--android-H5">
            <circle cx="50" cy="50" r="20" fill="none" :style="{color:color}" :stroke-width="3"></circle>
        </svg>
        <!-- #endif -->
        <!-- #ifndef APP-NVUE || H5 -->
        <view v-if="!webviewHide && (iconType==='circle' || iconType==='auto' && platform === 'android') && status === 'loading' && showIcon"
        :style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--android-MP">
            <view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
            <view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
            <view :style="{borderTopColor:color,borderTopWidth:iconSize/12}"></view>
        </view>
        <!-- #endif -->
        <!-- #ifndef APP-NVUE -->
        <view v-else-if="!webviewHide && status === 'loading' && showIcon" :style="{width:iconSize+'px',height:iconSize+'px'}" class="uni-load-more__img uni-load-more__img--ios-H5">
            <image src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QzlBMzU3OTlEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QzlBMzU3OUFEOUM0MTFFOUI0NTZDNERBQURBQzI4RkUiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpDOUEzNTc5N0Q5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpDOUEzNTc5OEQ5QzQxMUU5QjQ1NkM0REFBREFDMjhGRSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pt+ALSwAAA6CSURBVHja1FsLkFZVHb98LM+F5bHL8khA1iSeiyQBCRM+YGqKUnnJTDLGI0BGZlKDIU2MMglUiDApEZvSsZnQtBRJtKwQNKQMFYeRDR10WOLd8ljYXdh+v8v5fR3Od+797t1dnOnO/Ofce77z+J//+b/P+ZqtXbs2sJ9MJhNUV1cHJ06cCJo3bx7EPc2aNcvpy7pWrVoF+/fvDyoqKoI2bdoE9fX1F7TjN8a+EXBn/fkfvw942Tf+wYMHg9mzZwfjxo0LDhw4EPa1x2MbFw/fOGfPng1qa2tzcCkILsLDydq2bRsunpOTMM7TD/W/tZDZhPdeKD+yGxHhdu3aBV27dg3OnDlzMVANMheLAO3btw8KCwuDmpoaX5OxbgUIMEq7K8IcPnw4KCsrC/r37x8cP378/4cAXAB3vqSkJMuiDhTkw+XcuXNhOWbMmKBly5YhUT8xArhyFvP0BfwRsAuwxJZJsm/nzp2DTp06he/OU+cZ64K6o0ePBkOHDg2GDx8e6gEbJ5Q/NHNuAJQ1hgBeHUDlR7nVTkY8rQAvAi4z34vR/mPs1FoRsaCgIJThI0eOBC1atEiFGGV+5MiRoS45efJkqFjJFXV1dQuA012m2WcwTw98fy6CqBdsaiIO4CScrGPHjvk4odhavPquRtFWXEC25VgkREKOCh/qDSq+vn37htzD/mZTOmOc5U7zKzBPEedygWshcDyWvs30igAbU+6oyMgJBCFhwQE0fccxN60Ay9iebbjoDh06hMowjQxT4fXq1SskArmHZpkArvixp/kWzHdMeArExSJEaiXIjjRjRJ4DaAGWpibLzXN3Fm1vA5teBgh3j1Rv3bp1YgKwPdmf2p9zcyNYYgPKMfY0T5f5nNYdw158nJ8QawW4CLKwiOBSEgO/hok2eBydR+3dYH+PLxA5J8Vv0KBBwenTp0P2JWAx6+yFEBfs8lMY+y0SWMBNI9E4ThKi58VKTg3FQZS1RQF1cz27eC0QHMu+3E0SkUowjhVt5VdaWhp07949ZHv2Qd1EjDXM2cla1M0nl3GxAs3J9yREzyTdFVKVFOaE9qRA8GM0WebRuo9JGZKA7Mv2SeS/Z8+eoQ9BArMfFrLGo6jvxbhHbJZnKX2Rzz1O7QhJJ9Cs2ZMaWIyq/zhdeqPNfIoHd58clIQD+JSXl4dKlyIAuBdVXZwFVWKspSSoxE++h8x4k3uCnEhE4I5KwRiFWGOU0QWKiCYLbdoRMRKAu2kQ9vkfLU6dOhX06NEjlH+yMRZSinnuyWnYosVcji8CEA/6Cg2JF+IIUBqnGKUTCNwtwBN4f89RiK1R96DEgO2o0NDmtEdvVFdVVYV+P3UAPUEs6GFwV3PHmXkD4vh74iDFJysVI/MlaQhwKeBNTLYX5VuA8T4/gZxA4MRGFxDB6R7OmYPfyykGRJbyie+XnGYnQIC/coH9+vULiYrxrkL9ZA9+0ykaHIfEpM7ge8TiJ2CsHYwyMfafAF1yCGBHYIbCVDjDjKt7BeB51D+LgQa6OkG7IDYEEtvQ7lnXLKLtLdLuJBpE4gPUXcW2+PkZwOex+4cGDhwYDBkyRL7/HFcEwUGPo/8uWRUpYnfxGHco8HkewLHLyYmAawAPuIFZxhOpDfJQ8gbUv41yORAptMWBNr6oqMhWird5+u+iHmBb2nhjDV7HWBNQTgK8y11l5NetWzc5ULscAtSj7nbNI0skhWeUZCc0W4nyH/jO4Vz0u1IeYhbk4AiwM6tjxIWByHsoZ9qcIBPJd/y+DwPfBESOmCa/QF3WiZHucLlEDpNxcNhmheEOPgdQNx6/VZFQzFZ5TN08AHXQt2Ii3EdyFuUsPtTcGPhW5iMiCNELvz+Gdn9huG4HUJaW/w3g0wxV0XaG7arG2WeKiUWYM4Y7GO5ezshTARbbWGw/DvXkpp/ivVvE0JVoMxN4rpGzJMhE5Pl+xlATsDIqikP9F9D2z3h9nOksEUFhK+qO4rcPkoalMQ/HqJLIyb3F3JdjrCcw1yZ8joyJLR5gCo54etlag7qIoeNh1N1BRYj3DTFJ0elotxPlVzkGuYAmL0VSJVGAJA41c4Z6A3BzTLfn0HYwYKEI6CUAMzZEWvLsIcQOo1AmmyyM72nHJCfYsogflGV6jEk9vyQZXSuq6w4c16NsGcGZbwOPr+H1RkOk2LEzjNepxQkihHSCQ4ynAYNRx2zMKV92CQMWqj8J0BRE8EShxRFN6YrfCRhC0x3r/Zm4IbQCcmJoV0kMamllccR6FjHqUC5F2R/wS2dcymOlfAKOS4KmzQb5cpNC2MC7JhVn5wjXoJ44rYhLh8n0eXOCorJxa7POjbSlCGVczr34/RsAmrcvo9s+wGp3tzVhntxiXiJ4nvEYb4FJkf0O8HocAePmLvCxnL0AORraVekJk6TYjDabRVXfRE2lCN1h6ZQRN1+InUbsCpKwoBZHh0dODN9JBCUffItXxEavTQkUtnfTVAplCWL3JISz29h4NjotnuSsQKJCk8dF+kJR6RARjrqFVmfPnj3ZbK8cIJ0msd6jgHPGtfVTQ8VLmlvh4mct9sobRmPic0DyDQQnx/NlfYUgyz59+oScsH379pAwXABD32nTpoUHIToESeI5mnbE/UqDdyLcafEBf2MCqgC7NwxIbMREJQ0g4D4sfJwnD+AmRrII05cfMWJE+L1169bQr+fip06dGp4oJ83lmYd5wj/EmMa4TaHivo4EeCguYZBnkB5g2aWA69OIEnUHOaGysjIYMGBAMGnSpODYsWPZwCpFmm4lNq+4gSLQA7jcX8DwtjEyRC8wjabnXEx9kfWnTJkSJkAo90xpJVV+FmcVNeYAF5zWngS4C4O91MBxmAv8blLEpbjI5sz9MTdAhcgkCT1RO8mZkAjfiYpTEvStAS53Uw1vAiUGgZ3GpuQEYvoiBqlIan7kSDHnTwJQFNiPu0+5VxCVYhcZIjNrdXUDdp+Eq5AZ3Gkg8QAyVZRZIk4Tl4QAbF9cXJxNYZMAtAokgs4BrNxEpCtteXg7DDTMDKYNSuQdKsnJBek7HxewvxaosWxLYXtw+cJp18217wql4aKCfBNoEu0O5VU+PhctJ0YeXD4C6JQpyrlpSLTojpGGGN5YwNziChdIZLk4lvLcFJ9jMX3QdiImY9bmGQU+TRUL5CHITTRlgF8D9ouD1MfmLoEPl5xokIumZ2cfgMpHt47IW9N64Hsh7wQYYjyIugWuF5fCqYncXRd5vPMWyizzvhi/32+nvG0dZc9vR6fZOu0md5e+uC408FvKSIOZwXlGvxPv95izA2Vtvg1xKFWARI+vMX66HUhpQQb643uW1bSjuTWyw2SBvDrBvjFic1eGGlz5esq3ko9uSIlBRqPuFcCv8F4WIcN12nVaBd0SaYwI6PDDImR11JkqgHcPmQssjxIn6bUshygDFJUTxPMpHk+jfjPgupgdnYV2R/g7xSjtpah8RJBewhwf0gGK6XI92u4wXFEU40afJ4DN4h5LcAd+40HI3JgJecuT0c062W0i2hQJUTcxan3/CMW1PF2K6bbA+Daz4xRs1D3Br1Cm0OihKCqizW78/nXAF/G5TXrEcVzaNMH6CyMswqsAHqDyDLEyou8lwOXnKF8DjI6KjV3KzMBiXkDH8ij/H214J5A596ekrZ3F0zXlWeL7+P5eUrNo3/QwC15uxthuzidy7DzKRwEDaAViiDgKbTbz7CJnzo0bN7pIfIiid8SuPwn25o3QCmpnyjlZkyxPP8EomCJzrGb7GJMx7tNsq4MT2xMUYaiErZOluTzKsnz3gwCeCZyVRZJfYplNEokEjwrPtxlxjeYAk+F1F74VAzPxQRNYYdtpOUvWs8J1sGhBJMNsb7igN8plJs1eSmLIhLKE4rvaCX27gOhLpLOsIzJ7qn/i+wZzcvSOZ23/du8TZjwV8zHIXoP4R3ifBxiFz1dcVpa3aPntPE+c6TmIWE9EtcMmAcPdWAhYhAXxcLOQi9L1WhD1Sc8p1d2oL7XGiRKp8F4A2i8K/nfI+y/gsTDJ/YC/8+AD5Uh04KHiGl+cIFPnBDDrPMjwRGkLXyxO4VGbfQWnDH2v0bVWE3C9QOXlepbgjEfIJQI6XDG3z5ahD9cw2pS78ipB85wyScNTvsVzlzzhL8/jRrnmVjfFJK/m3m4nj9vbgQTguT8XZTjsm672R5uJKEaQmBI/c58gyus8ZDagLpEVSJBIyHp4jn++xqPV71OgQgJYEWOtZ/haxRtKmWOBu8xdBLftWltsY84zE6WIEy/eIOWL+BaayMx+KHtL7EAkqdNDLiEXmEMUHniedtJqg9HmZtfvt26vNi0BdG3Ft3g8ZOf7PAu59TxtzivLNIekyi+wD1i8CuUiD9FXAa8C+/xS3JPmZnomyc7H+fb4/Se0bk41Fel621r4cgVxbq91V4jVqwB7HTe2M7jgB+QWHavZkDRPmZcASoZEmBx6i75bGjPcMdL4/VKGFAGWZkGzPG0XAbdL9A81G5LOmUnC9hHKJeO7dcUMjblSl12867ElFTtaGl20xvvLGPdVz/8TVuU7y0x1PG7vtNg24oz9Uo/Z412++VFWI7Fcog9tu9Lm6gvRmIPv9x1xmQAu6RDkXtbOtlGEmpgD5Nvnyc0dcv0EE6cfdi1HmhMf9wDF3k3gtRvEedhxjpgfqPb9PU9iEJHnyOUA7bQUXh6kq/D7l2iTjWv7XOD530BDr8jIrus+srXjt4MzumJMHuTsBa63YKE1+RR5lBjEikCCnWKWiHdzOgKO+nRIBAF88za/IFmJ3eMZov4CYxGBabcpGL8EYx+SeMXJeRwHNsV/h+vdxeuhEpN3ZyNY78Gm2fknJxVGhyjixPiQvVkNzT1elD9Py/aTAL64Hb9vcYmC9zfdXdT/C1LeGbg4rnBaAihDFJH12W5ulfNCNe/xTsP3bp8ikzJs5BF+5PNfAQYAPaseTdsEcaYAAAAASUVORK5CYII="
                         mode="widthFix"></image>
        </view>
        <!-- #endif -->
        <text class="uni-load-more__text" :style="{color: color}">{{ status === 'more' ? contentText.contentdown : status === 'loading' ? contentText.contentrefresh : contentText.contentnomore }}</text>
    </view>
</template>
<script>
    let platform
    setTimeout(() => {
            platform = uni.getSystemInfoSync().platform
    }, 16)
    /**
     * LoadMore 加载更多
     * @description 用于列表中,做滚动加载使用,展示 loading 的各种状态
     * @tutorial https://ext.dcloud.net.cn/plugin?id=29
     * @property {String} status = [more|loading|noMore] loading 的状态
     *     @value more loading前
     *     @value loading loading中
     *     @value noMore 没有更多了
     * @property {Number} iconSize 指定图标大小
     * @property {Boolean} iconSize = [true|false] 是否显示 loading 图标
     * @property {String} iconType = [snow|circle|auto] 指定图标样式
     *     @value snow ios雪花加载样式
     *     @value circle 安卓唤醒加载样式
     *     @value auto 根据平台自动选择加载样式
     * @property {String} color 图标和文字颜色
     * @property {Object} contentText 各状态文字说明,值为:{contentdown: "上拉显示更多",contentrefresh: "正在加载...",contentnomore: "没有更多数据了"}
     * @event {Function} clickLoadMore 点击加载更多时触发
     */
    export default {
        name: 'UniLoadMore',
        props: {
            status: {
                // 上拉的状态:more-loading前;loading-loading中;noMore-没有更多了
                type: String,
                default: 'more'
            },
            showIcon: {
                type: Boolean,
                default: true
            },
            iconType: {
                type: String,
                default: 'auto'
            },
            iconSize: {
                type: Number,
                default: 24
            },
            color: {
                type: String,
                default: '#777777'
            },
            contentText: {
                type: Object,
                default () {
                    return {
                        contentdown: '上拉显示更多',
                        contentrefresh: '正在加载...',
                        contentnomore: '没有更多数据了'
                    }
                }
            }
        },
        data() {
            return {
                webviewHide: false,
                platform: platform
            }
        },
        // #ifndef APP-NVUE
        computed:{
            iconSnowWidth(){
                return (Math.floor(this.iconSize/24)||1)*2
            }
        },
        // #endif
        mounted() {
            // #ifdef APP-PLUS
            var pages = getCurrentPages();
            var page = pages[pages.length - 1];
            var currentWebview = page.$getAppWebview();
            currentWebview.addEventListener('hide', () => {
                this.webviewHide = true
            })
            currentWebview.addEventListener('show', () => {
                this.webviewHide = false
            })
            // #endif
        },
        methods: {
            onClick() {
                this.$emit('clickLoadMore', {
                    detail: {
                        status: this.status,
                    }
                })
            }
        }
    }
</script>
<style lang="scss" scoped>
    .uni-load-more {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        flex-direction: row;
        height: 40px;
        align-items: center;
        justify-content: center;
    }
    .uni-load-more__text {
        font-size: 15px;
    }
    .uni-load-more__img {
        width: 24px;
        height: 24px;
        margin-right: 8px;
    }
    .uni-load-more__img--nvue {
        color: #666666;
    }
    .uni-load-more__img--android,
    .uni-load-more__img--ios {
        width: 24px;
        height: 24px;
        transform: rotate(0deg);
    }
    /* #ifndef APP-NVUE */
    .uni-load-more__img--android {
        animation: loading-ios 1s 0s linear infinite;
    }
    @keyframes loading-android {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
    .uni-load-more__img--ios-H5 {
        position: relative;
        animation: loading-ios-H5 1s 0s step-end infinite;
    }
    .uni-load-more__img--ios-H5>image {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
    }
    @keyframes loading-ios-H5 {
        0% {
            transform: rotate(0deg);
        }
        8% {
            transform: rotate(30deg);
        }
        16% {
            transform: rotate(60deg);
        }
        24% {
            transform: rotate(90deg);
        }
        32% {
            transform: rotate(120deg);
        }
        40% {
            transform: rotate(150deg);
        }
        48% {
            transform: rotate(180deg);
        }
        56% {
            transform: rotate(210deg);
        }
        64% {
            transform: rotate(240deg);
        }
        73% {
            transform: rotate(270deg);
        }
        82% {
            transform: rotate(300deg);
        }
        91% {
            transform: rotate(330deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
    /* #endif */
    /* #ifdef H5 */
    .uni-load-more__img--android-H5 {
        animation: loading-android-H5-rotate 2s linear infinite;
        transform-origin: center center;
    }
    .uni-load-more__img--android-H5>circle {
        display: inline-block;
        animation: loading-android-H5-dash 1.5s ease-in-out infinite;
        stroke: currentColor;
        stroke-linecap: round;
    }
    @keyframes loading-android-H5-rotate {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
    @keyframes loading-android-H5-dash {
        0% {
            stroke-dasharray: 1, 200;
            stroke-dashoffset: 0;
        }
        50% {
            stroke-dasharray: 90, 150;
            stroke-dashoffset: -40;
        }
        100% {
            stroke-dasharray: 90, 150;
            stroke-dashoffset: -120;
        }
    }
    /* #endif */
    /* #ifndef APP-NVUE || H5 */
    .uni-load-more__img--android-MP {
        position: relative;
        width: 24px;
        height: 24px;
        transform: rotate(0deg);
        animation: loading-ios 1s 0s ease infinite;
    }
    .uni-load-more__img--android-MP>view {
        position: absolute;
        box-sizing: border-box;
        width: 100%;
        height: 100%;
        border-radius: 50%;
        border: solid 2px transparent;
        border-top: solid 2px #777777;
        transform-origin: center;
    }
    .uni-load-more__img--android-MP>view:nth-child(1){
        animation: loading-android-MP-1 1s 0s linear infinite;
    }
    .uni-load-more__img--android-MP>view:nth-child(2){
        animation: loading-android-MP-2 1s 0s linear infinite;
    }
    .uni-load-more__img--android-MP>view:nth-child(3){
        animation: loading-android-MP-3 1s 0s linear infinite;
    }
    @keyframes loading-android {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
    @keyframes loading-android-MP-1{
        0%{
            transform: rotate(0deg);
        }
        50%{
            transform: rotate(90deg);
        }
        100%{
            transform: rotate(360deg);
        }
    }
    @keyframes loading-android-MP-2{
        0%{
            transform: rotate(0deg);
        }
        50%{
            transform: rotate(180deg);
        }
        100%{
            transform: rotate(360deg);
        }
    }
    @keyframes loading-android-MP-3{
        0%{
            transform: rotate(0deg);
        }
        50%{
            transform: rotate(270deg);
        }
        100%{
            transform: rotate(360deg);
        }
    }
    /* #endif */
</style>
components/uni-nav-bar/uni-nav-bar.vue
New file
@@ -0,0 +1,251 @@
<template>
    <view class="uni-navbar">
        <view :class="{ 'uni-navbar--fixed': fixed, 'uni-navbar--shadow': shadow, 'uni-navbar--border': border }" :style="{ 'background-color': backgroundColor }"
         class="uni-navbar__content">
            <status-bar v-if="statusBar" />
            <view :style="{ color: color,backgroundColor: backgroundColor }" class="uni-navbar__header uni-navbar__content_view">
                <view @tap="onClickLeft" class="uni-navbar__header-btns uni-navbar__header-btns-left uni-navbar__content_view">
                    <view class="uni-navbar__content_view" v-if="leftIcon.length">
                        <uni-icons :color="color" :type="leftIcon" size="24" />
                    </view>
                    <view :class="{ 'uni-navbar-btn-icon-left': !leftIcon.length }" class="uni-navbar-btn-text uni-navbar__content_view"
                     v-if="leftText.length">
                        <text :style="{ color: color, fontSize: '14px' }">{{ leftText }}</text>
                    </view>
                    <slot name="left" />
                </view>
                <view class="uni-navbar__header-container uni-navbar__content_view" @tap="onClickTitle">
                    <view class="uni-navbar__header-container-inner uni-navbar__content_view" v-if="title.length">
                        <text class="uni-nav-bar-text" :style="{color: color }">{{ title }}</text>
                    </view>
                    <!-- 标题插槽 -->
                    <slot />
                </view>
                <view :class="title.length ? 'uni-navbar__header-btns-right' : ''" @tap="onClickRight" class="uni-navbar__header-btns uni-navbar__content_view">
                    <view class="uni-navbar__content_view" v-if="rightIcon.length">
                        <uni-icons :color="color" :type="rightIcon" size="24" />
                    </view>
                    <!-- 优先显示图标 -->
                    <view class="uni-navbar-btn-text uni-navbar__content_view" v-if="rightText.length && !rightIcon.length">
                        <text class="uni-nav-bar-right-text">{{ rightText }}</text>
                    </view>
                    <slot name="right" />
                </view>
            </view>
        </view>
        <view class="uni-navbar__placeholder" v-if="fixed">
            <status-bar v-if="statusBar" />
            <view class="uni-navbar__placeholder-view" />
        </view>
    </view>
</template>
<script>
    import statusBar from "./uni-status-bar.vue";
    /**
     * NavBar 自定义导航栏
     * @description 导航栏组件,主要用于头部导航
     * @tutorial https://ext.dcloud.net.cn/plugin?id=52
     * @property {String} title 标题文字
     * @property {String} leftText 左侧按钮文本
     * @property {String} rightText 右侧按钮文本
     * @property {String} leftIcon 左侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
     * @property {String} rightIcon 右侧按钮图标(图标类型参考 [Icon 图标](http://ext.dcloud.net.cn/plugin?id=28) type 属性)
     * @property {String} color 图标和文字颜色
     * @property {String} backgroundColor 导航栏背景颜色
     * @property {Boolean} fixed = [true|false] 是否固定顶部
     * @property {Boolean} statusBar = [true|false] 是否包含状态栏
     * @property {Boolean} shadow = [true|false] 导航栏下是否有阴影
     * @event {Function} clickLeft 左侧按钮点击时触发
     * @event {Function} clickRight 右侧按钮点击时触发
     * @event {Function} clickTitle 中间标题点击时触发
     */
    export default {
        name: "UniNavBar",
        components: {
            statusBar
        },
        props: {
            title: {
                type: String,
                default: ""
            },
            leftText: {
                type: String,
                default: ""
            },
            rightText: {
                type: String,
                default: ""
            },
            leftIcon: {
                type: String,
                default: ""
            },
            rightIcon: {
                type: String,
                default: ""
            },
            fixed: {
                type: [Boolean, String],
                default: false
            },
            color: {
                type: String,
                default: "#000000"
            },
            backgroundColor: {
                type: String,
                default: "#FFFFFF"
            },
            statusBar: {
                type: [Boolean, String],
                default: false
            },
            shadow: {
                type: [Boolean, String],
                default: false
            },
            border: {
                type: [Boolean, String],
                default: true
            }
        },
        mounted() {
          if(uni.report && this.title !== '') {
              uni.report('title', this.title)
          }
        },
        methods: {
            onClickLeft() {
                this.$emit("clickLeft");
            },
            onClickRight() {
                this.$emit("clickRight");
            },
            onClickTitle() {
                this.$emit("clickTitle");
            }
        }
    };
</script>
<style lang="scss" scoped>
    $nav-height: 44px;
    .uni-nav-bar-text {
        /* #ifdef APP-PLUS */
        font-size: 34rpx;
        /* #endif */
        /* #ifndef APP-PLUS */
        font-size: $uni-font-size-lg;
        /* #endif */
    }
    .uni-nav-bar-right-text {
        font-size: $uni-font-size-base;
    }
    .uni-navbar__content {
        position: relative;
        background-color: $uni-bg-color;
        overflow: hidden;
        // width: 750rpx;
    }
    .uni-navbar__content_view {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        align-items: center;
        flex-direction: row;
        // background-color: #FFFFFF;
    }
    .uni-navbar__header {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        flex-direction: row;
        height: $nav-height;
        line-height: $nav-height;
        font-size: 16px;
        // background-color: #ffffff;
    }
    .uni-navbar__header-btns {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        flex-wrap: nowrap;
        width: 120rpx;
        padding: 0 6px;
        justify-content: center;
        align-items: center;
        /* #ifdef H5 */
        cursor: pointer;
        /* #endif */
    }
    .uni-navbar__header-btns-left {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        width: 150rpx;
        justify-content: flex-start;
    }
    .uni-navbar__header-btns-right {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        width: 150rpx;
        padding-right: 30rpx;
        justify-content: flex-end;
    }
    .uni-navbar__header-container {
        flex: 1;
    }
    .uni-navbar__header-container-inner {
        /* #ifndef APP-NVUE */
        display: flex;
        /* #endif */
        flex: 1;
        align-items: center;
        justify-content: center;
        font-size: $uni-font-size-base;
    }
    .uni-navbar__placeholder-view {
        height: $nav-height;
    }
    .uni-navbar--fixed {
        position: fixed;
        z-index: 998;
        /* #ifdef H5 */
        left: var(--window-left);
        right: var(--window-right);
        /* #endif */
        /* #ifndef H5 */
        left:0;
        right: 0;
        /* #endif */
    }
    .uni-navbar--shadow {
        /* #ifndef APP-NVUE */
        box-shadow: 0 1px 6px #ccc;
        /* #endif */
    }
    .uni-navbar--border {
        border-bottom-width: 1rpx;
        border-bottom-style: solid;
        border-bottom-color: $uni-border-color;
    }
</style>
components/uni-nav-bar/uni-status-bar.vue
New file
@@ -0,0 +1,25 @@
<template>
    <view :style="{ height: statusBarHeight }" class="uni-status-bar">
        <slot />
    </view>
</template>
<script>
    var statusBarHeight = uni.getSystemInfoSync().statusBarHeight + 'px'
    export default {
        name: 'UniStatusBar',
        data() {
            return {
                statusBarHeight: statusBarHeight
            }
        }
    }
</script>
<style lang="scss" scoped>
    .uni-status-bar {
        // width: 750rpx;
        height: 20px;
        // height: var(--status-bar-height);
    }
</style>
package.json
New file
@@ -0,0 +1,24 @@
{
  "dependencies": {
    "@smallwei/avue": "^2.8.14",
    "axios": "^0.21.1",
    "js-md5": "^0.7.3",
    "uni-read-pages": "^1.0.5",
    "uview-ui": "^1.8.4"
  },
  "name": "qfqk-android",
  "version": "1.0.0",
  "main": "main.js",
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "http://192.168.0.105:10010/r/qfqk-android.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}
pages/login/login-account.vue
@@ -3,46 +3,45 @@
        <u-navbar :is-fixed="false" :border-bottom="false" :is-back="false" back-icon-name="arrow-leftward" title="登录"
            :background="{ background: '#fff' }" title-color="#000000">
            <view class="" slot="right">
                <image src="/static/images/user/c8.png" class="set-icon" mode="widthFix"></image>
                <image src="/static/images/login/c8.png" class="set-icon" mode="widthFix"></image>
            </view>
        </u-navbar>
        <view class="content">
            <view class="top">
                <image src="/static/images/logo.png" class="logo" mode="widthFix"></image>
                <view class="titie">
                    <span>智慧保安互联网APP</span>
                </view>
                <view class="cell">
                    <view class="name">账号</view>
                    <view class="input-box">
                        <input type="text" v-model="username" placeholder="请输入账号" class="ipt" placeholder-class="hold"
                        <input type="text" v-model="names" placeholder="请输入账号" class="ipt" placeholder-class="hold"
                            @blur="handleInputCheck" />
                    </view>
                </view>
                <view class="cell">
                    <view class="name">密码</view>
                    <view class="input-box">
                        <input type="password" v-model="password" placeholder="请输入密码" class="ipt"
                        <input type="password" v-model="passwords" placeholder="请输入密码" class="ipt"
                            placeholder-class="hold" @blur="handleInputCheck" />
                    </view>
                </view>
                <!-- <view class="agree">
                    登录即代表同意
                    <text class="a">《用户协议》</text>
                    和
                    <text class="a">《隐私政策》</text>
                </view> -->
                <button class="submit" @click="submit" :disabled="disabled">登录</button>
                <view class="tip">未注册用户验证后将自动注册并登录</view>
                <navigator url="/pages/login/login-phone" hover-class="none" class="change">手机登录 ></navigator>
                <button class="submit" @click="longing(names,passwords)" :disabled="disabled">登录</button>
                <view class="tip">未注册用户注册审核通过后才可登录</view>
                <navigator url="/pages/registerUser/registerUser" hover-class="none" class="change">注册 ></navigator>
            </view>
            <!-- 社交账号登录 -->
            <view class="bottom">
                <view class="tag">社交账号登录</view>
                <view class="chat-arr">
                    <image src="/static/images/wx.png" class="icon" mode=""></image>
                    <image src="/static/images/qq.png" class="icon" mode=""></image>
                    <image src="/static/images/wb.png" class="icon" mode=""></image>
                </view>
                <view class="tag"></view>
                <!-- <view class="tsp">江西北邮信息通信技术有限公司</view> -->
            </view>
        </view>
        <!--  -->
@@ -50,39 +49,131 @@
</template>
<script>
    import md5 from '@/utils/md5.js'
    import WxStorage from "../../static/lib/wxStorage.js" //微信Storage
    export default {
        data() {
            return {
                tenantId: '000000',
                username: '',
                password: '',
                icons: '',
                names: '',
                passwords: '',
                msg: '',
                colors: '#123456',
                disabled: true
            };
            }
        },
        computed: {
            OURpass() {
                return this.$store.state.loging;
            }
        },
        methods: {
            submit() {
                this.$u.api.token(this.tenantId, this.username, md5(this.password)).then(data => {
                    this.$u.func.login(data)
                }).catch(err => {
                    console.log(err)
                    this.$u.func.showToast({
                        title: '用户名或密码错误',
                    })
                })
            judgeUse() {
                var login = WxStorage.get("init") //重复登录
                var name = WxStorage.get("name")
                var userID = WxStorage.get("ids")
                var accounts = WxStorage.get("accounts");
                var pass = WxStorage.get("pass");
                console.log(login);
                if (login == "true" && name != '') {
                    //获取用户信息
                    var data = {
                        userName: name,
                        userID: userID
                    }
                    this.$store.commit('getUse', data)
                    // wx.reLaunch({
                    //     url: '/pages/alarm_list/alarm_list?login=' + data.userName
                    // })
                    this.names = accounts;
                    this.passwords = pass;
                }
            },
            judgeMsg() {
                this.msg = this.names == '' ? (this.passwords == '' ? '账号密码不能为空' : '账号不能为空') : (this.passwords == '' ?
                    '密码不能为空' : this.passwords.length <= 5 ? '密码最少6位' :
                    '格式正确');
                if (this.msg == "格式正确") {
                    this.icons = 'success';
                    this.colors = '#4ac503';
                    this.disabled = false
                } else {
                    this.icons = 'warn';
                    this.colors = '#d53c00';
                }
            },
            longing(name, pass) {
                var data = {
                    name: name,
                    pass: pass,
                }
                this.judgeMsg();
                if (this.msg == "格式正确") {
                    uni.showNavigationBarLoading();
                    this.$store.dispatch('loging', data)
                }else{
                    uni.showToast({
                        title: '格式错误,请重试',
                        icon:'none',
                        duration: 2000
                    });
                }
            },
            handleInputCheck() {
                this.disabled = false
                //this.disabled = false
            },
            zhuce(){
                uni.navigateTo({
                    url:'/pages/registerUser/registerUser'
                })
            }
        },
        created() {
            this.judgeUse();
        },
        watch: {
            names() {
                this.judgeMsg();
            },
            passwords() {
                this.judgeMsg();
            },
            OURpass() {
                if (this.OURpass == true) {
                    this.passwords = '******';
                    uni.hideNavigationBarLoading();
                    uni.reLaunch({
                        url: '../home/home'
                    })
                    return '成功登录'
                } else {
                    this.icons = 'warn';
                    this.colors = '#d53c00';
                    this.msg = '账号密码错误';
                    this.$store.commit('loginReset', this); //重置登录
                    uni.hideNavigationBarLoading();
                    return '未成功登录'
                }
            }
        }
    };
    }
</script>
<style lang="scss">
    .titie{
        display: block;
        width: 420rpx;
        height: auto;
        margin: 0 auto 120rpx;
        span {
            font-weight: 600;
            font-size: 6vw;
            color: #14b9c8;
        }
    }
    .container {
        min-height: 100vh;
        overflow: hidden;
        .set-icon {
            vertical-align: middle;
            width: 41rpx;
@@ -90,33 +181,33 @@
            margin-right: 35rpx;
        }
    }
    .content {
        display: flex;
        flex-direction: column;
        justify-content: space-around;
        align-items: center;
        height: 90vh;
        width: 100%;
        .top {
            width: 100%;
        }
        .logo {
            display: block;
            width: 281rpx;
            height: auto;
            margin: 0 auto 120rpx;
        }
        .cell {
            width: 100%;
            padding: 0 85rpx;
            box-sizing: border-box;
            margin-top: 36rpx;
            .name {
                font-size: 22rpx;
                font-family: Source Han Sans CN;
@@ -125,31 +216,31 @@
                line-height: 30rpx;
                opacity: 0.72;
            }
            .input-box {
                padding: 30rpx 0;
                border-bottom: 2rpx solid #f6f6f6;
                display: flex;
                align-items: center;
                .code {
                    font-size: 22rpx;
                    font-family: Source Han Sans CN;
                    font-weight: 400;
                    color: #0d0d0d;
                    line-height: 30rpx;
                    text {
                        color: #14b9c8;
                    }
                }
                .ipt {
                    flex: 1;
                    // height: 24rpx;
                    font-size: 24rpx;
                }
                .hold {
                    font-size: 26rpx;
                    font-family: Source Han Sans CN;
@@ -160,7 +251,7 @@
                }
            }
        }
        .agree {
            margin: 27rpx 95rpx 0;
            font-size: 22rpx;
@@ -168,12 +259,12 @@
            font-weight: normal;
            color: #cacaca;
            line-height: 34rpx;
            .a {
                color: #000000;
            }
        }
        .submit {
            margin: 60rpx 90rpx 0;
            border: none;
@@ -184,15 +275,15 @@
            border-radius: 15rpx;
            background-color: #14b9c8;
            color: #ffffff;
            &::after {
                content: none;
            }
            &::before {
                content: none;
            }
            &[disabled='true'] {
                background: #e4e4e4;
                font-size: 36rpx;
@@ -201,7 +292,7 @@
                color: #ffffff;
            }
        }
        .tip {
            margin-top: 30rpx;
            text-align: center;
@@ -211,7 +302,16 @@
            color: #cacaca;
            line-height: 34rpx;
        }
        .tsp {
            margin-top: 30rpx;
            text-align: center;
            font-size: 28rpx;
            font-family: Adobe Heiti Std;
            font-weight: normal;
            color: #a8a8a8;
            line-height: 34rpx;
        }
        .change {
            margin-top: 20rpx;
            text-align: center;
@@ -221,7 +321,7 @@
            color: #14b9c8;
            line-height: 34rpx;
        }
        .tag {
            display: flex;
            justify-content: center;
@@ -231,7 +331,7 @@
            font-weight: normal;
            color: #9f9f9f;
            line-height: 34rpx;
            &::before {
                content: '';
                display: block;
@@ -240,7 +340,7 @@
                background: #d8d8d8;
                opacity: 0.86;
            }
            &::after {
                content: '';
                display: block;
@@ -250,13 +350,13 @@
                opacity: 0.86;
            }
        }
        .chat-arr {
            margin-top: 50rpx;
            display: flex;
            align-items: center;
            justify-content: space-between;
            .icon {
                width: 73rpx;
                height: 73rpx;
router/router.js
New file
@@ -0,0 +1,38 @@
// router.js
import {
    RouterMount,
    createRouter
} from 'uni-simple-router';
import WxStorage from "../static/lib/wxStorage.js" //微信Storage
const router = createRouter({
    platform: process.env.VUE_APP_PLATFORM,
    routes: [...ROUTES]
});
//全局路由前置守卫
router.beforeEach((to, from, next) => {
    console.log('跳转开始')
    if (to.name == 'loging') {
        next();
        return
    }
    var inTher = WxStorage.get("init");
    console.log(inTher);
    if (inTher == "false") {
        next({
            name: 'loging'
        });
    } else if (inTher == "true") {
        next();
    }
});
// 全局路由后置守卫
router.afterEach((to, from) => {
    console.log('跳转结束')
})
export {
    router,
    RouterMount
}
static/lib/axios.js
New file
@@ -0,0 +1,3 @@
/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(22),u=n(10),c=r(u);c.Axios=i,c.create=function(e){return r(a(c.defaults,e))},c.Cancel=n(23),c.CancelToken=n(24),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(25),c.isAxiosError=n(26),e.exports=c,e.exports.default=c},function(e,t,n){"use strict";function r(e){return"[object Array]"===R.call(e)}function o(e){return"undefined"==typeof e}function s(e){return null!==e&&!o(e)&&null!==e.constructor&&!o(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function i(e){return"[object ArrayBuffer]"===R.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function u(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function c(e){return"string"==typeof e}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function d(e){if("[object Object]"!==R.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Date]"===R.call(e)}function h(e){return"[object File]"===R.call(e)}function m(e){return"[object Blob]"===R.call(e)}function y(e){return"[object Function]"===R.call(e)}function g(e){return p(e)&&y(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function x(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function w(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function b(e,t){if(null!==e&&"undefined"!=typeof e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n<o;n++)t.call(null,e[n],n,e);else for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.call(null,e[s],s,e)}function E(){function e(e,n){d(t[n])&&d(e)?t[n]=E(t[n],e):d(e)?t[n]=E({},e):r(e)?t[n]=e.slice():t[n]=e}for(var t={},n=0,o=arguments.length;n<o;n++)b(arguments[n],e);return t}function j(e,t,n){return b(t,function(t,r){n&&"function"==typeof t?e[r]=S(t,n):e[r]=t}),e}function C(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}var S=n(3),R=Object.prototype.toString;e.exports={isArray:r,isArrayBuffer:i,isBuffer:s,isFormData:a,isArrayBufferView:u,isString:c,isNumber:f,isObject:p,isPlainObject:d,isUndefined:o,isDate:l,isFile:h,isBlob:m,isFunction:y,isStream:g,isURLSearchParams:v,isStandardBrowserEnv:w,forEach:b,merge:E,extend:j,trim:x,stripBOM:C}},function(e,t){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";function r(e){this.defaults=e,this.interceptors={request:new i,response:new i}}var o=n(2),s=n(5),i=n(6),a=n(7),u=n(22);r.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{},e.url=arguments[0]):e=e||{},e=u(this.defaults,e),e.method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[a,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach(function(e){t.unshift(e.fulfilled,e.rejected)}),this.interceptors.response.forEach(function(e){t.push(e.fulfilled,e.rejected)});t.length;)n=n.then(t.shift(),t.shift());return n},r.prototype.getUri=function(e){return e=u(this.defaults,e),s(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},o.forEach(["delete","get","head","options"],function(e){r.prototype[e]=function(t,n){return this.request(u(n||{},{method:e,url:t,data:(n||{}).data}))}}),o.forEach(["post","put","patch"],function(e){r.prototype[e]=function(t,n,r){return this.request(u(r||{},{method:e,url:t,data:n}))}}),e.exports=r},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(2);e.exports=function(e,t,n){if(!t)return e;var s;if(n)s=n(t);else if(o.isURLSearchParams(t))s=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&"undefined"!=typeof e&&(o.isArray(e)?t+="[]":e=[e],o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),s=i.join("&")}if(s){var a=e.indexOf("#");a!==-1&&(e=e.slice(0,a)),e+=(e.indexOf("?")===-1?"?":"&")+s}return e}},function(e,t,n){"use strict";function r(){this.handlers=[]}var o=n(2);r.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},r.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},r.prototype.forEach=function(e){o.forEach(this.handlers,function(t){null!==t&&e(t)})},e.exports=r},function(e,t,n){"use strict";function r(e){e.cancelToken&&e.cancelToken.throwIfRequested()}var o=n(2),s=n(8),i=n(9),a=n(10);e.exports=function(e){r(e),e.headers=e.headers||{},e.data=s(e.data,e.headers,e.transformRequest),e.headers=o.merge(e.headers.common||{},e.headers[e.method]||{},e.headers),o.forEach(["delete","get","head","post","put","patch","common"],function(t){delete e.headers[t]});var t=e.adapter||a.adapter;return t(e).then(function(t){return r(e),t.data=s(t.data,t.headers,e.transformResponse),t},function(t){return i(t)||(r(e),t&&t.response&&(t.response.data=s(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)})}},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t,n){return r.forEach(n,function(n){e=n(e,t)}),e}},function(e,t){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t,n){"use strict";function r(e,t){!s.isUndefined(e)&&s.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}function o(){var e;return"undefined"!=typeof XMLHttpRequest?e=n(12):"undefined"!=typeof process&&"[object process]"===Object.prototype.toString.call(process)&&(e=n(12)),e}var s=n(2),i=n(11),a={"Content-Type":"application/x-www-form-urlencoded"},u={adapter:o(),transformRequest:[function(e,t){return i(t,"Accept"),i(t,"Content-Type"),s.isFormData(e)||s.isArrayBuffer(e)||s.isBuffer(e)||s.isStream(e)||s.isFile(e)||s.isBlob(e)?e:s.isArrayBufferView(e)?e.buffer:s.isURLSearchParams(e)?(r(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):s.isObject(e)?(r(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300}};u.headers={common:{Accept:"application/json, text/plain, */*"}},s.forEach(["delete","get","head"],function(e){u.headers[e]={}}),s.forEach(["post","put","patch"],function(e){u.headers[e]=s.merge(a)}),e.exports=u},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t){r.forEach(e,function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])})}},function(e,t,n){"use strict";var r=n(2),o=n(13),s=n(16),i=n(5),a=n(17),u=n(20),c=n(21),f=n(14);e.exports=function(e){return new Promise(function(t,n){var p=e.data,d=e.headers;r.isFormData(p)&&delete d["Content-Type"];var l=new XMLHttpRequest;if(e.auth){var h=e.auth.username||"",m=e.auth.password?unescape(encodeURIComponent(e.auth.password)):"";d.Authorization="Basic "+btoa(h+":"+m)}var y=a(e.baseURL,e.url);if(l.open(e.method.toUpperCase(),i(y,e.params,e.paramsSerializer),!0),l.timeout=e.timeout,l.onreadystatechange=function(){if(l&&4===l.readyState&&(0!==l.status||l.responseURL&&0===l.responseURL.indexOf("file:"))){var r="getAllResponseHeaders"in l?u(l.getAllResponseHeaders()):null,s=e.responseType&&"text"!==e.responseType?l.response:l.responseText,i={data:s,status:l.status,statusText:l.statusText,headers:r,config:e,request:l};o(t,n,i),l=null}},l.onabort=function(){l&&(n(f("Request aborted",e,"ECONNABORTED",l)),l=null)},l.onerror=function(){n(f("Network Error",e,null,l)),l=null},l.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),n(f(t,e,"ECONNABORTED",l)),l=null},r.isStandardBrowserEnv()){var g=(e.withCredentials||c(y))&&e.xsrfCookieName?s.read(e.xsrfCookieName):void 0;g&&(d[e.xsrfHeaderName]=g)}if("setRequestHeader"in l&&r.forEach(d,function(e,t){"undefined"==typeof p&&"content-type"===t.toLowerCase()?delete d[t]:l.setRequestHeader(t,e)}),r.isUndefined(e.withCredentials)||(l.withCredentials=!!e.withCredentials),e.responseType)try{l.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&l.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&l.upload&&l.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then(function(e){l&&(l.abort(),n(e),l=null)}),p||(p=null),l.send(p)})}},function(e,t,n){"use strict";var r=n(14);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n.request,n)):e(n)}},function(e,t,n){"use strict";var r=n(15);e.exports=function(e,t,n,o,s){var i=new Error(e);return r(i,t,n,o,s)}},function(e,t){"use strict";e.exports=function(e,t,n,r,o){return e.config=t,n&&(e.code=n),e.request=r,e.response=o,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},e}},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){return{write:function(e,t,n,o,s,i){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(o)&&a.push("path="+o),r.isString(s)&&a.push("domain="+s),i===!0&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}()},function(e,t,n){"use strict";var r=n(18),o=n(19);e.exports=function(e,t){return e&&!r(t)?o(e,t):t}},function(e,t){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t){"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},function(e,t,n){"use strict";var r=n(2),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,n,s,i={};return e?(r.forEach(e.split("\n"),function(e){if(s=e.indexOf(":"),t=r.trim(e.substr(0,s)).toLowerCase(),n=r.trim(e.substr(s+1)),t){if(i[t]&&o.indexOf(t)>=0)return;"set-cookie"===t?i[t]=(i[t]?i[t]:[]).concat([n]):i[t]=i[t]?i[t]+", "+n:n}}),i):i}},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){function e(e){var t=e;return n&&(o.setAttribute("href",t),t=o.href),o.setAttribute("href",t),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}var t,n=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");return t=e(window.location.href),function(n){var o=r.isString(n)?e(n):n;return o.protocol===t.protocol&&o.host===t.host}}():function(){return function(){return!0}}()},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t){function n(e,t){return r.isPlainObject(e)&&r.isPlainObject(t)?r.merge(e,t):r.isPlainObject(t)?r.merge({},t):r.isArray(t)?t.slice():t}function o(o){r.isUndefined(t[o])?r.isUndefined(e[o])||(s[o]=n(void 0,e[o])):s[o]=n(e[o],t[o])}t=t||{};var s={},i=["url","method","data"],a=["headers","auth","proxy","params"],u=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],c=["validateStatus"];r.forEach(i,function(e){r.isUndefined(t[e])||(s[e]=n(void 0,t[e]))}),r.forEach(a,o),r.forEach(u,function(o){r.isUndefined(t[o])?r.isUndefined(e[o])||(s[o]=n(void 0,e[o])):s[o]=n(void 0,t[o])}),r.forEach(c,function(r){r in t?s[r]=n(e[r],t[r]):r in e&&(s[r]=n(void 0,e[r]))});var f=i.concat(a).concat(u).concat(c),p=Object.keys(e).concat(Object.keys(t)).filter(function(e){return f.indexOf(e)===-1});return r.forEach(p,o),s}},function(e,t){"use strict";function n(e){this.message=e}n.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},n.prototype.__CANCEL__=!0,e.exports=n},function(e,t,n){"use strict";function r(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(e){t=e});var n=this;e(function(e){n.reason||(n.reason=new o(e),t(n.reason))})}var o=n(23);r.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},r.source=function(){var e,t=new r(function(t){e=t});return{token:t,cancel:e}},e.exports=r},function(e,t){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},function(e,t){"use strict";e.exports=function(e){return"object"==typeof e&&e.isAxiosError===!0}}])});
//# sourceMappingURL=axios.min.map
static/lib/wxStorage.js
New file
@@ -0,0 +1,27 @@
const _getStorage = (key)=>{
  return wx.getStorageSync( key );
}
// 设置本地存储对应key
const _setStorage = (key,value)=>{
  return wx.setStorageSync( key,value );
}
// 清除全部本地存储
const _clearStorage = ()=>{
  wx.clearStorageSync();
}
// 清除指定key本地存储
const _removeStorage = ( key )=>{
  wx.removeStorageSync( key );
}
const WxStorage = {
    get : _getStorage,
    set : _setStorage,
    clear : _clearStorage,
    remov : _removeStorage,
}
export default WxStorage
store/actions.js
New file
@@ -0,0 +1,90 @@
import md5 from 'js-md5'
import axios from 'axios'
const actions = {
    loging(store, data) {
        var user = [{
                    name: '1',
                    password: '111111'
                },
                {
                    name: '2',
                    password: '222222'
                },
                {
                    name: '3',
                    password: '333333'
                },
            ],
            pasw = md5(data.pass),
            url = 'http://s16s652780.51mypc.cn/api/blade-auth/oauth/token?tenantId=963841&username=' + data.name +
            ' &password=' + pasw + '&grant_type=password&scope=all&type=account';
        // url ='http://192.168.0.109:82/blade-auth/oauth/token';
        // url ='http://192.168.0.109:82/blade-auth/oauth/token?tenantId=000000&username=admin&password=93369e86dc5fa854a0eaf75558c4039d&grant_type=password';
        // url ='http://web.byisf.com/api/blade-auth/oauth/token?tenantId=000000&username=admin&password=93369e86dc5fa854a0eaf75558c4039d&grant_type=password&scope=all';
        // console.log(url);
        wx.request({ //uniapp 自带axios
            url: url, //仅为示例,并非真实接口地址。
            // data: d,
            // data: {
            //     tenantId: '000000',
            //     username: data.name,
            //     password: pasw,
            //     grant_type: 'password',
            //     scope: 'all',
            //     type: "account"
            // },
            header: {
                // "Content-Type":"",
                "Authorization": "Basic c2FiZXI6c2FiZXJfc2VjcmV0",
                "Tenant-Id": "963841"
                // "Cookie": "JSESSIONID=maOJY05vT2jj4nHwsQGSPgWWVFH1mY-TGWOLYCSh"
            },
            method: "post",
            //     // dataType: 'JSON',
            success: (res) => {
                if (res.statusCode == 200) {
                    if(res.data.error_code == "400"){
                        uni.showToast({
                            title: '密码错误,请重试',
                            icon:'none',
                            duration: 2000
                        });
                        return;
                    }
                    store.commit('getUserData',res.data)
                    // console.log(res.data,123542);
                    data.isit = true;
                    data.userName = res.data.nick_name; //警袁姓名
                    data.userID = res.data.user_id; //警袁id
                    data.avatar = res.data.avatar; //头像
                    data.accounts = data.name;
                    data.pass = data.pass;
                    // data.userPhon = res.user_id;
                    store.commit('login', data);
                }
            },
            fail: (res) => {
                console.log('失去连接 请稍等');
                // console.log(res);
            }
        });
        // var time = setTimeout(() => { //模拟请求时间
        //     var ud = user,
        //         isit = false;
        //     for (var key in ud) {
        //         if (ud[key].name == data.name && ud[key].password == data.pass) {
        //             isit = true;
        //             break;
        //         } else {
        //             isit = false;
        //         }
        //     }
        //     data.isit = isit;
        //     store.commit('login', data);
        // }, 2000)
    }
}
export default actions
store/index.js
@@ -1,5 +1,7 @@
import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations.js'
import actions from './actions.js'
Vue.use(Vuex)
let lifeData = {};
@@ -41,29 +43,48 @@
        isLogin: lifeData.isLogin ? lifeData.isLogin : false,
        // 如果version无需保存到本地永久存储,无需lifeData.version方式
        version: '1.0.0',
        loging: false,
        message: {
            useName: '过客 ',
        },
        logPath: '',
        piAPI: 'http://s16s652780.51mypc.cn/api/',
        // piAPI: 'http://localhost:82/',
        puserName: '',
        puserID: '',
        puserIphone:'',
        avatar:"../../static/logo.png",
        UserData: {},
        tabbar:[{
                iconPath: "/static/tabbar/index01.png",
                selectedIconPath: "/static/tabbar/index02.png",
                text: '首页',
                pagePath: "/pages/home/home"
            },
            {
                iconPath: "/static/tabbar/article.png",
                selectedIconPath: "/static/tabbar/articleH.png",
                text: '资讯',
                pagePath: "/pages/article/article"
            },
            {
                iconPath: "/static/tabbar/workbench.png",
                selectedIconPath: "/static/tabbar/workbenchH.png",
                text: '工作台',
                count: 2,
                isDot: false,
                pagePath: "/pages/business/business"
            },
            {
                iconPath: "/static/tabbar/my.png",
                selectedIconPath: "/static/tabbar/my-blue.png",
                text: '我的',
                pagePath: "/pages/myself/myself"
            },
        ]
    },
    mutations: {
        $uStore(state, payload) {
            // 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
            let nameArr = payload.name.split('.');
            let saveKey = '';
            let len = nameArr.length;
            if (nameArr.length >= 2) {
                let obj = state[nameArr[0]];
                for (let i = 1; i < len - 1; i++) {
                    obj = obj[nameArr[i]];
                }
                obj[nameArr[len - 1]] = payload.value;
                saveKey = nameArr[0];
            } else {
                // 单层级变量,在state就是一个普通变量的情况
                state[payload.name] = payload.value;
                saveKey = payload.name;
            }
            // 保存变量到本地,见顶部函数定义
            saveLifeData(saveKey, state[saveKey])
        }
    }
    mutations: mutations,
    actions:actions
})
export default store
store/mutations.js
New file
@@ -0,0 +1,54 @@
import WxStorage from "../static/lib/wxStorage.js" //微信Storage
const mutations = {
    $uStore(state, payload) {
        // 判断是否多层级调用,state中为对象存在的情况,诸如user.info.score = 1
        let nameArr = payload.name.split('.');
        let saveKey = '';
        let len = nameArr.length;
        if (nameArr.length >= 2) {
            let obj = state[nameArr[0]];
            for (let i = 1; i < len - 1; i++) {
                obj = obj[nameArr[i]];
            }
            obj[nameArr[len - 1]] = payload.value;
            saveKey = nameArr[0];
        } else {
            // 单层级变量,在state就是一个普通变量的情况
            state[payload.name] = payload.value;
            saveKey = payload.name;
        }
        // 保存变量到本地,见顶部函数定义
        saveLifeData(saveKey, state[saveKey])
    },
    login(state, data) {
        // console.log(data);
        state.loging = data.isit; //登录状态
        if (data.isit) { //写入用户数据
            state.message.useName = data.userName;
            state.puserName = data.userName;
            state.puserID = data.userID;
            state.avatar = data.avatar;
        }
        //储存用户
        WxStorage.set("init", "true");
        WxStorage.set("name", data.userName);
        WxStorage.set("ids", data.userID);
        WxStorage.set("accounts", data.accounts);
        WxStorage.set("pass", data.pass);
    },
    loginReset(state) { //重置
        state.loging = false;
        state.message.useName = '过客 ';
        WxStorage.clear();
    },
    getUse(state,data){
        state.puserName = data.userName;
        state.puserID = data.userID;
    },
    getUserData(state,data){
        state.UserData = data;
    }
}
export default mutations