【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
  // 弹窗控制器,控制打开/关闭,必须传入,且名称必须为:controller
  controller: CustomDialogController
  // 弹窗中的按钮事件
  cancel: () => void
  confirm: () => 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 = {
        // 当数据库文件不存在时是否创建数据库,默认为true
        createIfMissing: 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) => void
  private 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基础组件实现一个柱状图,不断学习,期望鸿蒙不断强大完善。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

简单了解SQL宽字节注入与httpXFF头注入(基于sqllabs演示)

1、宽字节注入 sqllabs-less-32为例 使用单引号进行测试 提示我们输入的单引号被转义符 \ 进行了转义&#xff0c;即转义符自动的出现在输入的特殊字符前面&#xff0c;这是防止sql注入的一种方法&#xff0c;导致无法产生报错。 这种情况我们就可以尝试宽字节注入&#xff…

报表控件FastReport VCL 中的新 S3 传输 (Amazon)

在本文中&#xff0c;我们将探讨新的 S3 传输。从功能上来说&#xff0c;S3 与大多数人习惯使用的有很大不同&#xff0c;因此在本文的开头&#xff0c;我们将详细介绍它的主要功能。 FastReport .NET 是适用于.NET Core 3&#xff0c;ASP.NET&#xff0c;MVC和Windows窗体的全…

数据结构--二叉搜索树的实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 二叉搜索树的插入 中序遍历(常用于排序) 二叉搜索树的查找 二叉搜索树的删除 完整二叉树代码&#xff1a; 二叉搜索树的应用 key/value搜索模型整体代码 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一…

亚信安慧AntDB数据并行加载工具的实现(一)

1.概述 数据加载速度是评判数据库性能的重要指标&#xff0c;能否提高数据加载速度&#xff0c;对文件数据进行并行解析&#xff0c;直接影响数据库运维管理效率。基于此&#xff0c;AntDB分布式数据库提供了两种数据加载方式&#xff1a; 一是类似于PostgreSQL的Copy命令&am…

ES6之解构赋值详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

Nacos注册

一、简介 Nacos是阿里云开源的一个服务发现、配置管理和服务鉴权平台&#xff0c;它提供了一种更简单、更便捷、更开放的方式来管理服务&#xff0c;帮助开发者快速实现服务的发现、配置的管理、服务的鉴权等功能。Nacos可以帮助开发者轻松管理微服务应用中的服务提供者、服务…

《整机柜服务器通用规范》由OCTC正式发布!浪潮信息牵头编制

近日&#xff0c;中国电子工业标准化技术协会开放计算标准工作委员会&#xff08;OCTC&#xff09;正式批准发布了《整机柜服务器通用规范》&#xff0c;该标准由浪潮信息牵头&#xff0c;中国工商银行、中国质量认证中心、英特尔、中国计量科学研究院等十余家单位联合编制&…

Github 2023-12-30 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-30统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目4JavaScript项目2C项目1Python项目1Java项目1HTML项目1Dart项目1非开发语言项目1 令人惊叹的 …

一起玩儿物联网人工智能小车(ESP32)——13. 用ESP32的GPIO控制智能小车运动起来(一)

摘要&#xff1a;本文更深入的讲述了GPIO的相关知识&#xff0c;并完成了导线连接工作&#xff0c;为下一步的软件开发做好了准备。 通用输入输出端口&#xff08;GPIO&#xff1a;General Purpose Input/Output Port&#xff09;&#xff0c;在前面已经有了初步的介绍&#xf…

代码随想录-刷题第四十二天

0-1背包理论基础 0-1背包问题介绍 0-1背包问题&#xff1a;有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 0-1背包问题可以使用回溯法进…

mongoose中http server服务器解决“Access-Control-Allow-Origin mongoose”跨域问题

问题 使用mongoose做http服务器&#xff0c;自己构造的浏览器端jquery在访问server时&#xff0c;会遇到&#xff1a; Access to XMLHttpRequest at http://127.0.0.1:8000/ from origin null has been blocked by CORS policy: No Access-Control-Allow-Origin header is pr…

Android Camera

1. 相关的API Android有三套关于摄像头的API(库)&#xff0c;分别是Camera、Camera2和CameraX&#xff0c;其中Camera已废弃&#xff0c;在Android5.0以后推荐使用Camera2和CameraX&#xff0c;Camera2推出是用来替换Camera的&#xff0c;它拥有丰富的API可以为复杂的用例提供…

ArcGIS批量计算shp面积并导出shp数据总面积(建模法)

在处理shp数据时&#xff0c; 又是我们需要知道许多个shp字段的批量计算&#xff0c;例如计算shp的总面积、面积平均值等&#xff0c;但是单个查看shp文件的属性进行汇总过于繁琐&#xff0c;因此可以借助建模批处理来计算。 首先准备数据&#xff1a;一个含有多个shp的文件夹。…

树莓派 ubuntu20.04下 python调讯飞的语音API,语音识别和语音合成

目录 1.环境搭建2.去讯飞官网申请密钥3.语音识别&#xff08;sst&#xff09;4.语音合成&#xff08;tts&#xff09;5.USB声卡可能报错 1.环境搭建 #环境说明&#xff1a;(尽量在ubuntu下使用, 本次代码均在该环境下实现) sudo apt-get install sox # 安装语音播放软件 pip …

【零基础入门VUE】VueJS - 模板

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门VUE专栏https://blog.csdn.net/arthas777/category_12537076.html 我们在前面的章节中学习了如何在屏幕上以文本内容的形式输出。在本章中&#xff0c;我们将学习如何在屏幕上以 HTML 模板的形式获取输出。 为了…

使用element中el-cascader级联选择器动态懒加载以及回显 (单选)

<template><!-- 新增||修改弹框 --><el-dialog :close-on-click-modal"false" :close-on-press-escape"false" :title"title" :visible.sync"open"width"800px" append-to-body><el-form ref"for…

2023年高级软考系统架构师考题参考

对于一些有实践经验的同学来说&#xff0c;感觉不难&#xff0c;但是落笔到纸面上&#xff0c;就差强人意了&#xff0c;平时这方面要多练习&#xff0c;所想所思要落到纸面上&#xff0c;或者表达清晰让别人听懂&#xff0c;不仅是工作中的一个基本素质&#xff0c;也是个非常…

跟小德学C++之配置文件(形式)

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

C/C++转WebAssembly及微信小程序调用

上一篇文章讲了C/C如何转WebAssembly&#xff0c;并测试了在Web端调用。本篇内容和上篇一样&#xff0c;介绍C/C包转的.wasm包如何在小程序中调用。 说明 本篇是在上一篇步骤1-4的基础上&#xff0c;再做修改&#xff0c;供微信小程序端调用的方法和步骤。 本篇操作手册可以…

再见2023,你好2024

再见2023&#xff0c;你好2024 生活1月 悲伤与治愈2~4月 运动与偏爱5月 体验与美食6月 婚礼与热爱7~8月 就医与别离9~11月 陪伴与暖房12月 体验&新生 运动追剧读书总结 生活 生活是一个修罗场&#xff0c;来世间一场&#xff0c;要经历丰腴有趣的人生。去体验各种滋味&…