Vue2电商平台项目 (三) Search模块、面包屑(页面自己跳自己)、排序、分页器!

news2024/11/15 13:46:19

文章目录

  • 一、Search模块
    • 1、Search模块的api
    • 2、Vuex保存数据
    • 3、组件获取vuex数据并渲染
      • (1)、分析请求数据的数据结构
      • (2)、getters简化数据、渲染页面
    • 4、Search模块根据不同的参数获取数据
      • (1)、 派发actions的操作封装为函数
      • (2)、设置带给服务器的参数
      • (3)、Object.assign整理参数值(该方法在JS高级的浅拷贝中提到过)
      • (4)、监听路由以实现根据不同参数 多次发送请求(有意思)
    • 5、SearchSelector读取动态数据
  • 二、面包屑
    • 1、展示面包屑(关键词+分类名)
    • 2、面包屑删除事件(关键词+分类名)
      • (1) 删除分类面包屑 (Search页面通过路由跳自己)
      • (2) 删除关键词面包屑
    • 3、品牌名的面包屑
      • (1)、添加品牌面包屑--自定义事件
      • (2)、删除品牌面包屑
    • 4、售卖属性的面包屑
      • (1)、添加售卖属性面包屑
      • (2)、删除售卖属性面包屑
  • 三、排序
    • 1、order属性
    • 2、高亮设置:绑定class样式
    • 3、添加箭头
    • 4、点击改变高亮和箭头升降
  • 四、分页器 (重重重点)
    • 1. 分页器参数
    • 2. 连续页码的起始数字与结束数字
      • (1)、计算总页数
      • (2)、连续页码的起始数字和结束数字
      • (3)、页码展示(省略号等什么时候展示)(好好琢磨)
    • 3. 分页器绑定动态数据
    • 4. 点击页码获取新的数据
    • 5. 上一页和下一页按钮禁用
    • 6. 当前页的页码高亮

一、Search模块

模块开发的几个步骤

  • 静态页面+静态组件拆分
  • 发请求(API)
  • 数据保存到vuex中(配置好vuex中的actions、mutations、state)
  • 组件获取vuex动态数据,渲染页面

1、Search模块的api

注意传递的参数至少应该是一个空对象,否则请求会出错。

// src/api/index.js 本文件对于API接口进行统一管理
import requests from './request'
import mockRequests from './mockRequest'
...
// 搜索模块数据,地址:/api/list 请求方式:post, 参数:需要带参数
// 当前这个接口,给服务器传递参数params,params至少应该是一个空对象,否则请求会出错
// 即: reqSearchInfo()----reqSearchInfo({})------不会出错
export const reqSearchInfo = (params) => {
  return requests({ url: '/list', method: 'post', data: params })
}

在main.js中测试该api:

import { reqSearchInfo } from './api'
reqSearchInfo({})

得到的返回信息为:
在这里插入图片描述

2、Vuex保存数据

获取的是Search模块的数据,所以应该保存在search小仓库中:

// src/store/search/index.js
import { reqSearchInfo } from '@/api'
export default {
  namespaced: true,
  state: {
    searchList: {}    // 仓库初始状态
  },
  actions: {
    async getSearchInfo (context, param = {}) {
      const result = await reqSearchInfo(param)
      if (result.code === 200) {
        console.log(result.data);
        context.commit('GETSEARCHINFO', result.data)
      }
    }
  },
  mutations: {
    GETSEARCHINFO (state, searchList) {
      state.searchList = searchList
    }
  },
  getters: {...}

3、组件获取vuex数据并渲染

(1)、分析请求数据的数据结构

在这里插入图片描述
对应在页面上:
在这里插入图片描述
如果Search组件通过mapState读取这些数据(麻烦且易出错):

...mapState('search', {
    goodsList: state => state.search.searchList.goodsList,
    attrsList: state => state.search.searchList.attrsList,
    trademarkList: state => state.search.searchList.trademarkList
})

(2)、getters简化数据、渲染页面

在这里插入图片描述
然后将数据渲染到页面即可,没什么重要的点。
在这里插入图片描述

4、Search模块根据不同的参数获取数据

(1)、 派发actions的操作封装为函数

目前派发actions的操作放在mounted里,组件挂载完毕会执行一次,但也只能发送一次。当搜索的参数发生变化时,应该再次发送请求,所以应该将请求封装成一个函数。
Search/index.vue
在这里插入图片描述

(2)、设置带给服务器的参数

  之前写Search模块的api时,为了测试,参数传的是空对象。此处要配置参数具体的值。
  观察api接口文档,发现向服务器发请求时可以带10个参数。我们将这些参数的默认值配置在Search组件的data中,以对象的形式存储,然后在派发actions请求时把这个对象传过去,就能够作为axios发送ajax请求的请求体参数。(这段话的原文链接:https://blog.csdn.net/weixin_42044763/article/details/126817322)
在这里插入图片描述

(3)、Object.assign整理参数值(该方法在JS高级的浅拷贝中提到过)

  从首页的三级联动跳转到Search页面时,路由携带了query参数(categoryId与categoryName)。
  Header组件搜索关键词跳转到Search页面时,路由携带了params参数(keyword)。
Search组件在挂载完时(mounted)就要发送一次请求获取页面数据以渲染页面。在发送请求之前,应该将携带的参数带给服务器。

  // 封装参数,其实在mounted里也可以,这里是为了回顾一下生命周期函数
  beforeMount () {
    // 复杂
     this.searchParams.category1Id = this.$route.query.category1Id
     this.searchParams.category2Id = this.$route.query.category2Id
     this.searchParams.category3Id = this.$route.query.category3Id
     this.searchParams.categoryName = this.$route.query.categoryName
  },
  mounted () {
  // 在这里整理参数也可以,只要在发送请求之前整理好即可
    this.getData()
  },

这种整理参数的方式也可以,但比较复杂,不是最优。采用Object.assign优化一下。
Object.assign(target, source):可以合并具有相同属性的对象,返回修改后的对象。
在这里插入图片描述

  beforeMount () {
    Object.assign(this.searchParams, this.$route.query, this.$route.params)
  },
  mounted () {
  // 在这里整理参数也可以,只要在发送请求之前整理好即可
    this.getData()
  }

至此实现了:从其他页面跳转到Search页面时,Search组件会根据已有的参数值向服务器请求对应的数据。渲染到页面上。但是当输入关键字或进行其他操作时,应该根据参数值再次发起请求,获取数据。

(4)、监听路由以实现根据不同参数 多次发送请求(有意思)

当路由发生变化时,说明发生了路由跳转,
在这里插入图片描述

5、SearchSelector读取动态数据

数据在进入Search页面时都请求到了,并且在Vuex中也用过getter简化了,所以这里直接从Vuex中取数据即可。不用父子组件传值。

SearchSelector.vue
在这里插入图片描述
这里用slice是因为返回的一些数据是测试数据,不好看,就不展示了。

二、面包屑

1、展示面包屑(关键词+分类名)

面包屑的值包括好几类,先看这两类:三级联动里的分类名,搜索输入框里的关键字。
在这里插入图片描述
可通过查看SearchParams里是否包含分类名或者关键字来判断是否显示面包屑。
为什么SearchParams里会包含这两个信息呢?在Search组件挂载完成(mounted)或者再次发送请求信息时,用户搜索的参数已整合到SearchParams里了。

<!--Search.vue-->
   <ul class="fl sui-tag">
     <!-- 分类面包屑 -->
     <li class="with-x" v-if="searchParams.categoryName">
       {{ searchParams.categoryName }}<i @click="deleteCategory">×</i>
     </li>
     <!-- 关键词面包屑 -->
     <li class="with-x" v-if="searchParams.keyWord">
       {{ searchParams.keyWord }}<i @click="deleteKeyWord">×</i>
     </li>
   </ul>

2、面包屑删除事件(关键词+分类名)

点击面包屑的叉号,删除面包屑。删除面包屑相当于改变了用户搜索的条件,所以需要重新发送请求。上边的代码已经分别给这两类面包屑添加了点击事件。

(1) 删除分类面包屑 (Search页面通过路由跳自己)

  首先是让控制面包屑的v-if为false,即categoryName 值为空。
  其次,由于删除了面包屑,说明用户的搜索不包含这个分类了,则需要重新发送一次请求。为了获取全部的数据,对应的对应的categoryId也需要清空。
  小Tips参数值为null时这些参数还会发给服务器,值为undefined时,这些参数就不会发送给服务器了。(这是视频里说的,但是我自己试的时候还是都会发给服务器)

    // 删除分类面包屑
    deleteCategory () {
      // 1. categoryName置空,以让v-if的值为false,不显示面包屑
      this.searchParams.categoryName = ''
    // 2. 对应的categoryId也需要清空。但由于不清楚是哪个分类Id,就全都置空
    // 清空可以赋值为null,也可赋值为undefined。
    //由于删除了面包屑,说明再次请求时不需要包含这些条件了,所以发送请求可以不携带这些参数,以减少资源的消耗。
      this.searchParams.category1Id = undefined
      this.searchParams.category2Id = undefined
      this.searchParams.category3Id = undefined
      // 重新发送请求
      this.getData()
    },

此时页面变化了,但是地址栏仍旧是

http://localhost:8080/#/search/华为?categoryName=手机&category3Id=61

此时需要去掉地址栏中的query参数(三级联动分类),保留params参数(关键词)。地址栏的内容是路由跳转时形成的。所以发送请求之后,需要再次进行路由跳转。上面的代码改为:

    // 删除分类面包屑
    deleteCategory () {
    // 1. categoryName置空,以让v-if的值为false,不显示面包屑
     this.searchParams.categoryName = undefined
     // 2. 跳转路由,自己跳自己
     this.$router.push({ name: 'search', params: this.$route.params })
    },

(1)、为什么不调用getData方法了
之前写过一个监视路由,当路由发生变化时,重新发送请求。这里为了改变地址栏的内容,重新进行了路由跳转。相比原来的路由,此次路由跳转里取消了query参数,所以路由发生了变化,也会触发watch里的代码,watch里已经由重新发送请求了,这里就不用写了。
(2)categoryId怎么不置空了。
在这里插入图片描述

(2) 删除关键词面包屑

删除流程为:

  • 点击×号、
  • 清除面包屑、
  • 输入框里的关键词清空、
  • 重新发送请求。

关键词清空涉及到了兄弟组件Header,这里采用全局事件总线(vue(九)全局事件总线):

安装全局事件总线:

new Vue({
  // KV一致时省略V[router小写的r]
  router,
  store,
  render: h => h(App),
  beforeCreate () {
    // 全局事件总线
    Vue.prototype.$bus = this
  }
}).$mount('#app')

接收消息的组件(Header)绑定事件,发送消息的组件(Search)触发事件:
在这里插入图片描述

Search组件删除关键词的回调函数:

// 删除关键词面包屑
deleteKeyWord () {
  // 1. 关键词置空,让v-if值为false
  this.searchParams.keyWord = '' 
  // 兄弟组件Header组件的输入框清空--触发事件
  this.$bus.$emit('clear')
  // 改变路由地址,进行路由跳转,如果还有query参数则携带query参数
  this.$router.push({ name: 'search', query: this.$route.query })
  // this.getData()     // 重新发送请求,上边那行触发了对路由的监视,在监视里也会重新发送请求,所以写了上面那行就不用写这行了。
},

同样的,改变路由地址就会被watch监视到路由发生变化,进而重新整理参数、发送请求。

3、品牌名的面包屑

点击品牌名,生成品牌名的面包屑,配置品牌名的参数,重新发送请求
在这里插入图片描述

1、品牌信息是在子组件SearchSelector里。SearchSelector通过mapGetter获取仓库里的品牌列表信息trademarkList。页面上通过v-for循环渲染了品牌信息。
2、发送请求时,需要将品牌信息作为参数带给服务器。问题是这个请求应该子组件SearchSelector发,还是父组件Search

答:应该是父组件发。携带给服务器的参数都整理在SearchParams里了,而这个属性在父组件里。所以应该子给父传递品牌信息参数,然后由父组件发请求。

(1)、添加品牌面包屑–自定义事件

页面结构:
在这里插入图片描述
自定义事件
在这里插入图片描述
父组件的回调函数为:

  // 自定义事件,获取品牌信息
  trademarkInfo (trademark) {
    // 为什么要这么拼接字符串,接口要求: "ID:名称" 
    this.searchParams.trademark = `${trademark.tmId}:${trademark.tmName}`
    // 2. 发送请求以获取search模块列表数据进行展示
    this.getData()
  },

(2)、删除品牌面包屑

绑定点击事件,具体见上边给出的页面结构截图

  // 回调函数
 deleteTrademark () {
   // 1. 置空信息,让v-if的值为false,取消显示面包屑
   this.searchParams.trademark = ''
   // 2. 再次发送请求
   this.getData()
 },

4、售卖属性的面包屑

在这里插入图片描述

(1)、添加售卖属性面包屑

 页面结构:
在这里插入图片描述
  思路和上边的品牌面包屑差不多。根据接口要求来确定子组件向父组件要传递什么值。
在这里插入图片描述
仍旧采用自定义事件实现子传父:
SearchSelector.vue
在这里插入图片描述

attrHandler (attr, attrValue) {
   // 传递给父组件,触发事件,传参数
   this.$emit('attrInfo', attr, attrValue)
 }

父组件SearchInfo

<!--绑定自定义事件-->
<SearchSelector @trademarkInfo="trademarkInfo" @attrInfo="attrInfo" />
<script>
    // 自定义事件-属性
    attrInfo (attr, attrValue) {
      // 售卖属性["属性ID:属性值:属性名"]
      let prop = `${attr.attrId}:${attrValue}:${attr.attrName}`
      //判断是否已存在此属性,如果存在,也不会再添加到props里
      if (this.searchParams.props.indexOf(prop) === -1) {
        this.searchParams.props.push(prop)
      }
      // 2. 发送请求以获取search模块列表数据进行展示
      this.getData()
    },
</script>

与品牌面包屑不同的是,SearchParams里的售卖属性props是个数组,因此点击售卖属性时,需要判断数组中是否已有该属性
在这里插入图片描述

(2)、删除售卖属性面包屑

就是从数据里删除这个属性。没别的重要的点。

    deleteAttr (index) {
      // 删除属性
      this.searchParams.props.splice(index, 1)
      // 重新发送请求
      this.getData()
    },

三、排序

在这里插入图片描述

1、order属性

在这里插入图片描述
1:表示按综合排序
2:表示按价格排序
desc:降序
asc:增序

2、高亮设置:绑定class样式

  综合标签高亮还是价格标签高亮,取决于当前的order属性值。如果order里是1,则综合标签高亮,如果是2,则价格标签高亮。此处采用计算属性来动态绑定class样式。

  computed: {
    isOne () {
      // 等于-1说明order里没有1
      return this.searchParams.order.indexOf('1') !== -1 
    },
    isTwo () {
      return this.searchParams.order.indexOf('2') !== -1
    }
 }

在这里插入图片描述

3、添加箭头

  如何判断谁应该有箭头?谁高亮谁就有箭头显示。我们用一个span标签来包裹箭头。用v-show来控制。当前标签高亮时,就显示箭头,否则就不显示。所以箭头与高亮的显示是同步的,那就也用计算属性来控制。
在这里插入图片描述
此处箭头的样式采用阿里巴巴矢量图(具体步骤看博客:Vue中使用iconfont-阿里巴巴矢量图标库)。箭头是升还是降还是取决于order里的值,所以还是通过计算属性来控制

computed(){
  // 升序
    isAsc () {
      return this.searchParams.order.indexOf('asc') !== -1
    },
    // 降序
    isDesc () {
      return this.searchParams.order.indexOf('desc') !== -1
    },
}

采用动态绑定class样式来显示上升的箭头或下降的箭头
在这里插入图片描述

4、点击改变高亮和箭头升降

在这里插入图片描述

这里的需求是:
(1) 如果当前的高亮标签是综合
  点击综合标签,该标签的排序方式改变(由升变降或由降变升);
  点击价格 标签,则改为价格标签高亮,且排序方式改为默认的降序desc。
(2) 如果当前的高亮标签是价格,则同理。
根据不同的排序方式重新发送请求,获取数据。

 changeOrder (orderNum) {
      console.log('点的是', orderNum);
      // 记录原本的排序
      let originOrder = this.searchParams.order
      let originNum = originOrder.split(':')[0] // 选的是综合还是价格
      let originType = originOrder.split(':')[1] // 增序还是降序

      // 改变
      if (originNum == orderNum) { // 类别没变,则只变排序方式
        this.searchParams.order = `${orderNum}:${originType === 'desc' ? 'asc' : 'desc'}`
      } else { // 类别变了,默认的还是降序
        this.searchParams.order = `${orderNum}:desc`
      }
      //再次发送请求 
      this.getData()
    }

四、分页器 (重重重点)

分页器在很多地方都用的到,封装为全局组件

// src/components/Pagination/index/vue
<template>
  <div class="pagination">
    <button>上一页</button>
    <button>1</button>
    <button>···</button>

    <button>3</button>
    <button>4</button>
    <button>5</button>
    <button>6</button>
    <button>7</button>
    
    <button>···</button>
    <button>9</button>
    <button>上一页</button>
    
    <button style="margin-left: 30px">共 60 条</button>
  </div>
</template>

<script>
  export default {
    name: "Pagination",
  }
</script>

<style lang="less" scoped>
  .pagination {
    button {
      margin: 0 5px;
      background-color: #f4f4f5;
      color: #606266;
      outline: none;
      border-radius: 2px;
      padding: 0 4px;
      vertical-align: top;
      display: inline-block;
      font-size: 13px;
      min-width: 35.5px;
      height: 28px;
      line-height: 28px;
      cursor: pointer;
      box-sizing: border-box;
      text-align: center;
      border: 0;

      &[disabled] {
        color: #c0c4cc;
        cursor: not-allowed;
      }

      &.active {
        cursor: not-allowed;
        background-color: #409eff;
        color: #fff;
      }
    }
  }
</style>

main.js
在这里插入图片描述
目前是在Search组件中用到了。

1. 分页器参数

展示分页器,至少应该有以下几项数据

  • pageNo:当前是第几页
  • pageSize:每一页展示多少条数据
  • total:一共多少条数据
  • continues:分页器连续的页码数。一般为5或7(奇数),因为这样对称好看。以下图为例,这样就是continues值为5的情况。

在这里插入图片描述


这几个属性一般由父组件给子组件传过去

 <!-- Search.vue 组件 -->
<Pagination :pageNo="27" :pageSize="3" :total="91" :continues="5" />	   

子组件接收

  // 当前页码,每页多少数据,总共多少条数据,分页器的连续页码数
  props: ["pageNo", "pageSize", "total", "continues"]

2. 连续页码的起始数字与结束数字

自定义的分页器要先用假数据进行调试,等调试好了,再换成真数据

(1)、计算总页数

computed(){
	// 总共多少页
    totalPage () {
    // 总数/每页的数据条数
      return Math.ceil(this.total / this.pageSize) //向上取整
    },
}

(2)、连续页码的起始数字和结束数字

computed(){
// 计算出连续页码的起始数字和结束数字
 startNumAndEndNum () {
   let start = 0;
   let end = 0
   // 1. 如果总页数 < 连续页码数, 则展示所有的页数
   if (this.totalPage < this.continues) {
     start = 1
     end = this.totalPage
   } else {
     //2. 如果总页数 >= 连续页码数 分不同的情况讨论
     //2.1 正常情况,假设连续页码数是5,pageNo是6,则这部分连续页码是4 5 6 7 8
     start = this.pageNo - Math.floor(this.continues / 2) // 6-(5/2)   
     end = this.pageNo + Math.floor(this.continues / 2)   // 6-(5/2)   
     // 2.2 如果上边计算出来,start是负数,说明pageNo比较靠前,那么就展示前几页 
     if (start <= 0) {
       start = 1
       end = this.continues
     }
     // 如果尾页数超过总页数,说明pageNo很靠后,那就将最后continues页展示出来
     if (end > this.totalPage) {
       start = this.totalPage - this.continues + 1
       end = this.totalPage
     }
   }
   let numObj = { start, end }
   return numObj
 }
}

(3)、页码展示(省略号等什么时候展示)(好好琢磨)

整个分页器可分为三个区域:
在这里插入图片描述

1、中间部分
已知连续页码的起始数字和结束数字,所以考虑采用循环生成button。

老师的写法:

    <button v-for="page in  startNumAndEndNum.end" :key="page" 
    v-if="page >=  startNumAndEndNum.start">
      {{ page }}
    </button>

  v-for也可以用来遍历数字。假设这里startNumAndEndNum.end的值是10, startNumAndEndNum.start的值是6。v-for遍历数字10,生成的是值为1~ 10的10个button。而1~5是不需要的,所以有了if判断。但是我自己写的时候,vue提示不允许v-for与v-if同时使用。所以采取下面这种做法。

  <button v-for="page in middlePage" :key="page">
    {{ page }}
  </button>
  <script>
      // 中间页码
  middlePage () {
    let start = this.startNumAndEndNum.start
    let end = this.startNumAndEndNum.end
    // 构造一个array数组
    let array = []
    for (let index = start; index <= end; index++) {
      array.push(index)
    }
    return array
  }
  </script>

  就是手动生成连续页码这个数组,然后在html里遍历。目前想不到别的方法,有好的想法可以评论区交流一下。

2、页码前半部分

为了避免这样的bug:

  • startNumAndEndNum.start为1时,前边的1不应该展示
    在这里插入图片描述

  • startNumAndEndNum.start为1或2时,前边的...按钮也不该展示:
    在这里插入图片描述
    于是进行了这样的v-if判断

     <button>上一页</button>
     <button v-if="startNumAndEndNum.start > 1">1</button>
     <button v-if="startNumAndEndNum.start > 2">···</button>
    

3、页码后半部分
和上边同样的问题
如果startNumAndEndNum.end的值是总页数totalPage,就会出现:
在这里插入图片描述
如果startNumAndEndNum.end的值是总页数totalPage-1,就会出现:
在这里插入图片描述
同样加了v-if判断
在这里插入图片描述

3. 分页器绑定动态数据

父组件给子组件传递的当前页pageNo等数据需要换成真实值
在这里插入图片描述

4. 点击页码获取新的数据

  和之前一样,服务器携带的参数SearchParams在组件Search里,所以此处需要分页子组件将数据传递给父组件。采用自定义事件的方式。

父组件Search绑定自定义事件:
在这里插入图片描述
回调函数为:

    // 得到页码 
    getPageNo (pageNo) {
      // 整理参数带给服务器
      this.searchParams.pageNo = pageNo
      // 重新发送请求
      this.getData()
    }

子组件Pagination
在这里插入图片描述

5. 上一页和下一页按钮禁用

在这里插入图片描述

6. 当前页的页码高亮

只给这部分的页码加高亮是因为:比如上半部分的页码,当开始页面是1是,这个1的页码按钮来自于中间部分的循环遍历,而不是上半部分中的那个1(v-if条件不满足,被隐藏了)。同理,下半部分的页码也不用加高亮
在这里插入图片描述
Pagination页面结构的完整代码:

<template>
  <div class="pagination">
    <!-- 上半部分 -->
    <button @click="$emit('getPageNo', pageNo - 1)" :disabled="pageNo == 1">
      上一页
    </button>
    <button v-if="startNumAndEndNum.start > 1" @click="$emit('getPageNo', 1)">
      1
    </button>
    <button v-if="startNumAndEndNum.start > 2">···</button>

    <!-- 中间 -->
    <button
      v-for="page in middlePage"
      :key="page"
      @click="$emit('getPageNo', page)"
      :class="{ active: pageNo == page }"
    >
      {{ page }}
    </button>
    <!-- 下半部分 -->
    <button v-if="startNumAndEndNum.end < totalPage - 1">···</button>
    <button
      v-if="startNumAndEndNum.end < totalPage"
      @click="$emit('getPageNo', totalPage)"
    >
      {{ totalPage }}
    </button>

    <button
      @click="$emit('getPageNo', pageNo + 1)"
      :disabled="pageNo == totalPage"
    >
      下一页
    </button>
    <button style="margin-left: 30px">共 {{ total }}条</button>
  </div>
</template>

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

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

相关文章

第十一章 【后端】商品分类管理微服务(11.1)——创建父工程

第十一章 【后端】商品分类管理微服务 11.1 创建父工程 项目名称:EasyTradeManagerSystem:Easy 表示简单易用,Trade 表示交易,Manager 表示管理,System 表示系统,强调系统在商品交易管理方面的便捷性,简称 etms。 新建工程 yumi-etms yumi-etms 作为所有模块的父工程,…

基于java 的医院排号管理系统设计与实现

博主介绍&#xff1a;专注于Java .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的可以…

1863. 找出所有子集的异或总和再求和

目录 一&#xff1a;题目&#xff1a; 二&#xff1a;代码&#xff1a; 三&#xff1a;结果&#xff1a; 一&#xff1a;题目&#xff1a; 一个数组的 异或总和 定义为数组中所有元素按位 XOR 的结果&#xff1b;如果数组为 空 &#xff0c;则异或总和为 0 。 例如&#x…

C++--类的实例化

一、实例化的概念 用类类型在屋里内存中创建对象的过程&#xff0c;称为类实例化出对象 类是对对象进行一种抽象描述&#xff0c;是一个模型一样的东西&#xff0c;限定了类有哪些成员变量&#xff0c;这些成员变量只是声明&#xff0c;没有分配空间&#xff0c;用类实例化出…

【C++前后缀分解 动态规划】2100. 适合野炊的日子|1702

本文涉及知道点 C前后缀分解 C动态规划 LeetCode2100. 适合野炊的日子 你和朋友们准备去野炊。给你一个下标从 0 开始的整数数组 security &#xff0c;其中 security[i] 是第 i 天的建议出行指数。日子从 0 开始编号。同时给你一个整数 time 。 如果第 i 天满足以下所有条件…

2024最新版MySQL详细学习教程

MySQL数据库提供了很多函数包括&#xff1a; 数学函数&#xff1b;字符串函数&#xff1b;日期和时间函数&#xff1b;条件判断函数&#xff1b;系统信息函数&#xff1b;加密函数&#xff1b;格式化函数&#xff1b; 一、数学函数 数学函数主要用于处理数字&#xff0c;包括…

基于paddleocr的批量图片缩放识别

说明 在进行ocr文字识别的时候&#xff0c;有时候我们需要使用批量测试的功能&#xff0c;但是有些图片会识别失败或者个别根本识别不出来&#xff0c;这时候我们可以通过对原图片进行缩放&#xff0c;提高图像的分辨率&#xff0c;然后再次识别&#xff0c;这样可以大大提高图…

Vue学习记录之一(介绍及脚手架的使用)

一、背景知识介绍 1、构建工具介绍 Vite, Webpack,Rollup, Parce 构建工具优点缺点Vite- 快速启动&#xff0c;秒级热更新&#xff0c;更快的构建速度&#xff0c;更好的开发体验&#xff1b;- 支持 Vue3 和 ES modules 的原生特性&#xff0c;轻松实现按需加载。- 对于单页…

项目实现:云备份②(文件操作、Json等工具类的实现)

云备份 前言文件操作实用工具类设计文件属性的获取文件的读写操作文件压缩与解压缩的实现文件目录操作 Json 实用工具类设计编译优化 前言 如果有老铁不知道当前项目实现的功能是什么的话&#xff0c;可以先移步这篇文章内容&#xff1a; 云备份项目的介绍 其中介绍了云备份项…

【吊打面试官系列-MySQL面试题】简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别?

大家好&#xff0c;我是锋哥。今天分享关于【简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; 简述在 MySQL 数据库中 MyISAM 和 InnoDB 的区别&#xff1f; MyISAM&#xff1a; 不支持事务&#xff0c;但是每次查…

跳出大厂圈子——普通程序员如何开启逆袭之路

时间&#xff1a;2024年09月16日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 音频&#xff1a;喜马拉雅 大家好&#xff0c;欢迎来到“小蒋聊技术”&#xff01;今天咱们聊点特别现实的事儿——普通程序员的出路。互联网时代…

化学实验室器具识别系统源码分享

化学实验室器具识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

android设置实现广告倒计时功能

文章目录 CountDownTimer基本使用增加基础BaseActivity增加固定活动 在Android中&#xff0c;CountDownTimer 是一个用于计时的类&#xff0c;它允许你在指定的时间段内执行某些操作。通常用于倒计时功能&#xff0c;例如显示一个倒计时进度条或者在倒计时结束后执行某个动作。…

采用qt做一个命令行终端

qt做一个类似系统命令行终端的工具&#xff0c;方便集成到自己的软件里使用&#xff0c;这样能保证软件的整体性&#xff0c;而且是真正的做到和系统命令行终端一样的交互方式&#xff0c;而不是单独搞个编辑框的方式输入命令&#xff08;大部分博客都是做成这个样子&#xff0…

不善言辞的程序员适合做项目经理吗?

项目经理的角色需要承担多重任务&#xff0c;包括团队协调、资源调配、风险管理、沟通与汇报等。因此&#xff0c;很多人认为项目经理需要较强的沟通能力和外向性格。然而&#xff0c;不善言辞的程序员是否适合这一职位&#xff0c;实际上取决于多个因素。以下从不同角度进行分…

程序设计题(25-32)

第二十五题 题目 请编写函数fun&#xff0c;其功能是:在一个含有11个四位数的数组中&#xff0c;统计出这些数的奇数、偶数个数&#xff0c;然后计算出个数多的那些数的算数平均值并由函数返回&#xff0c;个数通过yy传回。 例如&#xff0c;若11个数据为:1101, 1202, 1303,…

AI+RPA 实战揭秘:DrissionPage 助力 CSDN 热榜数据抓取与 AI 结合

在前一篇文章《AIRPA&#xff1a;开启智能自动化新时代》 发布之后&#xff0c;今天我们将以实战的方式深入介绍数据分析中的RPA究竟是怎样抓取数据的&#xff0c;以及它与 AI 又是如何紧密结合的。首先&#xff0c;让我们来认识一个重要的工具包 ——DrissionPage。 一、Dris…

【例题】lanqiao301 实现基数排序

输入输出样例 输入 6 7 1 4 8 5 2输出 1 2 4 5 7 8解题思路 翻译&#xff1a;就是从个位到十位、……比较大小。 代码 nint(input()) alist(map(int,input().split())) a.sort() print( .join(map(str,a)))

Linux: network: delay and burst

最近遇到一个false-network的问题&#xff0c;抓到的网络包的特征是&#xff0c;有十几秒的延迟&#xff0c;然后来了一个burst。这个现象说明这个包肯定是缓存在了一个地方&#xff0c;但是具体是什么地方&#xff0c;就需要抓包确定。 这次的缓存的地方是虚拟机内部。由于一…

【刷题】Day5--数字在升序数组中出现的次数

Hi! 今日份刷题~ 数字在升序数组中出现的次数_牛客题霸_牛客网 我感觉题目简单&#xff0c;我的解答也很简单&#xff0c;二分法遗忘&#xff0c;有时间复习一下尝试新的解法。 /*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的…