(五)、编辑页面-发布长文-富文本编辑【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

导读:本篇文章讲解 (五)、编辑页面-发布长文-富文本编辑【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

1,edit页面

1.1 新建edit页面

在这里插入图片描述

1.2 从本地相册选择图片或使用相机拍照。

uni.chooseImage(OBJECT)

1.3 直接上传文件到云存储。

uploadFile(Object object)

1.4 从富文本编辑器获取编辑器内容

editorContext.getContents(OBJECT)

首页富文本编辑器初始化完成时,在 onEditReady()方法中通过uni.createSelectorQuery()获取富文本编辑器的上下文( this.editorCtx):

      //编辑器初始化完成时触发
      onEditReady() {
        uni.createSelectorQuery().in(this).select('.myEdit').fields({
          size: true,
          context: true
        }, res => {
          console.log(res)
          this.editorCtx = res.context
        }).exec()
      },

打印出的内容:
在这里插入图片描述

1.5 data中定义文章数据结构
        artObj: {
          title: "",//标题
          content: "",//内容
          description: "",//80字描述
          picurls: "",//图片
          province: ""//省份地址
        }
1.6 点击确认发布方法

点击确认按钮,首先获取富文本编辑器中的内容,然后赋值给artObj对象
具体代码:

      //点击提交按钮
      onSubmit() {
        this.editorCtx.getContents({
          success: res => {
            console.log(res)
            this.artObj.description = res.text.slice(0, 80);
            this.artObj.content = res.html;
            this.artObj.picurls = getImgSrc(res.html)
            uni.showLoading({
              title: "发布中..."
            })
            console.log(this.artObj)
            //this.addData();
          }
        })
      },
1.7 封装一个从html中获取image的方法

方法写在utils/tools.js中,然后使用进行引入。

//获取富文本内的图片url地址
export function getImgSrc(richtext, num = 3) {
  let imgList = [];
  richtext.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
    imgList.push(capture);
  });
  imgList = imgList.slice(0, num)
  return imgList;
}

注明:num是获取图片的数量。

1.8 封装一个利用高德地图ip的api获取省份地址的方法

需要注册高德web服务api高德web服务api
在这里插入图片描述

IP定位
P定位是一套简单的HTTP接口,根据用户输入的IP地址,能够快速的帮用户定位IP的所在位置。
在这里插入图片描述

//获取高德地图ip的api接口,通过ip获取所在地址省市
function getIp() {
  return new Promise((resolve, reject) => {
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=自己创建应用的对应key",
      success: res => {
        console.log("向高德地图发送网络请求,通过ip获取所在地址省市")
        console.log(res)
        let str = ""
        //处理ip不是国内ip时,返回的地址为自定义的火星地址
        typeof(res.data.province) == "string" ? str = res.data.province: str = "火星"
        resolve(str)
        let obj = {
          province: str,
          time: Date.now()
        }
        uni.setStorageSync("historyProvince", obj);
      },
      fail: err => {
        reject(err)
      }
    })
  })
}

两个重点:1,判断返回的省份地址数据类型如果是字符串,就赋值给str,如果不是字符串,省份地址用“火星”代替。
2,省份地址数据结构中加入当前日期信息,只允许在时间范围内发送网络请求(用此防止高频重复请求问题)。
在这里插入图片描述

//向外导出省份
export function getProvince() {
  return new Promise((resolve, reject) => {
    let historyProvince = uni.getStorageSync("historyProvince");
    //判读是否在本地缓存中有地址
    if (historyProvince) {
      //判断超过1天时间 ,重新发起网络请求
      if ((Date.now() - historyProvince.time) > 1000 * 10) {
        getIp().then(res => {
          console.log("重新网络请求")
          resolve(res)
        }).catch(err => {
          reject(err)
        })
      } else {
        console.log("直接从本地缓存中读取")
        resolve(historyProvince.province);
      }
    } else { //缓存中没存地址 调用发送网络请求的方法(返回的一个promise对象)
      getIp().then(res => {
        console.log("第一次网络请求")
        console.log(res)
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    }
  })
}

业务逻辑:首先判断本地缓存中是否存在省份地址数据,如果存在,再判断本地缓存中的数据日期是否在1天内,如果超过1天了,重新发送网络请求,如果没有超过1天,直接从本地缓存读取数据(减少发送网络请求的频次);缓存中没存地址 调用发送网络请求的方法,请求数据(返回的一个promise对象)。

在onload中调用方法:

    onLoad() {
      //获取省份地址 从高德api 通过ip地址
      getProvince().then(res => {
        this.artObj.province = res
      })
    },
1.4 完整代码
<template>
  <view class="edit">
    <!-- 文章标题 -->
    <view class="title">
      <input type="text" v-model="artObj.title" placeholder="请输入完整的标题" placeholder-class="placeholderClass">
    </view>
    <!-- 文章内容 -->
    <view class="content">
      <editor class="myEdit" placeholder="写点什么吧~~" show-img-size show-img-toolbar show-img-resize @focus="onFocus"
        @ready="onEditReady" @statuschange="onStatuschange"></editor>
    </view>
    <!-- 确认发布按钮 -->
    <view class="btnGroup">
      <u-button @click="onSubmit" type="primary" :disabled="!artObj.title.length" text="确认发表"></u-button>
    </view>
    <!-- 工具栏  富文本编辑器 -->
    <view class="tools" v-if="toolShow">
      <view class="item" @click="clickHead">
        <text class="iconfont icon-zitibiaoti" :class="headShow ? 'active' : ''"></text>
      </view>
      <view class="item" @click="clickBold">
        <text class="iconfont icon-zitijiacu" :class="boldShow ? 'active': ''"></text>
      </view>
      <view class="item" @click="clickItalic">
        <text class="iconfont icon-zitixieti" :class="italicShow ? 'active' : ''"></text>
      </view>
      <view class="item" @click="clickDivider"><text class="iconfont icon-fengexian"></text> </view>
      <view class="item" @click="clickInsertImage"><text class="iconfont icon-charutupian"></text> </view>
      <view class="item" @click="editOk"><text class="iconfont icon-duigou_kuai"></text> </view>
    </view>
  </view>
</template>

<script>
  import {
    getImgSrc,
    getProvince
  } from "@/utils/tools.js"
  const db = uniCloud.database()
  export default {
    data() {
      return {
        toolShow: false,
        headShow: false,
        boldShow: false,
        italicShow: false,
        artObj: {
          title: "",
          content: "",
          description: "",
          picurls: "",
          province: ""
        }
      };
    },
    onLoad() {
      //获取省份地址 从高德api 通过ip地址
      getProvince().then(res => {
        this.artObj.province = res
      })
    },
    methods: {
      //点击提交按钮
      onSubmit() {
        this.editorCtx.getContents({
          success: res => {
            console.log(res)
            this.artObj.description = res.text.slice(0, 80);
            this.artObj.content = res.html;
            this.artObj.picurls = getImgSrc(res.html)
            uni.showLoading({
              title: "发布中..."
            })
            console.log(this.artObj)
            this.addData();
          }
        })
      },
      //添加数据到云数据库quanzi_articles
      addData() {
        db.collection("quanzi_articles").add({
          ...this.artObj
        }).then(res => {
          uni.hideLoading();
          uni.showToast({
            title: "发布成功"
          })
          setTimeout(() => {
            uni.reLaunch({
              url: "/pages/index/index"
            })
          }, 800)
        })
      },
      //富文本标签中的初始化
      onEditReady() {
        uni.createSelectorQuery().in(this).select('.myEdit').fields({
          size: true,
          context: true
        }, res => {
          console.log(res)
          this.editorCtx = res.context
        }).exec()
      },
      //检查样式改变的状态
      checkStatus(name, detail, obj) {
        if (detail.hasOwnProperty(name)) {
          this[obj] = true;
        } else {
          this[obj] = false;
        }
      },
      // 当样式发生改变的时候
      onStatuschange(e) {
        let detail = e.detail
        this.checkStatus("header", detail, "headShow");
        this.checkStatus("bold", detail, "boldShow");
        this.checkStatus("italic", detail, "italicShow");
      },
      //添加图像
      clickInsertImage() {
        uni.chooseImage({
          success: async res => {
            uni.showLoading({
              title: "上传中请稍后",
              mask: true
            })
            for (let item of res.tempFiles) {
              let suffix = item.path.substring(item.path.lastIndexOf("."));
              let randomName = Date.now() + "" + String(Math.random()).substr(3, 6) + suffix
              let res = await uniCloud.uploadFile({
                filePath: item.path,
                cloudPath: item.name || randomName
              })
              this.editorCtx.insertImage({
                src: res.fileID
              })
            }
            uni.hideLoading()
          }
        })
      },
      //点击工具条的确认
      editOk() {
        this.toolShow = false;
      },
      //加粗
      clickBold() {
        this.boldShow = !this.boldShow
        this.editorCtx.format("bold")
      },
      //设置倾斜
      clickItalic() {
        this.italicShow = !this.italicShow;
        this.editorCtx.format("italic")
      },
      //添加大标题
      clickHead() {
        this.headShow = !this.headShow
        this.editorCtx.format("header", this.headShow ? 'H2' : false)
      },
      //添加分割线
      clickDivider() {
        this.editorCtx.insertDivider();
      },
      //离开焦点
      onFocus() {
        this.toolShow = true
      },
    }
  }
</script>

<style lang="scss">
  /deep/ .ql-blank::before {
    font-style: normal;
    color: #e0e0e0;
  }
  .edit {
    padding: 30rpx;
    .title {
      input {
        height: 120rpx;
        font-size: 46rpx;
        border-bottom: 1px solid #e4e4e4;
        margin-bottom: 30rpx;
        color: #000;
      }
      .placeholderClass {
        color: #e0e0e0;
      }
    }
    .content {
      .myEdit {
        height: calc(100vh - 500rpx);
        margin-bottom: 30rpx;
      }
    }
    .tools {
      width: 100%;
      height: 80rpx;
      background: #fff;
      border-top: 1rpx solid #f4f4f4;
      position: fixed;
      left: 0;
      bottom: 0;
      display: flex;
      justify-content: space-around;
      align-items: center;
      .iconfont {
        font-size: 36rpx;
        color: #333;
        &.active {
          color: #0199FE
        }
      }
    }
  }
</style>

2,工具类tools.js

//获取富文本内的图片url地址
export function getImgSrc(richtext, num = 3) {
  let imgList = [];
  richtext.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/g, (match, capture) => {
    imgList.push(capture);
  });
  imgList = imgList.slice(0, num)
  return imgList;
}

//向外导出省份
export function getProvince() {
  return new Promise((resolve, reject) => {
    let historyProvince = uni.getStorageSync("historyProvince");
    //判读是否在本地缓存中有地址
    if (historyProvince) {
      //判断超过1天时间 ,重新发起网络请求
      if ((Date.now() - historyProvince.time) > 1000 * 10) {
        getIp().then(res => {
          console.log("重新网络请求")
          resolve(res)
        }).catch(err => {
          reject(err)
        })
      } else {
        console.log("直接从本地缓存中读取")
        resolve(historyProvince.province);
      }
    } else { //缓存中没存地址 调用发送网络请求的方法(返回的一个promise对象)
      getIp().then(res => {
        console.log("第一次网络请求")
        console.log(res)
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    }
  })
}

//获取高德地图ip的api接口,通过ip获取所在地址省市
function getIp() {
  return new Promise((resolve, reject) => {
    uni.request({
      url: "https://restapi.amap.com/v3/ip?key=2eae11112968b53f162a109960d4efd1",
      success: res => {
        console.log("向高德地图发送网络请求,通过ip获取所在地址省市")
        console.log(res)
        let str = ""
        //处理ip不是国内ip时,返回的地址为自定义的火星地址
        typeof(res.data.province) == "string" ? str = res.data.province: str = "火星"
        resolve(str)
        let obj = {
          province: str,
          time: Date.now()
        }
        uni.setStorageSync("historyProvince", obj);
      },
      fail: err => {
        reject(err)
      }
    })
  })
}

//获取昵称
export function giveName(item) {
  return item.user_id[0].nickname || item.user_id[0].username || item.user_id[0].mobile || "请设置昵称"
}

//获取默认头像
export function giveAvatar(item) {
  return item.user_id[0]?.avatar_file?.url ?? '../../static/images/user-default.jpg'
}


const db = uniCloud.database();
const utilsObj = uniCloud.importObject("utilsObj", {
  customUI: true
});

//点赞操作数据库的方法
export async function likeFun(artid) {
  let count = await db.collection("quanzi_like")
    .where(`article_id=="${artid}" && user_id==$cloudEnv_uid`).count()
  if (count.result.total) {
    db.collection("quanzi_like").where(`article_id=="${artid}" && user_id==$cloudEnv_uid`)
      .remove();
    utilsObj.operation("quanzi_article", "like_count", artid, -1)

  } else {
    db.collection("quanzi_like").add({
      article_id: artid
    })
    utilsObj.operation("quanzi_article", "like_count", artid, 1)
  }
}

3,uniapp内置富文本编辑器edit组件的刨析

3.1 支持平台差异说明

在这里插入图片描述

3.2 属性

在这里插入图片描述

3.3 支持的标签

在这里插入图片描述

3.4 支持的内联样式

在这里插入图片描述

3.5 相关 api—editorContext

editor 组件对应的 editorContext 实例,可通过 uni.createSelectorQuery 获取

代码示例:

      //编辑器初始化完成时触发
      onEditReady() {
        uni.createSelectorQuery().in(this).select('.myEdit').fields({
          size: true,
          context: true
        }, res => {
          console.log(res)
          this.editorCtx = res.context
        }).exec()
      },
3.6 节点参数说明

在这里插入图片描述

4,edit页面效果

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/135738.html

(0)

相关推荐

发表回复

登录后才能评论
半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!