按vue组件实例类型实现非侵入式国际化多语言翻译
#vue3##国际化##本地化##international#
web界面国际化,I18N(Internationalization,国际化),I11L(International,英特纳雄耐尔),L10N(Localization,本地化),显示文字多语言化是其主要内容。
浏览器的js提供了Intl全局对象,html提供了translate属性。
console.log(Intl,window.Intl);
<p translate="no">Don't translate this!</p>
某些浏览器插件支持一键“翻译网页”。其实现很简单,递归遍历找到<span><text>等文字标签,按通用字典对照翻译,并监听dom的变化,对弹出的内容或更新的内容也能即时翻译。这种一网打尽式的翻译,对某些wiki、doc、博客、新闻类网站比较适合,但是对一些ERP等管理系统,不太适合:
- 不精准。不该翻译的地方翻译了,比如用户输入的内容:产品编码、产品型号,Grid的cell内容...除非能用“translate='no'”把不翻译的dom标注得很完整。
- 不专业。翻译的字典是通用的,可能因为行业不同,牛头不对马嘴。插件能支持用我自己的字典? 因此,ERP这种管理系统,一般要有自己的多语言方案。
要做一个翻译方案,要考虑以下问题:
- 字典。字典格式(json,csv,xml)、字典的读取、解析、编辑。
- 国家语言标识。语言代码( Language Code)、国家代码( Country Code)、Windows Language Code Identifier (LCID),一般不再使用旧的Code Page(简体中文936,繁体中文950)。
- 语言切换。LCID存哪里。是否重加载页面。
- 翻译函数。高效的把一个文本字串,查找字典,翻译成对照文本。
- 翻译的时机。在何时调用翻译函数。
i18n(http://npmmirror.com/package/i18n,http://npmmirror.com/package/i18next)组件提供了一套简单的机制。 对vue框架,i18n对照有个vue-i18n(http://npmmirror.com/package/vue-i18n)。 i18n的实现了多语言化的基本机制,需要程序员配合,在合适的地方调用翻译函数。
我这里要讲的是一种非侵入式的,外挂式的多语言转换机制,比较适合已经完成的系统,突然要加多语言机制。 我的这篇老文章里(https://nodejs.blog.csdn.net/article/details/248218)谈到了这种方法,那是在delphi、c#开发的winform程序中,在web开发中,因为有了react、vue这样的框架实现了web组件化,因此也可以使用类似的方案。这个方案的主要思想是:为每个vue类注册一个翻译函数,在必要时把vue组件实例按其类的翻译函数来逐个翻译。
acroMLClassMethod.register('DataGrid',t_DataGrid);
acroMLClassMethod.register('GridColumn',t_GridColumn);
acroMLClassMethod.register('GridFilterButton',t_GridFilterButton);
acroMLClassMethod.register('Menu',t_Menu);
acroMLClassMethod.register('MenuItem',t_MenuItem);
翻译函数,如:v3-easyui组件的翻译函数,像这个样子:
function t_GridColumn(t,instWrap){let inst=instWrap.$;acroMLClassMethod.translateProps(t,inst.props,['title']);
}
function t_GridFilterButton(t,instWrap){let inst=instWrap.$;let items=instWrap.$data.items;if (items){for(let i=0;i<items.length;i++){let item=items[i];acroMLClassMethod.translateProps(t,item,['text']);}}
}
这个方案的几个特点:
- 外挂式。写页面的程序员一般情况下感觉它不存在。特殊的地方还是用显式的使用t函数,或标记translate='no'。
- 相对准确。相比浏览器的自动翻译,不会“误伤”。如DataGrid,会翻译column,footer的title,不会翻译到cell。相对于传统i18n机制显式的使用t函数,没那么精准,如:SelectBox下拉框,当选择的文本用于代码比较时是不能翻译的,还是需要显式的标记translate='no'或挂载beforeTranslate事件告知不翻译。
- 切换语言时能做到不重加载页面就刷新。传统i18n机制可能也能做到,只要t函数是响应式的,能响应locale的变化。但是,某些第3方组件包,其内置的一些文本字串,切换语言后,即使重加载了其对应的内置字典,也不会自动刷新。如devextreme-vue的DataGrid的noDataText。
文无第一,武无第二,各种方案没有绝对的好坏,就像react与vue,暂时无法谁碾压谁,适合不同的场景和不同的团队。
这个方案的几个注意点:
- 如何从vue组件实例找到其类别。
- 注册类别还是注册类别名称。
- 何时调用翻译函数。
- 不同厂家的vue组件属性修改机制的差别。
- 切换语言时如何不重加载页面而刷新。
- 人为设定不翻译某些组件的机制。
- 切换语言时DDKey从哪里找。
1、如何从vue组件实例找到其类别
- instWrap.$options.name
- instWrap.$.constructor.name
- instWrap.$.type.name
translateCom(t,instWrap,isTranslateChildren=true){//console.log(instWrap);let inst=instWrap.$;let typeName=instWrap.$options.name;if (!typeName){if (inst.constructor && (inst.constructor.name!='Object')) typeName=inst.constructor.name;}if (!typeName) typeName=inst.type.name;if (!typeName){for(let i=0;i<classNameGetters.length;i++){typeName=classNameGetters[i](instWrap);if (typeName) break;}}//console.log(typeName,instWrap);let m;if (typeName){m=classMethods[typeName];}else{let {classID,method}=getClassMethod(inst.type);m=method;}if (m){if (instWrap.$attrs.translate!='no'){m(t,instWrap);}}if (isTranslateChildren){acroMLClassMethod.translateVNode(t,inst.subTree,isTranslateChildren);}},
如果从已知渠道拿不到类别名称,那再实现一个机制,让组件厂商告诉你如何获取。如:devextreme-vue组件,上面3个渠道是得不到组件类别名称的。只有特别处理:
acroMLClassMethod.registerClassNameGetter(function(instWrap){let className;if (instWrap.$_instance) className=instWrap.$_instance.NAME;if (!className) className=instWrap.widget;//if (!className) className=instWrap.$options.$_optionName;return className;
});
2、注册类别还是注册类别名称
前面看到注册翻译函数时,类别都是使用的类别名称,如果使用类别,也是可以实现的,即:
acroMLClassMethod.register(DataGrid,t_DataGrid);
acroMLClassMethod.register(Menu,t_Menu);
但是,直接用类别,需要把组件加载到内存中,有几个坏处:
- 组件包的组件全部加载了。实际项目可能没有用到那么多组件,比如devextreme中的甘特图、枢纽分析Grid组件;
- 组件加载机制可能与外部不同。你可能是用一个包加载,外面可能是用分文件加载,这会导致相同组件在内存中有两份,可能导致组件内部逻辑错误。
//加载方式1:
import DX from 'devextreme-vue';//加载方式2:
import {DxDataGrid,DxColumn,DxPager,DxPaging,DxGroupPanel,DxSearchPanel,DxSelection,DxFilterRow,DxScrolling} from 'devextreme-vue/data-grid';
import {DxTextBox,DxButton as DxTextBoxButton} from 'devextreme-vue/text-box';
import DxButton from 'devextreme-vue/button';
import DxCheckBox from 'devextreme-vue/check-box';
import DxColorBox from 'devextreme-vue/color-box';//加载方式3:
import DxButton from 'devextreme-vue/button.mjs';
import DxCheckBox from 'devextreme-vue/check-box.mjs';
3、何时调用翻译函数
谢天谢地,vue3还保留了app.mixin。可以混入mounted、updated、unmounted函数到全部的vue组件中,这是监测vue组件生命周期的好地方。
import acroMLClassMethod from 'acroml/vue/acroML.ClassMethod.mjs';
import {YJEvent} from 'foil/util.yjEvent.mjs';
/*** 用insts来维护vue组件实例列表。* 因为当多语言切换时,从$root不知道如何遍历到DxDropDownBox模版中的DxDataGrid*/
let insts=[];
let isTranslating=false;class YJLocaleTranslator extends YJEvent{init(app){let self=this;app.mixin({mounted(){/*** app.mixin混入到任何组件的生命周期中。只翻译当前组件。* 注意:这里的this是被混入的vue组件实例,不是YJVueTranslator实例*///let inst=Vue.getCurrentInstance();//console.log('DOM mounted:',this.$options.name,this);let instWrap=this;setTimeout(function(){/*** 混入的函数是先于组件的函数执行。* 用setTimeout造成异步效果,等待让DxDataGrid实例的$_instance有值。 * 如果不用setTimeout,混入到mounted函数中,那时DxDataGrid实例的$_instance也不会有值。*/if (self.translateInst(instWrap)){insts.push(instWrap);}}, 0);},unmounted(){let index=insts.indexOf(this);if (index>=0) insts.splice(index,1);},updated(){/*** 翻译可能导致组件再更新,进入死循环。* update可能有很多原因,大多与显示翻译无关。* 组件更新时,可能把父组件文本属性给子组件,必须再次翻译。*/if (isTranslating) return;let instWrap=this;//console.log('beforeUpdate',instWrap);setTimeout(function(){isTranslating=true;try{self.translateInst(instWrap);}finally{/*** 用setTimeout造成异步效果,让“因为翻译引起的组件更新”不再进入翻译*/setTimeout(function(){isTranslating=false;},0);}},0);}});}translate(){let self=this;let t1=new Date();for(let i=0;i<insts.length;i++){let inst=insts[i];self.translateInst(inst);}let t2=new Date();console.log(`acroml translated ${insts.length} instances used ${t2.getTime()-t1.getTime()} ms.`);}translateInst(instWrap){let self=this;let ops={isTranslate:true};self.emit('beforeTranslate',instWrap,ops);if (!ops.isTranslate) return false;acroMLClassMethod.translateCom(t,instWrap,false);//acroMLClassMethod.translateVNode(t,inst.vnode,false);self.emit('afterTranslate',instWrap);return true;}
}let yjLocaleTranslator=new YJLocaleTranslator();export default yjLocaleTranslator;
export {yjLocaleTranslator}
4、不同厂家的vue组件属性修改机制的差别
一般的组件,修改instWrap.$.props就可以,而且能做到不重新加载页面就刷新。如:ant-design-vue的Table:
function t_Table(t,instWrap){//console.log('t_Table',instWrap);let inst=instWrap.$;if (inst.props.columns){for(let i=0;i<inst.props.columns.length;i++){let column=inst.props.columns[i];acroMLClassMethod.translateProp(t,column,'title');}}acroMLClassMethod.translateProps(t,inst.props.locale);inst.props.locale={...inst.props.locale};
}
如:element-plus的ElTable:
function t_ElTable(t, instWrap){let inst=instWrap.$;//console.log(instWrap);acroMLClassMethod.translateProps(t,inst.props,['emptyText','confirmFilter','resetFilter','clearFilter','sumText']);let columns=instWrap.columns;if (columns){for(let i=0;i<columns.length;i++){acroMLClassMethod.translateProp(t,columns[i],'label');}}
}
但是,devextreme-vue比较特殊,这样修改instWrap.$.props无效或不会刷新(问了devexrpess厂家,说官方不支持切换语言后不重加载页面刷新)。因为它的核心组件包devextreme,也用于react和angular,而且对于DataGrid的内部组件,有prop和slot两种定义方式:
<DxDataGrid :show-borders="true":groupPanel="{visible:true,emptyPanelText:'File'}":searchPanel="{visible:true,placeholder:'Edit'}">
</DxDataGrid>
<DxDataGrid :show-borders="true"><DxSearchPanel :visible="true" placeholder='Edit' /><DxGroupPanel :visible="true" emptyPanelText='File' />
</DxDataGrid>
因此,它定义了一套API机制来更新属性。
instWrap.$_instance.option();
instWrap.$_instance.state();
instWrap.$_instance._getDefaultOptions();
因此,我们使用这些API来翻译组件:
function wrap_transDevextremeCom(proc){return function(t,instWrap){let inst=instWrap.$_instance;if (!inst){return;}let state;if (inst.state) state=inst.state();let defaultValues=inst._getDefaultOptions();let tag=switchLocale();switchLocale('en');let defaultDDKeys=inst._getDefaultOptions();switchLocale(tag);options=inst.option();//if (inst.NAME=='dxDataGrid') console.log(2,options);/*** inst.option()返回的类型是object,不知为何修改placeholder后用inst.option(options)放回去不生效。* 但是inst.option({'placeholder':'上海'});或inst.option('placeholder','上海');会刷新。* 必须在修改前用JSON.parse(JSON.stringify(options))或options={...options}处理一下。* 有一个警告:error:35 W0001 - dxPopup - 'closeOnOutsideClick' option is deprecated in 22.1. Use the 'hideOnOutsideClick' option instead.*///options=JSON.parse(JSON.stringify(options));options={...options};inst.beginUpdate();try{proc(t,instWrap,options,defaultDDKeys,defaultValues);inst.option(options);/**设置预设参数可能丢掉了状态,恢复 */if (state) inst.state(state);}finally{inst.endUpdate();}}
}
DxDataGrid的翻译就这样写了,也能做到切换语言时不重加载页面而刷新:
function t_DxDataGrid(t,instWrap,options,defaultDDKeys,defaultValues){//console.log('t_DxDataGrid',instWrap);/*** 不要企图通过instWrap.$.props去修改参数,因为DxDataGrid的某些参数有2种写法:* (1)<DxDataGrid searchPanel="{visible:true,placeholder:'search...'}"><DxDataGrid>* (2)<DxDataGrid><DxSearchPanel visible='true' placeholder='search...' /><DxDataGrid>* 用instWrap.$.props时,第2种写法的参数是找不到的。* 不能通过coumns属性更新column的caption,因为<DxDataGrid><DxColumn dataField='ID />这种写法,columns属性为空* 必须通过method:columnOption来更新column的caption*/acroMLClassMethod.translateProps(t,options,['hint','noDataText'],defaultDDKeys,defaultValues);acroMLClassMethod.translateNodeProps(t,options,['loadPanel'],['text']);acroMLClassMethod.translateNodeProps(t,options,['columnChooser'],['emptyPanelText','title']);acroMLClassMethod.translateNodeProps(t,options,['columnChooser','search','editorOptions'],['placeholder']);acroMLClassMethod.translateNodeProps(t,options,['columnFixing','texts'],['fix','leftPosition','rightPosition','unfix']);acroMLClassMethod.translateNodeProps(t,options,['editing','texts'],['addRow','cancelAllChanges','cancelRowChanges','confirmDeleteMessage','confirmDeleteTitle','deleteRow','editRow','saveAllChanges','saveRowChanges','undeleteRow','validationCancelChanges']);acroMLClassMethod.translateNodeProps(t,options,['export','texts'],['exportAll','exportSelectedRows','exportTo']);acroMLClassMethod.translateNodeProps(t,options,['filterPanel','texts'],['clearFilter','createFilter','filterEnabledHint']);acroMLClassMethod.translateNodeProps(t,options,['filterRow'],['applyFilterText','betweenEndText','betweenStartText','resetOperationText','showAllText']);acroMLClassMethod.translateNodeProps(t,options,['groupPanel'],['emptyPanelText'],defaultDDKeys,defaultValues);acroMLClassMethod.translateNodeProps(t,options,['grouping','texts'],['groupByThisColumn','groupContinuedMessage','groupContinuesMessage','ungroup','ungroupAll']);acroMLClassMethod.translateNodeProps(t,options,['headerFilter','texts'],['cancel','emptyValue','ok']);acroMLClassMethod.translateNodeProps(t,options,['pager'],['inforText']);acroMLClassMethod.translateNodeProps(t,options,['searchPanel'],['placeholder'],defaultDDKeys,defaultValues);acroMLClassMethod.translateNodeProps(t,options,['sorting'],['ascendingText','clearText','descendingText']);acroMLClassMethod.translateNodeProps(t,options,['summary','texts'],['avg','avgOtherColumn','count','max','maxOtherColumn','min','minOtherColumn','sum','sumOtherColumn']);let columns=options['columns'];if (columns){for (let i=0;i<columns.length;i++){let column=columns[i];acroMLClassMethod.translateProp(t,column,'caption',column.dataField);acroMLClassMethod.translateProps(t,column,['trueText','falseText']);}}
}
5、切换语言时如何不重加载页面而刷新
切换语言后,简单粗暴的方式是window.reload()重加载页面。但是全部状态都丢失。一般组件的内置文本,如devextreme-vue的DataGrid的noDataText,groupPanel的emptyPanelText,它是组件创建时按当前内置字典获取的,不会在字典重加载后自动刷新。但是本方案,因为切换语言时,会重翻译全部vue组件实例,所以可以刷新。
6、人为设定不翻译某些组件的机制
如果不翻译某个组件,可以设置translate属性为no,也可以实现一个beforeTranslate事件机制,如:
yjLocaleTranslator.on('beforeTranslate',function(instWrap,ops){//console.log(instWrap,ops);/*** 不翻译某个组件实例的方法:* (1)给组件设置一个attr:translate='no'* (2)挂载beforeTranslate事件,阻止某些组件翻译。*/if (instWrap===self.$refs.dropdownbox) ops.isTranslate=false;
});
7、切换语言时DDKey从哪里找
切换语言前,vue组件的显示字串已经翻译成当前语言了,如:"OK"翻译成了简体“确认”,再切换语言到繁体时,哪里去找OK的词?很简单,翻译前把OK作为DDKey保存起来,直接保存在vue组件实例上。
translateProp(t,obj,propName,propDefaultDDKey,propDefaultValue){if (!obj) return;/*** 没有属性值,没必要处理?* 不行,element-plus的ElTableColumn是不给label就不显示。* 但是devextreme-vue的DxColumn的caption可能没设置,但要按data-field来翻译显示。* DxDataGrid的groupPanel的emptyPanelText如果没有设置,使用官方的字典翻译。*///if (!obj[propName]) return;if (!obj._acroml_DDKeys) obj._acroml_DDKeys={};let DDKey=obj._acroml_DDKeys[propName];if (!DDKey){DDKey=obj[propName];/**保存原始的DDKey */if (!DDKey) DDKey=propDefaultDDKey;else if (DDKey===propDefaultValue) DDKey=propDefaultDDKey;}/**如果DDKey是undefine就让obj[propsName]保持undefined(这样组件会使用其当前字典),如果赋值''就显示空白了 */if (DDKey){let newValue=t(DDKey);if (newValue===DDKey){if (propDefaultValue) newValue=propDefaultValue;}if (obj[propName]!=newValue) obj[propName]=newValue;if (newValue!=DDKey) obj._acroml_DDKeys[propName]=DDKey;}else if (propDefaultValue && obj[propName]!=propDefaultValue) obj[propName]=propDefaultValue;},
注:写文章时,涉及到vue组件版本:
- vue,3.5.12
- devextreme-vue,23.2.8
- v3-easyui,3.0.14
- ant-design-vue,4.2.3
- element-plus,2.8.1
相关文章:
按vue组件实例类型实现非侵入式国际化多语言翻译
#vue3##国际化##本地化##international# web界面国际化,I18N(Internationalization,国际化),I11L(International,英特纳雄耐尔),L10N(Localization,本地化)&…...
2024年认证杯SPSSPRO杯数学建模B题(第一阶段)神经外科手术的定位与导航解题全过程文档及程序
2024年认证杯SPSSPRO杯数学建模 B题 神经外科手术的定位与导航 原题再现: 人的大脑结构非常复杂,内部交织密布着神经和血管,所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术,通常需要…...
51c视觉~合集24
我自己的原文哦~ https://blog.51cto.com/whaosoft/11870494 #R-Adapter 零样本模型微调新突破,提升鲁棒性与泛化能力 论文提出新颖的Robust Adapter(R-Adapter),可以在微调零样本模型用于下游任务的同时解决这两个问题。该方…...
idea启动tomcat服务中文乱码
在idea中启动tomcat服务后部分中文乱码 但是在tomcat日志部分正常 并且在tomcat中中文也是正常 查询大量资料修改idea编码,虚拟机编码、tomcat默认编码、终端默认编码,统统没有效果。 最终发现修改tomcat下文件夹 .\conf\logging.properties 网络上…...
android studio 读写文件操作(应用场景二)
android studio版本:2023.3.1 patch2 例程:readtextviewIDsaveandread 本例程是个过渡例程,如果单是实现下图的目的有更简单的方法,但这个方法是下一步工作的基础,所以一定要做。 例程功能:将两个textvi…...
【数据结构】【线性表】特殊的线性表-字符串
目录 字符串的基本概念 字符串的三要素 字符串的基本概念 串的编码 串的实现及基本运算 顺序串的实现 串的静态数组实现 串的动态数组的实现 顺序存储的四种方案 链式串的实现 基本运算 方案三 方案一 字符串的基本概念 数据结构千千万,…...
【AWS re:Invent 2024】一文了解EKS新功能:Amazon EKS Auto Mode
文章目录 一、为什么要使用 Amazon EKS Auto Mode?二、Amazon EKS自动模式特性2.1 持续优化计算成本2.2 迁移集群操作2.3 EKS 自动模式的高级功能 三、EKS Auto 集群快速创建集群配置四、查看来自 API 服务器的指标五、EKS 相关角色权限设置六、参考链接 一、为什么…...
HTTPS的工作过程
1.HTTPS协议原理 1.1HTTPS协议的由来 HTTP在传输网络数据的时候是明文传输的,信息容易被窃听甚至篡改,因此他是一个不安全的协议(但效率高)。在如今的网络环境中,数据安全是很重要的(比如支付密码又或者各…...
Java并发编程学习之从资本家的角度看多线程和并发性(一)
目录 前言前置知识一、单线程时代二、为什么要有多线程,多线程的优点?三、使用多线程会遇到什么问题?四、多线程和并发编程的关系总结 前言 这篇文章是打开Java多线程和并发编程的大门的开始,如标题《从老板的角度看多线程和并发…...
基于STM32设计的智能宠物喂养系统(华为云IOT)_273
文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】设计意义【5】国内外研究现状【6】摘要1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发1.5 参考文献1.6 系统框架图1.7 系统原理图1.8 实物图1.9…...
Mybatis-Plus的主要API
一、实体类操作相关API BaseMapper<T>接口 功能:这是 MyBatis - Plus 为每个实体类对应的 Mapper 接口提供的基础接口。它提供了一系列基本的 CRUD(增删改查)操作方法。例如insert(T entity)方法用于插入一条记录,d…...
Pillow:强大的Python图像处理库
目录 一、引言 二、Pillow 库的安装 三、Pillow 库的基本概念 四、图像的读取和保存 五、图像的基本属性 六、图像的裁剪、缩放和旋转 七、图像的颜色调整 八、图像的滤镜效果 九、图像的合成和叠加 十、图像的绘制 十一、示例程序:制作图片水印 十二、…...
Springboot定时任务详解
文章目录 Springboot定时任务详解一、引言二、cron表达式三、使用Scheduled注解1、开启定时任务2、添加定时任务 四、使用TaskScheduler接口1、注入TaskScheduler实例 五、集成Quartz框架1、集成Quartz 六、实际使用示例七、总结 Springboot定时任务详解 一、引言 在现代软件…...
【Linux】环境ChatGLM-4-9B 模型之 openai API 服务
一、摘要 最近看到 Function Call 比较感兴趣,它的核心是赋予大模型能够调用外部API的能力,能够解决大模型功能扩展性问题,允许模型调用外部数据库或API,提供特定领域的详细信息;解决信息实时性问题,模型可以实时获取最新数据;解决数据局限性问题,大模型训练数据虽多但…...
mobi文件转成pdf
将 MOBI 文件转换为 PDF 格式通常涉及两个步骤: 解析 MOBI 文件:需要提取 MOBI 文件的内容(文本、图片等)。将提取的内容转换为 PDF:将 MOBI 文件的内容渲染到 PDF 格式。 可用工具 kindleunpack 或 mobi࿱…...
Linux---对缓冲区的简单理解--第一个系统程序
前序: 首先先理解一下什么是回车与换行;回车和换行是两个概念,它们不是一个东西; 回车:光标回到开始;换行:换到下一行; 如下图: 行缓冲区 如何理解缓冲区问题? 可以认为࿰…...
word poi-tl 表格功能增强,实现表格功能垂直合并
目录 问题解决问题poi-tl介绍 功能实现引入依赖模版代码效果图 附加(插件实现)MergeColumnData 对象MergeGroupData 类ServerMergeTableData 数据信息ServerMergeTablePolicy 合并插件 问题 由于在开发功能需求中,word文档需要垂直合并表格&…...
鸿蒙实现数据管理
目录: 1、鸿蒙实现数据管理的三种方式2、用户首选项3、键值型数据管理3.1、获取KVManager实例,用于管理数据库对象3.2、创建并获取键值数据库3.3、调用put()方法向键值数据库中插入数据3.4、调用get()方法获取指定键的值3.5、调用delete()方法删除指定键…...
图片上传HTML
alioss sky:jwt:# 设置jwt签名加密时使用的秘钥admin-secret-key: itcast# 设置jwt过期时间admin-ttl: 7200000# 设置前端传递过来的令牌名称admin-token-name: tokenalioss:endpoint: ${sky.alioss.endpoint}access-key-id: ${sky.alioss.access-key-id}access-key-secret: $…...
golang 代发邮件支持附件发送,outlook案列,其他邮箱需要替换对应邮箱服务域名
GPT问答实例 import pandas as pd from openai.embeddings_utils import get_embedding, cosine_similarity import openai import os import logging as logger from flask_cors import CORS import os openai.api_key os.getenv(OPENAI_API_KEY)class Chatbot():def parse_…...
输出绝对值
输出绝对值 C语言代码C 代码Java代码Python代码 💐The Begin💐点点关注,收藏不迷路💐 输入一个浮点数,输出这个浮点数的绝对值。 输入 输入一个浮点数,其绝对值不超过10000。 输出 输出这个浮点数的绝对…...
docker desktop打包配置国内镜像地址
打包遇到无法访问外网资源,直接配置国内镜像地址 直接加入如下代码就行: {"builder": {"gc": {"defaultKeepStorage": "20GB","enabled": true}},"experimental": false,"registry-m…...
鸿蒙Next学习-监听指定页面显示/页面生命周期
自定义组件监听页面生命周期 使用无感监听页面路由的能力,能够实现在自定义组件中监听页面的生命周期。 // Index.ets import { uiObserver, router, UIObserver } from kit.ArkUI;Entry Component struct Index {listener: (info: uiObserver.RouterPageInfo) &g…...
计算机网络 —— HTTPS 协议
前一篇文章:计算机网络 —— HTTP 协议(详解)-CSDN博客 目录 前言 一、HTTPS 协议简介 二、HTTPS 工作过程 1.对称加密 2.非对称加密 3.中间人攻击 4.引入证书 三、HTTPS 常见问题 1.中间人能否篡改证书? 2.中间人能否调…...
Oracle之表空间迁移
问题背景:一个数据表随着时间的累积,导致所在表空间占用很高,里面历史数据可以清除,保留近2个月数据即可 首先通过delete删除了2个月以前的数据。 按网上的教程进行空间压缩,以下sql在表所在用户执行: -- 允许表重新…...
web组态可视化编辑器
随着工业智能制造的发展,工业企业对设备可视化、远程运维的需求日趋强烈,传统的单机版组态软件已经不能满足越来越复杂的控制需求,那么实现web组态可视化界面成为了主要的技术路径。 行业痛点 对于软件服务商来说,将单机版软件转…...
SpringMVC纯注解快速开发
此文章适合具有一定的java基础的同学看哦,如果有看不懂的基本代码还是先补补java基础哦。 此教程带您不使用xml文件而是纯注解开发,易懂、快捷、迅速,从0开始搭建,很快就能构建起一个SpringMVC项目,能学到两种使用tom…...
[读论文] Compositional 3D-aware Video Generation with LLM Director
Abstract 近年来,通过强大的生成模型和大规模互联网数据,文本到视频生成领域取得了显著进展。然而,在生成视频中精确控制单个概念(如特定角色的动作和外观、视角的移动)方面,仍存在巨大挑战。为此ÿ…...
FFmpeg 4.3 音视频-多路H265监控录放C++开发十八,ffmpeg解复用
为啥要封装和解封装呢? 1.封装就相当于将 h264 和aac 包裹在一起。既能播放声音,也能播放视频 2.在封装的时候没指定编码格式,帧率,时长,等参数;特别是视频,可以将视频帧索引存储,…...
ubuntu系统安装docker
1、 安装必要的依赖 sudo apt install apt-transport-https ca-certificates curl software-properties-common2、添加 Docker 的官方 GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -3、添加 Docker 的 APT 源 sudo add-apt-repos…...
STM32 BootLoader 刷新项目 (十三) Python上位机介绍
STM32 BootLoader 刷新项目 (十三) Python上位机介绍 大家好,这是我们STM32 BootLoader的最后一篇文章了,讲述用Python写的上位机,也更新了半年时间了,谢谢大家的支持,到目前为止,已经更新了12篇文章了&am…...
美畅物联丨智能监控,高效运维:视频汇聚平台在储能领域的实践探索
在当今全球能源格局不断变化的大背景下,对清洁能源的需求正以惊人的速度增长。储能项目作为平衡能源供需、提升能源利用效率的关键环节,其规模和复杂度也在不断攀升。在储能项目的运营管理过程中,安全监控、设备运维以及数据管理等方面面临着…...
T C P
文章目录 基于UDP应用场景 TCP协议TCP 协议段格式确认应答机制16位窗口大小 下定义32位序号和32位确认序号序号是什么?确认序号 基于UDP应用场景 UDP,tcp这样的协议根本不是直接谈UDP。tcp的应用场景,一定是上层写了应用层协议,所…...
MongoDB的简单使用
MongoDB(文档数据库)的简单使用 MongoDB最好的学习资料就是他的官方文档:SQL 到 MongoDB 的映射图表 - MongoDB 手册 v8.0 1.MongoDB CRUD操作 1.1Insert操作 基本方法: db.collection.insertOne() 将单个文档(document)插入集合中 db.collectio…...
【Exp】# Microsoft Visual C++ Redistributable 各版本下载地址
Microsoft官方页面 https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads Redistributable 2019 X86: https://aka.ms/vs/16/release/VC_redist.x86.exe X64: https://aka.ms/vs/16/release/VC_redist.x64.exe Redistributable 201…...
【MySQL】表的约束
目录 一、非空约束not null 二、默认值约束default 三、列描述comment 四、填充零zerofill 五、主键primary key 六、自增长auto_increment 七、唯一键unique 八、外键foreign key 一、非空约束not null 如果不对一个字段做非空约束,则默认为空。但空数据无…...
c++高级篇(四) ——Linux下IO多路复用之epoll模型
IO多路复用 —— epoll 前言 在之前我们就已经介绍过了select和poll,在作为io多路复用的最后一个的epoll,我们来总结一下它们之间的区别: a select 实现原理 select 通过一个文件描述符集合(fd_set)来工作,该集合可以包含需要监控的文件…...
基于Java Springboot环境保护生活App且微信小程序
一、作品包含 源码数据库设计文档万字PPT全套环境和工具资源部署教程 二、项目技术 前端技术:Html、Css、Js、Vue、Element-ui 数据库:MySQL 后端技术:Java、Spring Boot、MyBatis 三、运行环境 开发工具:IDEA/eclipse 微信…...
.NET 9 中 LINQ 新增功能实现过程
本文介绍了.NET 9中LINQ新增功能,包括CountBy、AggregateBy和Index方法,并提供了相关代码示例和输出结果,感兴趣的朋友跟随我一起看看吧 LINQ 介绍 语言集成查询 (LINQ) 是一系列直接将查询功能集成到 C# 语言的技术统称。 数据查询历来都表示为简单的…...
【Vue3中Router使用】
Vue3中Router使用 1. 安装vue-router组件2. 建两个测试页面2.1 测试页面Home.vue2.2 测试页面Category.vue 3. 创建路由对象4. 在入口main.js中引入router把App.vue改成路由页面5. 测试5.1 关闭检查解决ESlint报错5.2 改文件名解决ESlint检查报错测试WebHashHistory 和WebHisto…...
性能测试攻略(一):需求分析
性能测试成为软件开发和运维过程中不可或缺的一环。性能测试不仅能够帮助我们了解系统在特定条件下的表现,还能帮助我们发现并解决潜在的性能问题。那么我们怎么做一次完整的性能测试呢?首先,我们需要进行需求分析,来明确我们的测…...
android WebRtc 无法推流以及拉流有视频无声音问题
最近在开发使用WebRtc进行视频通话和语音通话,我使用的设备是MTK的手机,期间后台的技术人员几乎没法提供任何帮助,只有接口和测试的web端,有遇到不能推流。推流成功网页端有画面有声音,但是安卓端有画面,没…...
Socket编程TCP
【Linux】TCP编程 实验:通过TCP通信—在客户端输入要执行的指令,接收执行结果,另服务端接收指令并执行,向客户端发送执行结果 //主函数 #include<iostream> #include<string> #include"log.hpp" #include…...
《以 C++为笔,绘就手势识别人机交互新画卷》
在科技浪潮汹涌澎湃的当下,人机交互领域正处于深刻变革的前沿阵地。从古老的命令行输入到图形化界面的鼠标点击,再到如今风靡全球的触摸操控,每一次交互方式的革新都重塑了我们与电子设备的沟通模式。而近年来,手势识别技术作为一…...
【CSS】小球旋转loading加载动画
效果 css小球旋转loading动画 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document<…...
Leetcode经典题6--买卖股票的最佳时机
买卖股票的最佳时机 题目描述: 给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。…...
BA是什么?
目录 1.EKF的步骤 一、问题定义与模型建立 二、线性化处理 三、应用卡尔曼滤波 四、迭代与收敛 五、结果评估与优化 注意事项 2.BA问题的步骤 一、问题定义与数据准备 二、构建优化模型 三、选择优化算法 四、执行优化过程 五、结果评估与优化 六、应用与验证 1.…...
【IDEA】报错:Try to run Maven import with -U flag (force update snapshots)
问题 IDEA运行项目报错:Try to run Maven import with -U flag (force update snapshots) 原因 IDEA 的项目运行绑定的maven有问题, 解决问题 检查项目绑定的maven配置...
MATLAB提供的窗函数
加窗法 为什么使用加窗法? 在数字滤波器设计和频谱估计中,加窗函数的选择对于整体结果的质量有重大影响。加窗的主要作用是减弱因无穷级数截断而产生的吉布斯现象的影响。 windowDesigner 六种常见的窗函数 根据离散时间傅里叶变换的乘法性质&a…...
git 使用配置
新拿到机器想配置git 获取代码权限,需要的配置方法 1. git 配置用户名和邮箱 git config --global user.name xxxgit config --global user.email xxemail.com 2. 生成ssh key ssh-keygen -t rsa -C "xxemail.com" 3. 获取ssh key cat ~/.ssh/id_rsa.…...