当前位置: 首页 > news >正文

Vue3 + TS + Element-Plus —— 项目系统中封装表格+搜索表单 十分钟写五个UI不在是问题

9a69fede8b2044a79dd834e3e48f20b4.png前期回顾f8e3cc1a0f694ac2b665ca2ad14c49d7.png

纯前端 —— 200行JS代码、实现导出Excel、支持DIY样式,纵横合并-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_57904695/article/details/135537511?spm=1001.2014.3001.5501 

目录

一、🛠️  newTable.vue 封装Table

二、🚩 newForm.vue 封装搜索表单 

三、📝 TS类型 src\types\global.d.ts

四、♻️ 页面使用功能 - 静态 

 五、♻️ 页面使用功能 - 动态 

 六、🤖 仓库地址、演示地址

七、📝 结语 


 

在平时开发中,系统中写的最多的 表格+搜索表单排名No.1,每一次都在Element-Plus中 拷贝一遍 <template> ,显然是个大活,我们将其html封装,每一只写Data数据让其动态渲染,编写速度达达滴!

一、🛠️  newTable.vue 封装Table

<template><div class="container"><div class="container-main"><!-- 表单搜索区域 --><el-scrollbar v-if="isShowSearchRegion" max-height="300px" class="scrollbar-height"><slot name="search"></slot></el-scrollbar><!-- 表格上方搜索向下方按钮区域 --><slot name="btn"></slot><!-- 列表区域 --><el-tableref="multipleTableRef"v-bind="$attrs"stripestyle="width: 100%":data="filterTableData":border="tableBorder":height="tableHeight || excludeSearchAreaAfterTableHeight":row-key="getRowKeys"@selection-change="onSelectionChange"><template #empty><el-empty :image-size="emptyImgSize" description="暂无数据" /></template><el-table-columntype="selection"width="30"v-if="isSelection":reserve-selection="true":selectable="selectableCallback"/><el-table-columntype="index"label="序号"min-width="60":index="orderHandler"align="center"/><el-table-columnv-for="item in tableHeader"v-bind="item":key="item.prop"header-align="center"align="center"><template #header v-if="item.slotKey?.includes('tableHeaderSearch')"><el-inputv-model.trim="search"size="small":placeholder="getSearchInfo.label"/></template><template #default="{ row }" v-if="item.slotKey"><slotv-for="slot in item.slotKey.split(',')":name="slot":row="row"></slot><template v-if="item.slotKey.includes('default')"><el-link type="primary" :underline="false" @click="handleEdit(row)">编辑</el-link><el-popconfirm title="确定删除吗?" @confirm="handleDelete(row.id)"><template #reference><el-link type="danger" :underline="false">删除</el-link></template></el-popconfirm></template></template></el-table-column></el-table><!-- 分页区域--><el-paginationv-if="paginationFlag"background:page-sizes="pageSizesArr":current-page="pageNum":page-size="pageSize":layout="layout":total="total"popper-class="pagination-popper"@size-change="handleSizeChange"@current-change="handleCurrentChange"></el-pagination></div></div>
</template><script setup lang="ts">
import { onMounted, ref, watch, toRaw, nextTick, computed } from 'vue';
import { ElTable } from 'element-plus';
const multipleTableRef = ref<InstanceType<typeof ElTable>>();import myEmits from './newTableConfig/emits';
import myProps from './newTableConfig/props';
const emits = defineEmits(myEmits);
const props = defineProps(myProps);
const search = ref('');// 搜索过滤
const filterTableData = computed(() =>props.tableData?.filter((data) =>!search.value ||String(data[getSearchInfo.value.prop]).toLowerCase().includes(search.value.toLowerCase()))
);
// 计算那列用于展示搜索
const getSearchInfo = computed(() => {let searchInfo = { label: '', prop: '' };props.tableHeader?.find((v) => {if (v.searchFields) {searchInfo = { label: v.label, prop: v.prop };return true;}});return searchInfo;
});// 序号根据数据长度计算
const orderHandler = (index: number) => {const { pageNum, pageSize } = props;// 第0条 * 每页条数 + 当前索引+1return (pageNum - 1) * pageSize + index + 1;
};//  页数改变
const handleSizeChange = (val: number | string) => emits('handleSizeChange', val);
// 当前页改变
const handleCurrentChange = (val: number | string) => emits('handleCurrentChange', val);// 编辑、删除
const handleEdit = (row: object) => emits('handleEdit', row);
const handleDelete = (id: number) => emits('handleDelete', id);
// 复选框
const onSelectionChange = (val: any) => emits('selection-table-change', val);//记录每行的key值
const getRowKeys = (row: any) => row.id;// 根据父组件传递的id字符串,默认选中对应行
const toggleSelection = (rows?: any) => {if (props.isSelection) {if (rows) {rows.forEach((row: any) => {const idsArr = props.selectionIds?.split(',');if (idsArr?.includes(row.id.toString())) {//重要nextTick(() => multipleTableRef.value?.toggleRowSelection(row, true));}});} else {multipleTableRef.value!.clearSelection();}}
};const selectableCallback = (row: any) => {const idsArr = props.selectionIds?.split(',');if (props.isDisableSelection && idsArr?.includes(row.id.toString())) {return false;}return true;
};
watch(() => props.tableData,(newV) => {if (!!props.selectionIds) {// console.log('🤺🤺  selectionIds🚀 ==>:', props.selectionIds);// console.log('🤺🤺  newV ==>:', newV);toggleSelection(toRaw(newV));}}
);// 搜索区域高度及默认值
const Height = ref();
// 减去搜索区域高度后的table,不能有默认值不然会出现滚动条
const excludeSearchAreaAfterTableHeight = ref();// 获取表格高度-动态计算搜索框高度(onMounted、resize,208是已知的面包屑tebView高度)
const updateHeight = () => {let wrapEl = document.querySelector('.scrollbar-height') as HTMLElement | null;if (!wrapEl) return;Height.value = wrapEl.getBoundingClientRect().height;// console.log('🤺🤺  🚀 ==>:', wrapEl.getBoundingClientRect());if (props.isShowSearchRegion) {excludeSearchAreaAfterTableHeight.value = `calc(100vh - ${200 + Height.value}px)`;}
};onMounted(() => {// 表格下拉动画const tableContainer = <HTMLElement>document.querySelector('.container');setTimeout(() => {if (tableContainer) tableContainer.style.transform = 'translateY(0)';updateHeight();}, 800);
});window.addEventListener('resize', updateHeight);
defineExpose({toggleSelection,
});
</script><style scoped lang="scss">
.container {overflow: hidden;width: 100%;height: 100%;padding: 15px;transform: translateY(-100%);transition: transform 0.4s ease-in-out;background-color: #f8f8f8;// background-color: #870404;&-main {overflow: hidden;position: relative;padding: 15px;width: 100%;// height: 100%; el-scrollbar有默认高度100%,当页面列表渲前会继承这里高度,导致搜索区域铺满全屏background-color: #fff;border: 1px solid #e6e6e6;border-radius: 5px;&:hover {box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.1);}transition: box-shadow 0.3s ease-in-out;.scrollbar-height {min-height: 100px;}.el-pagination {display: flex;align-items: center;justify-content: center;margin-top: 20px;}}
}
// 穿透父组件
:deep(.el-link) {padding-left: 10px;
}
</style>

二、🚩 newForm.vue 封装搜索表单 

<template><el-form ref="searchFormRef" :model="searchForm" size="default"><!-- 使用了不稳定的 key,可能会导致一些不可预期的行为,比如输入框失去焦点。 --><el-row><el-col:xs="24":sm="24":md="24":lg="12":xl="6"v-for="item in formOptions":key="item.vm"><el-form-item :label="item.props.label" :prop="item.vm"><el-inputv-if="item.type === FormOptionsType.INPUT"v-model.lazy.trim="searchForm[item.vm]"v-bind="item.props"class="ml10 w100"></el-input><el-selectv-if="item.type === FormOptionsType.SELECT"v-model.lazy="searchForm[item.vm]"v-bind="item.props"class="ml10 w100"fit-input-width><el-optionv-for="option in item.selectOptions":key="option.value":label="option.label":value="option.value"><zw-tooltip-omit :content="option.label"></zw-tooltip-omit></el-option></el-select><el-cascaderv-if="item.type === FormOptionsType.CASCADER"v-model.lazy="searchForm[item.vm]":options="item.cascaderOptions"v-bind="item.props"class="ml10 w100"/><el-date-pickerv-if="item.type === FormOptionsType.DATE_PICKER"v-model.lazy="searchForm[item.vm]"v-bind="item.props"class="ml10 w100"/></el-form-item></el-col><el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="6" class="xs-mt"><el-form-item style="margin-left: 10px"><el-button @click="onSearch('reset')"><SvgIcon name="ant-ReloadOutlined"></SvgIcon>重置</el-button><el-button type="primary" @click="onSearch()"><SvgIcon name="ant-SearchOutlined"></SvgIcon>查询</el-button></el-form-item></el-col></el-row></el-form>
</template><script setup lang="ts" name="newForm">
import { toRefs, onBeforeUnmount, ref } from 'vue';
import type { PropType } from 'vue';
import { type FormInstance } from 'element-plus';
import { debounce } from '/@/utils/debounce';
const searchFormRef = ref<FormInstance>();enum FormOptionsType {INPUT = 'input', // 输入框SELECT = 'select', // 下拉框CASCADER = 'cascader', // 级联选择器DATE_PICKER = 'date-picker', // 日期选择器
}const props = defineProps({formOptions: {type: Array as PropType<FormOptions[]>,required: true,},searchForm: {type: Object as PropType<SearchFormType>,required: true,},
});
const { formOptions, searchForm } = toRefs(props);const emit = defineEmits(['search']);
const debouncedEmitSearch = debounce((type) => emit('search', type));
const onSearch = (type: string) => {if (type) searchFormRef.value?.resetFields();debouncedEmitSearch(type);
};onBeforeUnmount(() => searchFormRef.value?.resetFields());
defineExpose({ searchFormRef });
</script><style scoped lang="scss">
:deep(.el-form-item__label) {margin-left: 10px;
}
</style><style scoped lang="scss">
:deep(.el-form-item__label) {margin-left: 10px;
}
</style>

三、📝 TS类型 src\types\global.d.ts


// new-table
//表头数据类型定义
declare interface TableHeader<T = any> {label: string;prop: string;align?: string;overHidden?: boolean;minWidth?: string;sortable?: boolean;type?: string;fixed?: string;width?: string | number;// isActionColumn?: boolean; // 是否是操作列// isCustomizeColumn?: boolean; // 是否是自定义列slotKey?: string; // 自定义列的插槽名称searchFields?: boolean; // 是否是搜索字段
}/*newForm允许任何字符串作为索引不然会报错, 使用动态属性名,需要使用索引签名
*/
declare type SearchFormType = {[key: string]: string;
};declare type FormOptions = {type: string;props: {label: string;placeholder: string;type: string;clearable: boolean;};vm: string;selectOptions?: {value: string | number;label: string;}[];cascaderOptions?: any;
};

四、♻️ 页面使用功能 - 静态 

<template><new-table:tableHeader="tableHeader":tableData="tableData":total="100"@handleSizeChange="onHandleSizeChange"@handleCurrentChange="onHandleCurrentChange"@handleDelete="onHandleDelete"@handleEdit="onHandleEdit"><template #search><el-row><el-col:xs="24":sm="24":md="24":lg="12":xl="6"v-for="item in Math.ceil(Math.random() * 10)":key="item"class="scrollbar-demo-item">56546</el-col><el-col :xs="24" :sm="24" :md="24" :lg="12" :xl="6" class="xs-mt"><el-form-item><el-button> 重置 </el-button><el-button type="primary"> 查询 </el-button></el-form-item></el-col></el-row></template><template #switch="slotProps"><el-switchv-model="slotProps.row.status"active-text="开"inactive-text="关"active-color="#13ce66"inactive-color="#ff4949"@change="changeSwitchStatus(slotProps.row.id, slotProps.row.status)"/></template></new-table>
</template><script setup lang="ts" name="algorithmRegistrationQuery">
import { reactive, toRefs } from "vue";
const state = reactive({//表头数据tableHeader: <TableHeader[]>[{ label: "姓名", prop: "uname", width: "100px" },{ label: "年龄", prop: "age", slotKey: "switch" },{ label: "性别", prop: "sex" },{ label: "操作", width: "240px", fixed: "right", slotKey: "default" },],//表数据,从接口获取tableData: [{ uname: "小帅", age: "18", sex: "男", status: false, id: 1 },{ uname: "小美", age: "148", sex: "女", status: false, id: 2 },{ uname: "小明", age: "12", sex: "男", status: true, id: 3 },{ uname: "小红", age: "12", sex: "女", status: false, id: 4 },{ uname: "小黑", age: "12", sex: "男", status: true, id: 5 },{ uname: "小白", age: "12", sex: "女", status: false, id: 6 },{ uname: "小黑", age: "12", sex: "男", status: true, id: 7 },{ uname: "小白", age: "12", sex: "女", status: false, id: 8 },{ uname: "小黑", age: "12", sex: "男", status: true, id: 9 },{ uname: "小白", age: "12", sex: "女", status: false, id: 10 },{ uname: "小黑", age: "12", sex: "男", status: true, id: 11 },],
});
const { tableHeader, tableData } = toRefs(state);// 修改
const onHandleEdit = (row: object) => {console.log(row);
};// 删除
const onHandleDelete = (row: object) => {console.log(row);
};// switch
const changeSwitchStatus = (id: number, status: boolean) => {console.log(id, status);
};//分页改变
const onHandleSizeChange = (val: number) => {console.log("!这里输出 🚀 ==>:", val);
};
//分页改变
const onHandleCurrentChange = (val: number) => {console.log("!这里输出 🚀 ==>:", val);
};// //页容量改变
// const onHandleSizeChange = (val: number) => {
// 	// console.log('页容量 ==>:', val);
// 	pageSize.value = val;
// 	getTableList(pageNum.value, pageSize.value, tableId.value);
// };
// //当前分页改变
// const onHandleCurrentChange = (val: number) => {
// 	// console.log('当前页 🚀 ==>:', val);
// 	pageNum.value = val;
// 	getTableList(pageNum.value, pageSize.value, tableId.value);
// };
</script><style lang="scss" scoped>
.scrollbar-demo-item {display: flex;align-items: center;justify-content: center;height: 50px;margin: 10px;text-align: center;border-radius: 4px;background: var(--el-color-primary-light-9);color: var(--el-color-primary);
}
.xs-mt {display: flex;align-items: flex-end;
}
</style>

 五、♻️ 页面使用功能 - 动态 

<template><div class="container-wrapper"><!-- 动态 page --><new-tablev-bind="state":total="pageTotal"@handleSizeChange="onHandleSizeChange"@handleCurrentChange="onHandleCurrentChange"@handleEdit="onHandleEdit"@handleDelete="onHandleDelete"><template #search><new-form:formOptions="formOptions":searchForm="searchForm"					@search="onSearch"/></template><template #btn><el-button type="primary" size="default" class="btn-add"><SvgIcon name="ant-PlusOutlined"></SvgIcon>新建题目</el-button></template><template #switch="{ row }"><el-switchv-model="row.fileStatus"active-text="开"inactive-text="关":active-value="1":inactive-value="2"active-color="#13ce66"inactive-color="#ff4949"@change="changeSwitchStatus(row.id, row.fileStatus)"/></template></new-table></div>
</template><script setup lang="ts" name="algorithmRegistrationQuery">
import { onMounted, reactive, toRefs } from 'vue';
import { getTestList } from '/@/api/encryptionAlgorithm/templateDefinition';
import { STATUS_CODE } from '/@/enum/global';
const state = reactive({//表头数据// el-table-column有的属性都可以在这传/* searchFields:true 搜索字段slotKey: 'xxx' 自定义插槽 包含tableHeaderSearch则展示表格搜索框。包含default则展示 编辑删除其他值可以在父组件中使用插槽 template自定义内容#search 表单搜索#btn 列表上方的按钮*/tableHeader: <TableHeader[]>[{ label: '合规规则', prop: 'knowledgeName', searchFields: true },{ label: '文件数量', prop: 'documentNumber', width: '200px' },{ label: '文件状态', prop: 'fileStatus', slotKey: 'switch' },{ label: '操作', fixed: 'right', slotKey: 'default,tableHeaderSearch' , width: 200 },],//表项数据tableData: [],formOptions: <FormOptions[]>[{type: 'input',props: {label: '合规规则',placeholder: '请输入合规规则',type: 'text',clearable: true,},vm: 'knowledgeName',},{type: 'input',props: {label: '文件数量',placeholder: '请输入文件数量',type: 'text',clearable: true,},vm: 'documentNumber',},// 下拉选择器{type: 'select',props: {label: '所属部门',placeholder: '请选择',clearable: true,},vm: 'department',selectOptions: [{label: '数据安全',value: 1,},{label: '研发',value: 2,},{label: '事业',value: 3,},],},// 时间范围选择器{type: 'date-picker',props: {label: '时间范围',type: 'datetimerange', // datetimerange范围 datetime日期clearable: true,'range-separator': '-','start-placeholder': '开始日期','end-placeholder': '结束日期','value-format': 'YYYY-MM-DD HH:mm:ss',},vm: 'createTime',},// 级联选择器{type: 'cascader',props: {label: '所属部门',placeholder: '请选择',clearable: true,},vm: 'cascader',cascaderOptions: [{value: 'guide',label: 'Guide',children: [{value: 'disciplines',label: 'Disciplines',children: [{value: 'consistency',label: 'Consistency',},],},{value: 'navigation',label: 'Navigation',children: [{value: 'side nav',label: 'Side Navigation',},{value: 'top nav',label: 'Top Navigation',},],},],},{value: 'component',label: 'Component',children: [{value: 'basic',label: 'Basic',children: [{value: 'button',label: 'Button',},],},{value: 'form',label: 'Form',children: [{value: 'radio',label: 'Radio',},{value: 'checkbox',label: 'Checkbox',},],},{value: 'data',label: 'Data',children: [{value: 'table',label: 'Table',},],},{value: 'notice',label: 'Notice',children: [{value: 'alert',label: 'Alert',},],},{value: 'navigation',label: 'Navigation',children: [{value: 'menu',label: 'Menu',},],},{value: 'others',label: 'Others',children: [{value: 'dialog',label: 'Dialog',},],},],},{value: 'resource',label: 'Resource',children: [{value: 'axure',label: 'Axure Components',},],},],},],//这里允许动态属性所以可为空searchForm: <SearchFormType>{},pageNum: 1,pageSize: 10,pageTotal: 0,tableHeight: 'calc(100vh - 375px)', //如果开启#btn占位符需要手动设置表格高度
});
const { tableData, formOptions, searchForm, pageNum, pageSize, pageTotal } = toRefs(state);// 修改
const onHandleEdit = (row: object) => {console.log(row);
};// 删除
const onHandleDelete = (row: object) => {console.log(row);
};// switch
const changeSwitchStatus = (id: number, status: boolean) => {console.log(id, status);
};//页容量改变
const onHandleSizeChange = (val: number) => {// console.log('页容量 ==>:', val);pageSize.value = val;getTableList(pageNum.value, pageSize.value);
};
//当前分页改变
const onHandleCurrentChange = (val: number) => {// console.log('当前页 🚀 ==>:', val);pageNum.value = val;getTableList(pageNum.value, pageSize.value);
};// 获取表项数据
const getTableList = (pageNum: number, pageSize: number) => {// 处理searchForm.value createTime// if (searchForm.value.createTime) {// 	searchForm.value.startTime = searchForm.value.createTime[0];// 	searchForm.value.createTimeEnd = searchForm.value.createTime[1];// 	// delete searchForm.value.createTime;// }getTestList({pageNum,pageSize,...searchForm.value,}).then((res) => {if (res.code !== STATUS_CODE.SUCCESS) return;const { list, total } = res.data;tableData.value = list;// console.log('🤺🤺 表项 🚀 ==>:', list);pageTotal.value = total;});
};const onSearch = (isReset?: string) => {pageNum.value = isReset ? 1 : pageNum.value;getTableList(pageNum.value, pageSize.value);
};onMounted(() => getTableList(pageNum.value, pageSize.value));
</script><style scoped lang="scss">
.btn-add {float: right;margin-bottom: 20px;
}
</style>

 六、🤖 仓库地址、演示地址

仓库地址:

Vite + Ts + Vue3 - template -- 模板: 🎉🎉🔥 Vite + Vue3 + Ts + router + Vuex + axios + eslint 、prettier、stylelint、husky、gitCommit --- 集成多种组件、Hooks支持开封即用,严格的代码质量检验、祝您轻松上大分😷🤺🤺🤺 【动态路由、特效、N个组件、N个自定义指令...】 (gitee.com)

在线演示:

Vite + Vue + TS (gitee.io)

  

七、📝 结语 

封装其他组件在其余博文中也有详细描写,快来抱走把!

7730e2bd39d64179909767e1967da702.jpeg

 _______________________________  期待再见  _______________________________

相关文章:

Vue3 + TS + Element-Plus —— 项目系统中封装表格+搜索表单 十分钟写五个UI不在是问题

前期回顾 纯前端 —— 200行JS代码、实现导出Excel、支持DIY样式&#xff0c;纵横合并-CSDN博客https://blog.csdn.net/m0_57904695/article/details/135537511?spm1001.2014.3001.5501 目录 一、&#x1f6e0;️ newTable.vue 封装Table 二、&#x1f6a9; newForm.vue …...

Linux系统——测试端口连通性方法

目录 一、TCP端口连通性测试 1、ssh 2、telnet&#xff08;可能需要安装&#xff09; 3、curl 4、tcping&#xff08;需要安装&#xff09; 5、nc&#xff08;需要安装&#xff09; 6、nmap&#xff08;需要安装&#xff09; 二、UDP端口连通性测试 1、nc&#xff08;…...

Python虚拟环境轻松配置:Jupyter Notebook中的内核管理指南

问题 在Python开发中&#xff0c;一些人在服务器上使用Jupyter Notebook中进行开发。一般是创建虚拟环境后&#xff0c;向Jupyter notebook中添加虚拟环境中的Kernel&#xff0c;后续新建Notebook中在该Kernel中进行开发&#xff0c;这里记录一下如何创建Python虚拟环境以及添…...

大数据-hive函数与mysql函数的辨析及练习-将多行聚合成一行

目录 1. &#x1f959;collect_list: 聚合-不去重 2. &#x1f959;collect_set(col): 聚合-去重 3. &#x1f959;mysql的聚合函数-group_concat 4. leetcode练习题 1. &#x1f959;collect_list: 聚合-不去重 将组内的元素收集成数组 不会去重 2. &#x1f959;collec…...

【AI视野·今日NLP 自然语言处理论文速览 第七十三期】Tue, 9 Jan 2024

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 9 Jan 2024 Totally 80 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers FFSplit: Split Feed-Forward Network For Optimizing Accuracy-Efficiency Trade-off in Language Model Infe…...

vue知识-03

购物车案例 要实现的功能&#xff1a; 1、计算商品总价格 2、全选框和取消全选框 3、商品数量的增加和减少 <body> <div id"app"><div class"row"><div class"col-md-6 col-md-offset-3"><h1 class"text-center…...

关于httpClient 使用的注意事项

关于httpClient 使用的注意事项 用例 PoolingHttpClientConnectionManager connectionManager new PoolingHttpClientConnectionManager();// 最大连接数-不设置默认20connectionManager.setMaxTotal(200);// 每个路由最大连接数-不设置默认2connectionManager.setDefaultMax…...

Docker 发布自定义镜像到公共仓库

Docker 发布自定义镜像到公共仓库 引言 Docker 是一种轻量级、便携式的容器化技术&#xff0c;可以使应用程序在不同环境中更加可移植。在本文中&#xff0c;我们将学习如何使用 Docker 从公共仓库拉取 Nginx 镜像&#xff0c;定制该镜像&#xff0c;添加自定义配置文件&…...

程序员有哪些接单的渠道?

这题我会&#xff01;程序员接单的渠道那可太多了&#xff0c;想要接到合适的单子&#xff0c;筛选一个合适的平台很重要。如果你也在寻找一个合适的接单渠道&#xff0c;可以参考以下这些方向。 首先&#xff0c;程序员要对接单有一个基本的概念&#xff1a;接单渠道可以先粗略…...

服务容错-熔断策略之断路器hystrix-go

文章目录 概要一、服务熔断二、断路器模式三、hystrix-go3.1、使用3.2、源码 四、参考 概要 微服务先行者Martin Fowler与James Lewis在文章microservices中指出了微服务的九大特征&#xff0c;其中一个便是容错性设计(Design for failure)。正如文章中提到的&#xff0c;微服…...

C++进阶(三)多态

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、多态的概念1、概念 二、多态的定义及实现1、多态的构成条件2、虚函数3、虚函数的重写4、C…...

大众汽车宣布将ChatGPT,批量集成在多种汽车中!

1月9日&#xff0c;大众汽车在官网宣布&#xff0c;将ChatGPT批量集成到电动、内燃机汽车中。 大众表示&#xff0c;将ChatGPT与其IDA语音助手相结合&#xff0c;用户通过自然语言就能与ChatGPT进行互动&#xff0c;例如&#xff0c;帮我看看最近的三星米其林饭店在哪里&#…...

React----函数组件和类组件

函数组件与类组件&#xff1a;React 中的两种组件风格 React 是一个用于构建用户界面的流行 JavaScript 库&#xff0c;其中组件是构建块的基本单元。在 React 中&#xff0c;有两种主要的组件风格&#xff1a;函数组件和类组件。本文将使用TypeScript介绍它们的用法、区别以及…...

Kafka集群部署 (KRaft模式集群)

KRaft 模式是 Kafka 在 3.0 版本中引入的新模式。KRaft 模式使用了 Raft 共识算法来管理 Kafka 集群元数据。Raft 算法是一种分布式共识算法&#xff0c;具有高可用性、可扩展性和安全性等优势。 在 KRaft 模式下&#xff0c;Kafka 集群中的每个 Broker 都具有和 Zookeeper 类…...

Vue 自定义仿word表单录入之日期输入组件

因项目需要&#xff0c;要实现仿word方式录入数据&#xff0c;要实现鼠标经过时才显示编辑组件&#xff0c;预览及离开后则显示具体的文字。 鼠标经过时显示 正常显示及离开时显示 组件代码 <template ><div class"paper-input flex flex-col border-box "…...

Oracle与Java JDBC数据类型对照

Oracle Database JDBC开发人员指南和参考 SQL Data TypesJDBC Type CodesStandard Java TypesOracle Extension Java Types CHAR java.sql.Types.CHAR java.lang.String oracle.sql.CHAR VARCHAR2 java.sql.Types.VARCHAR java.lang.String oracle.sql.CHAR LONG jav…...

C++力扣题目226--翻转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例 3&#x…...

Gorm 数据库表迁移与表模型定义

文章目录 一、Docker快速创建MySQL实例1.1 创建1.3 创建数据库 二、AutoMigrate介绍与使用2.1 AutoMigrate介绍2.2 AutoMigrate 基本使用 三、模型定义3.1 模型定义3.2 快速增删改查3.3 约定3.4 gorm.Model 四、表模型主键、表名、列名的约定4.1 主键&#xff08;Primary Key&a…...

系列三、Spring Security中自定义用户名/密码

一、Spring Security中自定义用户名/密码 1.1、自定义用户名/密码 1.1.1、配置文件中配置 spring.security.user.nameroot spring.security.user.password123456 1.1.2、定义基于内存的用户 /*** Author : 一叶浮萍归大海* Date: 2024/1/11 21:50* Description:*/ Configu…...

如何顺滑使用华为云编译构建平台?

这两年平台构建服务需求越来越大&#xff0c;却一直苦于找不到一些指南&#xff0c; 这里特意写了一篇&#xff0c; 对在学习代码阶段和新手程序员朋友也蛮友好&#xff0c; 配置真的也不难&#xff0c; 也特别适合想尝试从0到1做个APP的朋友了。 以华为云的CodeArts Build为例…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...