当前位置: 首页 > news >正文

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

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_articlesaddData() {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.detailthis.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) + suffixlet 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.boldShowthis.editorCtx.format("bold")},//设置倾斜clickItalic() {this.italicShow = !this.italicShow;this.editorCtx.format("italic")},//添加大标题clickHead() {this.headShow = !this.headShowthis.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页面效果

在这里插入图片描述

相关文章:

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

1&#xff0c;edit页面 1.1 新建edit页面 1.2 从本地相册选择图片或使用相机拍照。 uni.chooseImage(OBJECT) 1.3 直接上传文件到云存储。 uploadFile(Object object) 1.4 从富文本编辑器获取编辑器内容 editorContext.getContents(OBJECT) 首页富文本编辑器初始化完成时…...

你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式

你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式&#x1f60e;前言&#x1f64c;大小端介绍&#x1f64c;什么大端小端呢&#xff1f;&#xff1a;大小端存储的标准定义&#xff1a;大端和小端存在的意义经典的面试题目&#x1f64c;总结撒花&#x1f49e;&a…...

从零开始的数模(二十六)单因素方差分析

目录 一、概念 1.1相关概念 1.2用途 1.3数据要求&#xff1a;独立性/正态性/方差齐性 1.4步骤 ​编辑1.5专业名词 二、基于python的单因素方差分析 2.2单因素方差分析的作用 一、概念 1.1相关概念 单因素方差分析是一种常用的统计分析方法&#xff0c;它用于比较一个因…...

C++变量类型

目录 一、c中的变量定义 二、c中的变量声明 三、c中的左值和右值 一、c中的变量定义 变量定义就是告诉编译器在何处创建变量的存储&#xff0c;以及如何创建变量的存储。 变量定义指定一个数据类型&#xff0c;并包含了该类型的一个或多个变量的列表&#xff0c;如下所示&…...

win10 安装 vs2015(社区版本)以及opencv-4.5.5

一、下载vs2015以及opencv-4.5.5从https://msdn.itellyou.cn/ 网站下载vs2015&#xff08;社区版本&#xff09;从https://opencv.org/releases/网站下载opencv-4.5.5二、安装vs2015和opencv-4.5.5解压后双击exe安装文件&#xff0c;完成安装&#xff08;默认&#xff09;双击下…...

867. 转置矩阵

给你一个二维整数数组 matrix&#xff0c; 返回 matrix 的 转置矩阵 。矩阵的 转置 是指将矩阵的主对角线翻转&#xff0c;交换矩阵的行索引与列索引。示例 1&#xff1a;输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]]输出&#xff1a;[[1,4,7],[2,5,8],[3,6,9]]示例 2&a…...

Datawahle组队学习——妙趣横生大数据 Day1

妙趣横生大数据 Day1[妙趣横生大数据 Juicy Big Data](https://datawhalechina.github.io/juicy-bigdata/#/?id妙趣横生大数据-juicy-big-data)一、大数据概述大数据——第三次信息化浪潮大数据概念大数据应用大数据关键技术二、Hadoop背景介绍特性项目架构实验1. 准备工作2. …...

网友眼中越老越吃香的行业,果然是风向变了!

越老越吃香的行业&#xff0c;一直都是被热议的话题。对于年轻人来说&#xff0c;找到一个适合自己的并且具有前景的工作&#xff0c;不是一件容易的事情。 最近&#xff0c;看到有人在平台上问相关的问题&#xff0c;本着认真看一看的态度点进去&#xff0c;却差点被热评第一…...

为什么时间序列预测这么难?本文将给你答案

机器学习和深度学习已越来越多应用在时序预测中。ARIMA 或指数平滑等经典预测方法正在被 XGBoost、高斯过程或深度学习等机器学习回归算法所取代。 尽管时序模型越来越复杂&#xff0c;但人们对时序模型的性能表示怀疑。有研究表明&#xff0c;复杂的时序模型并不一定会比时序…...

STC15系列单片机通过串口多字节数据读写EEPROM操作

STC15系列单片机通过串口多字节数据读写EEPROM操作&#x1f4cc;相关篇《STC15系列单片机EEPROM读写示例》 ⛳手册勘误信息注意事项 ⚡在手册上面描述STC15F2K60S2及STC15L2K60S2系列单片机内部EEPROM还可以用MOVC指令读&#xff0c;但此时首地址不再是0000H&#xff0c;而是程…...

计算机网络-ip数据报

在图中&#xff0c;网络层包含了四种协议&#xff1a;ARP、IP、ICMP、IGMP&#xff0c;由上下关系表明&#xff0c;ARP为IP协议服务&#xff0c;IP为ICMP和IGMP服务。 IP数据报格式 此处不区分数据报和分组的概念&#xff1a;当数据部分过长时&#xff0c;将数据部分拆分&…...

从零开始学C

以下是 该如何学习C语言的【思维导图】以及部分重点知识点的【博客链接】。其实C语言并不难&#xff0c;难的是没有人去教&#xff0c;没有耐心去学。不知道从哪下手学习&#xff0c;我将C的知识点做成一个思维导图&#xff0c;以供迷茫的小白参考&#xff0c;哪里不会&#xf…...

【云原生】手把手带你从零开始搭建kubernetes最新版本实战

文章目录前言一. 实验环境二. k8s 的介绍三 . k8s的安装3.1 搭建实验环境3.1.1 硬件层面的要求3.1.2 软件层面环境配置3.2 docker的安装3.2.1 搭建docker3.2.2 部署 cri-dockerd3.3 部署k8s3.3.1 配置添加阿里云的yum源3.3.2 安装kubeadm kubelet kubectl3.3.3 k8s-master节点初…...

trivy os软件包扫描原理分析

具体可以基于之前的博客来做 基于trivy获取基础镜像 参数修改一下&#xff1a; cliOpt.ListAllPkgs true 结果中会带有如下格式的结果&#xff1a; "Results":[{"Target":"192.168.1.94:443/test22/centos:7 (centos 7.9.2009)","Clas…...

算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ

算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物…...

Java 基础(1)—泛型简单使用

一、泛型定义及作用 泛型是一种编程机制&#xff0c;允许在编写代码时使用参数化类型&#xff0c;以在编译时实现类型安全。 以下是泛型作用&#xff1a; 增强代码可读性和可维护性&#xff1a;通过在代码中使用泛型参数&#xff0c;可以使代码更清晰、更具有可读性和可维护性…...

内存卡损坏了怎么恢复?

内存卡损坏了怎么恢复?现在我们身边有不少电子设备都是用存储卡来存储数据的。一旦需要方便我们直接导出使用。但这存储的数据也不是一定安全的&#xff0c;当我们将内存卡连接到电脑时&#xff0c;难免会碰到病毒、格式化等提示&#xff0c;在这些情况下&#xff0c;可能会导…...

Mysql使用规范(纯技术和实战建议)

1、事务隔级别: &#xff08;强制&#xff09;&#xff1a;Repeatable-Read&#xff08;重复读&#xff09;&#xff0c;且不能在会话操作时临时开启隔离级别。 注&#xff1a; Repeatable-Read&#xff08;重复读&#xff09;隔离级别解决不了幻读。 可用 show variables l…...

Netty源码解读-EventLoop(二)

一、简介 NioEventLoop的重要组成&#xff1a;Selector、线程、任务队列&#xff0c;他既会处理io事件&#xff0c;也会处理普通任务和定时任务. 1.下面是Selector&#xff0c;注意有两个哦后面会讲 2.下面的爷爷类提供的Thread变量&#xff0c;其实下面发excutor用的就是这个…...

OSI模型详解

今天&#xff0c;我们详解OSI&#xff08;Open System Inter-connection Reference Model&#xff09;模型&#xff0c;来看看工业物联网的网络互联和数据互通。 OSI模型 1984年&#xff0c;国际标准化组织&#xff08;International Organization for Standardization&#…...

Share Creators完成500万美元融资,以工具化手段帮助企业从数字资产管理中解放

近日&#xff0c;总部位于旧金山湾区的初创公司Share Creators宣布完成了新一轮500万美元的融资&#xff0c;投资方为五源资本和福昕PDF。本轮融资主要用于扩大客户基础&#xff0c;并加速在美国、欧洲和亚洲的业务发展。近几年&#xff0c;企业内容及数字资产管理全球市场正在…...

几个Base64编码工具,也有蹊跷

起因 需求&#xff1a;对一段内容进行base64加密&#xff0c;然后通过url的get请求进行发送到后台&#xff0c;由于加密的内容比较少&#xff0c;base64串也不是很长&#xff0c;我认为此方案可行。 于是找了三个base64编码的在线工具&#xff0c;分别是&#xff1a; 平台1&…...

Python|每日一练|排序|递归|字符串|数组|动态规划|单选记录:以特殊格式处理连续增加的数字|正则表达式匹配|地下城游戏

1、以特殊格式处理连续增加的数字&#xff08;排序&#xff09; 贡献者&#xff1a;EricLao 给出一串数字&#xff0c; 程序要把数字按照这样的格式输出&#xff0c;把连续增加的数字用 [x-y] 的形式表示&#xff0c;只显示这一组顺序数字的首位两个数字&#xff0c;不连续增…...

Spring Cloud微服务网关Gateway组件

目录 网关简介 什么是Spring Cloud Gateway Spring Cloud Gateway 功能特征 核心概念 工作原理 Spring Cloud Gateway快速开始 环境搭建 集成Nacos 路由断言工厂&#xff08;Route Predicate Factories&#xff09;配置 自定义路由断言工厂 过滤器工厂&#xff08; …...

cluster nodes(集群节点)

CLUSTER NODES 复制 自3.0.0起可用。 时间复杂度&#xff1a; O&#xff08;N&#xff09;其中N是 Cluster 节点的总数 Redis 集群中的每个节点都有其当前集群配置的视图&#xff0c;由已知节点的集合给出&#xff0c;我们与这些节点的连接状态&#xff0c;它们的标志&…...

【Android学习】下载jar慢和gradle慢的情况

目录 问题出现的原因 解决方法 解决Gradle下载问题&#xff1a;手动安装 解决jar包下载慢问题&#xff1a;更改下载源 问题出现的原因 国内访问谷歌被墙导致访问速度慢或者干脆无法下载 解决方法 解决Gradle下载问题&#xff1a;手动安装 访问官网Gradle | Release Candi…...

下一个排列-力扣31-java

一、题目描述整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。例如&#xff0c;arr [1,2,3] &#xff0c;以下这些都可以视作 arr 的排列&#xff1a;[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。整数数组的 下一个排列 是指其整数的下一个字典序更大的排列。更正式地&…...

前端面试题

1.HTTP request报文结构是怎样的 1.首行是Request-Line包括&#xff1a;请求方法&#xff0c;请求URI&#xff0c;协议版本&#xff0c;CRLF&#xff08;换行符&#xff09; 2.首行之后是若干行请求头&#xff0c;包括general-header&#xff0c;request-header或者entity-hea…...

jsp游戏门户网站系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 jsp 游戏门户网站系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql&#xff0c;使…...

Git与IDEA强强联合(HTTPS协议连接)

最近在写项目的时候&#xff0c;在台式机和笔记本之间频繁切换&#xff0c;竟然还是用qq传压缩包&#xff0c;我自己都感觉无语&#xff0c;有git这样强大的版本管理工具&#xff0c;我竟然没想起来。然后也没有相关的博文就想来更新一篇。 那么如何使idea和git强强联合呢&…...