基于antdv封装的特殊复杂表格,带通行描述信息、可展示通行的单元格信息、可跨页选择数据功能、分页功能、可编辑单元格功能

本文主要是介绍基于antdv封装的特殊复杂表格,带通行描述信息、可展示通行的单元格信息、可跨页选择数据功能、分页功能、可编辑单元格功能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于antdv封装的特殊复杂表格,带通行描述信息

主要功能:

  1. 可展示通行的单元格信息
  2. 可跨页选择数据功能
  3. 表单插槽、合计插槽、操作按钮区插槽
  4. 分页功能
  5. 接口内请求api
  6. 可编辑单元格
  7. 表格组件暴漏出的方法:查询、获取选中数据、接口返回数据、当前表格数据【设置可编辑单元格时获取数据】

页面示例:

本页主要是下面这种大通行效果【选择和序号都通行】
在这里插入图片描述
还有一种是通行不带选择和序号,如下:代码下载地址 : https://download.csdn.net/download/qq_32442967/87965962
在这里插入图片描述

使用示例:

页面文件page.vue

<template><self-tableref="selfTableRef":full-row-type="fullRowType":api="planManageListApi":columns="tableColumns(fullRowType)":full-row-key-list="['noId']":has-checkbox="true":allTableColumnsNum="8":tableProps="{}"><template #form><!-- 自定义表单组件 可用任意表单组件 submit为表单 查询按钮事件 --><BasicForm  @submit="handleSubmit" /></template><template #tableTitle> 订单总重量:[<span class="color-red">1244.533</span> 吨] </template><template #tableHead><a-button type="primary">导出</a-button></template><template #full-row="{ row }">计划单号:<a-button type="link" size="small" @click="handlePlanDetail(row)">{{ row.noId }}</a-button> 计划总量:1 吨申报时间:2023-04-2617:09:26 审核时间:2023-04-26 17:09:46</template><template #colSlot1="{ row }"><div>申报单位:{{ row.xa }}XXXXX有限责任公司</div><div>申报人:欧冶材料</div></template><template #colSlot4="{ row }"><div>钢材 10 {{ row.xs }}</div><div>钢材 20</div></template><template #action="{ row }"><a-button type="link" size="small" @click="handlePlanApply('edit', row)">修改</a-button></template></self-table>
</template>
<script setup lang="ts">import SelfTable from '/@/views/components/SelfTable/index.vue';import { ref } from 'vue';import { FullRowType } from '/@/views/components/SelfTable/selfTableTools';import { tableColumns } from '/@/views/planManage/planManage.data';import { planManageListApi } from '/@/views/planManage/planManage.api';// 定义通行类型const fullRowType: FullRowType = 'prev';const selfTableRef = ref();function handleSubmit(v) {selfTableRef.value.search(v);}</script><style scoped lang="less"></style>

planManage.data中tableColumns() 方法

export const tableColumns = (fullRowType): SelfTableColumnType[] => [{title: '计划信息',dataIndex: 'key1',width: 300,customCell: (_, index) => sharedOnCell(index, fullRowType),slot: 'colSlot1',},{title: '计划状态',dataIndex: 'planStatus',width: 120,customCell: (_, index) => sharedOnCell(index, fullRowType),},{title: '区域',dataIndex: 'oldRecordCdName',width: 220,align: 'center',customCell: (_, index) => sharedOnCell(index, fullRowType),},{title: '详情',dataIndex: 'createTime',width: 300,customCell: (_, index) => sharedOnCell(index, fullRowType),slot: 'colSlot4',},{title: '审核人',dataIndex: 'accountMark',width: 100,align: 'center',customCell: (_, index) => sharedOnCell(index, fullRowType),},{title: '操作',key: 'action',fixed: 'right',align: 'center',width: 180,customCell: (_, index) => sharedOnCell(index, fullRowType),},
];

参数说明:

字段类型描述
apiPromise表格数据api
dataSourcearray表格数据
columnsarray表格column数据,列数据一定要指定width
has-checkboxboolean是否可选,默认false
full-row-typestring通行类型 ‘prev’ 前一行,‘last’ 后一行 ,FullRowType类型
tablePropsObject传给antd table组件的数据
allTableColumnsNumnumber所有的表格列数【包含选择列和序号列】

SelfTable.vue组件

<template><a-card style="margin: 8px" v-if="$slots['form']"><slot name="form"></slot></a-card><component :is="isDiv ? 'div' : 'a-card'" style="margin: 8px"><!--  可放操作按钮  --><div class="table-head" v-if="$slots['tableHead']"><slot name="tableHead"></slot></div><!--  可放合计数据  --><div class="table-head" v-if="$slots['tableTitle']"><slot name="tableTitle"></slot></div><a-alert class="a-alert-cont" type="info" show-icon v-if="hasCheckbox"><template #message><span>{{ checkedAlertMessage }}</span><template v-if="checkedList.length"><a-divider type="vertical" /><a href="javascript:" @click="resetCheckbox">清空</a></template></template></a-alert><a-table:columns="columns":data-source="tableData":scroll="{ x: '100%' }":pagination="false"size="small"@change="pageChange"borderedv-bind="$attrs.tableProps"class="self-table"><!--   编辑列显示编辑ICON   --><template #headerCell="{ column, title }"><template v-if="column.isEdit === true"><div class="head-edit-cont"> <i class="vxe-cell--edit-icon vxe-icon--edit-outline"></i> {{ title }} </div></template><!--    选择    --><template v-if="column.dataIndex === 'rowSelection'"><a-checkbox :indeterminate="indeterminate" v-model:checked="checkAll" @change="onCheckAllChange" /></template></template><template #bodyCell="{ column, index, record, text }"><!--   序号  非通行时显示序号   --><template v-if="index % 2 === unFullRowIndex && column.dataIndex === 'selfIndex'">{{ tableIndex(index) }}</template><!--如果是通行则展示full-row插槽,如果不是通行并且传入了插槽则展示  --><template v-if="column.fullFirst"><div class="full-row-cont" v-if="index % 2 === fullRowIndex"><slot name="full-row" :row="record"></slot></div><!--   选择列     --><template v-else-if="column.dataIndex === 'rowSelection'"><a-checkboxname="tableCheckbox"class="my-checkbox"v-model:checked="record._checked":key="record.id":value="record.id"@change="onCheckBoxChange(record)"/></template><template v-else-if="column.slot"><slot :name="column.slot" :row="record" :rowIndex="index"></slot></template><template v-else>{{ text }}</template></template><!--   如果不是通行、并且传入了插槽,则展示     --><template v-else-if="index % 2 === unFullRowIndex && column.slot"><slot :name="column.slot" :row="record" :rowIndex="index"></slot></template><!--   操作     --><template v-if="column.key === 'action'"><template v-if="index % 2 === unFullRowIndex"><slot name="action" :row="record"></slot></template></template></template></a-table><!--   页码:传入dataSource时不显示页码     --><div class="my-footer" v-if="hasPagination"><a-paginationsize="small":total="total":current="pageNo":page-size="pageSize"show-size-changershow-quick-jumper:show-total="(total) => `共 ${total} 条数据`"@change="pageChange"/></div></component>
</template>
<script lang="ts" setup name="SelfTable">import type { TableColumnType } from 'ant-design-vue';import {checkColumnsHasExist,filterSelfTableColumns,filterSelfTableData,FullRowType,getIndeterminateAndCheckAllStatus,getAllCheckedListData,useFullRowIndex,SelfTableColumnType,columnColspanFull,indexColumnColspan,} from '/@/views/components/SelfTable/selfTableTools';import { computed, onMounted, reactive, ref, toRaw, watch } from 'vue';interface Props {dataSource?: any[]; // 数据,fullRowType: FullRowType; // 同行类型fullRowKeyList: any[]; // 展示在同行的数据,组件内自动转换数据api?: any;hasCheckbox?: boolean;hasPagination?: boolean;columns: TableColumnType[];allTableColumnsNum: number; // 表格列总数量isDiv?: boolean;}const props = defineProps<Props>();// fullRowType 通行索引  0代表偶数行为通行,即行下展示描述信息const { fullRowIndex, unFullRowIndex } = useFullRowIndex(props.fullRowType);// 表格基础数据let pageNo = ref(1); // 页码let pageSize = ref(10); // 页条数let total = ref(0); // 总条数let sourceData = ref([]); // 接口返回原始数据let tableSourceData = ref([]); // 接口返回原始数据中的表格数据let tableData = ref([]); // 表格数据const hasPagination = ref(true); // 是否显示页码const checkColumn: SelfTableColumnType = {title: ' ',dataIndex: 'rowSelection',key: Math.random(),fixed: 'left',align: 'center',width: 40,customCell: (_, index) => ({colSpan: columnColspanFull(index, fullRowIndex, props.allTableColumnsNum),}),fullFirst: props.hasCheckbox,};const indexColumn: SelfTableColumnType = {title: '序号',key: Math.random(),dataIndex: 'selfIndex',fixed: 'left',align: 'center',width: 40,customCell: (_, index) => ({colSpan: indexColumnColspan(index, fullRowIndex, unFullRowIndex, props.allTableColumnsNum, props.hasCheckbox),}),fullFirst: !props.hasCheckbox,};let columns = ref<TableColumnType[]>([]);columns.value = filterSelfTableColumns(toRaw(props.columns));!checkColumnsHasExist(props.columns, 'selfIndex') && columns.value.unshift(indexColumn);props.hasCheckbox && !checkColumnsHasExist(props.columns, 'rowSelection') && columns.value.unshift(checkColumn);/********* 选择 相关 start ***********/let checkAll = ref(false);let indeterminate = ref(false);let checkedList = ref([]);// 全选function onCheckAllChange(e: any) {const checked = e.target.checked;tableData.value.map((item) => {item._checked = checked;});checkedList.value = checked ? getAllCheckedListData(tableSourceData.value, checkedList.value) : [];indeterminate.value = false;}function onCheckBoxChange(record) {const index = checkedList.value.findIndex((item) => item.id === record.id);if (index > -1) {checkedList.value.splice(index, 1);} else {checkedList.value.push(record);}}const checkedAlertMessage = computed(() => {return checkedList.value.length === 0 ? '未选中任何数据' : `已选中 ${checkedList.value.length} 条记录(可跨页)`;});// 监听 选择改变watch(() => checkedList.value, reloadCheckStatus, {immediate: true,deep: true,});function reloadCheckStatus() {const { indeterminateStatus, checkAllStatus } = getIndeterminateAndCheckAllStatus(checkedList.value, tableSourceData.value);indeterminate.value = indeterminateStatus;checkAll.value = checkAllStatus;}// 重置选择function resetCheckbox() {onCheckAllChange({ target: { checked: false } });}// 给数据添加选项字段function addCheckedParam(data = []) {if (!props.hasCheckbox) {return data;}let nData = data;nData.map((item) => {const index = checkedList.value.findIndex((check) => item.id === check.id);item['_checked'] = index !== -1;});return nData;}/********* 选择 相关  end ***********/// index序号计算const tableIndex = computed(() => (index) => (index + unFullRowIndex) / 2 + fullRowIndex + (pageNo.value - 1) * pageSize.value);let searchData = reactive({});// 搜索 - 传入搜索数据function search(sd, reset = true) {searchData = sd;reload(reset);}// 重载表格async function reload(reset = false) {if (reset) pageNo.value = 1;const res = await props.api({...searchData,pageNo: pageNo.value,pageSize: pageSize.value,});// 保存接口数据sourceData.value = res || [];tableSourceData.value = addCheckedParam(res.records);total.value = res.total || 0;tableData.value = addCheckedParam(filterData(res.records));reloadCheckStatus();}/*** 修改表格数据* @param {number} rowIndex 行索引* @param {string} changeKey 改变的字段* @param value  要改变的值*/function setTableData(rowIndex: number, changeKey: string, value: any) {if (tableData.value[rowIndex] === undefined) return;if (tableData.value[rowIndex][changeKey] === undefined) return;tableData.value[rowIndex][changeKey] = value;}function filterData(records) {return filterSelfTableData(records, props.fullRowKeyList || [], fullRowIndex, unFullRowIndex);}onMounted(() => {hasPagination.value = props.hasPagination || true;if (props.dataSource) {// hasPagination.value = false;sourceData.value = props.dataSource;tableSourceData.value = addCheckedParam(props.dataSource);tableData.value = addCheckedParam(filterData(props.dataSource));} else {reload(true);}});// 页码改变事件function pageChange(pNo, pSize) {pageNo.value = pNo;// 页数改变时,页码设置1const reset = pageSize.value !== pSize;pageSize.value = pSize;reload(reset);}/*** 获取选中数据 - id* @return [string | number] 选中数据*/function getChecked(): (string | number)[] {let checkArr: (string | number)[] = reactive([]);let checkDom: any[] = document.querySelectorAll('input[name="tableCheckbox"]:checked') || [];checkDom.forEach((check) => {checkArr.push(check.value);});return toRaw(checkArr);}/*** 获取选中数据 - row* @return [string | number] 选中数据*/function getCheckedRows(): (string | number)[] {// let checkArr: [] = reactive([]);// let checkDom: any[] = document.querySelectorAll('input[name="tableCheckbox"]:checked') || [];// let getData = getTableData();// checkDom.forEach((check) => {//   let checkDataRows = getData.find((item) => item.id == check.value);//   checkArr.push(checkDataRows ? checkDataRows : {});// });return toRaw(checkedList.value);}// 获取当前表格的数据function getTableData() {const tData = tableData.value;let realData = [];tData.forEach((item, index) => {if (index % 2 === fullRowIndex) return;realData.push({ ...item, ...tData[index + 1] });});return realData;}/*** 暴露属性方法* @param {function} search 搜索方法* @param {function} getChecked 获取已选中数据方法 - id* @param {function} getCheckedRows  获取已选中数据方法 - row* @param {Array} sourceData 获取接口返回的数据* @param {Array} tableSourceData 获取接口返回的数据中表格的数据* @param {function} getTableData 获取表格数据* @param {function} setTableData 设置表格某行的某个单元格数据*/defineExpose({search,getChecked,getCheckedRows,sourceData,tableSourceData,getTableData,setTableData,});
</script>
<style lang="less" scoped>.a-alert-cont {margin-bottom: 8px;}.ant-table-striped :deep(.table-striped) td {background-color: #fafafa;}:deep(.ant-table-content) {border-right: 1px solid #f0f0f0;}:deep(.ant-table-thead) > tr > th,:deep(.ant-table-tbody) > tr > td,:deep(.ant-table tfoot) > tr > th,:deep(.ant-table) tfoot > tr > td {padding: 4px 8px;}.my-footer {display: flex;justify-content: flex-end;margin-top: 8px;}.my-checkbox {cursor: pointer;width: 16px;height: 16px;}.table-head {margin-bottom: 8px;:deep(.ant-btn) {margin-right: 8px;}margin-right: 8px;}.head-edit-cont {display: flex;align-items: center;:deep(.vxe-cell--edit-icon) {border-color: #606266 !important;margin-right: 3px;}}.full-row-cont {text-align: left;}
</style>

selfTableTools.ts

SelfTable组件的依赖工具方法

/*** 遍历表格数据 为 SelfTable数据类型* @param data 表格源数据* @param keys 要放到通行里使用的数据* @param fullRowIndex 通行索引* @param unFullRowIndex 非通行索引*/
export const filterSelfTableData = (data: any[], keys: any[], fullRowIndex: number, unFullRowIndex: number): any[] => {if (keys.length === 0) return [...data, ...data];const arr: any[] = [];data.map((d) => {const d2 = {};keys.map((k) => {d2[k] = d[k];});fullRowIndex && arr.push(d);d2['id'] = d.id;arr.push(d2);unFullRowIndex && arr.push(d);});return arr;
};// 过滤表单列
export const filterSelfTableColumns = (columns) => {return columns.filter((item) => item.ifShow === undefined || item.ifShow() === true);
};// 通行类型 'prev' 前一行 | 'last' 后一行
export type FullRowType = 'prev' | 'last';
export const useFullRowIndex = (type: FullRowType) => {const fullRowIndex = type === 'prev' ? 0 : 1;const unFullRowIndex = type === 'prev' ? 1 : 0;return { fullRowIndex, unFullRowIndex };
};// 除第一列外的普通列
export const sharedOnCell = (index, type: FullRowType) => {// 设置为0时不渲染return { colSpan: index % 2 === useFullRowIndex(type).fullRowIndex ? 0 : 1 };
};/*** 首位列* @param type 通行位置 prev | last* @param columnsNum 要合并的行数,也就是总列数,包括操作,不含序号和选择* @param index 索引*/
export const firstSharedOnCell = (type: FullRowType, columnsNum: number, index) => ({colSpan: index % 2 === useFullRowIndex(type).fullRowIndex ? columnsNum : 1,
});import { TableColumnType } from 'ant-design-vue';
// 表格column类型
export interface SelfTableColumnType extends TableColumnType {slot?: string;fullFirst?: boolean;isEdit?: boolean;ifShow?: () => boolean;
}export function checkColumnsHasExist(arr, key): boolean {return arr.findIndex((item) => item.dataIndex === key) !== -1;
}/*** 全选操作时,将所选数据加入到已选择列表中* @param currentPageData 当前页选中数据* @param checkedData 已选择的数据*/
export function getAllCheckedListData(currentPageData: any[], checkedData: any[]) {const result: any[] = checkedData;currentPageData.forEach((item) => {const index = result.findIndex((c) => c.id === item.id);// 不存在 && 添加index === -1 && result.push(item);});return result;
}interface CheckAllStatus {indeterminateStatus: boolean;checkAllStatus: boolean;
}
/*** 获取半选状态及全选状态* @param checkedList 已选列表* @param currentPageData 当前页数据*/
export function getIndeterminateAndCheckAllStatus(checkedList, currentPageData): CheckAllStatus {// 已选数据为空 或者 当前页数据为空if (!checkedList.length || !currentPageData.length) {return {indeterminateStatus: false,checkAllStatus: false,};}// 筛选当前页面数据未再已选列表的数据const notCheckedData = currentPageData.filter((item) => {const index = checkedList.findIndex((c) => c.id === item.id);return index === -1;});return {indeterminateStatus: notCheckedData.length > 0 && notCheckedData.length < currentPageData.length,checkAllStatus: notCheckedData.length === 0,};
}export const columnColspanFull = (index, fullRowIndex, allColumnNum) => (index % 2 === fullRowIndex ? allColumnNum : 1);export const columnColspanUnFull = (index, unFullRowIndex) => (index % 2 === unFullRowIndex ? 1 : 0);export const indexColumnColspan = (index, fullRowIndex, unFullRowIndex, allColumnNum, hasCheckbox) => {return hasCheckbox ? columnColspanUnFull(index, unFullRowIndex) : columnColspanFull(index, fullRowIndex, allColumnNum);
};

可编辑单元格使用:

页面示例:

在这里插入图片描述

使用示例:

主要依赖的就是组件中的setTableData方法,根据行index,和key去修改表格里面的数据

<SelfTableref="selfTableRef":has-checkbox="true":data-source="dataSource":full-row-type="fullRowType":columns="selfTableColumns(fullRowType)":full-row-key-list="['desc']":is-div="true":all-table-columns-num="16"><template #fileNumberSlot="scope"><div class="slot-cont"><a-input @change="(e) => selfTableRef.setTableData(scope.rowIndex, 'fileNumber', e.target.value)" /></div></template><template #inputSlot="scope"><div class="slot-cont"><a-input @change="(e) => selfTableRef.setTableData(scope.rowIndex, 'inputValue', e.target.value)" /></div></template><template #contractNoSlot="scope"><div class="slot-cont"><a-select style="width: 100%" @change="(value) => selfTableRef.setTableData(scope.rowIndex, 'contractNo', value)"><a-select-option value="jack">Jack</a-select-option><a-select-option value="lucy">Lucy</a-select-option></a-select></div></template><template #full-row="{ row }"> 其他等级: 资源号: 捆绑号:{{ row.id }}</template></SelfTable>

tableColumns方法需要增加isEdit字段,会显示编辑icon

    {title: '件数(件)',dataIndex: 'fileNumber',width: 100,customCell: (_, index) => sharedOnCell(index, fullRowType),slot: 'fileNumberSlot',isEdit: true,},{title: '重量(吨)',dataIndex: 'inputValue',width: 100,customCell: (_, index) => sharedOnCell(index, fullRowType),slot: 'inputSlot',isEdit: true,},

这篇关于基于antdv封装的特殊复杂表格,带通行描述信息、可展示通行的单元格信息、可跨页选择数据功能、分页功能、可编辑单元格功能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/241130

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time