running小程序重要技术流程文档

一、项目文件说明:

(注:getMyMoney无用已删除)
在这里插入图片描述

二、重要文件介绍

1.reinfo.js:位于utils文件下,该文件封装有统一的请求URL,和请求API同意封装供页面调用;调用时候需要在页面上先引入该文件,如下(index/index.js为例):

//先引入
import API from "../../utils/reinfo.js";

// 后使用的时候如下
wx.request({
  url: API.getSysConfig,//这里的API就是上面引入时候的名字,getSysConfig就是我们reinfo.js文件里封装的
  method:"get",
  success: function (res) {
  	// 调用接口成功后执行的
  }
})

2.app.js:这个是小程序的启动文件,每次小程序启动的话,必定会执行这个文件里的方法。

//onLaunch 小程序生命周期,启动就会执行
onLaunch: function () {
  var that=this;
  // 展示本地存储能力
  var openId = wx.getStorageSync('openId') || null
  // 获取用户openid、使用 Promise 
  // 这里的获取用户openid使用Promise 因为需要让index.js可以调用他来获取openid,因为index作为第一个小程序页面,也具有优先执行权,有时候会在app.js执行之前先执行,有时候会在app.js执行之后执行,所以这里使用Promise做一个异步请求,来供index.js页面调用回调获取用户数据
  const getUserOpenId = new Promise((resolve, reject) => {
    if(openId){
      console.log('缓存openid',openId)
      resolve(openId); // resolve Promise
    }else{
      // 登录code获取openid
      wx.login({
        success: function (res) {
          var code = res.code;//发送给服务器的code
            if (code) {
              wx.request({
                url: API.getSessinOpenid,
                method:"post",
                data: {
                  code: code,
                },
                header: {
                  'content-tpe': 'application/json'
                },
                success: function (res) {
                  console.log('获取到的用户openid为:',res)
                  //可以把openid保存到本地缓存,方便以后调用
                  wx.setStorageSync('openId', res.data.data);
                  // that.getUserInfoFun(res.data.data)
                  resolve(res.data.data); // resolve Promise
                },
                fail:function(res){
                  reject(err); // reject Promise
                  console.log(res)
                }
              })
            }
            else {
              console.log("获取用户登录态失败!");
            }
        },
        fail: function (error) {
        }
      })
    }
  });
   // 将 Promise 对象存储到全局数据对象中
   this.globalData.getUserOpenId = getUserOpenId;

  //  获取用户信息
  //这个获取用户信息同上意思
  const getUserInfo = new Promise((resolve, reject) => {
    wx.request({
      url: API.getUserInfo,
      method:"post",
      data: {
        openId: wx.getStorageSync('openId') || null,
      },
      success: function (res) {
        console.log('openid获取用户信息:',res)
        wx.setStorageSync('userInfo', res.data.data);
        resolve(res.data.data); // resolve Promise
      }
    })
  })
  // 将 Promise 对象存储到全局数据对象中
  this.globalData.getUserInfo = getUserInfo;
  
},

这个页面底部有个changeTabBar方法这个是自定义底部导航组件用来切换页面的公共方法
小程序组件的使用方法如下:
1.封装组件如comment\tabbar\tabbar.wxml这里就是封装了一个底部导航组件:
在这里插入图片描述
其他需要使用的页面进行引入(index/index):
wxml:


<import src="../../comment/tabbar/tabbar.wxml" />
<template is="tabbar" data="{{tabbar}}"/>

js:

//获取应用实例
const app = getApp();
Page({
/**
   * 页面的初始数据
   */
  data: {
    //底部导航栏
    tabbar: {},
  },
  //在onshow或者onload调用app下的changeTabBar方法来进行点击切换页面
  onload(){
    //调用app中的函数
    app.changeTabBar(); 
 } 
})

3.postOrder:发布订单是一个大麻烦:这里需要使用一个点击切换和滑动切换(同用户订单列表页和跑腿订单列表页)。
wxml:

<view class="navbar">
  <text wx:for="{{navbar}}" data-idx="{{index}}" class="item {{currentTab==index ? 'active' : ''}}" wx:key="unique" bindtap="navbarTap">{{item}}</text>
</view>

js:

/**
 * 页面的初始数据
 */
data: {
  navbar: ['帮我买', '帮我送', '帮我取'],
  currentTab: 0,
}


  //电机头部切换bar
  navbarTap: function (e) {
    console.log( e.currentTarget.dataset.idx)
    let initPrice = app.globalData.sysConfig.minDeliveryPrice
    // 切换的时候需要将数据清空,让用户重新输入
    let postData = {
      "commodity": "",
      "commodityCost": 0,
      "commodityWeight": 1,
      "deliveryAddress": "",
      "deliveryConcat": "",
      "deliveryPhone": "",
      "deliveryTime": "",
      "openId": "",
      "orderType": e.currentTarget.dataset.idx*1,
      "pickUpAddress": "",
      "pickUpContact": "",
      "pickUpPhone": "",
      "pickUpTime": "",
      "remark": "",
      "tipCost": 0,
      "totalCost": 0
    }
    // 设置取货时间、配送时间
    postData.deliveryTime = this.calculateFutureTime()
    if(postData.orderType == 1||postData.orderType == 2){
      postData.pickUpTime = this.calculateFutureTime()
    }
    var userInfo = wx.getStorageSync('userInfo') || {}
    postData.deliveryPhone = userInfo.phone
    // postData.orderType = e.currentTarget.dataset.idx
    this.setData({
      currentTab: e.currentTarget.dataset.idx,
      postData,
      
      multiIndex1: [0, 0], // 默认选择当天和第一个时间段
      multiIndex2: [0, 0], // 默认选择当天和第一个时间段
      multiIndex3: [0, 0], // 默认选择当天和第一个时间段
      multiIndex4: [0, 0], // 默认选择当天和第一个时间段

      price: initPrice
    })
    //全局变量
    app.globalData.currentTab = e.currentTarget.dataset.idx;
  },
  // 轮播切换,即左右滑动切换
  swiperChange: function (e) {
    let initPrice = app.globalData.sysConfig.minDeliveryPrice
    // 切换类型的话清空
    let postData = {
      "commodity": "",
      "commodityCost": 0,
      "commodityWeight": 1,
      "deliveryAddress": "",
      "deliveryConcat": "",
      "deliveryPhone": "",
      "deliveryTime": "",
      "openId": "",
      "orderType": e.detail.current*1,
      "pickUpAddress": "",
      "pickUpContact": "",
      "pickUpPhone": "",
      "pickUpTime": "",
      "remark": "",
      "tipCost": 0,
      "totalCost": 0
    }
    // 设置取货时间、配送时间
    postData.deliveryTime = this.calculateFutureTime()
    if(postData.orderType == 1||postData.orderType == 2){
      postData.pickUpTime = this.calculateFutureTime()
    }
    var userInfo = wx.getStorageSync('userInfo') || {}
    postData.deliveryPhone = userInfo.phone
    this.setData({
      currentTab: e.detail.current,
      postData,
      
      multiIndex1: [0, 0], // 默认选择当天和第一个时间段
      multiIndex2: [0, 0], // 默认选择当天和第一个时间段
      multiIndex3: [0, 0], // 默认选择当天和第一个时间段
      multiIndex4: [0, 0], // 默认选择当天和第一个时间段
      price: initPrice
    })
    //全局变量
    app.globalData.postOrderCurrentTab = e.detail.current;
  },

来实现顶部以及点击切换:在这里插入图片描述
配送时间的选择,进行一个立即配送和之后的每隔30分钟可供选择,有当天和次日,
在这里插入图片描述
wxml:

<view class="v1-item">
  <view>预计送达时间</view>
  <picker mode="multiSelector" bindcolumnchange="bindMultiPickerColumnChange" range="{{[dateRange, timeRange]}}" value="{{multiIndex1}}" data-id="1" bindchange="bindMultiPickerChange">
    <view class="picker">
      {{dateRange[multiIndex1[0]]}} {{timeRange[multiIndex1[1]]}}
    </view>
  </picker>
</view>

js:

data:{
    dateRange: ['今天', '明天'],
    timeRange: [], // 存储时间段的数组
    multiIndex1: [0, 0], // 默认选择当天和第一个时间段  帮我买:预计送达时间
    multiIndex2: [0, 0], // 默认选择当天和第一个时间段  帮我送:预计取货时间
    multiIndex3: [0, 0], // 默认选择当天和第一个时间段  帮我送:预计送达时间
    multiIndex4: [0, 0], // 默认选择当天和第一个时间段  帮我取:预计送达时间
}

  // 配送时间选择列表发生改变时候监听
  bindMultiPickerColumnChange(e){
    console.log('修改的列为', e.detail.column, ',值为', e.detail.value,e);
    if(e.detail.column == 0 && e.detail.value == 1){
      var startOfDay = new Date();
      startOfDay.setHours(0, 0, 0, 0);
      dayType = 1
      this.generateTimeRange(startOfDay)
    }
    else if(e.detail.column == 0 && e.detail.value == 0){
      dayType = 0
      this.generateTimeRange(new Date())
    }
  },
  // 计算时间选择列表
  generateTimeRange: function(now) {
    // var now = new Date();
    var hours = now.getHours();
    var minutes = now.getMinutes();
    var timeRange = [];
    
    // 生成时间段,每半个小时为一个时间段,共24小时
    for (var i = 0; i < 48; i++) {
      var hour = Math.floor(i / 2);
      var minute = (i % 2) * 30;
      
      // 格式化时间,补零操作
      var hourStr = hour < 10 ? '0' + hour : '' + hour;
      var minuteStr = minute === 0 ? '00' : '' + minute;
      
      if (hour > hours || (hour == hours && minute >= minutes)) {
        timeRange.push(hourStr + ':' + minuteStr);
      }
    }
    if(dayType == 0){
      timeRange[0] = '立即配送'
    }
    
    this.setData({
      timeRange: timeRange
    });
  },
  // 根据当前时间自动计算30分钟后的时间,并在遇到23:40时能正确计算到次日
  calculateFutureTime() {
    var currentDate = new Date();
    var futureDate = new Date(currentDate.getTime() + 30 * 60000); // 加上30分钟的毫秒数
  
    // 如果超过了当天的23:59:59,就设置到次日的00:30
    if (futureDate.getDate() > currentDate.getDate()) {
      futureDate = new Date(futureDate.getFullYear(), futureDate.getMonth(), futureDate.getDate(), 0, 30, 0);
      
      var originalDate = new Date(futureDate);
      var hour = originalDate.getHours()<10?'0'+originalDate.getHours():originalDate.getHours();
      // var minute = originalDate.getMinutes();
      var minute = originalDate.getMinutes()<10?'0'+originalDate.getMinutes():originalDate.getMinutes();
      var formattedTime = hour + ':' + minute;
      // var formattedTime = hour<10?0+hour:hour + ':' + minute;
      console.log("当前时间0000:" , currentDate);
      console.log("30分钟后的时间000:" , futureDate,formattedTime);
      return '次日 '+formattedTime;
    }
    var originalDate = new Date(futureDate);
    var hour = originalDate.getHours()<10?'0'+originalDate.getHours():originalDate.getHours();
    var minute = originalDate.getMinutes()<10?'0'+originalDate.getMinutes():originalDate.getMinutes();
    // var minute = originalDate.getMinutes();
    var formattedTime = hour + ':' + minute;
    // var formattedTime = hour<10?0+hour:hour + ':' + minute;

    console.log("当前时间111:" , currentDate);
    console.log("30分钟后的时间1111:" , futureDate,formattedTime);
    return '今天 '+formattedTime;
  },
  // 选择
  bindMultiPickerChange: function(e) {
    console.log('选择',e)
    let postData = this.data.postData
    let type = e.currentTarget.dataset.id
    console.log('这样可以吗?',this.data['multiIndex'+type])
    // 如果是立即配送自动匹配现在的30分钟后
    if(this.data.timeRange[e.detail.value[1]] == '立即配送'){
      postData.deliveryTime = this.calculateFutureTime()
    }
    if(type == 1){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 2){
      postData.pickUpTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 3){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    if(type == 4){
      postData.deliveryTime = this.data.dateRange[this.data['multiIndex'+type][0]] +' '+ this.data.timeRange[this.data['multiIndex'+type][1]]
    }
    
    this.setData({
      ['multiIndex'+type]: e.detail.value,
      postData,
    });
    console.log('结果》》》?',this.data['multiIndex'+type])
  },

图片上传列表
wxml:

<view class="v1">
     <!-- 图片列表 -->
     <view class="image-list">
       <block wx:for="{{images}}" wx:key="index">
         <view class="image-item">
           <image src="{{item}}" mode="aspectFill" data-src="{{item}}" bindtap="previewImage"></image>
           <view class="delete-btn" bindtap="deleteImage" data-index="{{index}}">×</view>
         </view>
       </block>
       <!-- 添加图片按钮 -->
       <view class="add-image" bindtap="chooseImage">
         <text>+</text>
       </view>
     </view>
   </view>

js:

data:{
    images: [], // 存储已选择的图片列表
}

 // 选择图片
  chooseImage() {
    let that = this;
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: (res) => {
        console.log('选择图片',res)
        wx.uploadFile({
          url: API.uploadImg,
          filePath: res.tempFilePaths[0],
          name: 'file',
          header: {
            "Content-Type": "multipart/form-data"
          },
          formData: {
            'type': 4 //1-表示头像,2-表示身份证,4-订单图片
          },
          success (resFile){
            let fileData = JSON.parse(resFile.data)
            console.log("文件上传接口",JSON.parse(resFile.data))
            if(fileData.code == 0){
              // 上传成功时候插入原有的数据中
              const newImages = that.data.images.concat(fileData.data);
              that.setData({
                images: newImages,
              });
            }else{
              wx.showToast({
                title: fileData.msg,
                icon: 'error'
              })
            }
          }
        })
        
      },
    });
  },

  // 预览图片
  previewImage(e) {
    const current = e.target.dataset.src;
    wx.previewImage({
      current: current,
      urls: this.data.images,
    });
  },

  // 删除图片
  deleteImage(e) {
    const index = e.target.dataset.index;
    const newImages = this.data.images;
    // 删除指定位置index的图片
    newImages.splice(index, 1);
    this.setData({
      images: newImages,
    });
  },

4.index:抢单大厅样式

//<!-- class使用三元运算符,动态设置class名称,用遍历数据,判断奇偶数来实现左右不同样式 -->
<view class="{{index%2 == 0?'v2-body-v1':'v2-body-v2'}}" wx:for="{{orderHallList}}"  bindtap="gotoOrderDetail" data-paymentStatus="{{item.paymentStatus}}" data-orderStatus="{{item.orderStatus}}" data-id="{{item.id}}" data-type="orderHall">
  <view class="{{index%2 == 0?'v2-body-v1-price':'v2-body-v2-price'}}">{{item.totalCost}}</view>
  <view class="{{index%2 == 0?'v2-body-v1-text':'v2-body-v2-text'}}">
    <image src="{{index%2 == 0?'/images/zuo.png':'/images/you.png'}}"></image>
    <text>{{item.orderType == 'BUY'?'帮我买':item.orderType == 'SEND'?'帮我送':item.orderType == 'TAKE'?'帮我取':''}}</text>
  </view>
  <view class="{{index%2 == 0?'v2-body-v1-img':'v2-body-v2-img'}}">
    <view>{{item.deliveryAddress}}</view>
    <view>{{item.deliveryTime}}</view>
  </view>
</view>

5.订单完成的评价打分
wxml:

<view class="v1-item">
  // <!-- 星星打分实现 -->
    <view style="width: 100%;line-height: 60rpx;">
      <view style="width: unset;margin-left: unset;" class='starLen' bindtap="myStarChoose">
        <block wx:for="{{starMap}}">
          <image wx:if="{{star>=index+1}}" class='star' data-star="{{index+1}}" src="../../images/start-2.png" /> 
          <image wx:if="{{star<index+1}}" class='star' data-star="{{index+1}}" src="../../images/start-1.png" />    
        </block>
      </view>
      <view class="scoreContent" style="width: unset;margin-left: unset;">{{starMap[star-1]}}</view>
    </view>
  </view>

js:

/**
   * 页面的初始数据
   */
  data: {
    star: 0,  //默认0分
    starMap: [
      '非常差',
      '差',
      '一般',
      '好',
      '非常好',
    ],
  },
  
  // 选星
  myStarChoose(e) {
    let star = parseInt(e.target.dataset.star) || 0;
    // 获取打的分
    this.setData({
      star: star,
    });
  },

这里列举这几个比较难的流程,如果后面对哪些模块的流程有不明白的可以再提出来

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

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

相关文章

有哪些已经上线的vue商城项目?

前言 下面是一些商城的项目&#xff0c;需要练手的同学可以挑选一些来练&#xff0c;废话少说&#xff0c;让我们直接开始正题~~ 1、newbee-mall-vue3-app 是一个基于 Vue 3 和 TypeScript 的电商前端项目&#xff0c;它是 newbee-mall 项目的升级版。该项目包含了商品列表、…

Linux--权限问题(1)

前文 Linux--初识和基本的指令&#xff08;1&#xff09;-CSDN博客 Linux--初识和基本的指令&#xff08;2&#xff09;-CSDN博客 Linux--初识和基本的指令&#xff08;3&#xff09;-CSDN博客 目录 前文 前言 1.剩余指令部分 1.1 打包和压缩的其它指令 2.权限部分 2.1权…

Python面向对象基础

Python面向对象基础 一、概念1.1面向对象的设计思想1.2 面向过程和面向对象1.2.1 面向过程1.2.2 面向对象1.2.3 面向过程和面向对象的优缺点 二、类和对象2.1 概念2.2 类的定义2.3 对象的创建2.3.1 类中未定义构造函数2.3.2 类中定义构造函数 2.4 类的设计 三、类中的成员3.1 变…

交付《啤酒游戏经营决策沙盘》的项目

感谢首富客户连续两年的邀请&#xff0c;交付《啤酒游戏经营决策沙盘》的项目&#xff0c;下周一JSTO首席学习官Luna想让我分享下系统思考与投资理财&#xff0c;想到曾经看过的一本书《深度思维》&#xff0c;看到一些结构来预判未来。不仅仅可以应用在企业经营和组织发展上&a…

Java Web应用小案例 - 实现用户登录功能

文章目录 一、使用纯JSP方式实现用户登录功能&#xff08;一&#xff09;项目概述&#xff08;二&#xff09;实现步骤1、创建Web项目2、创建登录页面 二、使用JSPServlet方式实现用户登录功能三、使用JSPServletDB方式实现用户登录功能 一、使用纯JSP方式实现用户登录功能 &a…

tomcat篇---第二篇

系列文章目录 文章目录 系列文章目录前言一、tomcat容器是如何创建servlet类实例?用到了什么原理?二、tomcat 如何优化?三、熟悉tomcat的哪些配置?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女…

认识 Redis - Redis 的安装与下载

Redis 从今天开始&#xff0c;我们迎接一个全新的专栏 - Redis 专栏。 相信我们在日常的学习中&#xff0c;肯定也是对 Redis 早有耳闻&#xff0c;今天我们还是先来了解一下 Redis 是什么&#xff1f;以及 Redis 应该怎么使用&#xff1f;… 1. Redis 是什么&#xff1f; …

React中使用react-json-view展示JSON数据

文章目录 一、前言1.1、在线demo1.2、Github仓库 二、实践2.1、安装react-json-view2.2、组件封装2.3、效果2.4、参数详解2.4.1、src(必须) &#xff1a;JSON Object2.4.2、name&#xff1a;string或false2.4.3、theme&#xff1a;string2.4.4、style&#xff1a;object2.4.5、…

Word插件-好用的插件-一键设置字体--大珩助手

常用字体 整理了论文、公文常用字体 整理了常用的论文字体&#xff0c;可一键设置当前节或选择的文字的字体 字体设置 包含字体选择、字体颜色 特殊格式 包含首字下沉、段落分栏、统一宽度、双行合一、上标切换、下标切换、转为全角、转为半角、挖词填空、当前日期、大写金…

Selenium+Unittest+HTMLTestRunner框架更改为Selenium+Pytest+Allure(二)

1 代码框架 整体项目结构如图&#xff1a; Common&#xff1a;公共库 Logs&#xff1a; 日志目录 Page&#xff1a; 页面元素 Report&#xff1a;测试报告 TestCase&#xff1a;测试用例 TestData&#xff1a; 测试数据 2 单模块运行 直接上代码&#xff1a; # -*- coding…

【C++学习手札】基于红黑树封装模拟实现map和set

​ &#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 &#x1f49c;本文前置知识&#xff1a; 红黑树 ♈️今日夜电波&#xff1a;漂流—菅原纱由理 2:55━━━━━━️&#x1f49f;──────── 4:29 …

学生护眼灯哪个牌子好?适合学生考研用的台灯推荐

不知道各位家长们有没有对孩子的视力健康关注过&#xff0c;如今中国近视的总人数接近6亿人口&#xff01;而我国儿童青少年近视比率更是超过了一半&#xff0c;达到了52.7%的近视率&#xff0c;也就是说每十个儿童青少年中就有五个是存在视力问题的。其中很大的原因就是长时间…

docker资源限制

目录 系统压力测试工具stress 1. cpu资源限制 1.1 限制CPU Share 1.2 限制CPU 核数 1.3 CPU 绑定 2. mem资源限制 3. 限制IO 二、端口转发 三、容器卷 四、部署centos7容器应用 五、docker数据存储位置 六、docker网络 容器网络分类 在使用 docker 运行容器时&…

办公人员必备简单拉伸操,为了保护自己的颈椎,赶快练起来吧

目录 一、办公人员必备简单拉伸操的必要性 二、教程介绍 第一节&#xff1a;双掌擦颈 第二节&#xff1a;左右转头 第三节&#xff1a;前后点头 第四节&#xff1a;旋肩舒颈 第五节&#xff1a;颈项争力 第六节&#xff1a;头部旋转 第七节&#xff1a;头手相抗 第八…

有一篇文章,共有3行文字,每行有80个字符。要求分别统计其中英文大写字母、小写字母、数字、空格以及其他字符的个数

目录 1解题思路&#xff1a; 2代码&#xff1a; 3运行代码&#xff1a; 4总结&#xff1a; 1解题思路&#xff1a; 有一篇文章&#xff0c;共有3行文字&#xff0c;每行有80个字符。要求分别统计其中英文大写字母、小写字母、数字、空格以及其他字符的个数 首先先设置一个字…

Qt工程文件分离、Qtimer定时器、Qt Creator 常用快捷键

Qt 工程文件分离 不含 UI 的文件分离 以堆栈窗体的代码为例。 firstpagewidget.h #ifndef FIRSTPAGEWIDGET_H #define FIRSTPAGEWIDGET_H#include <QtWidgets> // 记得修改class firstPageWidget : public QWidget {Q_OBJECT public:explicit firstPageWidget(QW…

『Linux升级路』进度条小程序

&#x1f525;博客主页&#xff1a;小王又困了 &#x1f4da;系列专栏&#xff1a;Linux &#x1f31f;人之为学&#xff0c;不日近则日退 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、预备知识 &#x1f4d2;1.1缓冲区 &#x1f4d2;1.2回车和换行 二、倒计…

pair的用法,详解

1.pair是什么 pair名为二元组&#xff0c;顾名思义&#xff0c;就是储存二元组的。 2.pair的初始化 pair<第一个值类型, 第二个值类型> pr 第一个值类型&#xff1a;要储存的第一个值的数据类型第二个值类型&#xff1a;要储存的第二个值的数据类型pair<int, int&g…

【数据结构】单调栈与单调队列算法总结

单调栈 知识概览 单调栈最常见的应用是找到每一个数离它最近的且比它小的数。单调栈考虑的方式和双指针类似&#xff0c;都是先想一下暴力做法是什么&#xff0c;然后再挖掘一些性质如单调性&#xff0c;最终可以把目光集中在比较少的状态中&#xff0c;从而达到降低时间复杂…

让聪明的车连接智慧的路,C-V2X开启智慧出行生活

“聪明的车 智慧的路”形容的便是车路协同的智慧交通系统&#xff0c;从具备无钥匙启动&#xff0c;智能辅助驾驶和丰富娱乐影音功能的智能网联汽车&#xff0c;到园区的无人快递配送车&#xff0c;和开放的城市道路上自动驾驶的公交车、出租车&#xff0c;越来越多的车联网应用…
最新文章