(五)、编辑页面-发布长文-富文本编辑【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,edit页面 1.1 新建edit页面 1.2 从本地相册选择图片或使用相机拍照。 uni.chooseImage(OBJECT) 1.3 直接上传文件到云存储。 uploadFile(Object object) 1.4 从富文本编辑器获取编辑器内容 editorContext.getContents(OBJECT) 首页富文本编辑器初始化完成时…...
你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式
你是真的“C”——【经典面试知识点】数据在内存中的大小端存储方式😎前言🙌大小端介绍🙌什么大端小端呢?:大小端存储的标准定义:大端和小端存在的意义经典的面试题目🙌总结撒花💞&a…...
从零开始的数模(二十六)单因素方差分析
目录 一、概念 1.1相关概念 1.2用途 1.3数据要求:独立性/正态性/方差齐性 1.4步骤 编辑1.5专业名词 二、基于python的单因素方差分析 2.2单因素方差分析的作用 一、概念 1.1相关概念 单因素方差分析是一种常用的统计分析方法,它用于比较一个因…...
C++变量类型
目录 一、c中的变量定义 二、c中的变量声明 三、c中的左值和右值 一、c中的变量定义 变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。 变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表,如下所示&…...
win10 安装 vs2015(社区版本)以及opencv-4.5.5
一、下载vs2015以及opencv-4.5.5从https://msdn.itellyou.cn/ 网站下载vs2015(社区版本)从https://opencv.org/releases/网站下载opencv-4.5.5二、安装vs2015和opencv-4.5.5解压后双击exe安装文件,完成安装(默认)双击下…...
867. 转置矩阵
给你一个二维整数数组 matrix, 返回 matrix 的 转置矩阵 。矩阵的 转置 是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。示例 1:输入:matrix [[1,2,3],[4,5,6],[7,8,9]]输出:[[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. …...
网友眼中越老越吃香的行业,果然是风向变了!
越老越吃香的行业,一直都是被热议的话题。对于年轻人来说,找到一个适合自己的并且具有前景的工作,不是一件容易的事情。 最近,看到有人在平台上问相关的问题,本着认真看一看的态度点进去,却差点被热评第一…...
为什么时间序列预测这么难?本文将给你答案
机器学习和深度学习已越来越多应用在时序预测中。ARIMA 或指数平滑等经典预测方法正在被 XGBoost、高斯过程或深度学习等机器学习回归算法所取代。 尽管时序模型越来越复杂,但人们对时序模型的性能表示怀疑。有研究表明,复杂的时序模型并不一定会比时序…...
STC15系列单片机通过串口多字节数据读写EEPROM操作
STC15系列单片机通过串口多字节数据读写EEPROM操作📌相关篇《STC15系列单片机EEPROM读写示例》 ⛳手册勘误信息注意事项 ⚡在手册上面描述STC15F2K60S2及STC15L2K60S2系列单片机内部EEPROM还可以用MOVC指令读,但此时首地址不再是0000H,而是程…...
计算机网络-ip数据报
在图中,网络层包含了四种协议:ARP、IP、ICMP、IGMP,由上下关系表明,ARP为IP协议服务,IP为ICMP和IGMP服务。 IP数据报格式 此处不区分数据报和分组的概念:当数据部分过长时,将数据部分拆分&…...
从零开始学C
以下是 该如何学习C语言的【思维导图】以及部分重点知识点的【博客链接】。其实C语言并不难,难的是没有人去教,没有耐心去学。不知道从哪下手学习,我将C的知识点做成一个思维导图,以供迷茫的小白参考,哪里不会…...
【云原生】手把手带你从零开始搭建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获取基础镜像 参数修改一下: cliOpt.ListAllPkgs true 结果中会带有如下格式的结果: "Results":[{"Target":"192.168.1.94:443/test22/centos:7 (centos 7.9.2009)","Clas…...
算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ
算法训练营 day48 动态规划 完全背包 零钱兑换 II 组合总和 Ⅳ 完全背包 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物…...
Java 基础(1)—泛型简单使用
一、泛型定义及作用 泛型是一种编程机制,允许在编写代码时使用参数化类型,以在编译时实现类型安全。 以下是泛型作用: 增强代码可读性和可维护性:通过在代码中使用泛型参数,可以使代码更清晰、更具有可读性和可维护性…...
内存卡损坏了怎么恢复?
内存卡损坏了怎么恢复?现在我们身边有不少电子设备都是用存储卡来存储数据的。一旦需要方便我们直接导出使用。但这存储的数据也不是一定安全的,当我们将内存卡连接到电脑时,难免会碰到病毒、格式化等提示,在这些情况下,可能会导…...
Mysql使用规范(纯技术和实战建议)
1、事务隔级别: (强制):Repeatable-Read(重复读),且不能在会话操作时临时开启隔离级别。 注: Repeatable-Read(重复读)隔离级别解决不了幻读。 可用 show variables l…...
Netty源码解读-EventLoop(二)
一、简介 NioEventLoop的重要组成:Selector、线程、任务队列,他既会处理io事件,也会处理普通任务和定时任务. 1.下面是Selector,注意有两个哦后面会讲 2.下面的爷爷类提供的Thread变量,其实下面发excutor用的就是这个…...
OSI模型详解
今天,我们详解OSI(Open System Inter-connection Reference Model)模型,来看看工业物联网的网络互联和数据互通。 OSI模型 1984年,国际标准化组织(International Organization for Standardization&#…...
从栅格到矢量:基于ArcScan的河道中心线智能提取与精度优化实践
1. 从栅格到矢量的技术背景 河道中心线提取是水文分析中的基础性工作。传统人工勾绘方式效率低下,一条10公里长的河道可能需要耗费专业人员半天时间。而基于ArcScan的自动化提取方法,能将这个时间缩短到10分钟以内,同时保证亚米级精度。 我在…...
10个无状态服务构建技巧:解锁gh_mirrors/awe/awesome-sre中的水平扩展最佳实践
10个无状态服务构建技巧:解锁gh_mirrors/awe/awesome-sre中的水平扩展最佳实践 【免费下载链接】awesome-sre A curated list of Site Reliability and Production Engineering resources. 项目地址: https://gitcode.com/gh_mirrors/awe/awesome-sre 在现代…...
先进制程EPE挑战:从系统误差到量测革命,如何驯服边缘位置误差
1. 从“理所当然”到“如履薄冰”:边缘位置误差如何成为先进制程的“隐形杀手”在半导体行业过去的黄金岁月里,工程师们有一个近乎奢侈的“共识”:芯片内部那些由光刻、刻蚀定义的特征边缘,可以被理所当然地看作是笔直且在不同工艺…...
告别导入报错!手把手教你用Navicat把Excel数据完美搬进MySQL(含字段超限处理)
从Excel到MySQL:Navicat数据迁移全流程实战指南 数据迁移是开发者和数据分析师日常工作中的高频需求。想象一下这样的场景:市场部门发来一份包含3000条客户信息的Excel表格,需要快速导入到测试环境的MySQL数据库中进行功能验证;或…...
AnyFlip下载器终极指南:3分钟快速将在线翻页书转为PDF
AnyFlip下载器终极指南:3分钟快速将在线翻页书转为PDF 【免费下载链接】anyflip-downloader Download anyflip books as PDF 项目地址: https://gitcode.com/gh_mirrors/an/anyflip-downloader 你是否在AnyFlip上发现了心仪的电子书,却苦于无法下…...
资本意志下的工程师生存指南:从高通裁员看技术与商业的博弈
1. 从一封信到四千七百张解雇单:当资本意志敲响工程师的门在科技行业,尤其是半导体这个以创新为生命线的领域,我们常常沉浸于晶体管密度、架构革新和制程竞赛的技术叙事中。然而,2015年夏天,一封来自华尔街的公开信&am…...
深度解析:libiec61850开源库如何解决电力系统通信的三大核心挑战
深度解析:libiec61850开源库如何解决电力系统通信的三大核心挑战 【免费下载链接】libiec61850 Official repository for libIEC61850, the open-source library for the IEC 61850 protocols 项目地址: https://gitcode.com/gh_mirrors/li/libiec61850 在电…...
5分钟快速上手Sonar CNES Report:让代码质量报告变得简单高效
5分钟快速上手Sonar CNES Report:让代码质量报告变得简单高效 【免费下载链接】sonar-cnes-report Generates analysis reports from SonarQube web API. 项目地址: https://gitcode.com/gh_mirrors/so/sonar-cnes-report 你是否经历过这样的场景?…...
手把手教你给天邑TY1608机顶盒刷机(S905L3B芯片,支持RTL8822CS/MT7668无线模块)
天邑TY1608机顶盒刷机全攻略:从零开始玩转S905L3B芯片 第一次拿到天邑TY1608机顶盒时,你可能被它原厂系统的各种限制所困扰——预装软件无法卸载、广告弹窗频繁出现、存储空间严重不足。这款搭载Amlogic S905L3B芯片的设备,配合RTL8822CS或MT…...
Swift原生大语言模型推理引擎llmfarm_core.swift集成与优化指南
1. 项目概述:一个为Swift生态打造的本地大语言模型推理引擎 最近在折腾一个iOS上的AI应用,想把一些轻量级的开源大语言模型(LLM)直接跑在手机端。大家都知道,现在主流的LLM推理框架,像llama.cpp、ollama&am…...
