el-table 组件实现 “合并单元格 + N行数据小计” 功能

目录

  • 需求 - 要实现的效果
  • 初始代码
  • 代码升级(可供多个表格使用)
    • `CommonTable.vue 子组件 `
    • 使用子组件1 - `父组件 - 图1~图3使用`
      • 效果展示
    • 使用子组件2 - `父组件 - 图4使用`
      • 效果展示
  • 注意
  • 【代码优化 - 解决bug】

需求 - 要实现的效果

在这里插入图片描述

父组件中 info 数据示例

const info = {
  itemMap: {
    警告: [
      {
        total: 28,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '12',
        wfxlView: '超速行驶',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 3,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '17',
        wfxlView: '未低速通过',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 6,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '26',
        wfxlView: '违法停车',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 21,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '28',
        wfxlView: '违法装载',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 3,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '49',
        wfxlView: '其他影响安全行为',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 1,
        cfzl: '1',
        cfzlView: '警告',
        wfxl: '28',
        wfxlView: '违法装载',
        jtfs: 'B21',
        jtfsView: '中型栏板半挂车'
      }
    ],
    罚款: [
      {
        total: 56,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '12',
        wfxlView: '超速行驶',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 6,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '17',
        wfxlView: '未低速通过',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 12,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '26',
        wfxlView: '违法停车',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 42,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '28',
        wfxlView: '违法装载',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 6,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '49',
        wfxlView: '其他影响安全行为',
        jtfs: 'B11',
        jtfsView: '重型栏板半挂车'
      },
      {
        total: 2,
        cfzl: '2',
        cfzlView: '罚款',
        wfxl: '28',
        wfxlView: '违法装载',
        jtfs: 'B21',
        jtfsView: '中型栏板半挂车'
      }
    ]
  },
  columns: [
    {
      // total: 28,
      // cfzl: '1',
      // cfzlView: '警告',
      // wfxl: '12',
      // wfxlView: '超速行驶',
      jtfs: 'B11',
      jtfsView: '重型栏板半挂车'
    },
    {
      // total: 1,
      // cfzl: '1',
      // cfzlView: '警告',
      // wfxl: '28',
      // wfxlView: '违法装载',
      jtfs: 'B21',
      jtfsView: '中型栏板半挂车'
    }
  ]
}

初始代码

父组件

<!-- info 数据来源 → info 数据示例 -->
<CommonTable :info="info"/>

CommonTable.vue 子组件

<template>
  <el-table
    :data="tableData"
    border
    stripe
    max-height="400"
    size="mini"
    :span-method="firstColMergeSpan"
  >
    <el-table-column align="center" prop="cfzl" label="处罚种类" />
    <el-table-column align="center" prop="wfxwfl" label="违法行为分类" />

    <el-table-column
      v-for="(item, index) in columns"
      :key="index"
      align="center"
      :prop="item.jtfs"
      :label="item.jtfsView || '-'"
    >
      <template slot-scope="{ row, $index }">
        <span>{{ row[item.jtfs] | noDataFilter }}</span>
      </template>
    </el-table-column>

    <el-table-column align="center" prop="xj" label="小计" />
  </el-table>
</template>

<script>
export default {
  name: 'CommonTable',
  components: {},

  props: {
    info: {
      type: Object,
      required: true
    }
  },

  data() {
    return {
      spanArr: []
    }
  },

  computed: {
    tableData() {
      const list = []
      Object.entries(this.info?.itemMap || {}).forEach((i) => {
        i[1]?.forEach((ii) => {
          list.push({
            // cfzl: ii.cfzlView,
            cfzl: i[0],
            wfxwfl: ii.wfxlView,
            [ii.jtfs]: ii.total,
            jtfs: ii.jtfs
          })
        })
      })
      return list.map((item) => {
        return {
          ...item,
          xj: this.columnKeyList.reduce((a, b) => {
            return a + (item[b] || 0)
          }, 0)
        }
      })
    },
    columns() {
      return this.info.columns || []
    },
    columnKeyList() {
      return this.columns.map((item) => item.jtfs)
    }
  },

  watch: {
    info() {
      this.xjPosition()
      this.firstColMergeCount()
    }
  },

  created() {},

  methods: {
    // 计算小计行插入位置
    xjPosition(Human = this.tableData) {
      const doctorMap = {}
      for (let i = 0; i < Human.length; i++) {
        // 找出相同名称的行数
        const doctorName = Human[i].cfzl
        if (doctorMap[doctorName] !== undefined) {
          doctorMap[doctorName].push(i)
        } else {
          doctorMap[doctorName] = [i]
        }
      }
      const keyArr = []
      for (const k in doctorMap) {
        // 取出key并倒序,防止正序插入会影响行下标
        keyArr.unshift(k)
      }
      keyArr.forEach((ele, index) => {
        const lastIndex = doctorMap[ele][doctorMap[ele].length - 1] // 找出相同名称最后一行插入合计数据
        const obj = this.xjRowDataCalc(Human, ele) // 计算出小计行数据
        Human.splice(lastIndex + 1, 0, obj) // 插入
      })
    },
    // 小计行计算
    xjRowDataCalc(data, name) {
      const obj = {
        cfzl: name, // 第一列用于合并单元格
        wfxwfl: '小计'
      }
      this.columnKeyList.forEach((key) => {
        obj[key] = 0
      })
      data.forEach((item) => {
        // “处罚种类” 相同的加起来
        if (item.cfzl === name) {
          this.columnKeyList.forEach((key) => {
            obj[key] += Number(item[key] || 0)
          })
        }
      })
      obj.xj = this.columnKeyList.reduce((a, b) => {
        return a + (obj[b] || 0)
      }, 0)
      return obj
    },
    // 合并单元格
    firstColMergeSpan({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    // 计算要合并的单元格
    firstColMergeCount() {
      let contactDot = 0
      this.spanArr = []
      this.tableData.forEach((item, index) => {
        item.index = index
        if (index === 0) {
          this.spanArr.push(1)
        } else {
          // 根据相同 “处罚种类” 来合并
          if (item.cfzl === this.tableData[index - 1].cfzl) {
            this.spanArr[contactDot] += 1
            this.spanArr.push(0)
          } else {
            contactDot = index
            this.spanArr.push(1)
          }
        }
      })
    }
  }
}
</script>

<style lang='scss' scoped>
</style>

代码升级(可供多个表格使用)

图1
在这里插入图片描述
图2
在这里插入图片描述
图3
在这里插入图片描述
图4
在这里插入图片描述

根据接口返回数据不同(数据格式一致,只是部分字段名不一致),向子组件传入不同的字段名。

CommonTable.vue 子组件

<template>
  <el-table
    :data="tableData"
    border
    stripe
    max-height="400"
    size="mini"
    :span-method="firstColMergeSpan"
  >
    <!-- 第一列 -->
    <el-table-column align="center" :prop="oneColPropField" :label="oneColLabelField" />
    <!-- 第二列 -->
    <el-table-column align="center" :prop="twoColPropField" :label="twoColLabelField" />

    <!-- 其他数量列 -->
    <el-table-column
      v-for="(item, index) in columns"
      :key="index"
      align="center"
      :prop="item[countColPropsField]"
      :label="item[countColLabelField] || '-'"
    >
      <template slot-scope="{ row, $index }">
        <span>{{ row[item[countColPropsField]] | noDataFilter }}</span>
      </template>
    </el-table-column>

    <!-- “小计”列 -->
    <el-table-column align="center" prop="xj" label="小计" />
  </el-table>
</template>

<script>
export default {
  name: 'CommonTable',
  components: {},

  props: {
    info: {
      type: Object,
      required: true
    },
    // 自定义表格列
    selfColumns: {
      type: Array,
      default: () => []
    },
    // 表格列非自定义时(接口获取)列字段名
    columnKeyField: {
      type: String,
      default: 'jtfs'
    },
    // 第一列字段名
    oneColPropField: {
      type: String,
      required: true
    },
    // 第一列展示header文本
    oneColLabelField: {
      type: String,
      required: true
    },
    // 第一列数据来源字段名
    oneColDataField: {
      type: String,
      required: true
    },
    // 第二列字段名
    twoColPropField: {
      type: String,
      required: true
    },
    // 第二列展示header文本
    twoColLabelField: {
      type: String,
      required: true
    },
    // 第二列数据来源字段名
    twoColDataField: {
      type: String,
      required: true
    },
    // 其他数量 列 字段名
    countColPropsField: {
      type: String,
      default: 'jtfs'
    },
    // 其他数量 列 展示header文本字段名
    countColLabelField: {
      type: String,
      default: 'jtfsView'
    },
    // 其他数量 列 数据来源字段名
    countColDataField: {
      type: String,
      default: 'total'
    }
  },

  data() {
    return {
      spanArr: []
    }
  },

  computed: {
    // 表格数据处理
    tableData() {
      const list = []
      Object.entries(this.info?.itemMap || {}).forEach((i) => {
        i[1]?.forEach((ii) => {
          list.push({
            // [this.oneColPropField]: ii[this.oneColDataField] // 第一列数据(第一列数据部分表格 ii 中无第一列数据,所以使用↓↓↓下一行代码 i[0] 取第一列数据)
            [this.oneColPropField]: i[0], // 第一列数据
            [this.twoColPropField]: ii[this.twoColDataField], // 第二列数据
            [ii[this.countColPropsField]]: ii[this.countColDataField] // 其他数量列数据
            // jtfs: ii.jtfs
          })
        })
      })
      return list.map((item) => {
        return {
          ...item,
          // 计算小计数量
          xj: this.columnKeyList.reduce((a, b) => {
            return a + (item[b] || 0)
          }, 0)
        }
      })
    },
    columns() {
      /**
       * 表格列获取
       *    父组件有传表格列 selfColumns 就用 selfColumns
       *    否则用接口获的表格列
       */
      return (this.selfColumns.length && this.selfColumns) || this.info.columns || []
    },
    columnKeyList() {
      // 获取表格每列字段名组成数组
      return this.columns.map((item) => item[this.columnKeyField])
    }
  },

  watch: {
    info() {
      this.xjPosition()
      this.oneColMergeCount()
    }
  },

  created() {},

  methods: {
    // 计算小计行插入位置
    xjPosition(Human = this.tableData) {
      const doctorMap = {}
      for (let i = 0; i < Human.length; i++) {
        // 找出相同名称的行数
        const doctorName = Human[i][this.oneColPropField]
        if (doctorMap[doctorName] !== undefined) {
          doctorMap[doctorName].push(i)
        } else {
          doctorMap[doctorName] = [i]
        }
      }
      const keyArr = []
      for (const k in doctorMap) {
        // 取出key并倒序,防止正序插入会影响行下标
        keyArr.unshift(k)
      }
      keyArr.forEach((ele, index) => {
        const lastIndex = doctorMap[ele][doctorMap[ele].length - 1] // 找出相同名称最后一行插入合计数据
        const obj = this.xjRowDataCalc(Human, ele) // 计算出小计行数据
        Human.splice(lastIndex + 1, 0, obj) // 插入
      })
    },
    // 小计行数据计算
    xjRowDataCalc(data, name) {
      const obj = {
        [this.oneColPropField]: name, // 第一列用于合并单元格
        [this.twoColPropField]: '小计' // 第二列数据
      }
      this.columnKeyList.forEach((key) => {
        obj[key] = 0 // 其他书两列数据
      })
      data.forEach((item) => {
        // 第一列 oneColPropField 数据相同的加起来
        if (item[this.oneColPropField] === name) {
          this.columnKeyList.forEach((key) => {
            obj[key] += Number(item[key] || 0)
          })
        }
      })
      // 小计列数据总和(小计行和小计列交汇处数据)
      obj.xj = this.columnKeyList.reduce((a, b) => {
        return a + (obj[b] || 0)
      }, 0)
      return obj
    },
    // 合并单元格
    firstColMergeSpan({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    // 计算要合并的单元格
    oneColMergeCount() {
      let contactDot = 0
      this.spanArr = []
      this.tableData.forEach((item, index) => {
        item.index = index
        if (index === 0) {
          this.spanArr.push(1)
        } else {
          // 第一列相同的合并
          if (item[this.oneColPropField] === this.tableData[index - 1][this.oneColPropField]) {
            this.spanArr[contactDot] += 1
            this.spanArr.push(0)
          } else {
            contactDot = index
            this.spanArr.push(1)
          }
        }
      })
    }
  }
}
</script>

<style lang='scss' scoped>
</style>

使用子组件1 - 父组件 - 图1~图3使用

<!-- info 数据来源 → info 数据示例 -->
<CommonTable
  :info="info"
  one-col-prop-field="cfzl"
  one-col-label-field="处罚种类"
  one-col-data-field="cfzlView"
  two-col-prop-field="wfxwfl"
  two-col-label-field="违法行为分类"
  two-col-data-field="wfxlView"
/>

效果展示

在这里插入图片描述

使用子组件2 - 父组件 - 图4使用

<CommonTable
  :info="info"
  one-col-prop-field="cfzl"
  one-col-label-field="处罚种类"
  one-col-data-field="cfzlView"
  two-col-prop-field="wfxwfl"
  two-col-label-field="违法行为分类"
  two-col-data-field="wfxlView"
  column-key-field="timenum"
  count-col-props-field="timenum"
  count-col-label-field="label"
  :self-columns="columns"
/>

<script>
	export default {
	  data() {
	    return {
	      columns: [...Array(24).keys()].map((item) => {
			return {
			  timenum: `${item}`,
			  label: `${item}-${item + 1}`
			}
	      }),
	      info: {
	        itemMap: {
	          警告: [
	            {
	              timenum: 17,
	              total: 9,
	              cfzl: '1',
	              cfzlView: '警告',
	              wfxl: '69',
	              wfxlView: '其他影响安全行为',
	              jtfs: null,
	              jtfsView: null
	            },
	            {
	              timenum: 17,
	              total: 3,
	              cfzl: '1',
	              cfzlView: '警告',
	              wfxl: '58',
	              wfxlView: '违法上道路行驶',
	              jtfs: null,
	              jtfsView: null
	            }
	          ]
	        },
	        columns: []
	      }
	    }
	  }
	}
</script>

效果展示

在这里插入图片描述

注意

  • 使用子组件1 和 使用子组件2 中 info 数据不同

【代码优化 - 解决bug】

解决数据重复问题
在这里插入图片描述

在这里插入图片描述

<template>
  <el-table
    :data="tableData"
    border
    stripe
    max-height="400"
    size="mini"
    :span-method="firstColMergeSpan"
  >
    <!-- 第一列 -->
    <el-table-column align="center" :prop="oneColPropField" :label="oneColLabelField" />
    <!-- 第二列 -->
    <el-table-column align="center" :prop="twoColPropField" :label="twoColLabelField" />

    <!-- 其他数量列 -->
    <el-table-column
      v-for="(item, index) in columns"
      :key="index"
      align="center"
      :prop="item[countColPropsField]"
      :label="item[countColLabelField] || '-'"
    >
      <template slot-scope="{ row, $index }">
        <span>{{ row[item[countColPropsField]] | noDataFilter }}</span>
      </template>
    </el-table-column>

    <!-- “小计”列 -->
    <el-table-column align="center" prop="xj" label="小计" />
  </el-table>
</template>

<script>
export default {
  name: 'CommonTable',
  components: {},

  props: {
    info: {
      type: Object,
      required: true
    },
    // 自定义表格列
    selfColumns: {
      type: Array,
      default: () => []
    },
    // 表格列非自定义时(接口获取)列字段名
    columnKeyField: {
      type: String,
      default: 'jtfs'
    },
    // 第一列字段名
    oneColPropField: {
      type: String,
      required: true
    },
    // 第一列展示header文本
    oneColLabelField: {
      type: String,
      required: true
    },
    // 第一列数据来源字段名
    oneColDataField: {
      type: String,
      required: true
    },
    // 第二列字段名
    twoColPropField: {
      type: String,
      required: true
    },
    // 第二列展示header文本
    twoColLabelField: {
      type: String,
      required: true
    },
    // 第二列数据来源字段名
    twoColDataField: {
      type: String,
      required: true
    },
    // 其他数量 列 字段名
    countColPropsField: {
      type: String,
      default: 'jtfs'
    },
    // 其他数量 列 展示header文本字段名
    countColLabelField: {
      type: String,
      default: 'jtfsView'
    },
    // 其他数量 列 数据来源字段名
    countColDataField: {
      type: String,
      default: 'total'
    }
  },

  data() {
    return {
      spanArr: []
    }
  },

  computed: {
    // 表格数据处理
    tableData() {
      const list = []
      Object.entries(this.info?.itemMap || {}).forEach((i) => {
        i[1]?.forEach((ii) => {
          /** ** 解决数据重复问题 start ****/
          const listDataIndex = list.findIndex(
            (listItem) => listItem[this.twoColPropField] === ii[this.twoColDataField] 
          )
          // 判断即将要 push 进 list 的数据 是否与 list 中已有数据的第二列数据有重复,有重复的话,就在 list 中重复的第二列数据的行数据中只添加当前数据为“其他数量列数据”
          if (listDataIndex !== -1) {
            list[listDataIndex][ii[this.countColPropsField]] = ii[this.countColDataField]
            return
          }
          /** ** 解决数据重复问题 end ****/
          list.push({
            // [this.oneColPropField]: ii[this.oneColDataField] // 第一列数据(第一列数据部分表格 ii 中无第一列数据,所以使用↓↓↓下一行代码 i[0] 取第一列数据)
            [this.oneColPropField]: i[0], // 第一列数据
            [this.twoColPropField]: ii[this.twoColDataField], // 第二列数据
            [ii[this.countColPropsField]]: ii[this.countColDataField] // 其他数量列数据
            // jtfs: ii.jtfs
          })
        })
      })
      return list.map((item) => {
        return {
          ...item,
          // 计算小计数量
          xj: this.columnKeyList.reduce((a, b) => {
            return a + (item[b] || 0)
          }, 0)
        }
      })
    },
    columns() {
      /**
       * 表格列获取
       *    父组件有传表格列 selfColumns 就用 selfColumns
       *    否则用接口获的表格列
       */
      return (this.selfColumns.length && this.selfColumns) || this.info.columns || []
    },
    columnKeyList() {
      // 获取表格每列字段名组成数组
      return this.columns.map((item) => item[this.columnKeyField])
    }
  },

  watch: {
    info() {
      this.xjPosition()
      this.oneColMergeCount()
    }
  },

  created() {},

  methods: {
    // 计算小计行插入位置
    xjPosition(Human = this.tableData) {
      const doctorMap = {}
      for (let i = 0; i < Human.length; i++) {
        // 找出相同名称的行数
        const doctorName = Human[i][this.oneColPropField]
        if (doctorMap[doctorName] !== undefined) {
          doctorMap[doctorName].push(i)
        } else {
          doctorMap[doctorName] = [i]
        }
      }
      const keyArr = []
      for (const k in doctorMap) {
        // 取出key并倒序,防止正序插入会影响行下标
        keyArr.unshift(k)
      }
      keyArr.forEach((ele, index) => {
        const lastIndex = doctorMap[ele][doctorMap[ele].length - 1] // 找出相同名称最后一行插入合计数据
        const obj = this.xjRowDataCalc(Human, ele) // 计算出小计行数据
        Human.splice(lastIndex + 1, 0, obj) // 插入
      })
    },
    // 小计行数据计算
    xjRowDataCalc(data, name) {
      const obj = {
        [this.oneColPropField]: name, // 第一列用于合并单元格
        [this.twoColPropField]: '小计' // 第二列数据
      }
      this.columnKeyList.forEach((key) => {
        obj[key] = 0 // 其他书两列数据
      })
      data.forEach((item) => {
        // 第一列 oneColPropField 数据相同的加起来
        if (item[this.oneColPropField] === name) {
          this.columnKeyList.forEach((key) => {
            obj[key] += Number(item[key] || 0)
          })
        }
      })
      // 小计列数据总和(小计行和小计列交汇处数据)
      obj.xj = this.columnKeyList.reduce((a, b) => {
        return a + (obj[b] || 0)
      }, 0)
      return obj
    },
    // 合并单元格
    firstColMergeSpan({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        const _row = this.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      }
    },
    // 计算要合并的单元格
    oneColMergeCount() {
      let contactDot = 0
      this.spanArr = []
      this.tableData.forEach((item, index) => {
        item.index = index
        if (index === 0) {
          this.spanArr.push(1)
        } else {
          // 第一列相同的合并
          if (item[this.oneColPropField] === this.tableData[index - 1][this.oneColPropField]) {
            this.spanArr[contactDot] += 1
            this.spanArr.push(0)
          } else {
            contactDot = index
            this.spanArr.push(1)
          }
        }
      })
    }
  }
}
</script>

<style lang='scss' scoped>
</style>

【注】计算小计插入位置等部分方法参考文章 https://blog.csdn.net/seeeeeeeeeee/article/details/133122424

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

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

相关文章

Redis篇 浅谈分布式系统

分布式系统 一. 单机架构二.分布式系统引入三.引入更多的应用服务器四.读写分离五.引入缓存服务器六. 将数据库服务器拆分七.微服务架构 一. 单机架构 单机架构,就是用一台服务器,完成所有的工作. 这时候就需要我们引入分布式系统了. 分布式系统是什么含义呢?就是由一台主机服…

MySQL实战——主从异步复制搭建(一主一从)

一、搭建前的准备 主库 192.168.1.76 从库 192.168.1.77 二、搭建 1、编辑配置文件 vi /etc/my.cnf 主库 [mysqld] log-binmysql-bin server-id1 从库 [mysqld] server-id2 2、在主库创建复制用户 create user repl192.168.1.77 identified by repl123; grant replic…

9、QT—SQLite使用小记

前言 开发平台&#xff1a;Win10 64位 开发环境&#xff1a;Qt Creator 13.0.0 构建环境&#xff1a;Qt 5.15.2 MSVC2019 64位 sqlite版本&#xff1a;sqlite3 文章目录 一、Sqlite是什么二、sqlite使用步骤2.1 下载2.2 安装2.3 使用 三、Qt集成sqlite33.1 关键问题3.2 封装sql…

C#, PCANBasicd.dll库读写CAN设备数据

PCAN-Basic是一个简单的 PCAN 系统编程接口。 通过 PCAN-Basic Dll,可以将自己的应用程序连接到设备驱动程序和 PCAN 硬件,以与 CAN 总线进行通信。支持C、C++、C#、Delphi、JAVA、VB、Python等语言。 PCAN-Basic库和驱动下载地址 ​ ​https://www.peak-system.com/filead…

【C#】未能加载文件或程序集“CefSharp.Core.Runtime.dll”或它的某一个依赖项。找不到指定的模块。

欢迎来到《小5讲堂》 这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。 温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01; 目录 背景错误提示分析原因解决方法Chromium知识点相关文章 背景 最近在使…

LeetCode 131题详解:高效分割回文串的递归与动态规划方法

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容&#xff0c;和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣&#xff01; 推荐&#xff1a;数据分析螺丝钉的首页 格物致知 终身学习 期待您的关注 导航&#xff1a; LeetCode解锁100…

Shell编程之条件判断语句

目录 一、条件判断 1、test命令 2、文件测试 3、整数值比较 4、字符串判断 5、逻辑测试 二、if语句 1、if单分支语句 2、双分支语句 3、多分之语句 4、case 分支语句 一、条件判断 Shell环境根据命令执行后的返回状态值&#xff08;echo $?&#xff09;来判断是否执行成…

力扣刷题---1748.唯一元素的和【简单】

题目描述 给你一个整数数组 nums 。数组中唯一元素是那些只出现 恰好一次 的元素。 请你返回 nums 中唯一元素的 和 。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3,2] 输出&#xff1a;4 解释&#xff1a;唯一元素为 [1,3] &#xff0c;和为 4 。 示例 2&#xff1a;…

基于BERT的医学影像报告语料库构建

大模型时代&#xff0c;任何行业&#xff0c;任何企业的数据治理未来将会以“语料库”的自动化构建为基石。因此这一系列精选的论文还是围绕在语料库的建设以及自动化的构建。 通读该系列的文章&#xff0c;犹如八仙过海&#xff0c;百花齐放。非结构的提取无外乎关注于非结构…

电路笔记 :元器件焊接相关 酒精灯松香浴加热取芯片

记录一下只使用松香和小火源加热&#xff08;如酒精灯、小蜡烛&#xff09;从电路板中取芯片。 过程 多放松香 让松香淹没芯片尽量均匀加热&#xff0c;等芯片旁边的松香开始从芯片里冒细小的“泡泡”&#xff0c;就差不多了 注&#xff1a;这种方法也可以用于焊接&#xff0…

UBUNTU22.04无法安装nvidia-driver-550 依赖于 nvidia-dkms-550 (<= 550.54.15-1)

类似的报错信息&#xff0c;就是卡在了nvidia-dkms-550无法安装 Loading new nvidia-550.40.07 DKMS files… Building for 6.5.0-15-generic Building for architecture x86_64 Building initial module for 6.5.0-15-generic ERROR: Cannot create report: [Errno 17] File e…

VLAN创建及配置

V-- 虚拟 LAN ---局域网 ---地理覆盖范围较小的网络 MAN ---城域网 WAN ---广域网 VLAN ---虚拟局域网 --- 交换机和路由器协同工作后&#xff0c;将原先的一个广播域&#xff0c;逻辑上切分为多个 第一步:创建VLAN [Huawei]display vlan---查看VLAN信息 VID -- VLAN ID ----…

DNS域名解析与智能选路

要开始访问公网了&#xff01;&#xff01; 你在访问百度的时候&#xff0c;你也不知道百度的IP地址是啥&#xff0c;你只知道他的域名是baidu AD这台设备可以做入站的负载平衡&#xff0c;AD来选择你访问的时候是用联通网还是电信网&#xff0c;避免卡顿 pc并不会域名解析&…

[算法] 优先算法(二): 双指针算法(下)

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏:&#x1f355; Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 &#x1f9c0;Java …

Python TCP编程简单实例

客户端&#xff1a;创建TCP链接时&#xff0c;主动发起连接的叫做客户端 服务端&#xff1a;接收客户端的连接 连接其他服务器 可以通过tcp连接其他服务器。 示例&#xff1a; import socket# 1.创建一个socket # 参数1&#xff1a;指定协议 AF_INET&#xff08;ipv4&#…

ftp是什么,ftp能做什么,ftp有什么用 -----在Windows搭建ftp服务器

大家好&#xff0c;我是风屿&#xff0c;今天教大家如何从零开始搭建一台属于自己的ftp&#xff0c;本期教大家搭建Windows客户端的&#xff0c;后面是linux的 首先第一步要有一台联网的Windows电脑 1打开控制面板&#xff0c;找到程序&#xff0c;点击打开或关闭Windows功能…

MQTT 5.0 报文解析 05:DISCONNECT

欢迎阅读 MQTT 5.0 报文系列 的第五篇文章。在上一篇中&#xff0c;我们已经介绍了 MQTT 5.0 的 PINGREQ 和 PINGRESP 报文。现在&#xff0c;我们将介绍下一个控制报文&#xff1a;DISCONNECT。 在 MQTT 中&#xff0c;客户端和服务端可以在断开网络连接前向对端发送一个 DIS…

QT项目-欢乐斗地主游戏

QT项目-欢乐斗地主游戏 游戏概述游戏规则牌型牌型的大小游戏角色游戏规则游戏的胜负游戏计分规则 游戏相关的类介绍卡牌类玩家类窗口类游戏控制类游戏策略类线程类音频类 游戏主要组件卡牌玩家窗口 游戏控制源码 游戏概述 游戏规则 不同地域游戏规则可能有些许差异&#xff0c…

CCF20220601——归一化处理

CCF20220601——归一化处理 代码如下&#xff1a; #include<bits/stdc.h> using namespace std; int main() {int n,a[1000],sum0;scanf("%d",&n);for(int i1;i<n;i){scanf("%d",&a[i]);suma[i];}double aver1.0,b0.0,d1.0;aversum/(n*1…

vue3使用mitt.js进行各种组件间通信

我们在vue工程中&#xff0c;除开vue自带的什么父子间&#xff0c;祖孙间通信&#xff0c;还有一个非常方便的通信方式&#xff0c;类似Vue2.x 使用 EventBus 进行组件通信&#xff0c;而 Vue3.x 推荐使用 mitt.js。可以实现各个组件间的通信 优点&#xff1a;首先它足够小&…