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

【HarmonyOS开发】案例-记账本开发

图片

OpenHarmony最近一段时间,简直火的一塌糊度,学习OpenHarmony相关的技术栈也有一段时间了,做个记账本小应用,将所学知识点融合记录一下。

1、记账本涉及知识点

  •     基础组件(Button、Select、Text、Span、Divider、Image)、容器(Row、Flex、List、Grid、Column)、定位(position)、路由(router)、Toast(promptAction)、Web组件;
  •     自定义弹窗(@CustomDialog);
  •     分布式键值数据库(@ohos.data.distributedKVStore);
  •     Web组件;
  •     OpenHarmony三方库;

2、效果预览

图片

  

图片

图片

  

图片

3、功能点实现简介

3.1 自定义弹窗


// 自定义弹窗定义
@CustomDialog
struct CustomDialogSetting {// 双向绑定传值@Link settingBudgetValue: string// 弹窗控制器,控制打开/关闭,必须传入,且名称必须为:controllercontroller: CustomDialogController// 弹窗中的按钮事件cancel: () => voidconfirm: () => void// 弹窗中的内容描述build() {Column() {Text($r('app.string.budget_setting')).fontSize(18).fontWeight(FontWeight.Bold).margin(12).textAlign(TextAlign.Center).width("100%")TextInput({placeholder: $r('app.string.estimated_amount_tips'),text: this.settingBudgetValue}).type(InputType.Number).height(60).width('90%').onChange((value: string) => {this.settingBudgetValue = value})Flex({ justifyContent: FlexAlign.SpaceAround }) {Button($r('app.string.cancel')).onClick(() => {this.settingBudgetValue = ''this.controller.close()this.cancel()}).backgroundColor(0xffffff).fontColor(Color.Black)Button($r('app.string.confirm')).onClick(() => {this.controller.close()this.confirm()}).backgroundColor(0xffffff).fontColor(AccountBookConstant.FONT_COLOR_BLUE)}.margin(15)}}
}
// 使用自定义弹窗
dialogController: CustomDialogController = new CustomDialogController({builder: CustomDialogSetting({cancel: this.onCancel.bind(this),confirm: this.onAccept.bind(this),settingBudgetValue: $settingBudgetValue}),cancel: this.onCancel,autoCancel: true,alignment: DialogAlignment.Center,gridCount: 4,customStyle: false
})// 开启弹窗
this.dialogController.open()

3.2 悬浮按钮

// 设置按钮, 通过position进行绝对定位
Button({  stateEffect: true }){Image($rawfile('setting.svg')).width(22).height(22)
}.width(42).height(42)
.borderRadius(90)
.shadow({ radius: 10, color: Color.Gray, offsetX: 5, offsetY:5 })
.position({ x: '98%', y: '98%' })
.markAnchor({ x: '98%', y: '98%'})
.margin(10).backgroundColor('#67C23A')
.onClick(() => {if (this.dialogController != undefined) {this.dialogController.open()}
})

3.3  数据存储

// 定义键值对存储类import distributedKVStore from '@ohos.data.distributedKVStore';const BUNDLE_NAME = "baseInfo"let context = getContext(this)
// 数据库对象
let kvManager: distributedKVStore.KVManager | undefined = undefined;
// KVStore数据库
let kvStore: distributedKVStore.SingleKVStore | undefined = undefined;class DistributedUtil {constructor() {this.createKeyValueDB();}async getKvManager(bundleName?: string) {const kvStoreConfig: distributedKVStore.KVManagerConfig = {context: context,bundleName: bundleName || BUNDLE_NAME};try {kvManager = distributedKVStore.createKVManager(kvStoreConfig);}catch (err) {console.error(`error:${err}`)}}// 创建并得到指定类型的KVStore数据库async createKeyValueDB(op?: distributedKVStore.Options) {if (!kvManager) {await this.getKvManager();}try {const options: distributedKVStore.Options = {// 当数据库文件不存在时是否创建数据库,默认为truecreateIfMissing: true,// 设置数据库文件是否加密,默认为false,即不加密encrypt: false,// 设置数据库文件是否备份,默认为true,即备份backup: false,// 设置数据库文件是否自动同步。默认为false,即手动同步autoSync: true,// kvStoreType不填时,默认创建多设备协同数据库kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION,// 多设备协同数据库:kvStoreType: distributedKVStore.KVStoreType.DEVICE_COLLABORATION,securityLevel: distributedKVStore.SecurityLevel.S1};kvManager.getKVStore<distributedKVStore.SingleKVStore>('storeId', op || options, (err, store: distributedKVStore.SingleKVStore) => {if (err) {console.error(`Failed to get KVStore: Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in getting KVStore.');kvStore = store;});} catch (e) {console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}return kvStore;}// 删除指定键值的数据async deleteStoreData(key: string) {if (!kvStore) {return;}try {kvStore.delete(key, (err) => {if (err !== undefined) {console.error(`Failed to delete data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in deleting data.');});} catch (e) {console.error(`An unexpected error occurred. Code:${e.code},message:${e.message}`);}}// 向键值数据库中插入数据async putStoreData(key: string, value: any) {if (!key || !value) {return}if(!kvStore) {kvStore = await this.createKeyValueDB();}try {kvStore.put(key, value, (err) => {if (err !== undefined) {console.error(`Failed to put data. Code:${err.code},message:${err.message}`);return;}console.info('Succeeded in putting data.');});} catch (e) {console.error(`putStoreData===>An unexpected error occurred. Code:${e.code},message:${e.message}`);}}// 获取指定键的值async getStoreData(key: string) {if (!key) {return}if(!kvStore) {kvStore = await this.createKeyValueDB();}return new Promise((resolve, reject) => {try {kvStore.get(key, (err, data) => {if (err != undefined) {console.error(`Failed to get data. Code:${err.code},message:${err.message}`);reject(err)return;}resolve(data)});} catch (err) {reject(err)console.error('TAG-getStoreData', `Failed to get value, Cause: ${err}`)}});}
}export default new DistributedUtil();
// 使用键值对存储
import distributedUtil from '../../common/distributedStrong'
// 1、增加
distributedUtil.putStoreData('amountRecords', JSON.stringify(dataArray))
// 2、 获取
distributedUtil.getStoreData('amountRecords').then((res: string) => {if(res) {const result = JSON.parse(res)// 处理存储的图片资源,会自动转换为id的形式,无法直接获取展示result.map(item => {item.icon = $rawfile(item.icon.params[0])return item})this.recordsArray = result}
})

3.4 统计图表

3.4.1 定义本地html文件

在resources下创建rawfile文件夹,增加chart.html文件

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>柱状图示例</title><script src="./js/echarts5.4.0.js"></script>
</head>
<body>
<h1>本月支出</h1>
<div id="chartBarContainer" style="width: 400px; height: 300px;"></div><div id="chartPieContainer" style="width: 400px; height: 300px;"></div></body>
<script>function initBarChart(chartData) {const data = JSON.parse(chartData);var chartContainer = document.getElementById('chartBarContainer');var chart = echarts.init(chartContainer);var option = {tooltip: {trigger: 'axis',axisPointer: {type: 'shadow'}},xAxis: {type: 'category',data: data.xAxisData},yAxis: {type: 'value'},series: [{data: data.seriesData,type: 'bar',showBackground: true,stack: 'Total',label: {show: true,position: 'top'},emphasis: {itemStyle: {color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#2378f7' },{ offset: 0.7, color: '#2378f7' },{ offset: 1, color: '#83bff6' }])}},itemStyle: {borderRadius: [25, 25, 0, 0],color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: '#83bff6' },{ offset: 0.5, color: '#188df0' },{ offset: 1, color: '#188df0' }])}}]};chart.setOption(option);}function initPieChart(chartData) {const data = JSON.parse(chartData);var chartContainer = document.getElementById('chartPieContainer');var chart = echarts.init(chartContainer);var option = {tooltip: {trigger: 'item'},legend: {show: false,top: '5%',left: 'center'},series: [{data: data.seriesData,type: 'pie',radius: ['40%', '70%'],avoidLabelOverlap: false,itemStyle: {borderRadius: 10,borderColor: '#fff',borderWidth: 2},startAngle: 180,labelLine: {show: true,length: 20, // 标签线的长度length2: 50 // 标签线的第二段长度},emphasis: {label: {show: true,fontSize: 40,fontWeight: 'bold'}},labelLine: {show: false}}]};chart.setOption(option);}
</script>
</html>

3.4.2 Web组件使用本地文件

import web_webview from '@ohos.web.webview'@Entry
@Component
struct Chart {controllerWeb: web_webview.WebviewController = new web_webview.WebviewController()build() {Web({ src: $rawfile('barChart.html'), controller: this.controllerWeb })}
}

3.4.3 Web组件向H5页面传值,调用H5中的方法

// 初始化柱状图
const codeJS = `initBarChart('${JSON.stringify(this.chartBarData)}')
`
this.controllerWeb.runJavaScript(codeJS)

3.4.4 完整调用代码

import web_webview from '@ohos.web.webview'
import router from '@ohos.router';interface ChartDataType {xAxisData?: Array<string | number>;seriesData?: Array<string | number | any>;
}@Entry
@Component
struct BarChart {controllerWeb: web_webview.WebviewController = new web_webview.WebviewController()private chartBarData: ChartDataType = {xAxisData: ['餐饮', '购物', '教育', '生活', '宠物', '运动', '娱乐', '其他'],seriesData: [10, 20, 15, 30, 10, 20, 15, 30],}private chartPieData: ChartDataType = {seriesData: [{ value: 10, name: '餐饮' },{ value: 20, name: '购物' },{ value: 15, name: '教育' },{ value: 30, name: '生活' },{ value: 10, name: '宠物' },{ value: 20, name: '运动' },{ value: 15, name: '娱乐' },{ value: 30, name: '其他' },],}build() {Column() {Row() {Button() {Image($rawfile('icon_back.png')).width(18)}.backgroundColor(Color.Transparent).padding(10).onClick(() => router.back())Text('图表分析').fontSize(20).fontWeight(FontWeight.Bold)}.padding(10).justifyContent(FlexAlign.SpaceBetween).width('100%')Web({ src: $rawfile('barChart.html'), controller: this.controllerWeb }).verticalScrollBarAccess(true).javaScriptAccess(true).onPageEnd(() => {// 初始化柱状图const codeJS = `initBarChart('${JSON.stringify(this.chartBarData)}')`this.controllerWeb.runJavaScript(codeJS)// 初始化饼图const codeJSPie = `initPieChart('${JSON.stringify(this.chartPieData)}')`this.controllerWeb.runJavaScript(codeJSPie)})}.width('100%').height('100%')}
}

3.4.5 传值注意点总结

  • 传递数据需要通过 JSON.stringify() 转换为字符串;
  • 传递的参数必须使用引号包裹,否则无法调用到H5中的方法;
  • H5中使用传过来的数据,同理,需要使用 JSON.parse() 进行转换;

3.5  自定义键盘

使用Grid布局,通过rowStart、rowEnd、columnStart、columnEnd进行单元格合并。或者使用column和row布局,循环即可。

参考:https://gitee.com/harmonyos/codelabs/tree/master/SimpleCalculator

Grid() {GridItem() {this.GridItemButtonBuilder('7')}.gridItemStyle().onClick(() => { this.clickBtn(7) })GridItem() {this.GridItemButtonBuilder('8')}.gridItemStyle().onClick(() => { this.clickBtn(8) })GridItem() {this.GridItemButtonBuilder('9')}.gridItemStyle().onClick(() => { this.clickBtn(9) })GridItem() {Text(this.time).backgroundColor(Color.White).width('100%').height('100%').textAlign(TextAlign.Center)}.gridItemStyle()GridItem() {this.GridItemButtonBuilder('4')}.gridItemStyle().onClick(() => { this.clickBtn(4) })GridItem() {this.GridItemButtonBuilder('5')}.gridItemStyle().onClick(() => { this.clickBtn(5) })GridItem() {this.GridItemButtonBuilder('6')}.gridItemStyle().onClick(() => { this.clickBtn(6) })GridItem() {this.GridItemButtonBuilder('remove')}.gridItemStyle().onClick(() => { this.clickBtn('remove') })GridItem() {this.GridItemButtonBuilder('1')}.gridItemStyle().onClick(() => { this.clickBtn('1') })GridItem() {this.GridItemButtonBuilder('2')}.gridItemStyle().onClick(() => { this.clickBtn('2') })GridItem() {this.GridItemButtonBuilder('3')}.gridItemStyle().onClick(() => { this.clickBtn('3') })GridItem() {this.GridItemButtonBuilder('保存', '#409EFF')}.rowStart(2).rowEnd(3).columnStart(3).columnEnd(4).onClick(() => { this.clickBtn('save') })GridItem() {this.GridItemButtonBuilder('清空')}.gridItemStyle().onClick(() => { this.clickBtn('clear') })GridItem() {this.GridItemButtonBuilder('0')}.gridItemStyle().onClick(() => { this.clickBtn('0') })GridItem() {this.GridItemButtonBuilder('.')}.gridItemStyle().onClick(() => { this.clickBtn('.') })
}
.height(220)
.columnsTemplate('1fr 1fr 1fr 1fr')
.rowsTemplate('1fr 1fr 1fr 1fr')
.rowsGap(0)
.margin({ top: 0 })

4、扩展(如何使用基础组件自定义柱状图)

  • 使用Stack容器进行堆叠
  • 通过Rect绘制柱子
  • 通过Divider绘制分割线

    一个简单的柱状图就完成了,具体可以参考健康生活,希望ArkUI可以早日集成Echarts类似的图表组件,JS版本的有Chart组件,ArkTs的还未集成,期待官方❤️❤️❤️

@Builder
content(item: OneMealStatisticsInfo) {Column() {if (item.totalFat > 0) {Rect({ width: 14, height: item.totalFat / 200 + 14, radius: 7 }).fill('#FD9A42').padding({ top: 14 }).margin({ bottom: -28 })}if (item.totalProtein > 0) {Rect({ width: 14, height: item.totalProtein / 200 + 14, radius: 7 }).fill('#FBD44E').padding({ top: 14 }).margin({ bottom: -21 })}if (item.totalCarbohydrates > 0) {Rect({ width: 14, height: item.totalCarbohydrates / 200 + 14, radius: 7 }).fill('#73CD57').padding({ top: 7 }).margin({ bottom: -7 })}}.clip(true)}@Builder
legendComponent(item: HistogramLegend) {Text(item.value).fontSize(12).fontColor('#18181A').fontFamily('HarmonyHeTi')
}@Component
struct Histogram {@Consume("dietData") dietData: Array<OneMealStatisticsInfo>@BuilderParam content?: (item: OneMealStatisticsInfo) => void@BuilderParam legendComponent?: (item: HistogramLegend) => voidprivate title: string | Resource = ''private legend: HistogramLegend[] = []build() {Column() {Text(this.title).textAlign(TextAlign.Start).fontSize(24).fontColor('#000000').fontFamily('HarmonyHeTi-Medium').width('100%').height(46)Stack({ alignContent: Alignment.Bottom }) {Column() {ForEach([0, 0, 0, 0, 0, 0], () => {Divider().strokeWidth(1).color('#D8D8D8')})}.height('100%').margin({ top: 20 }).justifyContent(FlexAlign.SpaceBetween)Column() {Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.SpaceEvenly, alignItems: ItemAlign.Start }) {ForEach(this.dietData, (item: OneMealStatisticsInfo) => {if (item.mealFoods.length > 1) {Column() {if (this.content !== undefined) {this.content(item)}Text(item.mealTime.name).fontSize(14).fontColor('#7E7E7E').fontFamily('HarmonyHeTi').margin({ top: 10 })}.justifyContent(FlexAlign.End).height('100%')}})}}.height(236)}.height(190)Row() {ForEach(this.legend, (item: HistogramLegend) => {Row() {Rect({ width: 9, height: 9, radius: 9 }).fill(item.color).margin({ right: 18 })if (this.legendComponent !== undefined) {this.legendComponent(item)}}})}.justifyContent(FlexAlign.SpaceEvenly).width('100%').margin({ top: 70 })}.height('100%').padding({ left: 32, right: 32 }).borderRadius(12).backgroundColor('#FFFFFF')}
}

后面计划基于canvas基础组件实现一个柱状图,不断学习,期望鸿蒙不断强大完善。

相关文章:

【HarmonyOS开发】案例-记账本开发

OpenHarmony最近一段时间&#xff0c;简直火的一塌糊度&#xff0c;学习OpenHarmony相关的技术栈也有一段时间了&#xff0c;做个记账本小应用&#xff0c;将所学知识点融合记录一下。 1、记账本涉及知识点 基础组件&#xff08;Button、Select、Text、Span、Divider、Image&am…...

webrtc中的接口代理框架

文章目录 接口代理框架Proxy体系类结构导出接口 webrtc的实际运用PeerConnectionFactoyPeerConnection使用 接口代理框架 webrtc体系庞大&#xff0c;模块化极好&#xff0c;大多数模块都可以独立使用。模块提供接口&#xff0c;外部代码通过接口来使用模块功能。 在webrtc中通…...

【AIGC-图片生成视频系列-4】DreamTuner:单张图像足以进行主题驱动生成

目录 一. 项目概述 问题&#xff1a; 解决&#xff1a; 二. 方法详解 a) 整体结构 b) 自主题注意力 三. 文本控制的动漫角色驱动图像生成的结果 四. 文本控制的自然图像驱动图像生成的结果 五. 姿势控制角色驱动图像生成的结果 2023年的最后一天&#xff0c;发个文记录…...

Jupyter Notebook的10个常用扩展介绍

Jupyter Notebook&#xff08;前身为IPython Notebook&#xff09;是一种开源的交互式计算和数据可视化的工具&#xff0c;广泛用于数据科学、机器学习、科学研究和教育等领域。它提供了一个基于Web的界面&#xff0c;允许用户创建和共享文档&#xff0c;这些文档包含实时代码、…...

uniapp项目如何引用安卓原生aar插件(避坑指南三)

官方文档说明&#xff1a;uni小程序SDK 【彩带- 避坑知识点】 如果引用原生aar插件&#xff0c;都配置好之后&#xff0c;云打包&#xff0c;报不包含此插件&#xff0c;除了检查以下步骤流程外&#xff0c;还要检查一下是否上打包的原生插件aar流程有问题。 1.第一步在uniapp项…...

YOLOv8改进 | 检测头篇 | ASFF改进YOLOv8检测头(全网首发)

一、本文介绍 本文给大家带来的改进机制是利用ASFF改进YOLOv8的检测头形成新的检测头Detect_ASFF&#xff0c;其主要创新是引入了一种自适应的空间特征融合方式&#xff0c;有效地过滤掉冲突信息&#xff0c;从而增强了尺度不变性。经过我的实验验证&#xff0c;修改后的检测头…...

思维训练-怎样设计一个MQ

架构师需要做各种设计&#xff0c;要不断地提高自己的设计能力。这有没有方法可以训练呢&#xff1f;有的&#xff0c;就是看到什么、想到什么&#xff0c;就假设对面坐着产品经理&#xff0c;一起讨论怎么把它设计出来。比如怎样设计一个MQ 我&#xff1a;首先我确认一下需求。…...

RK3399平台入门到精通系列讲解(导读篇)21天挑战Linux系统开发

🚀返回总目录 文章目录 一、关于作者1、博主的联系方式2、支持二、需要具备的知识和工具1、需掌握知识点2、需了解的知识点三、通过系列博客可以学到什么1、本系列博文特色2、21天学习目标3、21天学习内容4、学习时间5、学习产出...

企业微信会话存档sdk报错:A fatal error has been detected by the Java Runtime Environment

错误信息 # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc0x00007f218f93485d, pid10, tid58 # # JRE version: OpenJDK Runtime Environment 18.9 (11.0.14.11) (build 11.0.14.11) # Java VM: OpenJDK 64-Bit Server VM 18.9…...

nginx-docker 搭建websocket反向代理

下载镜像 docker pull nginx复制出配置文件 将/etc/nginx/nginx.conf和/etc/nginx/conf.d/default.conf复制到本机 nginx.conf文件内容 user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; pid /var/run/nginx.pid;events {worker_c…...

blender插件开发

Quickstart — Blender Python API Blender Python 编程&#xff1a;关键概念 - 知乎 系列目录链接&#xff08;更新中&#xff0c;如无链接说明未更新&#xff09; [Blender Python] 列出/插入/删除物体&#xff0c;Blender数据对象 - 知乎 (zhihu.com)[Blender Python] 设…...

【数据结构】二叉搜索(查找/排序)树

一、二叉搜索树基本概念 1、定义 二叉搜索树&#xff0c;又称为二叉排序树&#xff0c;二叉查找树&#xff0c;它满足如下四点性质&#xff1a; 1&#xff09;空树是二叉搜索树&#xff1b; 2&#xff09;若它的左子树不为空&#xff0c;则左子树上所有结点的值均小于它根结…...

Vue:Vue与VueComponent的关系图

1.一个重要的内置关系&#xff1a;VueComponent.prototype.proto Vue.prototype 2.为什么要有这个关系&#xff1a;让组件实例对象&#xff08;vc&#xff09;可以访问到 Vue原型上的属性、方法。 案例证明&#xff1a; <!DOCTYPE html> <html lang"en"&…...

Elasticsearch8集群部署

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 本文记录在3台服务器上离线搭建es8.7.1版本集群。 1. 修改系统配置 1.1 hosts配置 在三台es节点服务器加入hostname解析&…...

【小白专用】c# 如何获取项目的根目录

1、取得控制台应用程序的根目录方法 方法1、Environment.CurrentDirectory 取得或设置当前工作目录的完整限定路径 方法2、AppDomain.CurrentDomain.BaseDirectory 获取基目录&#xff0c;它由程序集冲突解决程序用来探测程序集 2、取得Web应用程序的根目录方法 方法1、HttpRun…...

【PXIE301-208】基于PXIE总线架构的Serial RapidIO总线通讯协议仿真卡

板卡概述 PXIE301-208是一款基于3U PXIE总线架构的Serial RapidIO总线通讯协议仿真卡。该板卡采用Xilinx的高性能Kintex系列FPGA作为主处理器&#xff0c;实现各个接口之间的数据互联、处理以及实时信号处理。板卡支持4路SFP光纤接口&#xff0c;支持一个PCIe x8主机接口&…...

软件测试/测试开发丨Windows系统chromedriver安装与环境变量配置

一、selenium 环境配置 1、chrome 浏览器的安装与配置 目前比较常用的浏览器是 Google Chrome 浏览器&#xff0c;所以本教程以 chrome 为主&#xff0c;后面简介一下其他浏览器的环境配置。 &#xff08;1&#xff09;chrome 下载: www.google.cn/chrome/ &#xff08;2&a…...

【vim 学习系列文章 3.1 -- vim 删除 ^M】

请阅读【嵌入式开发学习必备专栏 之 VIM 专栏】 文章目录 ^M 来源^M 删除 ^M 来源 在 Vim 中打开文件时&#xff0c;您可能会遇到行尾的 ^M 字符&#xff0c;这通常是因为文件使用了 Windows 风格的回车换行符&#xff08;CRLF&#xff09;&#xff0c;而不是 Unix/Linux 风格…...

深入理解 C# 中的字符串比较:String.CompareTo vs String.Equals

深入理解 C# 中的字符串比较&#xff1a;String.CompareTo vs String.Equals 在处理字符串时&#xff0c;了解如何正确比较它们对于编写清晰、有效和可靠的 C# 程序至关重要。本文将深入探讨 C# 中的两个常用字符串比较方法&#xff1a;String.CompareTo 和 String.Equals&…...

DevOps持续交付之容器化CICD流水线

DevOps持续交付 随着DevOps⼤规模化的落地和应⽤&#xff0c;持续集成以及持续交付已经是⼀种常态的。CI指的是持续集成&#xff0c;使⽤的开源⼯具是Jenkins&#xff0c;CD指的是持续交付和持续部署&#xff0c;⼀个完整的软件开发⽣命周期为: 主要流程可以具体为: 构建阶段…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

MySQL账号权限管理指南:安全创建账户与精细授权技巧

在MySQL数据库管理中&#xff0c;合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号&#xff1f; 最小权限原则&#xf…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

【iOS】 Block再学习

iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...

C++11 constexpr和字面类型:从入门到精通

文章目录 引言一、constexpr的基本概念与使用1.1 constexpr的定义与作用1.2 constexpr变量1.3 constexpr函数1.4 constexpr在类构造函数中的应用1.5 constexpr的优势 二、字面类型的基本概念与使用2.1 字面类型的定义与作用2.2 字面类型的应用场景2.2.1 常量定义2.2.2 模板参数…...

RKNN开发环境搭建2-RKNN Model Zoo 环境搭建

目录 1.简介2.环境搭建2.1 启动 docker 环境2.2 安装依赖工具2.3 下载 RKNN Model Zoo2.4 RKNN模型转化2.5编译C++1.简介 RKNN Model Zoo基于 RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用 Python API, CAPI 推理 RKNN 模型的流程.   本…...