uniapp富文本editor输入二次扩展兼容微信小程序

news2024/9/20 20:31:39

在uni-app中开发富文本输入功能,并使其兼容微信小程序,需要注意一些特定的限制和解决方案。由于微信小程序本身对HTML的支持有限,直接在小程序中实现像Web那样完整的富文本编辑功能(如使用CKEditor、Quill等)是不可能的。但你可以通过一些方法来实现基本的富文本输入或近似功能。

富文本编辑器,可以对图片、文字格式进行编辑和混排。

在web开发时,可以使用contenteditable来实现内容编辑。但这是一个dom API,在非H5平台无法使用。于是微信小程序和uni-app的App-vue提供了editor组件来实现这个功能,并且在uni-app的H5平台也提供了兼容。从技术本质来讲,这个组件仍然运行在视图层webview中,利用的也是浏览器的contenteditable功能。

编辑器导出内容支持带标签的 html和纯文本的 text,编辑器内部采用 delta 格式进行存储。

通过setContents接口设置内容时,解析插入的 html 可能会由于一些非法标签导致解析错误,建议开发者在应用内使用时通过 delta 进行插入。

组件扩展

<template>
	<view class="diygw-col-24">
		<view :style="{height:height}" class='flex  flex-direction-column wrapper'>
			<view class='toolbar' @tap="format">
				<view v-if="tools.indexOf('undo')>-1" class="iconfont icon-undo" @tap="undo"></view>
				<view v-if="tools.indexOf('redo')>-1" class="iconfont icon-redo" @tap="redo"></view>
				<view v-if="tools.indexOf('bold')>-1" :class="formats.bold ? 'ql-active' : ''" class="iconfont icon-zitijiacu" data-name="bold"></view>
				<view v-if="tools.indexOf('italic')>-1" :class="formats.italic ? 'ql-active' : ''" class="iconfont icon-zitixieti" data-name="italic"></view>
				<view v-if="tools.indexOf('underline')>-1" :class="formats.underline ? 'ql-active' : ''" class="iconfont icon-zitixiahuaxian" data-name="underline"></view>
				<view v-if="tools.indexOf('strike')>-1" :class="formats.strike ? 'ql-active' : ''" class="iconfont icon-zitishanchuxian" data-name="strike"></view>
				<view v-if="tools.indexOf('align-left')>-1" :class="formats.align === 'left' ? 'ql-active' : ''" class="iconfont icon-zuoduiqi" data-name="align" data-value="left"></view>
				<view v-if="tools.indexOf('align-center')>-1" :class="formats.align === 'center' ? 'ql-active' : ''" class="iconfont icon-juzhongduiqi" data-name="align" data-value="center"></view>
				<view v-if="tools.indexOf('align-right')>-1" :class="formats.align === 'right' ? 'ql-active' : ''" class="iconfont icon-youduiqi" data-name="align" data-value="right"></view>
				<view v-if="tools.indexOf('align-justify')>-1" :class="formats.align === 'justify' ? 'ql-active' : ''" class="iconfont icon-zuoyouduiqi" data-name="align" data-value="justify"></view>
				<view v-if="tools.indexOf('lineHeight')>-1" :class="formats.lineHeight ? 'ql-active' : ''" class="iconfont icon-line-height" data-name="lineHeight" data-value="2"></view>
				<view v-if="tools.indexOf('letterSpacing')>-1" :class="formats.letterSpacing ? 'ql-active' : ''" class="iconfont icon-Character-Spacing" data-name="letterSpacing" data-value="2em"></view>
				<view v-if="tools.indexOf('marginTop')>-1" :class="formats.marginTop ? 'ql-active' : ''" class="iconfont icon-722bianjiqi_duanqianju" data-name="marginTop" data-value="20px"></view>
				<view v-if="tools.indexOf('previewarginBottom')>-1" :class="formats.previewarginBottom ? 'ql-active' : ''" class="iconfont icon-723bianjiqi_duanhouju" data-name="marginBottom" data-value="20px"></view>
				<view v-if="tools.indexOf('removeFormat')>-1" class="iconfont icon-clearedformat" @tap="removeFormat"></view>
				<view v-if="tools.indexOf('fontFamily')>-1" :class="formats.fontFamily ? 'ql-active' : ''" class="iconfont icon-font" data-name="fontFamily" data-value="仿宋, 仿宋_GB2312"></view>
			
				<!-- <picker v-if="tools.indexOf('fontSize')>-1" :range="fontSizelist" @change="formatsChange" @tap.stop="formatsChange" data-name="size" class="iconfont icon-fontsize" :class="formats.size? ' ql-active' : ''"></picker> -->
				<picker v-if="tools.indexOf('fontSize')>-1" range-key="name" :range="fontSizelist" @change="formatsChange" @tap.stop="formatsChange" data-name="fontSize" class="iconfont icon-fontsize" :class="formats.fontSize? ' ql-active' : ''"></picker>
				<!-- <view v-if="tools.indexOf('fontSize')>-1" :class="formats.fontSize === '24px' ? 'ql-active' : ''" class="iconfont icon-fontsize" data-name="fontSize" data-value="24px"></view> -->
				<view v-if="tools.indexOf('color')>-1" :style="(formats.color != '#FFFFFF'&&formats.color != '#fff'&&formats.color != '#ffffff')? 'color:' + formats.color : ''" class="iconfont icon-text_color" data-name="color" @tap.stop="openColor"></view>
				<view v-if="tools.indexOf('backgroundColor')>-1" :style="(formats.backgroundColor != '#FFFFFF'&&formats.backgroundColor != '#fff'&&formats.backgroundColor != '#ffffff') ? 'color:' + formats.backgroundColor : ''" class="iconfont icon-fontbgcolor" data-name="backgroundColor" @tap.stop="openColor"></view>

				<view v-if="tools.indexOf('insertDate')>-1" class="iconfont icon-date" @tap="insertDate"></view>
				<view v-if="tools.indexOf('list')>-1" class="iconfont icon--checklist" data-name="list" data-value="check"></view>
				<view v-if="tools.indexOf('ordered')>-1" :class="formats.list === 'ordered' ? 'ql-active' : ''" class="iconfont icon-youxupailie" data-name="list" data-value="ordered"></view>
				<view v-if="tools.indexOf('bullet')>-1" :class="formats.list === 'bullet' ? 'ql-active' : ''" class="iconfont icon-wuxupailie" data-name="list" data-value="bullet"></view>
				
				<view v-if="tools.indexOf('indent-reduce')>-1" class="iconfont icon-outdent" data-name="indent" data-value="-1"></view>
				<view v-if="tools.indexOf('indent-add')>-1" class="iconfont icon-indent" data-name="indent" data-value="+1"></view>
				<view v-if="tools.indexOf('insert-divider')>-1" class="iconfont icon-fengexian" @tap="insertDivider"></view>
				<view v-if="tools.indexOf('insert-image')>-1" class="iconfont icon-charutupian" @tap="selectImage"></view>
				<picker v-if="tools.indexOf('header')>-1" :range="headerlist" @change="formatsChange" @tap.stop="formatsChange" data-name="header" :class="'iconfont icon-format-header-'+(headerindex==0?1:headerindex)+(formats.header? ' ql-active' : '')"></picker>
				<!-- <view v-if="tools.indexOf('header')>-1" :class="formats.header === 1 ? 'ql-active' : ''" class="iconfont icon-format-header-1" data-name="header" :data-value="3"></view> -->
				<view v-if="tools.indexOf('script-sub')>-1" :class="formats.script === 'sub' ? 'ql-active' : ''" class="iconfont icon-zitixiabiao" data-name="script" data-value="sub"></view>
				<view v-if="tools.indexOf('script-super')>-1" :class="formats.script === 'super' ? 'ql-active' : ''" class="iconfont icon-zitishangbiao" data-name="script" data-value="super"></view>
				<view v-if="tools.indexOf('direction')>-1" :class="formats.direction === 'rtl' ? 'ql-active' : ''" class="iconfont icon-direction-rtl" data-name="direction" data-value="rtl"></view>
				<view v-if="tools.indexOf('clear')>-1" class="iconfont icon-shanchu" @tap="clear"></view>
			
			</view>
			<view class="flex-sub editor-wrapper">
				<editor id="editor" class="ql-container" :placeholder="placeholder" showImgSize showImgToolbar showImgResize @statuschange="onStatusChange" :read-only="readOnly" @ready="onEditorReady" @input="editorChange">
				</editor>
			</view>
		</view>
		<block v-if="modal.show">
			<view class="mask" />
			<view class="modal">
				<view class="modal_title">{{modal.title}}</view>
				<input type="text" class="modal_input" v-model="modal.value" />
				<view class="modal_foot">
					<view class="modal_button" @tap="modalCancel">取消</view>
					<view class="modal_button" style="color:#576b95;border-left:1px solid rgba(0,0,0,.1)" @tap="modalConfirm">确定</view>
				</view>
			</view>
		</block>
		<diy-color-picker v-model="showColorPicker" :hexcolor="hexcolor" @confirm="getColor"></diy-color-picker>
	</view>
</template>

<script>
	import Emitter from "../../libs/util/emitter.js";
	
	export default {
		mixins: [Emitter],
		emits: ["update:modelValue", "change"],
		props: {
			value: {
				type: String
			},
			modelValue:{
				type: String
			},
			placeholder: {
				type: String,
				default: '开始输入...'
			},
			height:{
				type:String,
				default: '100vh'
			},
			tools: {
				type: Array,
				default: function() {
					return [
						'bold',
						'italic',
						'underline',
						'strike',
						'align-left',
						'align-center',
						'align-right',
						'align-justify',
						'lineHeight',
						'letterSpacing',
						'marginTop',
						'previewarginBottom',
						'removeFormat',
						'fontFamily',
						'fontSize',
						'color',
						'backgroundColor',
						'insertDate',
						'list',
						'ordered',
						'bullet',
						'redo',
						'undo',
						'indent-reduce',
						'indent-add',
						'insert-divider',
						'insert-image',
						'header',
						'script-sub',
						'script-super',
						'clear',
						'direction'
					];
				}
			},
			//上传图片
			action:{
				type:String,
				default: '/sys/storage/upload'
			}/*,
			uploadFile: {
				type: Function
			}*/
		},
		data() {
			return {
				modal: {
					show: false,
					title: '',
					value: ''
				},
				showColorPicker:false,
				html: '',
				fontSizelist: [{
					code: "",
					name: "默认"
				}, {
					code: "x-small",
					name: "超小"
				}, {
					code: "small",
					name: "小"
				}, {
					code: "medium",
					name: "中等"
				}, {
					code: "large",
					name: "大"
				}, {
					code: "x-large",
					name: "超大"
				}, {
					code: "xx-large",
					name: "超级大"
				}],
				headerlist: ['默认', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6'],
				headerindex: 0,
				colorPickerName: '',
				hexcolor: "#0000ff",
				readOnly: false,
				formats: {},
				update: 0,
				uForm:{
					inputAlign: "",
					clearable: ""
				}
			}
		},
		watch: {
			value: function(newval) {
				this.html = newval
			},
			modelValue: function(newval) {
				this.html = newval
			},
			html: function(newvar) {
				if (this.editorCtx) {
					if (this.update == 0) {
						this.editorCtx.setContents({
							html: this.html
						});
					} else {
						this.update = 0
					}
				}
			}
		},
		created() {
			this.html = this.value;
		},
		mounted() {
			let parent = this.$u.$parent.call(this, 'u-form');
			if (parent) {
				Object.keys(this.uForm).map(key => {
					this.uForm[key] = parent[key];
				});
			}
		},
		methods: {
			openColor(e) {
				let dataset = e.target.dataset
				this.colorPickerName = dataset.name;
				this.hexcolor = dataset.value;
				this.showColorPicker = true
				// this.$refs.colorPicker.open();
			},
			getColor(e) {
				let msg = '';
				switch (this.colorPickerName) {
					case 'backgroundColor':
						if (e.hex.toUpperCase() == '#FFFFFF') {
							e.hex = '';
						}
						msg = '背景色';
						break;
					case 'color':
						msg = '颜色';
						break;
				}
				this.setformat(this.colorPickerName, e.hex, msg + e.hex);
			},

			modalConfirm() {
				let src = this.modal.value || '';
				if (src) {
					this.insertImage(src, null, null)
				}
				this.modal.show = false;
			},
			modalCancel() {
				this.modal.show = false;
			},

			formatsChange(e) {
				if (e.type == 'click') { //不让上层触发点击事件
					return false;
				}

				let value = e.detail.value;
				let name = e.target.dataset.name
				if (name == 'header') {
					this.headerindex = value;
					if (value == 0) {
						value = null;
					}
				} else if (name == 'fontSize') {
					value = this.fontSizelist[value].code;
				} else if (name == 'size') {
					value = value > 0 ? value : 1;
				}
				let msg = name + '设置成功';
				console.log(value);
				this.setformat(name, value, msg)
				return false;
			},
			editorChange(e) {
				this.update = 1
				this.$emit('input', e.detail.html);
				
				this.$emit("update:modelValue", e.detail.html);
				
				// vue 原生的方法 return 出去
				this.$emit("change", e.detail.html);
				// 将当前的值发送到 u-form-item 进行校验
				this.dispatch("u-form-item", "onFieldBlur", e.detail.html);
			},
			readOnlyChange() {
				this.readOnly = !this.readOnly
			},
			onEditorReady() {
				const query = uni.createSelectorQuery().in(this);
				query.select('#editor').context((res) => {
					this.editorCtx = res.context
					if (this.html) {
						this.editorCtx.setContents({
							html: this.html
						});
					}
				}).exec()
			},
			undo() {
				this.editorCtx.undo()
			},
			redo() {
				this.editorCtx.redo()
			},
			format(e) {
				let {
					name,
					value
				} = e.target.dataset
				if (!name) return
				// console.log('format', name, value)
				this.editorCtx.format(name, value)

			},
			setformat(name, value, msg) {
				this.editorCtx.format(name, value);
				// this.toast(msg);
			},
			toast(msg) {
				uni.showToast({
					duration: 600,
					icon: 'none',
					title: msg
				});
			},
			onStatusChange(e) {
				const formats = e.detail
				this.formats = formats
			},
			insertDivider() {
				this.editorCtx.insertDivider({
					success: function() {
						console.log('insert divider success')
					}
				})
			},
			clear() {
				uni.showModal({
					content: "确定清空编辑器内容?",
					complete: (rs) => {
						if (rs.confirm) {
							this.editorCtx.clear({
								success: function(res) {
									console.log("clear success")
								}
							})
						}
					}
				})
			},
			removeFormat() {
				this.editorCtx.removeFormat()
			},
			insertDate() {
				const date = new Date()
				let month = date.getMonth() + 1
				if(month<10){
					month = "0" +month
				}
				let day = date.getDate()
				if(day<10){
					day = "0" + day
				}
				const formatDate = `${date.getFullYear()}-${month}-${day}`
				this.editorCtx.insertText({
					text: formatDate
				})
			},
			selectImage() {
				let thiz = this
				// 本地选取 自已处理上传方法,包括选择文件
				uni.chooseImage({
					count: 9,
					sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
					sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有javascript:;
					success: function (res) {
						// 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
						let tempFilePaths = res.tempFilePaths;
						for (let i = 0; i < tempFilePaths.length; i++) {
							let header = {}
							if(getApp().globalData.currentPage && getApp().globalData.currentPage.$session){
								header.Authorization =  getApp().globalData.currentPage.$session.getToken()||''
							}
							uni.uploadFile({
								url: getApp().globalData.currentPage && getApp().globalData.currentPage.$http?getApp().globalData.currentPage.$http.setUrl(thiz.action,{}):thiz.action,
								filePath: tempFilePaths[i],
								name: 'file',
								header:header,
								success(res) {
									let data = getApp().globalData.currentPage.$tools.fromJson(res.data);
									let url = ''
									if(data.url){
										url = getApp().globalData.currentPage.$tools.renderImage(data.url);
									}
									if(data.data &&getApp().globalData.currentPage.$tools.isObject(data.data) && data.data.url){
										url = getApp().globalData.currentPage.$tools.renderImage(data.data.url);
									}
									if(url){
										thiz.insertImage(url,null,null);
									}
								}
							});
						}
					},
				});
				// uni.showActionSheet({
				// 	itemList: ['本地选取', '远程链接'],
				// 	success: res => {
				// 		if (res.tapIndex === 0) {
							
				// 		} else {
				// 			thiz.modal = {
				// 				show: true,
				// 				title: '图片链接',
				// 				value: ''
				// 			}
				// 		}
				// 	}
				// })
			},
			insertImage(src, data, alt) {
				debugger
				let inserdata = {
					src: src
				}
				if (data) {
					inserdata.data = data
				}
				if (alt) {
					inserdata.alt = alt
				}
				this.editorCtx.insertImage({
					...inserdata,
					success: function() {
						console.log('insert image success')
					}
				})
			}
		}
	}
</script>

<style>
	@import "./editor-icon.css";

	.container {
		width: 100%;
	}

	.wrapper {
		width: 100%;
	}

	.editor-wrapper {
		width: 100%;
		background: #fff;
	}

	.iconfont {
		display: inline-block;
		padding: 8px 8px;
		cursor: pointer;
		font-size: 25px;
	}

	.toolbar {
		box-sizing: border-box;
		border-bottom: 0;
		font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
	}

	.ql-container {
		box-sizing: border-box;
		padding: 10px;
		width: 100%;
		min-height: 30vh;
		height: 100%;
		font-size: 16px;
		line-height: 1.5;
	}

	.ql-active {
		color: #06c;
	}

	/* 模态框 */
	.modal {
		position: fixed;
		z-index: 999999;
		top: 50%;
		left: 16px;
		right: 16px;
		background-color: #fff;
		border-radius: 12px;
		transform: translateY(-50%);
	}

	.modal_title {
		padding: 32px 24px 16px;
		font-size: 17px;
		font-weight: 700;
		text-align: center;
	}

	.modal_input {
		display: block;
		padding: 5px;
		line-height: 2.5em;
		height: 2.5em;
		margin: 0 24px 32px 24px;
		font-size: 14px;
		border: 1px solid #dfe2e5;
	}

	.modal_foot {
		display: flex;
		line-height: 56px;
		font-weight: 700;
		border-top: 1px solid rgba(0, 0, 0, .1);
	}

	.modal_button {
		flex: 1;
		text-align: center;
	}

	/* 遮罩版 */
	.mask {
		position: fixed;
		z-index: 99999;
		top: 0;
		right: 0;
		bottom: 0;
		left: 0;
		background-color: black;
		opacity: 0.5;
	}
</style>

组件调用

<template>
	<view class="container container329152">
		<u-form-item :borderBottom="false" class="diygw-col-24" labelPosition="top" prop="editor">
			<diy-editor height="500px" v-model="editor"></diy-editor>
		</u-form-item>
		<view class="clearfix"></view>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				//用户全局信息
				userInfo: {},
				//页面传参
				globalOption: {},
				//自定义全局变量
				globalData: {},
				editor: ''
			};
		},
		onShow() {
			this.setCurrentPage(this);
		},
		onLoad(option) {
			this.setCurrentPage(this);
			if (option) {
				this.setData({
					globalOption: this.getOption(option)
				});
			}

			this.init();
		},
		methods: {
			async init() {},
			// 新增方法 自定义方法
			async testFunction(param) {
				let thiz = this;
				console.log(this.checkbox);
			}
		}
	};
</script>

<style lang="scss" scoped>
	.container329152 {
	}
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2145025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法笔记/USACO Guide GOLD金组DP 3. Paths on Grids

今天学习背包DP&#xff08;Knapsack DP) 是USACO Guide的DP章节中第三点 What is grid DP? -Summary DP problems often involve a 2D grid where paths are analyzed. Movement is restricted to one direction on the x-axis and y-axis, typically starting from one c…

AI修手有救了?在comfyui中使用Flux模型实现局部重绘案例

&#x1f431;‍&#x1f409;背景 局部重绘相关的话题我们已经讨论和测试过很多次了&#xff0c;比如说inpaint模型、brushnet模型、powerpaint模型等等&#xff0c;最近对于flux模型重绘画面的案例也越来越多了&#xff0c;那我们就结合flux模型的重绘来试试看效果。 &…

体验几款AI论文写作工具后,我认为这个最值得尝试!

开学随之而来的论文写作肯定又让你头疼了吧&#xff0c;而现如今随着AI技术的飞快发展&#xff0c;许多人巧妙地借助AI论文辅助工具&#xff0c;迅速搭建起论文的基本框架&#xff0c;然后一键生成万字正文内容&#xff0c;准确获得大量文献引用&#xff0c;使得整个论文创作过…

[深度学习]Pytorch框架

1 深度学习简介 应用领域&#xff1a;语音交互、文本处理、计算机视觉、深度学习、人机交互、知识图谱、分析处理、问题求解 2 发展历史 1956年人工智能元年2016年国内开始关注深度学习2017年出现Transformer框架2018年Bert和GPT出现2022年&#xff0c;chatGPT出现&#xff0…

基于python+django+vue的美术馆预约系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于协同过滤pythondjangovue…

WSL中使用AMBER GPU串行版

前提是已经安装过wsl 1 在 WSL 2 中启用 NVIDIA CUDA 参考在 WSL 2 上启用 NVIDIA CUDA | Microsoft Learn 注意&#xff1a;勿在 WSL 中安装任何 Linux 显示驱动程序。Windows 显示驱动程序将同时安装本机 Windows 和 WSL 支持的常规驱动程序组件。 2 在WSL2中配置Cuda 不安…

SEO之页面优化(一-页面标题2)

初创企业搭建网站的朋友看1号文章&#xff1b;想学习云计算&#xff0c;怎么入门看2号文章谢谢支持&#xff1a; 1、我给不会敲代码又想搭建网站的人建议 2、“新手上云”能够为你开启探索云世界的第一步 博客&#xff1a;阿幸SEO~探索搜索排名之道 &#xff08;接上一篇。。…

OpenCV_最简单的鼠标截取ROI区域

在OpenCV中也存在鼠标的操作&#xff0c;今天我们先介绍一下鼠标中的操作事件 void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata0) setMousecallback参数说明&#xff1a; winname:窗口的名字 onMouse:鼠标响应函数&#xff0c;回调…

基于Springboot+vue的音乐网站

随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了音乐网站的开发全过程。通过分析音乐网站管理的不足&#xff0c;创建了一个计算机管理音乐网站的方案。文章介绍了音乐网站的系统分析部分&#xff0c;包括可行性分析…

828华为云征文|Flexus云服务器X实例部署宝塔运维面板

本次华为云Flexus云服务器X实例部署宝塔运维面板教学&#xff0c;这次是推陈出新啊 之前的云耀云服务器L实例已经很不错了&#xff0c;大力赞叹华为云的 同时感谢华为云提供优惠卷&#xff0c;只能说白嫖真是太棒了 华为云近期正在筹办华为云828企业节活动&#xff0c;90款免…

人类行为识别系统源码分享

人类行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

【资料分析】刷题日记1

第一套 第二个是相比2019年的增长率&#xff0c;错找为同比增长率 延申&#xff1a; 当出口和进口相比2019年的增长率相同时&#xff0c;可以用盐水解决 √ 一个假设分配&#xff08;第二次是1.4取1&#xff09;加法对比选项 基期倍数&#xff1a; 求A是B的多少倍&#x…

DBeaver纵向展示一行数据

DBeaver查询结果如果列数太多&#xff0c;横着看并不方便&#xff0c;这时可以点击左下角的【记录】按钮&#xff0c;然后可看到纵向的展示结果。如图 就这么一个小功能&#xff0c;没细看的话直接上网搜&#xff0c;不知为啥出来的都是一堆错误方法。所以这里记一下。

2、HDFS编程实践

目录 1、Hadoop三种Shell方式(1)目录操作1、查看目录2、创建目录3、删除目录 &#xff08;2&#xff09;文件操作1、创建文件2、上传文件3、下载文件4、拷贝文件 2、利用Web界面管理HDFS3、利用Java API 与 HDFS 进行交互&#xff08;1&#xff09;安装eclipse包&#xff08;2&…

【Python报错已解决】 Requests.exceptions.ProxyError: HTTPSConnectionPool

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

千益畅行:旅游卡免费服务,包含哪些内容?

​凭此卡可免费旅游&#xff0c;单卡支持2-6人同行&#xff0c;免费服务内容包含&#xff1a;酒店住宿、团餐、景区首道大门票、导游、大巴、旅游责任险、接送机等&#xff0c;目前支持全国40多条旅游线路&#xff0c;爱旅游的朋友们可以约起来&#xff01; #旅游卡服务#

Facebook直播限流是什么原因?是ip地址导致的吗

随着社交媒体和直播行业的蓬勃发展&#xff0c;Facebook直播已成为众多企业和个人进行品牌推广、产品展示和互动交流的重要平台。然而&#xff0c;在享受直播带来的便利与效益的同时&#xff0c;不少用户也面临着直播限流的困扰。本文将探讨Facebook直播限流的原因&#xff0c;…

戴尔科技VS惠与科技:谁是美股AI服务器领域更好的投资选择?

猛兽财经核心观点&#xff1a; &#xff08;1&#xff09;戴尔科技(DELL)和惠与科技(HPE)都是AI服务器领域的优质公司。 &#xff08;2&#xff09;惠与科技主导着以软件为中心的服务器市场&#xff0c;而戴尔科技则迎合着以硬件为中心的客户。 &#xff08;3&#xff09;两家公…

【C语言】带你手把手拿捏指针(3)(含转移表)

文章目录 一、字符指针变量二、数组指针变量1.数组指针变量是什么2.数组指针变量的初始化 三、二维数组传参的本质四、函数指针变量1. 函数指针变量的创建2.函数指针的使用3.案例解析&#xff1a; 五、typedof关键字六、函数指针数组和转移表1.函数指针数组2.转移表 一、字符指…

Linux基础---11优化系统

一.优化SSH连接速度 1&#xff09;修改配置文件 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak#备份vi /etc/ssh/sshd_config将79行和115行的yes修改为no,最后:wq保存退出&#xff08;79gg和115gg可直接跳至本行&#xff09; 79 行&#xff1a;GSSAPIAuthentication no…