vue3 + ts + element-plus 二次封装 el-table

news2024/11/6 8:14:57

一、实现效果:

(1)数据为空时:

(2)有数据时:存在数据合并;可自定义表头和列的内容

(3)新增行:

(4)删除行:

(5)双击编辑单元格内容:

二、组件代码:

(1)components / CustomTable / index.vue

<template>

  <div class="custom-table-dialog">

    <el-table :data="paginatedData" border :span-method="spanMethod"
              highlight-current-row @row-click="rowClick" @cell-dblclick="cellDbClick"
              @selection-change="handleSelection" :header-row-style="props?.headerRowStyle"
              :header-cell-style="props?.headerCellStyle"
              :row-style="props?.rowStyle" :cell-style="props?.cellStyle" :empty-text="props.emptyText">

      <!-- 多选 -->
      <el-table-column v-if="isSelection" type="selection" width="55" align="center"></el-table-column>

      <template v-for="column in columnList" :key="column.label">

        <custom-table-column :column="column">

          <template v-slot:[`header-${column.prop}`]="scope">
            <slot :name="`header-${column.prop}`" v-bind="scope"></slot>
          </template>

          <template v-slot:[`default-${column.prop}`]="scope">
            <slot :name="`default-${column.prop}`" v-bind="scope"/>
          </template>

        </custom-table-column>

      </template>

    </el-table>

    <el-pagination
        size="small"
        :hide-on-single-page="true"
        background
        layout="prev, pager, next"
        :total="tableData.length"
        :current-page="currentPage"
        :page-size="pageSize"
        @current-change="handlePageChange"
    />

  </div>

</template>

<script setup lang="ts">

import CustomTableColumn from "@/components/CustomTable/components/CustomTableColumn.vue";
import {computed, ref} from "vue";
import type {ColumnItem} from "@/types/table";
import EventBus from "@/plugins/event-bus";

const props = defineProps<{
  tableData: any[] // 表格数据
  columnList: ColumnItem[] // 表头数据
  pageSize: number // 每页显示条数
  selection?: boolean // 是否多选
  merge?: boolean // 是否合并
  mergeColumns?: string[] // 哪些列中的单元格需要合并
  distinguishColumns?: string[] // 哪些列中单元格的值不一样,就不合并
  headerRowStyle?: any // 表头行样式
  headerCellStyle?: any // 表头单元格样式
  rowStyle?: any // 行样式
  cellStyle?: any // 单元格样式
  emptyText?: string // 空数据时显示的文本内容
}>()

const currentPage = ref(1)
const pageSize = ref(props.pageSize)

const paginatedData = computed(() => { // 分页数据
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return props.tableData.slice(start, end)
})

const isSelection = computed(() => { // 是否多选(勾选行)
  let selection = false
  if (props.selection) {
    selection = props.selection
  }
  return selection
})

const colFields = computed(() => { // 所有列的 props
  let fields: string[] = []
  const properties = props.columnList.map((item: any) => {
    return item.prop
  })
  if (props.selection) {
    fields.push('')
    fields.push(...properties)
  } else {
    fields = properties
  }
  return fields
})
let spanArr: any[] = [] //存储合并单元格的开始位置

const handlePageChange = (page: number) => {
  currentPage.value = page
}

/* 行点击事件 */
const rowClick = (row: any, column: any) => {
  EventBus.emit('row-click', {row, column})
}

/* 单元格双击事件 */
const cellDbClick = (row: any, column: any) => {
  EventBus.emit('cell-dbClick', {row, column})
}

/* 行选择事件 */
const handleSelection = (data: any) => { // data 为所有处于勾选状态的行的数组
  EventBus.emit('row-selection', data)
}

// 分析每一列,找出相同的
const getSpanArr = () => {
  let mergeColumns: string[] = []
  let distinguishColumns: string[] = []
  if (props.mergeColumns) {
    mergeColumns = props.mergeColumns
  }
  if (props.distinguishColumns) {
    distinguishColumns = props.distinguishColumns
  }
  for (let i = 0; i < paginatedData.value.length; i++) {
    let row = i;
    // let col = i % this.colCount;
    if (row === 0) {
      // i 表示行 j表示列
      for (let j = 0; j < colFields.value.length; j++) {
        spanArr[i * colFields.value.length + j] = {
          rowspan: 1,
          colspan: 1,
        }
      }
    } else {
      for (let j = 0; j < colFields.value.length; j++) {
        // 当前和上一次的一样
        //  合并所有列的相同数据单元格
        if (mergeColumns.includes(colFields.value[j])) { // Check if the column is in mergeColumns
          if (distinguishColumns.some(col => paginatedData.value[row][col] !== paginatedData.value[row - 1][col])) {
            // If any distinguish column is different, do not merge
            spanArr[row * colFields.value.length + j] = {
              rowspan: 1,
              colspan: 1,
            }
          } else if (paginatedData.value[row][colFields.value[j]] === paginatedData.value[row - 1][colFields.value[j]]) {
            let beforeItem =
                spanArr[(row - 1) * colFields.value.length + j]
            spanArr[row * colFields.value.length + j] = {
              rowspan: 1 + beforeItem.rowspan, // Merge rows
              colspan: 1, // Merge columns
            }
            beforeItem.rowspan = 0
            beforeItem.colspan = 0
          } else {
            // No merge
            spanArr[row * colFields.value.length + j] = {
              rowspan: 1,
              colspan: 1,
            }
          }
        }
      }
    }
  }
  // 对数据进行倒序
  let stack = []
  for (let i = 0; i < colFields.value.length; i++) {
    for (let j = 0; j < paginatedData.value.length; j++) {
      // console.log("i=" + i + " j=" + j);
      // i 表示列 j表示行
      if (j === 0) {
        if (spanArr[j * colFields.value.length + i].rowspan === 0) {
          stack.push(spanArr[j * colFields.value.length + i])
        }
      } else {
        if (spanArr[j * colFields.value.length + i]?.rowspan === 0) {
          stack.push(spanArr[j * colFields.value.length + i])
        } else {
          stack.push(spanArr[j * colFields.value.length + i])
          while (stack.length > 0) {
            let pop = stack.pop()
            let len = stack.length
            spanArr[(j - len) * colFields.value.length + i] = pop
          }
        }
      }
    }
  }
}

const spanMethod = (data: { row: any, column: any, rowIndex: any, columnIndex: any }) => {
  if (props.merge) {
    getSpanArr()
    return spanArr[data.rowIndex * colFields.value.length + data.columnIndex]
  } else {
    return
  }
}

/*// 合并固定列
const spanMethod = (data: { row: any, column: any, rowIndex: any, columnIndex: any }) => {
  if (data.column.property === 'column1') { // 指定列相邻单元格的值相等就合并
    const currentValue = data.row[data.column.property] // 当前单元格的值
    const preRow = props.tableData[data.rowIndex - 1] // 上一行
    const preValue = preRow ? preRow[data.column.property] : null // 上一行相同列的值
    if (currentValue === preValue) { // 将当前单元格隐藏
      return {
        rowspan: 0,
        colspan: 0
      }
    } else { // 合并 —— 计算当前单元格应该跨多少行
      let rowSpan = 1 // 初始跨 1 行
      for (let i = data.rowIndex + 1; i < props.tableData.length; i++) {
        const nextRow = props.tableData[i] // 下一行
        const nextValue = nextRow ? nextRow[data.column.property] : null // 下一行相同列的值
        if (nextValue === currentValue) {
          rowSpan++
        } else {
          break
        }
      }
      return {
        rowspan: rowSpan,
        colspan: 1
      }
    }
  }
}*/

</script>

<style lang="scss">

.custom-table-dialog {

  //height: 100%;
  height: fit-content;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  //border: 1px solid red;

  .el-table {
    --el-table-border-color: rgba(218, 226, 237); // 边框颜色
    --el-table-bg-color: transparent;
    --el-table-text-color: rgba(165, 176, 193); // 表格数据部分文字颜色
    --el-table-header-text-color: rgba(251, 251, 251); // 表头文字颜色
    --el-table-row-hover-bg-color: rgba(252, 250, 255); // 鼠标悬浮时表行的背景色
    --el-table-header-bg-color: rgba(201, 213, 229); // 表头背景色
    --el-table-tr-bg-color: rgba(255, 255, 255); // 表格数据部分表行背景色
    background-color: transparent;

    .el-table__body tr.current-row > td.el-table__cell { // 高亮行单元格的背景色
      background: rgba(252, 250, 255);
    }

    .el-table__empty-block { // 数据为空时 表格 body 的样式
      background-color: #FFFFFF;
    }

  }

  .el-checkbox__input.is-checked .el-checkbox__inner {
    background-color: rgba(192, 172, 233);
    border-color: rgba(192, 172, 233);
  }

  .el-checkbox__input.is-indeterminate .el-checkbox__inner {
    background-color: rgba(192, 172, 233);
    border-color: rgba(192, 172, 233);
  }

  .el-checkbox__inner:hover {
    border-color: rgba(192, 172, 233);
  }

  //:deep(.custom-table-dialog .el-pagination) {
  //  //margin-top: 100px;
  //  position: absolute;
  //  left: 50%;
  //  transform: translateX(-50%);
  //  bottom: 20px;
  //}
  .el-pagination { /* 如要固定分页器的位置在容器底部,在父组件中使用:deep(.custom-table-dialog .el-pagination) {}修改,示例如上 */
    margin-top: 10px;
  }

  .el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {
    background-color: rgba(201, 213, 229);
    color: rgba(251, 251, 251);
  }

  .el-pagination.is-background .btn-next.is-active, .el-pagination.is-background .btn-prev.is-active, .el-pagination.is-background .el-pager li.is-active {
    background: rgba(192, 172, 233);
  }

}

</style>

(2)components / CustomTable / components / CustomTableColumn.vue

<template>

  <el-table-column v-if="column.children?.length" v-bind="getColumnProps(column)">

    <template #header="scope">
      <slot :name="`header-${column.prop}`" v-bind="scope">
        <span>{{ column.label }}</span>
      </slot>
    </template>

    <template v-for="child in column.children" :key="child.label">
      <custom-table-column :column="child"/>
    </template>

  </el-table-column>

  <el-table-column v-else v-bind="getColumnProps(column)">

    <template #header="scope">
      <slot :name="`header-${column.prop}`" v-bind="scope">
        <span>{{ column.label }}</span>
      </slot>
    </template>

    <template #default="scope">
      <slot :name="`default-${column.prop}`" v-bind="scope">
        <span>{{ scope.row[column.prop] }}</span>
      </slot>
    </template>

  </el-table-column>

</template>

<script setup lang="ts">

import type {ColumnItem} from "@/types/table";

defineProps<{
  column: ColumnItem
}>()

const getColumnProps = (column: ColumnItem) => {
  const {children, ...props} = column
  return props
}

</script>

<style scoped lang="scss">

</style>

(3)types / table.ts

/*
* 表列属性【 ?. 代表非必传,否则必传】
* */
export interface ColumnItem {
    label: string,
    prop: string,
    children?: ColumnItem[],
    align?: string, // 对齐方式
    width?: string | number, // 宽度
    sortable?: boolean | string, // 对应列是否可以排序,如果设置为 'custom',则代表用户希望远程排序,需要监听 Table 的 sort-change 事件

    /* 对象可以具有任意数量的键,这些键的类型为 string,对应的值的类型为 any */
    [key: string]: any
}

export enum TableSize {
    Large = 'large',
    Default = 'default',
    Small = 'small',
}

(4) plugins / event-bus.ts

import mitt from 'mitt' // 首先 npm install mitt
const EventBus = mitt()
export default EventBus

三、使用代码:

MyTable.vue

<template>

  <!-- 二次封装 el-table -->
  <div class="custom-table-container">
    <div class="table-header">
      <div>title</div>
      <div class="table-buttons">
        <div class="table-button" @click="addRow">
          <el-icon>
            <Plus/>
          </el-icon>
        </div>
        <div class="table-button" @click="deleteRows">
          <el-icon>
            <Delete/>
          </el-icon>
        </div>
      </div>
    </div>
    <custom-table :column-list="columnList" :page-size="15" :table-data="tableData" :selection="true" :merge="true"
                  :merge-columns="mergeColumns" :distinguish-columns="distinguishColumns" empty-text="Please set Data">
      <!-- 自定义表头单元格内容示例 -->
      <template #header-id="{row, column}">
        {{ column.label }} Here
      </template>
      <!-- 自定义列内容示例 -->
      <template #default-column1="{row, column}">
        <el-input ref="inputRef" v-model="row.column1"
                  v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"
                  size="small"/>
        <span v-else>{{ row.column1 }}</span>
      </template>
      <template #default-number1="{row, column}">
        <el-input ref="inputRef" v-model="row.number1"
                  v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"
                  size="small"/>
        <span v-else>{{ row.number1 }}</span>
      </template>
      <template #default-select1="{row, column}">
        <el-select ref="inputRef" v-model="row.select1"
                   v-if="editRow === row.id && editColumn === column.id" @blur="stopEdit"
                   size="small">
          <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
          />
        </el-select>
        <span v-else>{{ row.select1 }}</span>
      </template>
    </custom-table>
  </div>

</template>

<script setup lang="ts">

import CustomTable from "@/components/CustomTable/index.vue";
import type {ColumnItem} from "@/types/table";
import {nextTick, onMounted, ref} from "vue";
import EventBus from "@/plugins/event-bus";
import {Delete, Plus} from "@element-plus/icons-vue";
import {ElMessage} from "element-plus";

const columnList: ColumnItem[] = [
  {
    label: 'id',
    prop: 'id',
    align: 'center'
  },
  {
    label: 'column1',
    prop: 'column1',
    align: 'center',
    width: 100
  },
  {
    label: 'number1',
    prop: 'number1',
    align: 'center',
    width: 100
  },
  {
    label: 'select1',
    prop: 'select1',
    align: 'center'
  },
  {
    label: 'time1',
    prop: 'time1',
    align: 'center'
  },
  {
    label: 'time2',
    prop: 'time2',
    align: 'center'
  }
]

const mergeColumns = ['column1', 'select1'] // Specify merge columns
const distinguishColumns = ['column1'] // Specify distinguish columns

const headerCellStyle = (row: any) => { // 表头单元格样式示例
  return {
    backgroundColor: 'lightpink'
  }
}

const rowStyle = (data: any) => { // 行样式示例
  if (data.row.column1 === 'row1') {
    return {
      backgroundColor: 'lightpink'
    }
  } else {
    return {
      backgroundColor: 'lightgreen'
    }
  }
}

const tableData = ref<any[]>([ // 表格数据
  {
    id: 1,
    column1: 'row1',
    number1: 1,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  },
  {
    id: 2,
    column1: 'row1',
    number1: 2,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  },
  {
    id: 3,
    column1: 'row2',
    number1: 3,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  },
  {
    id: 4,
    column1: 'row2',
    number1: 4,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  },
  {
    id: 5,
    column1: 'row3',
    number1: 4,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  },
  {
    id: 6,
    column1: 'row4',
    number1: 5,
    select1: 'option1',
    time1: 'test',
    time2: 'test'
  }
])

const options = [
  {
    value: 'option1',
    label: 'option1'
  },
  {
    value: 'option2',
    label: 'option2'
  }
]

const editRow = ref<any>(null) // 正在编辑的行
const editColumn = ref<any>(null) // 正在编辑的列
const inputRef = ref<any>(null)

const selectedRows = ref<any[]>([]) // 选中的行

onMounted(() => {
  EventBus.on('cell-dbClick', (data: any) => { // 单元格双击事件
    editRow.value = null
    editColumn.value = null
    editRow.value = data.row.id
    editColumn.value = data.column.id
    nextTick(() => {
      inputRef.value.focus() // 输入框自动聚焦
    })
  })
})

const stopEdit = () => { // 停止编辑
  editRow.value = null
  editColumn.value = null
  inputRef.value = null
  /* 每次编辑后根据 column1 的内容重新排序 */
  const groupedTableData = tableData.value.reduce((acc, curr) => {
    (acc[curr.column1] = acc[curr.column1] || []).push(curr)
    return acc
  }, {})
  tableData.value = []
  Object.keys(groupedTableData).forEach((key: any) => {
    tableData.value.push(...groupedTableData[key])
  })
}

onMounted(() => {
  EventBus.on('row-selection', (data: any) => { // 行选择事件
    selectedRows.value = data
  })
})

const addRow = async () => { // 新增行
  const rowData = {
    id: tableData.value.length + 1,
    column1: '',
    number1: '',
    select1: '',
    time1: '',
    time2: ''
  }
  tableData.value.push(rowData)
}

const deleteRows = () => { // 删除行
  if (selectedRows.value.length > 0) {
    selectedRows.value.forEach((item: any) => {
      tableData.value = tableData.value.filter((data: any) => data.id !== item.id)
    })
  } else {
    ElMessage.error('Please select the row to delete')
  }
}

</script>

<style scoped lang="scss">

.custom-table-container {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: rgba(233, 237, 246);
  padding: 20px;

  .table-header {
    background: rgba(200, 180, 243);
    color: rgba(254, 255, 253);
    font-family: Consolas;
    font-size: 20px;
    font-weight: bolder;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 10px 15px;
  }

  .table-buttons {
    display: flex;

    .table-button {
      color: rgba(255, 254, 254);
      background: rgba(192, 172, 233);
      font-size: 20px;
      font-family: Consolas;
      width: fit-content;
      padding: 10px;
      margin-right: 10px;
      cursor: pointer;
    }

    .table-button:last-child { // 最右边的按钮 margin-right = 0
      margin-right: 0;
    }
  }

}

</style>

四、参考文章

el-table表格动态合并相同数据单元格(可指定列+自定义合并)_el-table 合并单元格动态-CSDN博客

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

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

相关文章

Python CGI编程-cookie的设置、检索

设置检索 其他&#xff1a; 1. http.cookies和http.cookiejar区别&#xff1a; http.cookies主要用于创建和操作单个cookie对象&#xff0c;适用于需要精细控制单个cookie属性的场景。http.cookiejar则用于管理多个cookie&#xff0c;适用于需要自动处理多个请求和响应中的coo…

k8s 二进制部署安装(三)

目录 部署Calico Calico 工作原理 部署Calico 部署CoreDNS 负载均衡部署 部署dashboard 部署Calico 安装步骤来到 CNI 网络组件 &#xff0c;在&#xff08;二&#xff09;中我们安装了flannel&#xff0c;现在我们要尝试安装另一网络组件Calico calico 不使用隧道或NAT…

idea 创建web工程

模块添加Add Framework Support web Application 改为4.0以上

Linux系列-进程的概念

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 这篇文章&#xff0c;我们主要分析一下进程。 之前&#xff0c;我们讲过了冯诺依曼体系架构&#xff0c; 我们常见的计算机&#xff0c;像笔记本&#xff0c;或者不常见的计算机…

Rust的enum枚举的强大用法

在Rust中&#xff0c;enum&#xff08;枚举&#xff09;是一种非常强大的类型&#xff0c;它可以包含多个变体&#xff08;variants&#xff09;&#xff0c;每个变体可以是不同的类型&#xff0c;包括复杂类型。这使得enum在Rust中不仅用于表示简单的状态或选项集合&#xff0…

【初识Linux】

十点半的飞机快要到了&#xff0c;机场还是那么的拥挤.......................................................................... 文章目录 一、【初识指令】 1、 ls✔ 2、pwd✔ 3、cd✔ 4. touch✔ 5.mkdir✔ 6.rmdir✔ 7、rm ✔ 8.man✔ 9.cp✔ ​10、mv✔ 11、cat✔…

头歌——算法设计与分析(贪心法)

文章目录 第1关&#xff1a;贪心法代码 第2关&#xff1a;最小生成树代码 第3关&#xff1a;Huffman 编码代码 第4关&#xff1a;单源点最短路径代码 第1关&#xff1a;贪心法 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;贪心法 ;。 贪心法&#xff0c;又称…

面试题:JVM(四)

new对象流程&#xff1f;&#xff08;龙湖地产&#xff09; 对象创建方法&#xff0c;对象的内存分配。&#xff08;360安全&#xff09; 1. 对象实例化 创建对象的方式有几种&#xff1f; 创建对象的步骤 指针碰撞&#xff1a;以指针为分界线&#xff0c;一边是已连续使用的…

【进阶sql】复杂sql收集及解析【mysql】

开发时会出现&#xff0c;必须写一些较复杂sql的场景 可能是给会sql的客户 提供一些统计sql 或是临时需要统计数据信息但是 开发一个统计功能有来不及的情况 也可能是报表系统组件 只支持 sql统计的情况 特地记录下这些sql 作为积累 substring 截取查询出的字符串&#xff…

Python实现全国岗位招聘信息可视化分析(源码+论文+部署讲解)

项目源码&数据源获取 利用Python实现全国岗位招聘信息可视化分析 项目背景&#xff1a; 1.为企业招聘决策提供科学的依据和参考&#xff0c;可以帮助人力资源部门、招聘机构和求职者了解当前的就业形势、行业趋势和人才需求&#xff0c;从而做出更明智的招聘和求职决策。…

Python毕业设计选题:基于django+vue的宠物寄养平台的设计与实现

开发语言&#xff1a;Python框架&#xff1a;djangoPython版本&#xff1a;python3.7.7数据库&#xff1a;mysql 5.7数据库工具&#xff1a;Navicat11开发软件&#xff1a;PyCharm 系统展示 1. 前台系统功能模块 系统首页界面 用户注册界面 用户登录界面 宠物商城界面 宠物店…

Linux云计算 |【第五阶段】CLOUD-DAY10

主要内容&#xff1a; 部署Dashboard、部署Prometheus、部署HPA集群 一、Dashboard介绍 Dashboard是基于网页的Kubernetes用户界面&#xff0c;可以使用Dashboard将容器应用部署到Kubernetes集群中&#xff0c;也可以对容器应用排错&#xff0c;还能管理集群资源。可以使用Da…

将Notepad++添加到右键菜单【一招实现】

一键添加注册表 复制以下代码保存为 Notepad.reg&#xff0c;将红框内路径修改为自己电脑的“Notepad.exe路径”后&#xff0c;再双击运行即可。 Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\*\shell\NotePad] "Notepad" "Icon""D:\\N…

Git下载-连接码云-保姆级教学(连接Gitee失败的解决)

Git介绍 码云连接 一、Git介绍 二、Git的工作机制 下载链接&#xff1a;Git - 下载软件包 三、使用步骤 创建一个wss的文件夹&#xff0c;作为‘工作空间’ 四、连接码云账号 五、连接Gitee失败的解决方法 一、Git介绍 Git是一个免费的、开源的分布式版本控制…

Spring Boot 与 Vue 共铸卓越采购管理新平台

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 &#x1f345;获取源码联系方式请查看文末&#x1f345; 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目…

DataFlow v202410 版本更新 一站式数据处理平台

DataFlow 是 OpenCSG 推出的一站式数据处理平台&#xff0c;与 CSGHub 无缝集成&#xff0c;形成数据到模型的全生命周期闭环&#xff0c;助力持续优化。平台兼容多种数据格式与来源&#xff0c;支持本地、云端和网络数据接入&#xff0c;并提供高效转换和读取工具&#xff0c;…

【搜索引擎】俄罗斯搜索引擎yandex

俄罗斯搜索引擎yandex 1997年&#xff0c;俄罗斯搜索引擎Yandex&#xff08;俄语意为&#xff1a;语言目录&#xff09;首次上线&#xff0c;已发展成为全球第四大搜索引擎和第二大非英语搜索引擎 https://yandex.com/

电脑没有下载声卡驱动怎么办?电脑声卡驱动安装方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到电脑没有声音的问题&#xff0c;这往往与声卡驱动缺失或损坏有关。声卡驱动是连接电脑硬件&#xff08;声卡&#xff09;与操作系统之间的桥梁&#xff0c;确保音频信号能够正常输入输出。那么&#xff0c;当电脑没有声卡驱动…

DEVOPS: 集群伸缩原理

概述 阿里云 K8S 集群的一个重要特性&#xff0c;是集群的节点可以动态的增加或减少有了这个特性&#xff0c;集群才能在计算资源不足的情况下扩容新的节点&#xff0c;同时也可以在资源利用 率降低的时候&#xff0c;释放节点以节省费用理解实现原理&#xff0c;在遇到问题的…

git 删除远程不存在本地命令却能看到的分支

要删除远程不存在但本地却能看到的分支&#xff0c;你可以按照以下步骤操作&#xff1a; 删除本地分支&#xff1a; 如果你确定要删除的分支已经没有用处&#xff0c;可以使用以下命令来删除本地分支&#xff1a; git branch -d <branch-name>这里的 <branch-name>…