鸿蒙5.0项目开发——接入有道大模型翻译

【高心星出品】

项目效果图

在这里插入图片描述

项目功能

  1. 文本翻译功能

    • 支持文本输入和翻译结果显示

    • 使用有道翻译API进行翻译

    • 支持自动检测语言(auto)

    • 支持双向翻译(源语言和目标语言可互换)

  2. 文本操作功能

    • 支持文本复制

    • 支持文本全选

    • 支持长按选择文本

    • 支持滚动查看长文本

  3. 生词本功能

    • 可以将翻译结果保存到生词本

    • 支持保存选中文本的翻译

    • 支持保存整个翻译结果

    • 记录保存时间

  4. 用户界面特点

    • 采用上下布局,上方为输入区,下方为结果显示区

    • 支持实时翻译

    • 提供清晰的视觉反馈

    • 支持长按菜单操作

  5. 数据存储

    • 使用鸿蒙系统的数据存储能力

    • 支持生词本的本地存储

    • 支持历史记录保存

  6. 网络功能

    • 集成有道翻译API

    • 支持HTTP请求

    • 支持错误处理

    • 支持数据流式传输

  7. 安全特性

    • 使用API密钥进行身份验证

    • 支持数据加密传输

    • 实现签名验证机制

  8. 其他功能

    • 支持剪贴板操作

    • 提供操作提示(Toast提示)

    • 支持文本格式化

    • 支持多语言界面

大模型翻译 API 简介

大型模型翻译:翻译的好助手,使用此服务可以完成翻译、润色、扩写等功能。API可以处理各种复杂的语言结构、词汇和语境,提供高质量的翻译结果。 同时,可以根据用户的需 求和偏好进行定制化的翻译。用户可以通过调整参数、提供上下文信息或者进行反馈,使翻译结果更符合个人或特 定领域的要求,从而实现更加精准、个性化的翻译体验。

接入有道翻译过程

  • 首先要注册成为有道智云的开发者并创建应用:https://ai.youdao.com/doc.s#guide,就可以拿到 应用ID应用密钥

  • 大模型翻译API HTTPS地址:

https://openapi.youdao.com/llm_trans
  • 请求方式:
规则描述
传输方式HTTPS
请求方式GET/POST
字符编码统一使用UTF-8 编码
请求格式表单
响应格式text/event-stream
  • 请求参数:
字段名类型含义必填备注
itext待翻译文本True必须是UTF-8编码,限制5000字符
prompttext提示词False必须是UTF-8编码,限制1200字符、400单词
fromtext源语言True参考下方支持语言 (可设置为auto)
totext目标语言True参考下方支持语言
streamTypetext流式返回类型False参考下方 流式返回类型
appKeytext应用IDTrue可在应用管理 查看
salttext随机字符串,可使用UUID进行生产Trueuuid (可使用uuid生成)
signtext签名Truesha256(应用ID+input+salt+curtime+应用密钥)
signTypetext签名类型Truev3
curtimetext当前UTC时间戳(秒)TrueTimeStamp
handleOptiontext处理模式选项False参考下方 处理模式选项
polishOptiontext润色选项False参考下方 润色选项
expandOptiontext扩写选项False参考下方 扩写选项

签名生成方法如下: signType=v3; sign=sha256(应用ID+input+salt+curtime+应用密钥); 其中,input的计算方式为:input=i前10个字符 + i长度 + i后10个字符(当i长度大于20)或 input=i字符串(当i长度小于等于20);

  • 流式返回类型SSE:
event:begindata:{"requestId":"11","type":"zh-CHS2en"}event:messagedata:{"transFull":null,"transIncre":"The"}event:messagedata:{"transFull":null,"transIncre":" w"}...............event:enddata:{"requestId":"11","type":"zh-CHS2en","eventTokenUsage":{"inputToken":5,"outputToken":7,"totalToken":12}}

网络请求工具封装

由于大模型翻译获取的是增量的翻译结果,一次应答只能获取部分翻译结果,所以我们发送请求的方式要用requestInStream发起流式请求,然后在 req.on(‘dataReceive’, (data) =>{})中获取每次返回的SSE结果。

此工具封装最复杂的就是请求参数的获取,时间戳curtime要获取当前系统时间的秒级结果,并且服务器会将服务器时间与发送请求的时间戳进行对比,如果差距超过15分钟,请求就会失败,所以要关注一下运行该段代码设备的时间。

/*** 生成请求参数* @param q 待翻译的文本* @returns 包含签名等信息的请求参数对象*/
export function genparm(q: string): reqparam {q = q.trim()let salt = util.generateRandomUUID()let curtime = Math.round(new Date().getTime() / 1000) + ''let param: reqparam = {i: q,q: q,from: 'auto',to: 'auto',appKey: APPKEY,curtime: curtime,signType: 'v3',salt: salt,sign: sign(q, curtime, salt)}return param
}/*** 生成签名* @param q 待翻译的文本* @param curtime 当前时间戳* @param salt 随机字符串* @returns SHA256加密后的签名*/
function sign(q: string, curtime: string, salt: string) {let str = APPKEY + getinput(q) + salt + curtime + APPSECRETlet result: string = ''try {let mdAlgName = 'SHA256'; // 使用SHA256算法let md = cryptoFramework.createMd(mdAlgName);// 更新数据md.updateSync({ data: new Uint8Array(buffer.from(str, 'utf-8').buffer) });let mdResult = md.digestSync();// 将摘要结果转换为十六进制字符串result = Array.from(mdResult.data).map(byte => byte.toString(16).padStart(2, '0')).join('');} catch (error) {console.error('SHA256编码失败:', error);}return result
}/*** 处理输入文本* @param q 待处理的文本* @returns 处理后的文本* 如果文本长度大于20,则取前10个字符和后10个字符,中间加上长度*/
function getinput(q: string) {let len = q.lengthlet result: stringif (len <= 20) {result = q} else {let startstr = q.substring(0, 10)let endstr = q.substring(len - 10, len)result = startstr + len + endstr}return result
}/*** 发送LLM翻译请求* @param q 待翻译的文本* @param recievedata 接收数据的回调函数* @returns Promise<number> 请求ID*/
export function postllm(q: string, recievedata: (data: string) => void) {let req = http.createHttp()let param = genparm(q)let opt: http.HttpRequestOptions = {method: http.RequestMethod.POST,header: {'Content-Type': 'application/x-www-form-urlencoded'},extraData: `i=${param.i}&q=${param.q}&from=auto&to=auto&appKey=${param.appKey}&curtime=${param.curtime}&signType=v3&salt=${param.salt}&sign=${param.sign}`}let strs: string[] = []req.on('dataReceive', (data) => {// 处理接收到的数据let result = buffer.from(data).toString()console.log('gxxt result ', result)if (!result.endsWith('\n')) {strs.push(result.substring(result.lastIndexOf('\n') + 1))result = result.substring(0, result.lastIndexOf('\n') + 1)} else {if (strs.length > 0) {result = strs.join('') + resultstrs = []}}console.log('gxxt newresult ', result)recievedata(result)})return new Promise<number>((resolve, reject) => {req.requestInStream(BASEURL, opt).then((num) => {resolve(num)}).catch((e: Error) => {reject(e.message)})})
}

流式返回数据的处理

目前鸿蒙还没有支持解析SSE数据的工具,需要开发者自己封装,其实就是对于字符串的处理。鉴于SSE的结构,可以按照\n\n双换行来切割获取不同的事件类型,然后只处理event:message事件即可。

/*** 解析服务器返回的SSE(Server-Sent Events)数据* @param data 服务器返回的原始数据字符串* @returns 解析后的翻译结果数组,如果发生错误则返回undefined*/export function getResult(data: string) {let ret: string[] = []// 检查是否包含错误信息if (data.lastIndexOf('event:error') !== -1) {return}// 按事件分割数据let events = data.split('\n\n')events.forEach((item: string) => {// 处理消息事件if (item.indexOf('event:message') !== -1) {let data1 = item.split('event:message\n')data1.forEach((itemn: string) => {// 提取JSON数据并解析if (itemn.length > 1 && itemn.indexOf('{') !== -1) {let jsondata = itemn.substring(itemn.indexOf('{'), itemn.indexOf('}') + 1)let res = JSON.parse(jsondata) as resdataret.push(res.transIncre)}})}})return ret}

主界面代码

这是一个名为"星星翻译"的鸿蒙应用主界面,界面设计简洁实用,主要分为三个部分:

顶部是标题栏,显示"星星翻译"的应用名称,采用简洁的白色背景设计。

中间是核心的翻译区域,采用上下分栏布局:

  • 上方是文本输入区,用户可以在这里输入需要翻译的内容

  • 下方是翻译结果显示区,实时显示翻译结果

  • 两个区域之间有一个翻译按钮,点击即可执行翻译操作

  • 翻译结果支持长按选择文本,可以进行复制、全选等操作

底部是功能操作栏,提供两个主要功能按钮:

  • 复制按钮:可以将翻译结果一键复制到剪贴板

  • 生词本按钮:可以将当前的翻译内容保存到生词本中,方便后续复习

/*** 星星翻译应用主页面* 提供文本翻译、复制结果、生词本记录等功能*/
import { postllm } from '../utils/HttpUtils';
import { getResult, gettime } from '../utils/StringUtils';
import { contentview } from '../views/contentview';
import { footerview } from '../views/footerview';
import { headerview } from '../views/headerview';
import { pasteboard } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
import { saveshengci } from '../utils/Dbutils';
import { common } from '@kit.AbilityKit';/*** 翻译应用主页面组件*/
@Entry
@Component
struct Index {// 源文本和翻译结果状态@State @Watch('clear') sourcetext: string = ''    // 源文本,监听变化@State targettext: string = ''                    // 翻译结果private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext  // 应用上下文/*** 源文本清空时的监听函数* 当源文本为空时,清空翻译结果*/clear() {if (this.sourcetext === '') {this.targettext = ''}}/*** 翻译结果回调函数* @param data 翻译返回的数据* @description 处理翻译结果并更新到目标文本*/cb(data: string) {getResult(data)?.forEach((item) => {this.targettext += item})}/*** 执行翻译操作* @description * 1. 检查源文本是否为空* 2. 清空之前的翻译结果* 3. 调用翻译API* 4. 处理可能的错误*/to: () => void = () => {if (this.sourcetext) {this.targettext = ''postllm(this.sourcetext, this.cb.bind(this)).catch((e: string) => {console.error('gxxt ', e)})} else {AlertDialog.show({title: '提示', message: '请输入要翻译的内容', confirm: {value: '确定', action: () => {}}})}}/*** 复制翻译结果到剪贴板* @description * 1. 检查是否有翻译结果* 2. 创建剪贴板数据* 3. 设置到系统剪贴板* 4. 显示操作结果提示*/cpck: () => void = () => {if (this.targettext !== '') {let pasttext = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, this.targettext)let jianqieban = pasteboard.getSystemPasteboard()jianqieban.setDataSync(pasttext)promptAction.showToast({ message: '已经复制到剪切板' })} else {promptAction.showToast({ message: '没有翻译结果,无法复制到剪切板' })}}/*** 保存到生词本* @description * 1. 记录翻译内容* 2. 记录原文* 3. 记录保存时间*/tobeiwanglu: () => void = () => {saveshengci({content: this.targettext,trans: this.sourcetext,time: gettime()}, this.context)}/*** 构建UI界面* @description * 1. 顶部标题栏* 2. 中间内容区域(源文本和翻译结果)* 3. 底部操作栏(复制和生词本功能)*/build() {Column() {headerview({ text: '星星翻译', isleft: false })contentview({ sourcetext: this.sourcetext, targettext: this.targettext, transopt: this.to })footerview({ clipck: this.cpck, tobeiwanglu: this.tobeiwanglu })}.width('100%').height('100%')}
}

子组件contentview核心代码:

/*** contentview.ets* 翻译内容视图组件* 提供文本输入、翻译结果显示、文本选择、复制、生词本等功能*/import { promptAction } from "@kit.ArkUI"
import { pasteboard } from "@kit.BasicServicesKit"
import { saveshengci } from "../utils/Dbutils"
import { posttxt } from "../utils/HttpUtils"
import { common } from "@kit.AbilityKit"
import { gettime } from "../utils/StringUtils"/***作者:gxx*时间:2025/5/6 14:51*功能:**/
@Preview
@Component
export struct contentview {// 源文本,用于存储用户输入的待翻译文本@Link sourcetext: string// 目标文本,用于存储翻译结果@Link targettext: string// 获取UI上下文private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext// 翻译操作回调函数transopt: () => void = () => {}// 当前选中的文本private selecttext: string = ''// 是否全选状态@State isquanxuan: boolean = false// 是否显示菜单@State ismenushow: boolean = truebuild() {Stack() {Column() {// 输入区域Column() {TextArea({ placeholder: '要翻译的文本' }).width('100%').height('100%').backgroundColor(Color.Transparent).onChange((value) => {this.sourcetext = value.trim()})}.width('100%').height('45%').padding(10).border({ width: 2, color: '#eee' }).borderRadius({ topLeft: 10, topRight: 10 }).backgroundColor(Color.White)// 翻译结果区域Column() {Scroll() {Text(this.targettext === '' ? '翻译结果' : this.targettext).width('100%').copyOption(CopyOptions.InApp).fontWeight(FontWeight.Bolder).backgroundColor(Color.Transparent).fontColor(this.targettext === '' ? Color.Gray : Color.Black)// 绑定长按菜单.bindSelectionMenu(TextSpanType.TEXT, this.genselectmenu(), TextResponseType.LONG_PRESS, {onDisappear: () => {this.ismenushow = truethis.isquanxuan = false}})// 文本选择变化监听.onTextSelectionChange((start: number, end: number) => {this.selecttext = this.targettext.substring(start, end)})// 全选状态控制.selection(this.isquanxuan ? 0 : -1, this.isquanxuan ? this.targettext.length : 0)}.scrollable(ScrollDirection.Vertical)}.width('100%').height('45%').padding(10).backgroundColor('#eee').borderRadius({ bottomLeft: 10, bottomRight: 10 })}.width('100%').height('100%').justifyContent(FlexAlign.SpaceBetween)// 翻译按钮SymbolGlyph($r('sys.symbol.reverse_order')).fontSize(35).fontWeight(FontWeight.Bolder).border({ width: 2, radius: 10 }).padding(5).stateStyles({normal: {.backgroundColor(Color.White)},pressed: {.backgroundColor(Color.Gray)}}).onClick(() => {this.transopt()})}.width('100%').height('80%').padding(10)}/*** 生成文本选择菜单* 包含复制、全选、添加到生词本等功能*/@Buildergenselectmenu() {Row({ space: 15 }) {// 复制按钮Text('复制').fontSize(12).onClick(() => {let pasttext = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, this.selecttext)let jianqieban = pasteboard.getSystemPasteboard()jianqieban.setDataSync(pasttext)promptAction.showToast({ message: '已经复制到剪切板' })this.ismenushow = false})// 全选按钮(仅在非全选状态显示)if (!this.isquanxuan) {Text('全选').fontSize(12).onClick(() => {this.isquanxuan = true})}// 生词本按钮Text('生词本').fontSize(12).onClick(() => {this.ismenushow = falseif (this.isquanxuan) {// 全选状态下保存整个翻译结果saveshengci({content: this.targettext,trans: this.sourcetext,time: gettime()}, this.context)} else {// 选中状态下翻译选中文本并保存posttxt(this.selecttext).then((value) => {let target = value.query// 拼接好的翻译结果let source = value.translation.join(',')saveshengci({content: target,trans: source,time: gettime()}, this.context)}).catch((e: Error) => {console.error('gxxt 文本翻译结果: ', e.message)})}})}.backgroundColor(Color.White).padding(10).borderRadius(20).border({ width: 1 }).visibility(this.ismenushow ? Visibility.Visible : Visibility.None)}
}

生词本页面代码

这是一个生词本界面,采用简洁现代的设计风格。界面顶部是标题栏,显示"生词本"标题,左侧配有返回按钮,方便用户返回上一页面。

主体部分是一个可滚动的生词列表,每个生词条目以卡片形式展示,包含两个主要信息:上方显示生词内容,采用较大字号和粗体样式;下方显示对应的翻译内容,使用灰色字体。每个条目右侧都有一个箭头图标,提示用户可以点击查看详情。

用户可以通过左滑生词条目来显示删除按钮,点击删除按钮会弹出确认对话框,防止误操作。点击生词条目会弹出一个详情对话框,以更大的字体展示完整的生词内容和翻译,并显示保存时间。如果内容较长,对话框支持滚动查看。

/*** shengciben.ets* 生词本页面组件* 提供生词列表展示、详情查看、删除等功能*/import { shengci } from '../model/shengci';
import { delbyid, querylimit } from '../utils/Dbutils';
import { common } from '@kit.AbilityKit';
import { headerview } from '../views/headerview';
import { ComponentContent, router } from '@kit.ArkUI';/*** 生成生词详情对话框* @param p 对话框参数,包含生词信息、删除回调、滚动高度等*/
@Builder
function gendialog(p: param) {Stack() {// 关闭按钮SymbolGlyph($r('sys.symbol.xmark')).fontSize(20).onClick(() => {p.delck()}).zIndex(2)Column({ space: 10 }) {// 标题Text('生词详情').fontSize(25).fontWeight(FontWeight.Bolder)Divider().color(Color.Grey).margin({ top: 10, bottom: 10 })// 内容区域Scroll() {Column({ space: 10 }) {// 生词内容Text(p.item.content).fontSize(18).fontWeight(FontWeight.Bold)// 翻译内容Text(p.item.trans).fontSize(14).fontColor(Color.Gray)}.alignItems(HorizontalAlign.Start)}.height(p.scrollheight)Divider().color(Color.Grey).margin({ top: 10, bottom: 10 })// 时间信息Text('时间:').fontSize(18).fontWeight(FontWeight.Bold)Text(p.item.time).fontSize(14).fontColor(Color.Gray)}.width('100%').alignItems(HorizontalAlign.Start)}.width('80%').borderRadius(10).alignContent(Alignment.TopEnd).backgroundColor(Color.White).border({ width: 1 }).padding(10)
}/*** 对话框参数接口*/
interface param {item: shengci,        // 生词信息delck: () => void,    // 删除回调函数scrollheight: Length, // 滚动区域高度
}/*** 生词本页面组件*/
@Entry
@Component
struct Shengciben {@State message: string = 'Hello World';@State datas: shengci[] = []  // 生词列表数据private builder: ComponentContent<param> | null = nullprivate context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext/*** 组件即将出现时加载数据*/aboutToAppear(): void {querylimit(this.context, 1).then((value) => {this.datas = value}).catch((e: Error) => {console.error('gxxt 查询生词本错误: ', e.message)})}build() {Column() {// 顶部标题栏headerview({text: '生词本', isright: false, leftck: () => {router.back()}})// 生词列表List({ space: 5 }) {ForEach(this.datas, (item: shengci, index: number) => {ListItem() {this.genlistitem(item)}.swipeAction({ end: this.genitemend(item.id, index) })  // 左滑显示删除按钮.onClick(() => {// 点击显示详情弹窗let p: param = {item: item,delck: () => {this.getUIContext().getPromptAction().closeCustomDialog(this.builder)},scrollheight: item.content.length + item.trans.length > 150 ? 300 : 'auto'}this.builder = new ComponentContent(this.getUIContext(), wrapBuilder<[param]>(gendialog), p)this.getUIContext().getPromptAction().openCustomDialog(this.builder, {alignment: DialogAlignment.Center})})})}.margin({ top: 5 })}.width('100%').height('100%')}/*** 生成列表项右滑删除按钮* @param id 生词ID* @param index 列表索引*/@Buildergenitemend(id: number, index: number) {Row() {SymbolGlyph($r('sys.symbol.trash_fill')).fontSize(30).fontColor([Color.Red])}.padding({left: 10,top: 5,bottom: 5,right: 10}).border({ width: 1, radius: 10 }).margin(5).onClick(() => {// 删除确认对话框AlertDialog.show({title: '提示',message: '确定要删除吗?',primaryButton: {value: '确定', action: () => {delbyid(id, this.context).then(() => {this.datas.splice(index, 1)})}},secondaryButton: {value: '取消', action: () => {}}})})}/*** 生成列表项内容* @param item 生词信息*/@Buildergenlistitem(item: shengci) {Row() {Column({ space: 5 }) {// 生词内容Text(item.content).fontSize(20).fontWeight(FontWeight.Bolder).width('60%').textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1)// 翻译内容Text(item.trans).fontSize(14).fontColor(Color.Gray).width('60%').textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1)}Blank()// 右箭头图标SymbolGlyph($r('sys.symbol.chevron_right')).fontSize(20)}.width('100%').padding({left: 5,top: 10,bottom: 10,right: 5}).border({ width: 1, radius: 5 })}
}

完整项目代码:

https://download.csdn.net/download/gao_xin_xing/90892395

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vim 中设置插入模式下输入中文

在 Vim 中设置插入模式下输入中文需要配置输入法切换和 Vim 的相关设置。以下是详细步骤&#xff1a; 1. 确保系统已安装中文输入法 在 Linux 系统中&#xff0c;常用的中文输入法有&#xff1a; IBus&#xff08;推荐&#xff09;&#xff1a;支持拼音、五笔等Fcitx&#xf…

湖北理元理律师事务所:债务优化中的“生活锚点”设计

在债务重组领域&#xff0c;一个常被忽视的核心矛盾是&#xff1a;还款能力与生存需求的冲突。过度压缩生活支出还债&#xff0c;可能导致收入中断&#xff1b;放任债务膨胀&#xff0c;又加剧精神压力。湖北理元理律师事务所通过“三步平衡法”&#xff0c;尝试在法理框架内破…

Prometheus + Grafana 监控常用服务

一、引言 Prometheus监控常见服务的原理主要包括服务暴露指标和Prometheus抓取指标。一方面&#xff0c;被监控服务通过自身提供的监控接口或借助Exporter将服务的性能指标等数据以HTTP协议的方式暴露出来&#xff1b;另一方面&#xff0c;Prometheus根据配置好的采集任务&…

基于YOLOv8 的分类道路目标系统-PyTorch实现

本文源码: https://download.csdn.net/download/shangjg03/90873939 1. 引言 在智能交通和自动驾驶领域,道路目标分类是一项关键技术。通过对摄像头捕获的图像或视频中的目标进行分类识别,可以帮助车辆或系统理解周围环境,做出更安全的决策。本教程将介绍如何使用 PyTorch …

知识图谱:AI时代语义认知的底层重构逻辑

在生成式人工智能&#xff08;GEO&#xff09;的技术架构中&#xff0c;知识图谱已从辅助性工具演变为驱动机器认知的核心神经中枢。它通过结构化语义网络的重构&#xff0c;正在突破传统数据处理的线性逻辑&#xff0c;建立机器对复杂业务场景的深度理解能力。 一、语义解构&a…

如何使用 Python 的胶水语言特性

Python 作为“胶水语言”最核心的特性在于&#xff1a;跨语言集成能力强、支持丰富的 C/C 扩展模块、嵌入式调用简便、适配多种数据交换格式、拥有强大的封装能力。其中&#xff0c;Python 对 C/C 模块的快速封装能力&#xff0c;使其能够将底层高性能库暴露为易用接口&#xf…

[网页五子棋][匹配模块]服务器开发、用户管理器(创建匹配请求/响应对象、处理连接成功、处理下线)

文章目录 MatchAPI 类用户管理器创建匹配请求/响应对象处理连接成功—afterConnectionEstablished处理下线——handleTransportError/afterConnectionClosed MatchAPI 类 创建 api.MatchAPI&#xff0c;继承自 TextWebSocketHandler 作为处理 WebSocket 请求的入口类 准备好一…

软件测试的潜力与挑战:从“质量守门员”到“工程效能催化剂”的进化

1. 潜力&#xff1a;为什么软件测试的未来比想象中更广阔&#xff1f; ✅ 行业趋势驱动需求爆发 DevOps/持续交付&#xff1a;测试成为流水线的核心环节&#xff0c;自动化能力直接影响发布频率&#xff08;案例&#xff1a;某头部互联网企业日均发布100次&#xff0c;依赖自动…

indel_snp_ssr_primer

好的&#xff0c;我们可以逐步分析这个 Perl 脚本的每个部分。脚本的主要功能是基于给定的 VCF 文件和参考基因组文件&#xff0c;设计引物并进行电子 PCR&#xff08;e-PCR&#xff09;分析。我们将从脚本的头部和初始化部分开始讲解。 第一部分&#xff1a;脚本头部和初始化…

2.4GHz 射频前端芯片AT2401C

射频前端芯片作为无线通信系统的核心组件&#xff0c;涵盖功率放大器&#xff08;PA&#xff09;、滤波器、开关、低噪声放大器&#xff08;LNA&#xff09;等关键器件&#xff0c;其性能直接影响通信质量、功耗及信号稳定性。 AT2401C是一款面向 Zigbee&#xff0c;无线传感网…

Batch Normalization[[

error surface如果很崎岖,那么就代表比较难train,我们有没有办法去改变这个landscape呢 可以用batch normalization. 如果 ( x_1 ) 的取值范围很小&#xff08;如 1, 2&#xff09;&#xff0c;而 ( x_2 ) 的取值范围很大&#xff08;如 100, 200&#xff09;&#xff0c;那么…

c++结构化绑定

author: hjjdebug date: 2025年 05月 28日 星期三 15:57:58 CST descrip: c结构化绑定: 结构化绑定: 名称辨析: 名称叫绑定好还是叫解绑好&#xff1f; 解绑意思是原来是一个整体,现在被分成了若干个部分,所以叫解. 绑定强调的意思是. 被分解的某个变量,绑定到了整体的某个变量…

大数据治理:理论、实践与未来展望(一)

文章目录 一、大数据治理的定义与重要性&#xff08;一&#xff09;定义&#xff08;二&#xff09;重要性 二、大数据治理的应用场景&#xff08;一&#xff09;金融行业&#xff08;二&#xff09;医疗行业&#xff08;三&#xff09;制造业&#xff08;四&#xff09;零售行…

AI系统化学习月计划6月计划

以下是为技术总监设计的 AI系统化学习月计划&#xff08;每天投入2小时&#xff0c;共30天&#xff09;&#xff0c;结合战略思维、技术基础、实战应用和行业趋势&#xff0c;帮助您快速掌握AI的核心知识&#xff0c;并转化为业务决策能力。 第一周&#xff1a;AI基础与战略思维…

详解MySQL调优

目录 1. SQL 语句优 1.1 避免低效查询 1.2 索引优化 1.3 分析执行计划 2. 数据库配置优化 2.1 核心参数调整 2.2 表结构与存储引擎 2.3 存储引擎选择 3. 事务与锁优化 3.1 事务控制 3.2 锁机制优化 3.3 批量操作优化 4. 其他优化手段 4.1 监控与分析工具 4.2 读写…

VScode单双引号、分号格式

1、settings.json中添加&#xff1a; 1 2 3 "prettier.semi": false, // 取消自动加分号 "prettier.singleQuote": true, // 保持单引号&#xff0c;不自动变双引号 "prettier.trailingComma": "none" // 去掉结尾的逗号 2、如上一步…

自动驾驶规划控制教程——不确定环境下的决策规划

引言:驾驭未知——不确定性下的自动驾驶决策挑战 自动驾驶汽车 (Autonomous Vehicles, AVs) 的愿景是彻底改变交通运输的面貌,提高道路安全、提升交通效率、改善驾乘体验。然而,要将这一愿景安全可靠地付诸实践,自动驾驶系统必须能够在复杂、动态且充满不确定性的真实世界…

电缆中性点概念

电缆中性点概念 电缆中性点(也称“中性点”或“中性线”)是电力系统和电气设备中一个非常重要的概念,尤其在三相电系统中。下面是对中性点概念的系统性解释。 1. 基本定义 中性点:三相电缆(A/B/C相)的电压矢量交汇点,理想情况下三相平衡时该点电压为零。对于星形(Y形…

MyBatis 动态 SQL 详解:灵活构建强大查询

MyBatis 的动态 SQL 功能是其最强大的特性之一&#xff0c;它允许开发者根据不同条件动态生成 SQL 语句&#xff0c;极大地提高了 SQL 的灵活性和复用性。本文将深入探讨 MyBatis 的动态 SQL 功能&#xff0c;包括 OGNL 表达式的使用以及各种动态 SQL 元素&#xff08;如 if、c…

嵌入式自学第三十天(5.28)

&#xff08;1&#xff09;多线程资源竞争问题&#xff1a; 互斥&#xff1a;在多线程中对临界资源的排他性访问。 解决方案&#xff1a;互斥锁 mutex互斥锁在进程pcb块&#xff0c;ret 为0说明别人在用&#xff0c;1说明空闲。 阻塞锁 man pthread_mutex_init man pthread_…