【微信小程序开发】宠物预约医疗项目实战-注册实现

news2024/11/25 13:00:46

【微信小程序开发】宠物预约医疗项目实战-注册实现

第二章 宠物预约医疗项目实战-注册实现

文章目录

  • 【微信小程序开发】宠物预约医疗项目实战-注册实现
  • 前言
  • 一、打开项目文件
  • 二、编写wxss代码
    • 2.1 什么是wxss
    • 2.2 配置主程序全局样式
  • 三. 在sign文件下的wxml文件中编写如下代码并保存
  • 四 .sign.js文件代码编写如下
    • 4.1 js函数使用
    • 4.2 全局变量与局部变量使用
    • 4.3 request方法请求接口的使用
    • 4.4 在sign.ts中引入全局配置
    • 4.5. 代码编写
    • 4.6. 运行
  • 总结


前言


注册是指向某个平台、网站或应用程序提供您的个人信息以获取账户的过程。注册对于现代社会的人们来说非常重要,以下是几个原因:

方便性:注册后,您可以随时登录到您的账户,使您能够方便地管理和使用平台的服务和功能。

个性化服务:许多网站和应用程序需要您提供个人信息以提供个性化的服务,例如推荐商品或根据您的兴趣推送内容。

安全性:通过注册,您可以创建一个账户和密码,使您的个人信息更安全。此外,许多网站和应用程序要求您使用多种安全措施,例如启用两步验证(2FA)等。

沟通:注册后,您可以参与交流、评论或定期接收电子邮件通知,这有助于您跟进相关信息和最新动态。

授权:某些平台需要您注册才能提供访问内容或服务的授权,例如社交媒体平台或在线购物网站。

总之,注册是连接您和平台、网站和应用程序的重要步骤,可以为您提供许多方便、个性化的服务,并加强您的个人安全。`

一、打开项目文件

在这里插入图片描述
1.在pages里新建注册页面然后ctrl+s保存

    "pages/sign/sign",

在这里插入图片描述
2.确认登录页面被新建出来
在这里插入图片描述

二、编写wxss代码

2.1 什么是wxss

wxss文件是微信小程序中的样式文件,用于定义小程序页面的样式和布局。与CSS类似,wXss文件支持选择器、属性和值等基本语法,但是它有着自己的特点和限制。例如,wXss不支持外部链接和@import语句,需要直接在文件中定义所有样式。此外,wXss还支持一些微信小程序特有的样式属性,例如rpx(响应式像素)用于适配不同屏幕大小的移动设备。 大家可以理解为是css

2.2 配置主程序全局样式

  1. 点击进入app.wxss文件
    在这里插入图片描述
  2. 编写下面罗列的代码后保存运行
/**app.wxss**/
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  box-sizing: border-box;
} 

button {
  background: initial;
}

button:focus{
  outline: 0;
}

button::after{
  border: none;
}


page {
  background: #f6f6f6;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.userinfo, .uploader, .tunnel {
  margin-top: 40rpx;
  height: 140rpx;
  width: 100%;
  background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-left: none;
  border-right: none;
  display: flex;
  flex-direction: row;
  align-items: center;
  transition: all 300ms ease;
}

.userinfo-avatar {
  width: 100rpx;
  height: 100rpx;
  margin: 20rpx;
  border-radius: 50%;
  background-size: cover;
  background-color: white;
}

.userinfo-avatar:after {
  border: none;
}

.userinfo-nickname {
  font-size: 32rpx;
  color: #007aff;
  background-color: white;
  background-size: cover;
}

.userinfo-nickname::after {
  border: none;
}

.uploader, .tunnel {
  height: auto;
  padding: 0 0 0 40rpx;
  flex-direction: column;
  align-items: flex-start;
  box-sizing: border-box;
}

.uploader-text, .tunnel-text {
  width: 100%;
  line-height: 52px;
  font-size: 34rpx;
  color: #007aff;
}

.uploader-container {
  width: 100%;
  height: 400rpx;
  padding: 20rpx 20rpx 20rpx 0;
  display: flex;
  align-content: center;
  justify-content: center;
  box-sizing: border-box;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.uploader-image {
  width: 100%;
  height: 360rpx;
}

.tunnel {
  padding: 0 0 0 40rpx;
}

.tunnel-text {
  position: relative;
  color: #222;
  display: flex;
  flex-direction: row;
  align-content: center;
  justify-content: space-between;
  box-sizing: border-box;
  border-top: 1px solid rgba(0, 0, 0, 0.1);
}

.tunnel-text:first-child {
  border-top: none;
}

.tunnel-switch {
  position: absolute;
  right: 20rpx;
  top: -2rpx;
}

.disable {
  color: #888;
}

.service {
  position: fixed;
  right: 40rpx;
  bottom: 40rpx;
  width: 140rpx;
  height: 140rpx;
  border-radius: 50%;
  background: linear-gradient(#007aff, #0063ce);
  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3);
  display: flex;
  align-content: center;
  justify-content: center;
  transition: all 300ms ease;
}

.service-button {
  position: absolute;
  top: 40rpx;
}

.service:active {
  box-shadow: none;
}

.request-text {
  padding: 20rpx 0;
  font-size: 24rpx;
  line-height: 36rpx;
  word-break: break-all;
}

三. 在sign文件下的wxml文件中编写如下代码并保存

在这里插入图片描述

=<view class="container">

<image   src="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fc-ssl.duitang.com%2Fuploads%2Fitem%2F201502%2F24%2F20150224235124_vda4m.thumb.1000_0.jpeg&refer=http%3A%2F%2Fc-ssl.duitang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1677326688&t=b461a24be6ba1e8736e3bb9c525f925f"></image>

</view>

<view class="login_box">

<view class="section">

  <input placeholder="请输入用户名" placeholder-class="color" bindblur='username' />
 
</view>

<view class="section">

  <input type='number' maxlength='11' placeholder="请输入手机号" placeholder-class="color" bindblur='mobile' />

  <image src=""></image>

</view>

<view class="section">

  <input password="true" placeholder="请输入密码" placeholder-class="color" bindblur='pass1' />

  <image src=""></image>

</view>

<view class="section">

  <input password="true" placeholder="确认密码" placeholder-class="color" bindblur='pass2' />

  <image src=""></image>

</view>
<button class="login1" type="primary" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">用户注册</button>
<button class="register" type="warn" open-type="getUserInfo" bindgetuserinfo="okzhuche">已有账号/登录</button>

       <!--底部确认-->
       <view class="shen_title">
            <image class="about" src="" />使用申明
      </view>
      <view class="des">1. 在未经您同意及确认之前,本程序不会将您的注册信息用于任何其它商业目的。</view>
      <view class="des">2. 本程序将对您的信息进行严格的保护</view>
      <view class="des">3. 请您放心使用!</view>
</view>




此时保存后编译,你可以看见展示的效果,但是注册点击时没有效果的。原因在于,没有编写sign.js文件接入数据

四 .sign.js文件代码编写如下

涉及知识点:

  1. js函数调用使用
  2. 全局变量与局部变量使用
  3. request方法请求接口的使用

下面我们一个一个来:

4.1 js函数使用

函数的定义与java不同:
函数名称+函数输入参数+花括号
比如下段:

 onReady: function(a) {
  //函数体
  },

其中onReady为函数名称,function(a)为函数定义参数。多个参数通过,区分,如function(a,b)
代码亦可以简化为:

 onReady(a) {
  //函数体
  },

4.2 全局变量与局部变量使用

在这里插入图片描述
页面的全局变量定义在data中,当需要获取data中的数据时,通常写法如下:

 onReady: function(a) {
  //函数体
  var a = this.data.username;
  },

我们将data中的username的值传给了var a局部变量

设置全局变量data的写法如下:

  username(e) {

    this.setData({

      username: e.detail.value

    })

  },

通过 this.setData({ ---- })的方式将传入函数中的值赋值给data中的username


4.3 request方法请求接口的使用

注册的接口见先导篇中我提供的接口文档,下面带大家使用使用
1.登录接口文档地址:
点击进入文档地址
在这里插入图片描述
2. 找到用户增加接口
在这里插入图片描述
3.在app.ts和index.d.ts中引入域名接口并保存
在这里插入图片描述
在这里插入图片描述

  mydata: {
    // ip:"http://127.0.0.1:9004/",
    ip:"http://122.51.174.157:9004/"
  },

在定义一个时间生成函数

  time() {
    var date = new Date();
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const hour = date.getHours();
    const minute = date.getMinutes();
    const second = date.getSeconds();
    var time = year + '-' + month + '-' + day + ' ' + hour + '时' + minute +'分'+ second+'秒';
    return time;
  },

整体代码编写为:

// app.ts
App({
  globalData: {},
  mydata: {
    // ip:"http://127.0.0.1:9004/",
    ip:"http://122.51.174.157:9004/"
  },
  time() {
    var date = new Date();
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const hour = date.getHours();
    const minute = date.getMinutes();
    const second = date.getSeconds();
    var time = year + '-' + month + '-' + day + ' ' + hour + '时' + minute +'分'+ second+'秒';
    return time;
  },
  onLaunch() {
    // 展示本地存储能力
    const logs = wx.getStorageSync('logs') || []
    logs.unshift(Date.now())
    wx.setStorageSync('logs', logs)

    // 登录
    wx.login({
      success: res => {
        console.log(res.code)
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
      },
    })
  },

})

4.4 在sign.ts中引入全局配置


在这里插入图片描述

// 获取应用实例
const app = getApp<IAppOption>()

如果你版本较低,文件为sign.js则引入

var app = getApp();

4.5. 代码编写


// 获取应用实例
const app = getApp<IAppOption>()
Page({

  /**
   * 页面的初始数据
   */
  data: {

    username: '', //用户名

    mobile: '', //手机号

    pass1: '', //密码

    pass2: '', //确认密码

  },

  // 用户名失去焦点

  username(e) {

    this.setData({

      username: e.detail.value

    })

  },

  // 手机号失去焦点

  mobile(e) {

    this.setData({

      mobile: e.detail.value

    })

  },

  // 密码失去焦点

  pass1(e) {

    var pattern = /^[\w_]{0,6}$/; //密码正则

    if (!pattern.test(e.detail.value)) {

      this.setData({

        pass1: ''

      })

      wx.showToast({

        title: '密码长度必须为0-6位,并且由字母,数字或下划线组成',

        icon: 'none',

        duration: 3000

      })

    } else {

      this.setData({

        pass1: e.detail.value

      })

    }

  },

  // 确认密码失去焦点

  pass2(e) {

    this.setData({

      pass2: e.detail.value

    })

  },

  // 接种用户点击注册按钮

  bindGetUserInfo: function(e){

    if (e.detail.userInfo) {

      //用户按了允许授权按钮

        wx.showLoading({

          title: '正在注册...',

        })

        if (this.data.username == '') {

          wx.showToast({

            title: '用户名不能为空',

            icon: 'none',

            duration: 2000

          })

        } else if (this.data.mobile == '') {

          wx.showToast({

            title: '手机号不能为空',

            icon: 'none',

            duration: 2000

          })

        } else if (!(/^1[3456789]\d{9}$/.test(this.data.mobile))) {

          wx.showToast({

            title: '手机号码格式有误,请重新输入!',

            icon: 'none',

            duration: 2000

          })

        } else if (this.data.pass1 == '') {

          wx.showToast({

            title: '密码不能为空',

            icon: 'none',

            duration: 2000

          })

        } else if (this.data.pass2 == '') {

          wx.showToast({

            title: '请再次输入密码',

            icon: 'none',

            duration: 2000

          })

        } else if (this.data.pass1 != this.data.pass2) {

          wx.showToast({

            title: '两次密码输入不一致,请重新输入!',

            icon: 'none',

            duration: 2000

          })

        } else {

          var that = this

          // 注册这个账户之前,我们首先要做的就是查询一下这个集合表中是否已经存在过这个用户了

          wx.request({
            url: app.mydata.ip+'api/user/checkname',
         data: {
               username:this.data.username,
               },
         header: {
         // 'content-type': 'application/json'
         'content-type': 'application/x-www-form-urlencoded'
          },
         method: 'POST',

              success: function(res) {
                 console.log(res)
                if (res.data=='no') { //判断用户名是否被注册过,等于空说明没被查询到,就是没有注册过,
//我写的数用户名和手机号都可以登录,所以同一个手机号和用户名只能算一个账号,也要验证一下手机号是否被注册过

            wx.request({
             url: app.mydata.ip+'api/user/checkphone',
          data: {
                phone:that.data.mobile,
                },
          header: {
          // 'content-type': 'application/json'
          'content-type': 'application/x-www-form-urlencoded'
           },
          method: 'POST',
          success: function(res) {

        if (res.data == 'no') { //判断手机号是否被注册过,等于空说明没被查询到,就是没有注册过,
                 wx.request({
                    url: app.mydata.ip+'api/user/register',
                  data: {
                 id:1,   
                 username:that.data.username,
                 password:that.data.pass2,
                 phone:that.data.mobile,
                 root:1,
                 sex:"男",
                 birthTime:app.time()
                },
                  header: {
                'content-type': 'application/json'
                    },
                   method: 'GET',
                  success: function(res) {

                              if (res.data.code == 1) { //接口调取成功,也就是注册成功
                                  // 这里面你可以加一下注册成功之后的逻辑,是直接登录也好,或者是跳到登录页面页面

                                wx.hideLoading();

                                wx.showToast({

                                  title: '注册成功',

                                  icon: 'none'

                                })
                                setTimeout(function() {
                                  wx.showLoading({
                                    title: '正在跳转',
                                  })
                                  setTimeout(function() {
                                    wx.hideLoading();
                                    wx.navigateTo({
                                      url: '../login/login',
                                    })
                                  }, 300)
                                }, 100)
                              }
                            }
                          })
                        } else {
                          wx.showToast({
                            title: '此手机号已被别人注册,换一个试试!',
                            icon: 'none',
                            duration: 2000
                          })
                        }
                      }
                    })
                } else {
                  wx.showToast({
                    title: '此用户名已被别人注册,换一个试试!',
                    icon: 'none',
                    duration: 2000
                  })
                }
              }
            })
          }

      } else {

        //用户按了拒绝按钮

          wx.showModal({

            title: '警告',

            content: '您点击了拒绝授权,将无法进行账号注册,请授权之后再注册!!!',

            showCancel: false,

            confirmText: '返回授权',

            success: function(res) {}

          })

      }

   

  },



  okzhuche: function() {

    setTimeout(function() {
      wx.showLoading({
        title: '正在跳转',
      })
      setTimeout(function() {
        wx.hideLoading();
        app.globalData.register=true;
      }, 300)
    }, 100)
    
    wx.navigateTo({

      url: "../login/login"

    }) 
  },

  /**

   * 生命周期函数--监听页面加载

   */

  onLoad: function(options) {

    

  },

 

  /**

   * 生命周期函数--监听页面初次渲染完成

   */

  onReady: function() {

 

  },

 

  /**

   * 生命周期函数--监听页面显示

   */

  onShow: function() {

 

  },

 

  /**

   * 生命周期函数--监听页面隐藏

   */

  onHide: function() {

 

  },

 

  /**

   * 生命周期函数--监听页面卸载

   */

  onUnload: function() {

 

  },

 

  /**

   * 页面相关事件处理函数--监听用户下拉动作

   */

  onPullDownRefresh: function() {

 

  },

 

  /**

   * 页面上拉触底事件的处理函数

   */

  onReachBottom: function() {

 

  },

 

  /**

   * 用户点击右上角分享

   */

  onShareAppMessage: function() {

 

  }

})

4.6. 运行

在这里插入图片描述
1.打开改属性设置,原因是域名接口不是小程序授权接口
2.输入注册信息
在这里插入图片描述
3.确认注册
在这里插入图片描述
在这里插入图片描述
4.重新注册使用同账号或者同电话号码会被拦截
在这里插入图片描述

总结

学习如逆水行舟,不进则退。视频教程于周内于哔哩哔哩更新,同学需提前熟悉代码与操作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用qt完善对话框功能

1、 完善登录框 点击登录按钮后&#xff0c;判断账号&#xff08;admin&#xff09;和密码&#xff08;123456&#xff09;是否一致&#xff0c;如果匹配失败&#xff0c;则弹出错误对话框&#xff0c;文本内容“账号密码不匹配&#xff0c;是否重新登录”&#xff0c;给定两…

【深度学习实验】线性模型(五):使用Pytorch实现线性模型:基于鸢尾花数据集,对模型进行评估(使用随机梯度下降优化器)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入库 1. 线性模型linear_model 2. 损失函数loss_function 3. 鸢尾花数据预处理 4. 初始化权重和偏置 5. 优化器 6. 迭代 7. 测试集预测 8. 实验结果评估 9. 完整代码 一、实验介…

大语言模型的机遇和挑战

自然语言处理包含自然语言理解和自然语言生成两个方面, 常见任务包括文本分类, 结构分析 (词法分析, 分词, 词性标注, 句法分析, 篇章分析), 语义分析, 知识图谱, 信息提取, 情感计算, 文本生成, 自动文摘, 机器翻译, 对话系统, 信息检索和自动问答等. 在神经网络方法出现之前,…

Vue3_vite

使用Vue-cli创建 使用vite创建 Composition API 组合API setup 1.Vue3中的一个新的配置项,值为一个函数 2.可以将组件中所用到的数据,方法等配置在setup中. 3.setup函数的两种返回值 3.1若返回一个对象,则对象中的属性,方法,在模板中均可以直接使用. 3.2若返回一个渲染函数…

Leetcode.337 打家劫舍 III

题目链接 Leetcode.337 打家劫舍 III mid 题目描述 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为 root 。 除了 root 之外&#xff0c;每栋房子有且只有一个“父“房子与之相连。一番侦察之后&#xff0c;聪明的小偷意识到“这个地方的所有…

「聊设计模式」之建造者模式(Builder)

&#x1f3c6;本文收录于《聊设计模式》专栏&#xff0c;专门攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎持续关注&&收藏&&订阅&#xff01; 前言 设计模式是众多优秀软件开发实践的总结和提炼&#xff0c;…

STM32 ADC介绍和应用

目录 1.ADC是什么&#xff1f; 2.ADC的性能指标 3.ADC特性 4.ADC通道 5.ADC转换顺序 6.ADC触发方式 7.ADC转化时间 8.ADC转化模式 扫描模式 单次转换/连续转换 9.ADC实验 使用ADC读取烟雾传感器的值 代码实现思路&#xff1a; 1.ADC是什么&#xff1f; 全称&#…

DMNet复现(一)之数据准备篇:Density map guided object detection in aerial image

一、生成密度图 密度图标签生成 采用以下代码&#xff0c;生成训练集密度图gt&#xff1a; import cv2 import glob import h5py import scipy import pickle import numpy as np from PIL import Image from itertools import islice from tqdm import tqdm from matplotli…

UG NX二次开发(C#)-计算直线到各个坐标系轴向的投影角度

文章目录 1、前言2、需求分析3、NXOpen方法实现3.1 创建基准坐标系3.2 然后计算直线到基准坐标系的轴向角度3.3 代码调用4、测试效果为:1、前言 最近有个粉丝问我如何计算直线到坐标系各个轴向的角度,这里用UG NX二次开发(C#)实现。当然,这里的内容是经验之谈,如果有更好的…

基于matlab实现的船舶横摇运动仿真程序

完整程序&#xff1a; clc clear syms w we; w0.4:0.05:1.6;mu90;v6;%kb1;kt1;%航速6m/s&#xff0c;航向90度&#xff0c;即横浪&#xff0c;cos(90)0 T3;B10;Sw0.785;%船宽10米&#xff0c;吃水3米,水线面系数假设为0.785 weww.^2.*v/9.8; for i1:24 delta_we(i)we(i1)-…

【计算机网络】——数据链路层(应用:局域网、广域网、设备 )

//仅做个人复习和技术交流&#xff0c;图片取自王道考研&#xff0c;侵删 一、大纲 1、介质访问控制 信道划分介质访问控制 随机访问介质访问控制 2、局域网 3、广域网 4、数据链路层设备 二、局域网 1、局域网基本概念和体系结构 局域网(LocalArea Network): 简称LAN&…

Stable Diffusion - 采样器 DPM++ 3M SDE Karras 与 SDXL Refiner 测试

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132978866 Paper: DPM-Solver: Fast Solver for Guided Sampling of Diffusion Probabilistic Models 扩散概率模型&#xff08;DPMs&#xff09;…

基于matlab实现的多普勒脉冲雷达回波仿真

完整程序&#xff1a; clear all;clc;close all; fc3e9; %载波频率 PRF2000; Br5e6; %带宽 fs10*Br; %采样频率 Tp5e-6; %脉宽 KrBr/Tp; %频率变化率 c3e8; %光速 lamda…

linux入门---共享内存

目录标题 共享内存的原理共享内存的理解shmget函数key和shmid的区别ipcs -m和shmctlshmatshmdt共享内存的通信共享内存的优点共享内存的缺点共享内存的特点 共享内存的原理 通过前面的内容我们知道不同的进程通过虚拟地址空间和页表能够将自己的数据映射到内存上的不同地方比如…

2023全新TwoNav开源网址导航系统源码 | 去授权版

2023全新TwoNav开源网址导航系统源码 已过授权 所有功能可用 测试环境&#xff1a;NginxPHP7.4MySQL5.6 一款开源的书签导航管理程序&#xff0c;界面简洁&#xff0c;安装简单&#xff0c;使用方便&#xff0c;基础功能免费。 TwoNav可帮助你将浏览器书签集中式管理&#…

Qt5开发及实例V2.0-第三章-Qt布局管理

Qt5开发及实例V2.0-第三章-Qt布局管理 第3章 Qt 5布局管理3.1 分割窗口QSplitter类3.2 停靠窗口QDockWidget类3.3 堆栈窗体QStackedWidget类3.4 基本布局&#xff08;QLayout&#xff09; 本章相关例程源码下载1.Qt5开发及实例_CH301.rar 下载2.Qt5开发及实例_CH302.rar 下载3.…

将json-bigint处理为数值分区数组的字段全部自动转为字符串

json-bigint虽然能帮我们处理好id 但 他的模式 显然不是直接可以用的 我们如果要到业务逻辑单独处理 那就太麻烦了 对系统也非常不友好 我们可以在vue项目中 src目录下创建一个utils 下面创建一个conversionLong.js 这个名字大家随便取 参考代码如下 var data {}; const Br…

黑马JVM总结(十四)

&#xff08;1&#xff09;分代回收_1 Java虚拟机都是结合前面几种算法&#xff0c;让他们协同工作&#xff0c;具体实现是虚拟机里面一个叫做分代的垃圾回收机制&#xff0c;把我们堆内存大的区域划分为两块新生代、老年代 新生代有划分为伊甸园、幸存区Form、幸存区To 为什…

Linux常用工具

文章目录 前言一、Linux编辑器-vim使用1.vim的基本概念2. vim的基本操作3. vim命令集1. 正常模式1. 模式切换和光标移动2. 删除文字及复制3. 其他操作 2. 底行模式 二、Linux编译器-gcc/g使用1. 命令和选项2. 预处理3. 编译4. 汇编(生成机器可识别代码)5. 连接(生成可执行文件或…

工业相机镜头选型相关内容参数(1)

工业相机镜头选型相关内容参数&#xff08;1&#xff09;https://www.bilibili.com/video/BV1PF411r7Yy/?spm_id_from333.999.0.0