基于arkTS开发鸿蒙app应用案例——通讯录案例

1.项目所用技术栈

  • arkTS

  • node.js express

  • mongoDB

2.效果图

3.源码

Index.ets(登录页)

登陆时让前端访问数据库中已经存好的账号密码,如果可以查询到数据库中的数据,则账号密码正确,登录成功,否则登录失败。

import  axios  from '@ohos/axios'
import router from '@ohos.router'

@Entry
@Component
struct Index {
  // 上传数据
  @State zhanghao: string = ''
  @State mima: string = ''
  @State zhanghao_find:string =''
  @State mima_find:string =''
  build() {
    Column() {
      Text('淼学通讯录')
        .margin({top:70})
        .fontWeight(FontWeight.Bold)
        .fontSize(30)
      Image('./components/img/appimg.jpg')
        .width(200)
        .height(200)
        .borderRadius(20)
        .margin({top:50,bottom:20})
      // 账号登录
      Row(){
        Image('./components/img/zhanghao.png')
          .width(20)
          .height(20)
        TextInput({placeholder:'账号'})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.zhanghao_find = value
          })
      }
      .borderRadius(12)
      .borderWidth(1)
      .borderColor('#E4DFDF')
      .padding(5)
      .margin({top:10})
      Row(){
        Image('./components/img/mima.png')
          .width(20)
          .height(20)
        TextInput({placeholder:'密码'})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.mima_find = value
          })
      }
      .borderRadius(12)
      .padding(5)
      .margin({top:10})

      Button('登录',{type:ButtonType.Normal,stateEffect:true})
        .borderRadius(10)
        .margin({top:40})
        .width(250)
        .height(55)
        .onClick(()=>{
          axios({
            method: "get",
            url: 'http://localhost:3000/users/find/'+this.zhanghao_find+ '/' + this.mima_find,
          }).then(res => {
            console.info('result:' + JSON.stringify(res.data));
            // 获取data数组中的第一个元素
            const zhanghao = res.data.data[0].zhanghao;
            console.log(JSON.stringify(zhanghao))
            // 获取data数组中的第一个元素
            // 获取zhanghao字段的值
            router.pushUrl({
              url: 'pages/App_one',
              params: {
                zhanghao
              }
            })
          }).catch(error => {
            console.error(error);
          })
        })
    }
    .width('100%')
    .height('100%')
  }
}

App_one.ets(功能页)

显示该登录的用户所添加的联系人。

import { Header } from '../components/Toubu'
import router from '@ohos.router'
import  axios  from '@ohos/axios'

@Entry
@Component
struct App_one {
  @State items:Array<Object> = []
  @State Ondata: object = router.getParams()
  onPageShow(){
    axios({
      method: "get",
      url: 'http://localhost:3000/lianxirens/find/'+this.Ondata?.['zhanghao'],
    }).then(res => {
      console.info('result:123123123' + JSON.stringify(res.data));
      this.items = res.data.data;
    }).catch(error => {
      console.error(error);
    })
  }

  build() {
      Column() {
        Header()
        .margin(20)
        Row(){
          Text('我的联系人')
            .fontSize(20)
            .padding({left:10,right:10})
        }
        .borderRadius(5)
        .borderWidth(1)
        .borderColor('#E4DFDF')
        .padding(10)
        .margin({top:10})

        Image('./components/img/add.png')
          .height(70)
          .width(70)
          .position({ x: 280, y: 500,})
          .zIndex(20)
          .onClick(()=>{
            router.pushUrl({
              url: 'pages/add',
              params: {
                zhanghao:this.Ondata?.['zhanghao']
              }
            })

          })
        // Scroll(){
          Column() {
            List({ space: 20, initialIndex: 0 }) {
              ForEach(this.items, (item) => {
                ListItem() {
                  Row(){
                    Image('./components/img/one.png')
                    .width(30)
                      .onClick(()=>{
                        // 获取点击物品的number
                        console.log(JSON.stringify(item.number))
                        router.pushUrl({
                          url: 'pages/detail',
                          params: {
                            id: item._id,
                            zhanghao:this.Ondata?.['zhanghao']
                          }
                        })
                      })
                    .margin({right:50,left:25})
                    if (item.sex == '男') {
                      Image('./components/img/nan.png')
                        .width(20)
                    } else {
                      Image('./components/img/nv.png')
                        .width(20)
                    }
                    Text(item.name)
                      .fontWeight(800)
                      .margin({ left: 20 })
                    Text(item.number)
                      .fontWeight(800)
                      .margin({ left: 20 })
                  }
                }
                .borderColor('#E4DFDF')
                .margin({ top: 10 })
              })
            }

          }
          .height(700)
          // .backgroundColor('#E4DFDF')
      }
      .width('100%')
  }
}

add.ets(功能页)

根据上个页面的跳转传递过来的账号参数,并向该账号的数据表的该条数据中添加数据。

import { Header } from '../components/Toubu'
import  axios  from '@ohos/axios'
import router from '@ohos.router'
@Entry
@Component
struct Add {
  @State number:string =''

  @State name:string =''

  @State sex:string ='男'

  @State Ondata: object = router.getParams()

  build() {
      Column() {
        Header()
          .margin(20)
        // 手机号
        TextInput({placeholder:'手机号',})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.number= value
          })
          .border({width: {  bottom: '3' },})
          .borderColor('#E4DFDF')
          .padding(15)
          .margin({top:20})
        // 姓名
        TextInput({placeholder:'姓名',})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.name= value
          })
          .border({width: {  bottom: '3' },})
          .borderColor('#E4DFDF')
          .padding(15)
          .margin({top:20})
        // 性别
        Row(){
          Column(){
            Radio({ value: 'nan', group: 'radioGroup' }).checked(true)
              .height(30)
              .width(30)
              .onChange((isChecked: boolean) => {
                console.log('Radio1 status is ' + isChecked)
                this.sex = '男'
              })
            Text('男')
          }
          Column(){
            Radio({ value: 'nv', group: 'radioGroup' }).checked(false)
              .height(30)
              .width(30)
              .onChange((isChecked: boolean) => {
                console.log('Radio2 status is ' + isChecked)
                this.sex = '女'
              })
            Text('女')
          }
          .margin({left:20})
        }
        .borderRadius(12)
        .borderWidth(1)
        .borderColor('#E4DFDF')
        .padding({left:20,right:20})
        .margin({top:30})

        Button('添加',{type:ButtonType.Normal,stateEffect:true})
          .borderRadius(10)
          .margin({top:100})
          .width(250)
          .height(55)
          .onClick(()=>{
            axios({
              method: "post",
              url: 'http://localhost:3000/lianxirens/add',
              data:{
                number:this.number,
                name:this.name,
                sex:this.sex,
                zhanghao:this.Ondata?.['zhanghao']
              }
            }).then(res => {
              console.info('result:' + JSON.stringify(res.data));
              router.back()
            }).catch(error => {
              console.error(error);
            })
          })
      }
      .width('100%')
  }
}

detail.ets(功能页)

在页面刷新之前首先通过组件生命周期函数访问数据表中的数据,拿到数据库之后复制在输入框中,根据上个页面传过来的参数对该登录的账号的用户所设计的联系人进行修改信息和删除。

import { Header } from '../components/Toubu'
import router from '@ohos.router'
import  axios  from '@ohos/axios'
@Entry
@Component
struct Detail {
  @State _id: string = ''

  @State number:string =''

  @State name:string =''

  @State sex:string ='男'
  // @State number: string = ''
  @State shuju: object = router.getParams()
  onPageShow(){
    console.info('result:' + JSON.stringify(this.shuju?.['id']));
    axios({
      method: "get",
      url: 'http://localhost:3000/lianxirens/find1/'+this.shuju?.['id'],
    }).then(res => {
      console.info('result:' + JSON.stringify(res.data.data[0]));
      this.number = res.data.data[0].number
      this.name = res.data.data[0].name
      // this.sex = res.data.data[0].sex
    }).catch(error => {
      console.error(error);
    })
  }

  build() {
      Column() {
        Header()
          .margin(20)
        TextInput({placeholder:'手机号',text:this.number})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.number= value
          })
          .border({width: {  bottom: '3' },})
          .borderColor('#E4DFDF')
          .padding(15)
          .margin({top:20})
        // 姓名
        TextInput({placeholder:'姓名',text:this.name})
          .backgroundColor('#00FFFFFF')
          .width('75%')
          .onChange(value =>{
            console.log(value)
            this.name= value
          })
          .border({width: {  bottom: '3' },})
          .borderColor('#E4DFDF')
          .padding(15)
          .margin({top:20})
        // 性别
        Row(){
          Column(){
            Radio({ value: 'nan', group: 'radioGroup' }).checked(true)
              .height(30)
              .width(30)
              .onChange((isChecked: boolean) => {
                console.log('Radio1 status is ' + isChecked)
                this.sex = '男'
              })
            Text('男')
          }
          Column(){
            Radio({ value: 'nv', group: 'radioGroup' }).checked(false)
              .height(30)
              .width(30)
              .onChange((isChecked: boolean) => {
                console.log('Radio2 status is ' + isChecked)
                this.sex = '女'
              })
            Text('女')
          }
          .margin({left:20})
        }
        .borderRadius(12)
        .borderWidth(1)
        .borderColor('#E4DFDF')
        .padding({left:20,right:20})
        .margin({top:30})

        Button('修改',{type:ButtonType.Normal,stateEffect:true})
          .borderRadius(10)
          .margin({top:100})
          .width(250)
          .height(55)
          .onClick(()=>{
            axios({
              method: "post",
              url: 'http://localhost:3000/lianxirens/upd',
              data:{
                number:this.number,
                name:this.name,
                sex:this.sex,
                _id:this.shuju?.['id']
              }
            }).then(res => {
              console.info('result:' + JSON.stringify(res.data));
              router.back()
            }).catch(error => {
              console.error(error);
            })
          })

        Button('删除',{type:ButtonType.Normal,stateEffect:true})
          .borderRadius(10)
          .margin({top:30})
          .width(250)
          .height(55)
          .onClick(()=>{
            axios({
              method: "post",
              url: 'http://localhost:3000/lianxirens/delete',
              data:{
                _id:this.shuju?.['id']
              }
            }).then(res => {
              console.info('result:' + JSON.stringify(res.data));
              router.back()
            }).catch(error => {
              console.error(error);
            })
          })
      }
      .width('100%')
    .height('100%')
  }
}

后端node.js文件架构

主要代码:

db.js

负责创建数据库中数据表的结构,并连接数据库,为数据表中的键值创建模型。负责创建数据库中数据表的结构,并连接数据库,为数据表中的键值创建模型。

const mongoose = require('mongoose')

//连接mongodb数据库
mongoose.connect("mongodb://localhost:27017/tongxunlu")
    .then(() => {
        console.log("数据库连接成功!")
    })
    .catch((err) => {
        console.log("数据库连接失败!", err)
    })

// 创建表用户表
const Users = new mongoose.Schema({
    number: {
        type: String,
    },
    name: {
        type: String
    },
    sex:{
        type:String
    },
    list:{
        type:Array
    }
})
const Lianxirens = new mongoose.Schema({
    zhanghao:{
        type: String,
    },
    number: {
        type: String,
    },
    name: {
        type: String
    },
    sex:{
        type:String
    },
})



const users = mongoose.model("Users", Users);
const lianxirens = mongoose.model("Lianxirens", Lianxirens);
module.exports = {
    users,
    lianxirens
}

index.js


后端主入口程序,引用自定义组件进行进一步的模块封装。

// index.js
const express = require('express');
const app = express();
const userApi = require('./user_ctrl/user_api');
const lianxirensApi = require('./lianxiren_ctrl/lianxiren_api');


app.use('/users', userApi);
app.use('/lianxirens', lianxirensApi);



app.listen(3000, () => {
    console.log('server running');
});

user_api.js

负责该登录用户的联系人的查询以及账号的登录。

// user_api.js
const express = require('express');
const router = express.Router();
const { users } = require('../db');

router.use(express.urlencoded({ extended: true }));
router.use(express.json());

// 查询联系人
router.get("/findusers/:zhanghao", async (req, res) => {
    try {
        const zhanghao = req.params.zhanghao;

        // 使用 find 查询匹配指定 zhanghao 的数据记录
        const result = await users.findOne({ zhanghao });

        if (result) {
            // 如果找到匹配的记录,则返回该记录
            res.json({ data: result, message: "登录成功!" });
        } else {
            res.status(404).json({ message: "未找到匹配的记录" });
        }
    } catch (error) {
        res.status(500).json({ message: "服务器内部错误" });
    }
});



// 账号登录
router.get("/find/:zhanghao/:mima", async (req, res) => {
    try {
        const zhanghao = req.params.zhanghao;
        const mima = req.params.mima;

        // 使用 find 查询所有匹配指定 name 的数据记录
        const results = await users.find({ zhanghao, mima });

        if (results.length > 0) {
            // 如果找到匹配的记录,则返回所有匹配的记录
            res.json({ data: results, message: "登录成功!" });
        } else {
            res.status(404).json({ message: "未找到匹配的记录" });
        }
    } catch (error) {
        res.status(500).json({ message: "服务器内部错误" });
    }
});

module.exports = router;

lianxiren_api.js

负责修改该登录的用户所涉及的联系人的信息,以及删除联系人的信息数据。

// user_api.js
const express = require('express');
const router = express.Router();
const { lianxirens } = require('../db');

router.use(express.urlencoded({ extended: true }));
router.use(express.json());

// 修改联系人信息
router.post("/add", async (req, res) => {
    try {
      const { zhanghao ,number,name,sex } = req.body;
        await lianxirens.create({
            zhanghao,
            number,
            name,
            sex
        }); 
      res.send("success"); 
    } catch (error) {
      res.send(error, "error");
  }
  });
//
  router.get("/find/:zhanghao", async (req, res) => {
    try {
        const zhanghao = req.params.zhanghao;
  
        // 使用 find 查询所有匹配指定 name 的数据记录
        const results = await lianxirens.find({ zhanghao });
  
        if (results.length > 0) {
            // 如果找到匹配的记录,则返回所有匹配的记录
            res.json({ data: results, message: "登录成功!" });
        } else {
          res.json({ data: results, message: "None" });
        }
    } catch (error) {
        res.status(500).json({ message: "服务器内部错误" });
    }
  });
//   查找联系人

  router.get("/find1/:_id", async (req, res) => {
    try {
        const _id = req.params._id;
  
        // 使用 find 查询所有匹配指定 name 的数据记录
        const results = await lianxirens.find({ _id });
  
        if (results.length > 0) {
            // 如果找到匹配的记录,则返回所有匹配的记录
            res.json({ data: results, message: "查找联系人成功!" });
        } else {
          res.json({ data: results, message: "None" });
        }
    } catch (error) {
        res.status(500).json({ message: "服务器内部错误" });
    }
  });

// 修改联系人信息
router.post("/upd", async (req, res) => {
    try {
        const { _id, number, name, sex } = req.body;
        // 使用 updateOne 更新指定 _id 的数据记录的 number、name 和 sex 字段
        const result = await lianxirens.updateOne({ _id }, { $set: { number, name, sex } });
        res.json({ message: "修改联系人信息成功!", result });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});
// 删除联系人
router.post("/delete", async (req, res) => {
    try {
        const { _id } = req.body;
        // 使用 deleteOne 删除指定 _id 的数据记录
        const result = await lianxirens.deleteOne({ _id });
        res.json({ message: "删除联系人信息成功!", result });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});





module.exports = router;

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

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

相关文章

Vue项目中引入html页面(vue.js中引入echarts数据大屏html [静态非数据传递!] )

在项目原有vue&#xff08;例如首页&#xff09;基础上引入html页面 1、存放位置 vue3原有public文件夹下 我这边是新建一个static文件夹 专门存放要用到的html文件 复制拖拽过来 index为html的首页 2、更改路径引入到vue中 这里用到的是 iframe 方法 不同于vue的 component…

springCloudAlibaba集成gateWay实战(详解)

一、初识网关&#xff1f; 1、网关介绍 ​ 在微服务架构中&#xff0c;一个系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢&#xff1f;如果没有网关的存在&#xff0c;我们只能在客户端记录每个微服务的地址&#xff0c;然后分别去调用。这样的话…

3D DRAM在2025年来袭

4月1日消息&#xff0c;据半导体工程报道&#xff0c;在行业大会Memcon 2024上&#xff0c;三星电子宣布其计划成为首家在2025年后步入3D DRAM内存时代的行业领军者。随着DRAM内存行业在本十年后期将线宽压缩至低于10纳米&#xff0c;现有的设计解决方案在如此精细的尺度上难以…

渗透测试练习题解析 5(CTF web)

1、[安洵杯 2019]easy_serialize_php 1 考点&#xff1a;PHP 反序列化逃逸 变量覆盖 【代码审计】 通过 GET 的方式获取参数 f 的值&#xff0c;传递给变量 function 定义一个过滤函数&#xff0c;过滤掉特定字符&#xff08;用空字符替换&#xff09; 下面的代码其实没什么用…

【Android Studio3.5.2安装以及错误错误解决】

前言 下面是博主在安装Android studio时遇到的一些问题&#xff0c;并且花费很长时间寻找解决方法&#xff0c;经过了血和泪的教训下面将自己在安装过程中遇到的查看的资料贴出来&#xff08;感谢各位大佬的文章帮助本闲狗解答疑惑&#xff0c;此处贴出原文链接&#xff0c;如…

Docker基础系列之TLS和CA认证

Docker基础系列之TLS和CA认证 文章目录 Docker基础系列之TLS和CA认证1. 引言2. 初识TLS和CA3. 开启TLS和CA认证3.1 生成证书3.2 配置TLS 4. 参考和感谢 1. 引言 我们日常工作当中会遇到这些需求&#xff1a; 监控Docker容器在idea开发工具中连接Docker&#xff0c;直接发布至…

【漏洞复现】Wordpress saveconfiguration接口处存在任意文件上传漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

String Encryptor custom Bean not found with name ‘jasyptStringEncryptor‘...

项目采用 spring boot 2.6.13 jasypt-spring-boot-starter 3.0.5 apollo-client 1.6.0 自定义jasyptStringEncryptor&#xff0c;服务器上启动死活报找不到bean jasyptStringEncryptor&#xff0c;采用默认的&#xff0c;密文配置项自然解密失败导致服务无法启动。 经过一…

计算机网络——33多点访问协议

多点访问协议 多路访问链路和协议 两种类型的链路&#xff08;一个子网内部链路连接形式&#xff09; 点对点 拨号访问的PPP以太网交换机和主机之间的点对点链路 广播 传统以太网HFC上行链路802.11无线局域网 多路访问协议 单个共享的广播型链路 2个过更多结点同时传送&am…

【C语言】联合和枚举

个人主页点这里~ 联合和枚举 一、联合体1、联合体类型的声明2、联合体成员的特点3、与结构体对比4、计算联合体大小 二、枚举1、枚举的声明2、枚举的优点3、枚举类型的使用 一、联合体 1、联合体类型的声明 联合体的定义与结构体相似&#xff0c;但是联合体往往会节省更多的空…

软考 - 系统架构设计师 - 数据流图案例题

阅读以下关于系统数据分析与建模的叙述&#xff0c;在答题纸上回答问题1至问题3。 【说明】 某公司正在研发一套新的库存管理系统。系统中一个关键事件是接收供应商供货。项目组系统分析员小王花了大量时间在仓库观察了整个事件的处理过程&#xff0c;并开发出该过程所执行活动…

VTK中polydata的属性数据结构表示和用法

vtk中通过vtkDataArray进行数据的存储&#xff0c;通过vtkDataObject进行可视化数据的表达&#xff0c;在vtkDataObject内部有一个vtkFieldData的实例&#xff0c;负责对数据的表达&#xff1a; vtkFieldData存储数据的属性数据&#xff0c;该数据是对拓扑结构和几何结构信息的…

局域网与城域网(练习题)

局域网与城域网 ⭐️⭐️⭐️⭐️ 红色标记为答案⭐️⭐️⭐️⭐️ ⭐️⭐️⭐️ 蓝色标记为要点解析⭐️⭐️⭐️ 1.以下关于VLAN标记的说法中&#xff0c;错误的是&#xff08;&#xff09;。 A.交换机根据目标地址和VLAN标记进行转发决策 B.进入目的网段时&#xff0c;交换机…

C语言-atoi函数的模拟

模拟术语讲解 首先&#xff0c;需要定义一个标志位变量sign&#xff0c;用于表示转换结果的合法性1。定义一个函数My_atoi&#xff0c;用于实现atoi的功能1。在My_atoi函数中&#xff0c;首先遍历字符串&#xff0c;直到遇到第一个非空格字符1。如果第一个字符不是数字或正负号…

通讯录改造———文件版本

上一篇文章我们详细讲了文件操作&#xff0c;这时候我们就可以把通讯录保存到文件中&#xff0c;这样即使程序退出了&#xff0c;联系人的信息也还是保存着&#xff0c;下一次启动程序时我们就可以把文件中的数据读取到程序中来使用。 保存 首先我们要在退出通讯录之前把联系人…

Spring Boot 介绍

1、SpringBoot 介绍 用通俗的话讲&#xff0c;SpringBoot 在Spring生态基础上发展而来&#xff0c;它的发现不是取代Spring&#xff0c;是为了让人们更容易使用Spring。 2、相关依赖关系 Spring IOC/AOP > Spring > Spring Boot > Spring Cloud 3、 SpringBoot工作原…

R语言,数据类型转换

原文链接&#xff1a;R语言技能 | 不同数据类型的转换 本期教程 写在前面 今天是4月份的第一天&#xff0c;再过2天后再一次迎来清明小假期。木鸡大家是否正常放假呢&#xff1f; 我们在使用R语言做数据分析时&#xff0c;会一直对数据进行不同类型的转换&#xff0c;有时候…

IP地址与子网掩码

1 IP地址 1.1 IPv4与IPv6 1.2 IPv4地址详解 IPv4地址分4段&#xff0c;每段8位&#xff0c;共32位二进制数组成。 1.2.1 地址分类 这32位又被分为网络号和主机号两部分&#xff0c;根据网络号占用位数的不同&#xff0c;又可分为以下几类&#xff1a; A类地址&#xff1a;…

Higress 基于自定义插件访问 Redis

作者&#xff1a;钰诚 简介 基于 wasm 机制&#xff0c;Higress 提供了优秀的可扩展性&#xff0c;用户可以基于 Go/C/Rust 编写 wasm 插件&#xff0c;自定义请求处理逻辑&#xff0c;满足用户的个性化需求&#xff0c;目前插件已经支持 redis 调用&#xff0c;使得用户能够…

Windows提权—数据库提权-mysql提权mssql提权Oracle数据库提权

目录 Windows 提权—数据库提权一、mysql提权1.1 udf提权1.1.2 操作方法一 、MSF自动化--UDF提权--漏洞利用1.1.3 操作方法二、 手工导出sqlmap中的dll1.1.4 操作方法三、 moon.php大马利用 1.2 mof提权1.3 启动项提权1.4 反弹shell 二、MSSQL提权MSSQL提权方法1.使用xp_cmdshe…