小兔鲜--项目总结3

news2024/11/28 18:47:29

目录

结算模块-地址切换交互实现

地址切换交互需求分析

打开弹框交互实现

地址激活交互实现

订单模块-生成订单功能实现 

 支付模块-实现支付功能

支付业务流程

 支付模块-支付结果展示

支付模块-封装倒计时函数

理解需求

 实现思路分析

会员中心-个人中心信息渲染

分页逻辑实现

SKU组件封装

认识SKU组件

 点击规格更新选中状态

 点击规格更新禁用状态 - 生成有效路径字典(1)

点击规格更新禁用状态 - 生成有效路径字典(2)

点击规格更新禁用状态 - 初始化规格禁用

击规格更新禁用状态 - 点击时组合禁用更新

产出有效的SKU信息

完整代码


结算模块-地址切换交互实现

地址切换交互需求分析

1. 打开弹框交互:点击切换地址按钮,打开弹框,回显用户可选地址列表
2. 切换地址交互:点击切换地址,点击确定按钮,激活地址替换默认收货地址

打开弹框交互实现

1. 准备弹框模版

<el-dialog title="切换收货地址" width="30%" center>
  <div class="addressWrapper">
    <div class="text item" v-for="item in checkInfo.userAddresses"  :key="item.id">
      <ul>
      <li><span>收<i />货<i />人:</span>{{ item.receiver }} </li>
      <li><span>联系方式:</span>{{ item.contact }}</li>
      <li><span>收货地址:</span>{{ item.fullLocation + item.address }}</li>
      </ul>
    </div>
  </div>
  <template #footer>
    <span class="dialog-footer">
      <el-button>取消</el-button>
      <el-button type="primary">确定</el-button>
    </span>
  </template>
</el-dialog>

 2. 控制弹框打开

const showDialog = ref(false)

<el-button size="large" @click="showDialog = true">切换地址</el-button>

<el-dialog v-model="showDialog" title="切换收货地址" width="30%" center>
    <!-- 省略 -->
</el-dialog>

地址激活交互实现

原理:地址切换是我们经常遇到的 `tab切换类` 需求,这类需求的实现逻辑都是相似的
1. 点击时记录一个当前激活地址对象activeAddress, 点击哪个地址就把哪个地址对象记录下来
2. 通过动态类名:class 控制激活样式类型 active是否存在,判断条件为:激活地址对象的id === 当前项id

<script setup>
// 切换地址
const activeAddress = ref({})
const switchAddress = (item) => {
  activeAddress.value = item
}
</script>

<template>
<div class="text item" 
  :class="{ active: activeAddress.id === item.id }" 
  @click="switchAddress(item)"
  :key="item.id">
  <!-- 省略... -->
</div>
</template>

切换地址属于哪类通用型交互功能?

tab切换类交互
记录激活项(整个对象/id/index) + 动态类名控制

订单模块-生成订单功能实现 

业务需求说明

确定结算信息没有问题之后,点击提交订单按钮,需要做以下俩个事情:

1. 调用接口生成订单id,并且携带id跳转到支付页
2. 调用更新购物车列表接口,更新购物车状态

<script setup>
import { createOrderAPI } from '@/apis/checkout'

// 创建订单
const createOrder = async () => {
  const res = await createOrderAPI({
    deliveryTimeType: 1,
    payType: 1,
    payChannel: 1,
    buyerMessage: '',
    goods: checkInfo.value.goods.map(item => {
      return {
        skuId: item.skuId,
        count: item.count
      }
    }),
    addressId: curAddress.value.id
  })
  const orderId = res.result.id
  router.push({
    path: '/pay',
    query: {
      id: orderId
    }
  })
}

</script>

<template>
    <!-- 提交订单 -->
    <div class="submit">
      <el-button @click="createOrder" type="primary" size="large">提交订单</el-button>
    </div>
</template>

 支付模块-实现支付功能

支付业务流程

// 支付地址
const baseURL = 'http://pcapi-xiaotuxian-front-devtest.itheima.net/'
const backURL = 'http://127.0.0.1:5173/paycallback'
const redirectUrl = encodeURIComponent(backURL)
const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.id}&redirect=${redirectUrl}`

 支付模块-支付结果展示

业务需求理解

<script setup>
import { getOrderAPI } from '@/apis/pay'
import { onMounted, ref } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
const orderInfo = ref({})

const getOrderInfo = async () => {
  const res = await getOrderAPI(route.query.orderId)
  orderInfo.value = res.result
}

onMounted(() => getOrderInfo())

</script>


<template>
  <div class="xtx-pay-page">
    <div class="container">
      <!-- 支付结果 -->
      <div class="pay-result">
        <!-- 路由参数获取到的是字符串而不是布尔值 -->
        <span class="iconfont icon-queren2 green" v-if="$route.query.payResult === 'true'"></span>
        <span class="iconfont icon-shanchu red" v-else></span>
        <p class="tit">支付{{ $route.query.payResult === 'true' ? '成功' : '失败' }}</p>
        <p class="tip">我们将尽快为您发货,收货期间请保持手机畅通</p>
        <p>支付方式:<span>支付宝</span></p>
        <p>支付金额:<span>¥{{ orderInfo.payMoney?.toFixed(2) }}</span></p>
        <div class="btn">
          <el-button type="primary" style="margin-right:20px">查看订单</el-button>
          <el-button>进入首页</el-button>
        </div>
        <p class="alert">
          <span class="iconfont icon-tip"></span>
          温馨提示:小兔鲜儿不会以订单异常、系统升级为由要求您点击任何网址链接进行退款操作,保护资产、谨慎操作。
        </p>
      </div>
    </div>
  </div>
</template>

支付模块-封装倒计时函数

理解需求

 实现思路分析

import { computed, onUnmounted, ref } from 'vue'
import dayjs from 'dayjs'
// 封装倒计时逻辑
export const useCountDown = () => {
    const formatTime = computed(() => dayjs.unix(time.value).format('mm分ss秒'))
    // 1. 响应式的数据
    let timer = null
    const time = ref(0)
    // 2. 开启倒计时的函数
    const start = (currentTime) => {
        // 开始倒计时的逻辑
        // 核心逻辑的编写:每隔1s就减一
        time.value = currentTime
        timer = setInterval(() => {
            time.value--
        }, 1000)
    }
    // 组件销毁时清除定时器
    onUnmounted(() => {
        timer && clearInterval(timer)
    })

    return {
        formatTime,
        start
    }
}

会员中心-个人中心信息渲染

分页逻辑实现

页数 = 总条数 / 每页条数 

<script setup>
// 补充总条数
const total = ref(0)
const getOrderList = async () => {
  const res = await getUserOrder(params.value)
  // 存入总条数
  total.value = res.result.counts
}
// 页数切换
const pageChange = (page) => {
  params.value.page = page
  getOrderList()
}
</script>

<template>
   <el-pagination 
     :total="total" 
     @current-change="pageChange" 
     :page-size="params.pageSize" 
     background
     layout="prev, pager, next" />
</template>

SKU组件封装

认识SKU组件

SKU组件的作用是为了让用户能够选择商品的规格,从而提交购物车,在选择的过程中,组件的选中状态要进行更新, 组件还要提示用户当前规格是否禁用,每次选择都要产出对应的Sku数据\

 点击规格更新选中状态

 

基本思路:

  1. 每一个规格按钮都拥有自己的选中状态数据-selected,true为选中,false为取消选中
  2. 配合动态class,把选中状态selected作为判断条件,true让active类名显示,false让active类名不显示
  3. 点击的是未选中,把同一个规格的其他取消选中,当前点击项选中;点击的是已选中,直接取消
script setup>
// 省略代码

// 选中和取消选中实现
const changeSku = (item, val) => {
  // 点击的是未选中,把同一个规格的其他取消选中,当前点击项选中,点击的是已选中,直接取消
  if (val.selected) {
    val.selected = false
  } else {
    item.values.forEach(valItem => valItem.selected = false)
    val.selected = true
  }
}

</script>

<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="val in item.values" :key="val.name">
          <img v-if="val.picture" 
            @click="changeSku(item, val)" 
            :class="{ selected: val.selected }" 
            :src="val.picture"
            :title="val.name">
          <span v-else 
            @click="changeSku(val)" 
            :class="{ selected: val.selected }">{{ val.name }}</span>
        </template>
      </dd>
    </dl>
  </div>
</template>

 点击规格更新禁用状态 - 生成有效路径字典(1)

规格禁用的判断依据是什么?

 核心原理:当前的规格Sku,或者组合起来的规格Sku,在skus数组中对应项的库存为零时,当前规格会被禁用,生成 路径字典是为了协助和简化这个匹配过程

点击规格更新禁用状态 - 生成有效路径字典(2)

 

实现步骤:
1. 根据库存字段得到有效的Sku数组
2. 根据有效的Sku数组使用powerSet算法得到所有子集 3. 根据子集生成路径字典对象

export default function bwPowerSet (originalSet) {
  const subSets = []

  // We will have 2^n possible combinations (where n is a length of original set).
  // It is because for every element of original set we will decide whether to include
  // it or not (2 options for each set element).
  const numberOfCombinations = 2 ** originalSet.length

  // Each number in binary representation in a range from 0 to 2^n does exactly what we need:
  // it shows by its bits (0 or 1) whether to include related element from the set or not.
  // For example, for the set {1, 2, 3} the binary number of 0b010 would mean that we need to
  // include only "2" to the current set.
  for (let combinationIndex = 0; combinationIndex < numberOfCombinations; combinationIndex += 1) {
    const subSet = []

    for (let setElementIndex = 0; setElementIndex < originalSet.length; setElementIndex += 1) {
      // Decide whether we need to include current element into the subset or not.
      if (combinationIndex & (1 << setElementIndex)) {
        subSet.push(originalSet[setElementIndex])
      }
    }

    // Add current subset to the list of all subsets.
    subSets.push(subSet)
  }

  return subSets
}
// 创建生成路径字典对象函数
const getPathMap = (goods) => {
  const pathMap = {};
  // 1. 得到所有有效的Sku集合
  const effectiveSkus = goods.filter((sku) => sku.inventory > 0);

  // 2. 根据有效的Sku集合使用powerSet算法得到所有子集 [1,2] => [[1], [2], [1,2]]
  effectiveSkus.forEach((sku) => {
    // 2.1 获取可选规格值数组
    const selectedValArr = sku.specs.map((val) => val.valueName);
    // 2.2 获取可选值数组的子集
    const valueArrPowerSet = bwPowerSet(selectedValArr);
    // 3. 根据子集生成路径字典对象
    // 3.1 遍历子集 往pathMap中插入数据
    valueArrPowerSet.forEach((arr) => {
      // 根据Arr得到字符串的key,约定使用-分割 ['蓝色','美国'] => '蓝色-美国'
      const key = arr.join("-");
      // 给pathMap设置数据
      if (pathMap[key]) {
        pathMap[key].push(sku.id);
      } else {
        pathMap[key] = [sku.id];
      }
    });
  });
  console.log(pathMap);
  return pathMap;
};

点击规格更新禁用状态 - 初始化规格禁用

思路:遍历每一个规格对象,使用name字段作为key去路径字典pathMap中做匹配,匹配不上则禁用

 思路:判断规格的name属性是否能在有效路径字典中找到,如果找不到就禁用

// 1. 定义初始化函数
// specs:商品源数据 pathMap:路径字典
const initDisabledState = (specs, pathMap) => {
  // 约定:每一个按钮的状态由自身的disabled进行控制
  specs.forEach((item) => {
    item.values.forEach((val) => {
      console.log(val);
      if (pathMap[val.name]) {
        val.disabled = false;
      } else {
        val.disabled = true;
      }
    });
  });
};

击规格更新禁用状态 - 点击时组合禁用更新

思路(点击规格时):
1. 按照顺序得到规格选中项的数组 [‘蓝色’,‘20cm’, undefined]

2. 遍历每一个规格

2.1 把name字段的值填充到对应的位置
2.2 过滤掉undefined项使用join方法形成一个有效的key
2.3 使用key去pathMap中进行匹配,匹配不上,则当前项禁用

// 获取选中匹配数组 ['黑色',undefined,undefined]
const getSelectedValues = (specs) => {
  const arr = []
  specs.forEach(spec => {
    const selectedVal = spec.values.find(value => value.selected)
    arr.push(selectedVal ? selectedVal.name : undefined)
  })
  return arr
}

// 切换时更新选中状态
const updateDisabledState = (specs, pathMap) => {
  // 约定:每一个按钮的状态由自身的disabled进行控制
  specs.forEach((item, i) => {
    const selectedValues = getSelectedValues(specs);
    console.log(selectedValues);
    item.values.forEach((val) => {
      selectedValues[i] = val.name;
      const key = selectedValues.filter((value) => value).join("-");
      console.log(key);
      if (pathMap[key]) {
        val.disabled = false;
      } else {
        val.disabled = true;
      }
    });
  });
};

产出有效的SKU信息

什么是有效的SKU?

如何判断当前用户已经选择了所有有效的规格?
已选择项数组 [‘蓝色’,‘20cm’, undefined] 中找不到undefined, 那么用户已经选择了所有的有效规格,此时可以产出数据

如何获取当前的SKU信息对象?

把已选择项数组拼接为路径字典的key,去路径字典pathMap中找即可

 

// 选中和取消选中实现
const changeSku = (item, val) => {
  if (val.disabled) return;
  // 点击的是未选中,把同一个规格的其他取消选中,当前点击项选中,点击的是已选中,直接取消
  if (val.selected) {
    val.selected = false;
  } else {
    item.values.forEach((valItem) => (valItem.selected = false));
    val.selected = true;
  }
  updateDisabledState(goods.value.specs, pathMap);
  const index = getSelectedValues(goods.value.specs).findIndex(
    (item) => item === undefined
  );
  if (index > -1) {
    console.log("找到了,信息不完整");
  } else {
    console.log("没有找到,信息完整,可以产出");
    // 获取sku对象
    const key = getSelectedValues(goods.value.specs).join("-");
    const skuIds = pathMap[key];
    console.log(skuIds);
    // 以skuId作为匹配项去goods.value.skus数组中找
    const skuObj = goods.value.skus.find((item) => item.id === skuIds[0]);
    console.log("sku对象为", skuObj);
  }
};

完整代码

<script setup>
import { onMounted, ref } from "vue";
import axios from "axios";
import { bwPowerSet } from "@/utils/getPathMap";
// 商品数据
const goods = ref({});
let pathMap = {};
const getGoods = async () => {
  // 1135076  初始化就有无库存的规格
  // 1369155859933827074 更新之后有无库存项(蓝色-20cm-中国)
  const res = await axios.get(
    "http://pcapi-xiaotuxian-front-devtest.itheima.net/goods?id=1369155859933827074"
  );
  goods.value = res.data.result;

  // 后端返回的库存列表
  let skus = res.data.result.skus;
  // 规格列表
  let specs = res.data.result.specs;
  pathMap = getPathMap(skus);
  initDisabledState(specs, pathMap);
};
onMounted(() => getGoods());
// 创建生成路径字典对象函数
const getPathMap = (goods) => {
  const pathMap = {};
  // 1. 得到所有有效的Sku集合
  const effectiveSkus = goods.filter((sku) => sku.inventory > 0);

  // 2. 根据有效的Sku集合使用powerSet算法得到所有子集 [1,2] => [[1], [2], [1,2]]
  effectiveSkus.forEach((sku) => {
    // 2.1 获取可选规格值数组
    const selectedValArr = sku.specs.map((val) => val.valueName);
    // 2.2 获取可选值数组的子集
    const valueArrPowerSet = bwPowerSet(selectedValArr);
    // 3. 根据子集生成路径字典对象
    // 3.1 遍历子集 往pathMap中插入数据
    valueArrPowerSet.forEach((arr) => {
      // 根据Arr得到字符串的key,约定使用-分割 ['蓝色','美国'] => '蓝色-美国'
      const key = arr.join("-");

      // 给pathMap设置数据
      if (pathMap[key]) {
        pathMap[key].push(sku.id);
      } else {
        pathMap[key] = [sku.id];
      }
    });
  });
  console.log(pathMap);
  return pathMap;
};
// 1. 定义初始化函数
// specs:商品源数据 pathMap:路径字典
const initDisabledState = (specs, pathMap) => {
  // 约定:每一个按钮的状态由自身的disabled进行控制
  specs.forEach((item) => {
    item.values.forEach((val) => {
      console.log(val);
      if (pathMap[val.name]) {
        val.disabled = false;
      } else {
        val.disabled = true;
      }
    });
  });
};
// 获取选中匹配数组 ['黑色',undefined,undefined]
const getSelectedValues = (specs) => {
  const arr = [];
  specs.forEach((spec) => {
    const selectedVal = spec.values.find((value) => value.selected);
    arr.push(selectedVal ? selectedVal.name : undefined);
  });
  return arr;
};
// 切换时更新选中状态
const updateDisabledState = (specs, pathMap) => {
  // 约定:每一个按钮的状态由自身的disabled进行控制
  specs.forEach((item, i) => {
    const selectedValues = getSelectedValues(specs);
    console.log(selectedValues);
    item.values.forEach((val) => {
      selectedValues[i] = val.name;
      const key = selectedValues.filter((value) => value).join("-");
      console.log(key);
      if (pathMap[key]) {
        val.disabled = false;
      } else {
        val.disabled = true;
      }
    });
  });
};
// 选中和取消选中实现
const changeSku = (item, val) => {
  if (val.disabled) return;
  // 点击的是未选中,把同一个规格的其他取消选中,当前点击项选中,点击的是已选中,直接取消
  if (val.selected) {
    val.selected = false;
  } else {
    item.values.forEach((valItem) => (valItem.selected = false));
    val.selected = true;
  }
  updateDisabledState(goods.value.specs, pathMap);
  const index = getSelectedValues(goods.value.specs).findIndex(
    (item) => item === undefined
  );
  if (index > -1) {
    console.log("找到了,信息不完整");
  } else {
    console.log("没有找到,信息完整,可以产出");
    // 获取sku对象
    const key = getSelectedValues(goods.value.specs).join("-");
    const skuIds = pathMap[key];
    console.log(skuIds);
    // 以skuId作为匹配项去goods.value.skus数组中找
    const skuObj = goods.value.skus.find((item) => item.id === skuIds[0]);
    console.log("sku对象为", skuObj);
  }
};
</script>

<template>
  <div class="goods-sku">
    <dl v-for="item in goods.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="val in item.values" :key="val.name">
          <img
            v-if="val.picture"
            @click="changeSku(item, val)"
            :class="{ selected: val.selected, disabled: val.disabled }"
            :src="val.picture"
            :title="val.name"
          />
          <span
            v-else
            @click="changeSku(item, val)"
            :class="{ selected: val.selected, disabled: val.disabled }"
            >{{ val.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>
<style scoped lang="scss">
@mixin sku-state-mixin {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;

  &.selected {
    border-color: #27ba9b;
  }

  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}

.goods-sku {
  padding-left: 10px;
  padding-top: 20px;

  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;

    dt {
      width: 50px;
      color: #999;
    }

    dd {
      flex: 1;
      color: #666;

      > img {
        width: 50px;
        height: 50px;
        margin-bottom: 4px;
        @include sku-state-mixin;
      }

      > span {
        display: inline-block;
        height: 30px;
        line-height: 28px;
        padding: 0 20px;
        margin-bottom: 4px;
        @include sku-state-mixin;
      }
    }
  }
}
</style>

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

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

相关文章

【JavaSE】Java基础语法(二十六):Collection集合

文章目录 1. 数组和集合的区别2. 集合类体系结构3. Collection 集合概述和使用【应用】4. Collection集合的遍历【应用】5. 增强for循环【应用】 1. 数组和集合的区别 相同点 都是容器,可以存储多个数据不同点 数组的长度是不可变的,集合的长度是可变的 数组可以存基本数据类型…

【C++系列P4】‘类与对象‘-三部曲——[类](2/3)

前言 大家好吖&#xff0c;欢迎来到 YY 滴 C系列 &#xff0c;热烈欢迎&#xff01; 【 类与对象-三部曲】的大纲主要内容如下&#xff1a; 如标题所示&#xff0c;本章是【 类与对象-三部曲】三章中的第二章节——类章节&#xff0c;主要内容如下&#xff1a; 目录 一.类 1.…

CodeForces..学习读书吧.[简单].[条件判断].[找最小值]

题目描述&#xff1a; 题目解读&#xff1a; 给定一组数&#xff0c;分别是 “时间 内容”&#xff0c;内容分为00&#xff0c;01&#xff0c;10&#xff0c;11四种&#xff0c;求能够得到11的最小时间。 解题思路&#xff1a; 看似00&#xff0c;01&#xff0c;10&#xff0…

完整卸载office以及重装office 2021

完整卸载office以及重装 一.背景 之前很早安装的word最近发现打开&#xff0c;编辑等操作都很卡&#xff0c;而且占用的CPU很多&#xff0c;20%左右&#xff0c;而在网上搜索了一些结果无法解决问题后&#xff0c;决定卸载重装 二. 卸载的建议方法 直接参考官方链接从PC卸载…

华为OD机试之租车骑绿岛(Java源码)

租车骑绿岛 题目描述 部门组织绿岛骑行团建活动。租用公共双人自行车&#xff0c;每辆自行车最多坐两人&#xff0c;最大载重M。 给出部门每个人的体重&#xff0c;请问最多需要租用多少双人自行车。 输入描述 第一行两个数字m、n&#xff0c;分别代表自行车限重&#xff0c;部…

k8s 对外服务之 ingress|ingress的对外暴露方式|ingress http,https代理|ingress nginx的认证,nginx重写

k8s 对外服务之 ingress|ingress的对外暴露方式|ingress http&#xff0c;https代理|ingress nginx的认证&#xff0c;nginx重写 一 Ingress 简介二 Ingress 组成三 ingress 暴露服务的方式四 部署 nginx-ingress-controller4.1 修改 ClusterRole 资源配置4.2 DaemonSetHostNet…

STM32HAL库RS485-ModBus协议控制伺服电机

STM32HAL库RS485-ModBus协议控制伺服电机 一个月前&#xff0c;接手了一个学长的毕设小车&#xff0c;小车采用rs485通信的modbus协议驱动轮毂电机&#xff0c;与往常我学习的pwm控制电机方法大相径庭&#xff0c;在这里以这篇博客记录下该学习过程。 小车主要架构 电机型号 …

Python期末复习题库(上)——“Python”

小雅兰期末加油冲冲冲&#xff01;&#xff01;&#xff01; 1. (单选题) Python源程序的扩展名为&#xff08; A &#xff09; A. py B. c C. class D. ph 2. (单选题) 下列&#xff08; A &#xff09;符合可用于注释Python代码。 A. # B. */ C. // D. $ 3. (单选题)下列…

SMARTPHONE PLATFORM st解决方案

智能手机是最常用的计算设备。 它们展示了强大的硬件功能和复杂的操作系统&#xff0c;支持高级功能和人工智能应用、互联网和云访问、图像和视频采集、游戏以及语音通话和短信等核心电话功能。 要执行如此多样的应用&#xff0c;智能手机必须包含许多设备&#xff0c;包括大量…

一、电路分析的变量

点我回到主目录 ------------------------------------------------------------------------------------------------------------------------- 目录 1.电流 2.电压 3.功率 4.关联参考方向 5.电路吸收或发出功率的判断 1.电流 •电流 单位A&#xff08;安培…

vue基于Python的图书商城销售系统qo85w

系统以浏览器/服务器模式即B/S模板式为基础。本系统使用MySQL数据库,利用Python开发的操作系统&#xff1b;主要的功能有个人中心、用户管理、图书资讯管理、图书类型管理、图书信息管理、爬虫管理、留言板管理、系统管理、订单管理等组成。 本文首先介绍了现代化图书销售系统管…

2023电工杯B题全保姆论文讲解手把手教程 人工智能影响评价

更新&#xff1a;电工杯B题全保姆论文成品教程&#xff0c;手把手教你完成高质量成品 这次b题是这一道问卷分析题目&#xff0c;是我最擅长的题目之一了&#xff0c;问卷分析看起来简单&#xff0c;实际上没那么那简单&#xff0c;考验的是我们能不能把数据描述清楚&#xff0…

2023哈佛大学博士后/访问学者研究班一览

哈佛大学是全球顶尖的高等教育机构之一&#xff0c;其所拥有的丰富资源和卓越师资吸引了来自全球各地的优秀学者前来攻读博士学位或作为访问学者进行研究。而博士后访问学者研究班则是哈佛大学提供给这些博士后访问学者的一个重要平台。博士后访问学者研究班是一个跨学科的研究…

echarts 被封装后多次复用,图表被覆盖,解决方法

场景&#xff1a;为了方便样式统一&#xff0c;封装了一个盒子&#xff0c;其中包含echarts&#xff0c;option是从父组件传来的 问题&#xff1a; 多个父级页面使用这个盒子后&#xff0c;发现只有第一个盒子展示图表&#xff0c;但展示的是最后一个图片的样式&#xff0c;其他…

【数据结构】如何应用堆解决海量数据的问题

堆(Heap数据结构堆在计算机科学中有着广泛的应用&#xff0c;今天来介绍两种堆的应用&#xff1a;堆排序、Top-k问题&#x1f349; 堆排序 ​ 堆排序是一种基于堆数据结构的排序算法。它的基本思想是&#xff0c;将待排序的序列构建成一个大根堆&#xff08;或小根堆&#xff…

三展齐发,DBF户外展、高博会、健身展隆重开幕,火爆现场燃炸鹏城!

5月25日&#xff0c;深圳建设国家体育消费试点城市系列活动&#xff0c;第四届DBF深圳国际户外运动博览会&#xff0c;DBF深圳国际高尔夫运动博览会暨深圳国际健身运动博览会&#xff08;以下简称DBF运动户外生活展&#xff09;在深圳国际会展中心5.7号馆盛大举办&#xff01;开…

recurdyn接触特征参数含义

一般接触特征设置 Static Threshold Velocity静态门槛速度&#xff1a;判断静态摩擦和动态摩擦的标准&#xff0c;若相对速度小于此值&#xff0c;摩擦为静摩擦&#xff1b;若相对速度大于此值&#xff0c;摩擦为动摩擦。静态摩擦区域内摩擦系数计算函数为 Dynamic Threshold V…

【网络编程】详解UDP/TCP套接字的创建流程+守护进程

目录 一、网络编程套接字 1、一些概念 1.1源IP地址和目的IP地址 1.2端口号port 1.3TCP和UDP的性质 1.4网络字节序、IP地址类型转换、数据接收与发送函数、popen函数 2、UDP套接字 2.1UDP服务器创建流程 2.2UDP客户端创建流程 2.3创建socket套接字 2.4绑定套接字对应…

模仿抖音直播商城带货打赏功能做一个app系统

随着人们生活和互联网的高度整合&#xff0c;越来越多的人开始转变自身消费模式&#xff0c;从实体店购物逐渐转向足不出户即可享受购物快感的网上购物。许多企业看到了电子商务背后隐藏的巨大价值&#xff0c;想要寻找合适的开发商建立属于自己的电商直播系统&#xff0c;那么…

【新星计划·2023】网工知识——OSPF讲解

OSPF ( Open Shortest Path First开放式最短路径优先)是一种动态路由协议&#xff0c;属于内部网关协议( Interior Gateway Protocol&#xff0c;简称IGP )&#xff0c;是基于链路状态算法的路由协议。 一、OSPF是什么&#xff1f; OSPF意思是指一个内部网关协议(Interior Ga…