模仿ProTable创建ProTable组件

不多说废话直接上代码
父组件

// index.jsx/*** @description 此ProTable是根据ProComponents里的ProTable模仿封装的简易版本* */
import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useState } from 'react'
import { Card, Table } from 'antd'
import dayjs from 'dayjs'
import { connect } from 'dva'
import { cloneDeep } from 'lodash-es'import './index.less'
import SearchForm from './components/SearchForm'/*** 默认分页选择* */
const defaultTableProps = {pageSizeOptions: ['10', '20', '50', '100'], // 指定每页展示多少条bordered: true,
}let isFirstRequest = true/*** @description Table结合搜索封装组件** @function SearchForm* @param {object} props 父组件传参* @param {array} props.columns 列表&搜索类型参数集合* @param {string | null} props.size 表格大小* @default small* @param {array | null} props.pageSizeOptions 分页每页选择条数* @param {boolean} props.search 是否展示搜索* @param {array} props.optionsButton 操作按钮* @param {function} props.request 列表请求* @param {boolean} props.bordered 列表是否有边框* @param {ReactNode} props.middleDOM* @param {object} props.initialValues Form默认参数* @param {function | null} props.handlePrecedenceFatherLaterChildren 用于父组件执行结束之后再执行当前组件函数* @param {object | null} props.proTable 状态存储搜索参数* */
const ProTable = forwardRef((props, ref) => {const {columns = [],tableKey = 'code',size = 'small',pageSizeOptions = defaultTableProps.pageSizeOptions,bordered = defaultTableProps.bordered,search = true,optionsButton = [],middleDOM,initialValues,request,handlePrecedenceFatherLaterChildren,proTable,dispatch,rowSelection,loading,scroll,} = propsconst [current, setCurrent] = useState(1)const [pageSize, setPageSize] = useState(20)const [total, setTotal] = useState(0)const [dataSource, setDataSource] = useState([])const [searchValues, setSearchValues] = useState({})const [tableColumns, setTableColumns] = useState([])const [tableLoading, setTableLoading] = useState(false)const tableProps = {showQuickJumper: true,showSizeChanger: true,total,current,pageSize,onShowSizeChange: (page, size) => {setCurrent(page)setPageSize(size)},showTotal: totals => `共${totals}条记录`,onChange: (page, size) => {setCurrent(page)setPageSize(size)},}useEffect(() => {isFirstRequest = falseconst list = cloneDeep(columns)?.filter(item => !item?.hideInTable)?.map(item => {return { ...item, width: item?.width ?? getTextWidth(item?.title) + 20 }})setTableColumns(() => [...list])// 结构状态参数,并判断是否需要保存数据let { key, values } = proTableif (key !== location.pathname) {values = {}setSearchValues({})} else {setSearchValues(val => {return { ...val, ...values }})}// 放入异步队列,让执行顺序小于父组件if (handlePrecedenceFatherLaterChildren) {handlePrecedenceFatherLaterChildren().then(async () => {await handleSearch({ ...initialValues, ...values })})} else {handleSearch({ ...initialValues, ...values }).then()}}, [])useEffect(() => {const {proTable: { values },} = propsif ((current !== values.current && values.current > 0) ||(pageSize !== values.pageSize && values.pageSize > 0)) {isFirstRequest = truehandleSearch({ ...initialValues, ...searchValues }).then(res => res)}}, [current, pageSize])// 此方法 实际计算出来结果 会比手动计算大8px左右const getTextWidth = (text, font = '14px Microsoft YaHei') => {const canvas = document.createElement('canvas')let context = canvas.getContext('2d')context.font = fontlet textmetrics = context.measureText(`${text}:`)return textmetrics.width}// 遍历查询转换时间格式化const handleMapSearchTime = values => {for (let key in values) {if (key?.indexOf(',') > 0 && key?.indexOf('.') < 0) {// 判断某个参数是否传入默认format,如果没传默认为 YYYY-MM-DDlet format =initialValues && initialValues[`${key}.format`]? initialValues[`${key}.format`]: 'YYYY-MM-DD'// 格式化搜索参数let paramsList = key.split(',')if (paramsList?.length > 0 && values[key]?.length > 0) {values = {...values,[paramsList[0]]: dayjs(values[key][0]).format(format),[paramsList[1]]: dayjs(values[key][1]).format(format),}delete values[key]}}}return values}// 列表搜索const handleSearch = useCallback(async ({ current: searchCurrent, pageSize: searchPageSize, ...values }) => {if (loading.global || values?.isSearch || isFirstRequest) {delete values.isSearchsetTableLoading(true)}try {setSearchValues(val => ({ ...values }))if (searchCurrent || searchPageSize) {setCurrent(searchCurrent)setPageSize(searchPageSize)}dispatch({type: 'proTable/setSearchFormValues',payload: {key: location.pathname,values: {current: searchCurrent ?? current,pageSize: searchPageSize ?? pageSize,...values,},},})const resValues = handleMapSearchTime(values)const res = await request({current: searchCurrent ?? current,pageSize: searchPageSize ?? pageSize,values: resValues,})const { total: resTotal = 0, dataSource: resDataSource = [] } = ressetTotal(resTotal)setDataSource(() => [...resDataSource])} catch (e) {console.error('获取列表错误:', e)} finally {setTableLoading(false)}},[current, pageSize, searchValues])// 暴漏子组件参数useImperativeHandle(ref, () => ({handleSearch,}))// DOMreturn (<div className='pro-table'>{search && (<Card><SearchForm handleSearch={handleSearch} {...props} /></Card>)}<div>{middleDOM}</div><CardclassName='table-card'extra={optionsButton?.length > 0 ? optionsButton?.map(item => item) : ''}><Tableloading={tableLoading}columns={tableColumns}rowKey={tableKey}dataSource={dataSource}pagination={{ ...tableProps, pageSizeOptions }}size={size}bordered={bordered}sticky={true}rowSelection={rowSelection}scroll={scroll}className='table'/></Card></div>)
})// 由于ref被Hoc高阶组件{connect}隔离了
// 所以我们需要使用函数进行包裹
function wrap(Component) {const ForwardRefComp = props => {const { forwardedRef, ...rest } = propsreturn <Component ref={forwardedRef} {...rest} />}const StateComp = connect(state => state)(ForwardRefComp)return forwardRef((props, ref) => <StateComp {...props} forwardedRef={ref} />)
}export default wrap(ProTable)

子组件

/*** @description 此ProTable是根据ProComponents里的ProTable模仿封装的简易版本,搜索组件* */
import React, { useEffect, useState } from 'react'
import { Button, Col, DatePicker, Form, Input, Row, Select, Space } from 'antd'
import { DownOutlined } from '@ant-design/icons'
import dayjs from 'dayjs'
import { cloneDeep } from 'lodash-es'import '../index.less'/*** form表单默认参数* */
const defaultFormProps = {labelAlign: 'left',colon: true,buttonProps: {searchDisabled: false,resetDisabled: false,searchButtonText: '查询',searchResetText: '重置',},
}// 日期解析
const { RangePicker } = DatePicker// 默认布局
const rowCols = { xl: 8, lg: 8, md: 12, sm: 24 }// 时间选择快捷键
const defaultPresets = [{ label: '今天', value: [dayjs(), dayjs()] },{ label: '昨天', value: [dayjs().subtract(1, 'day'), dayjs().subtract(1, 'day')] },{ label: '本周', value: [dayjs().startOf('week'), dayjs()] },{label: '上周',value: [dayjs().subtract(1, 'week').startOf('week'),dayjs().subtract(1, 'week').endOf('week'),],},{ label: '本月', value: [dayjs().startOf('month'), dayjs()] },{label: '上月',value: [dayjs().subtract(1, 'month').startOf('month'),dayjs().subtract(1, 'month').endOf('month'),],},{ label: '今年', value: [dayjs().startOf('year'), dayjs()] },{label: '去年',value: [dayjs().subtract(1, 'year').startOf('year'),dayjs().subtract(1, 'year').endOf('year'),],},
]/*** @description 搜索组件** @function SearchForm* @param {object} props 父组件传参* @param {array} props.columns 列表&搜索类型参数集合* @param {object | null} props.buttonAuth Form操作按钮规则按钮* @param {function} props.handleSearch 搜索* @param {function} props.dispatch dva 状态管理* @param {object | null} props.initialValues Form初始化参数* @param {string} props.labelAlign 搜索默认布局* @param {object | null} props.proTable 状态存储搜索参数* */
const SearchForm = props => {const {columns = [],handleSearch,labelAlign = defaultFormProps.labelAlign,colon = defaultFormProps.colon,initialValues,pageSizeOptions,buttonProps: fatherButtonProps = defaultFormProps.buttonProps,proTable,} = propsconst buttonProps = { ...defaultFormProps.buttonProps, ...fatherButtonProps }const [form] = Form.useForm() // 初始化搜索实例const [expand, setExpand] = useState(false)const [puckOrOpen, setPuckOrOpen] = useState('展开')const [formList, setFormList] = useState([])useEffect(() => {const { key, values } = proTableif (key !== location?.pathname) {form.setFieldsValue({ ...initialValues })} else {form.setFieldsValue({ ...values })}}, [])// 根据columns更新列表useEffect(() => {if (columns?.length > 0) {getFormItemLabelWidth()}}, [columns])// 计算字体长度,返回最大宽度const getFormItemLabelWidth = () => {// sm 屏幕 ≥ 576px// md 屏幕 ≥ 768px// lg	屏幕 ≥ 992px// xl	屏幕 ≥ 1200pxlet cols = 1if (window.innerWidth >= 1200) {cols = 3} else if (window.innerWidth >= 992) {cols = 3} else if (window.innerWidth >= 768) {cols = 2}// 处理columnslet columnsFilter = cloneDeep(columns).filter(({ hideInSearch = false }) => !hideInSearch)// 处理每行列数const groupedColumns = new Array(cols).fill(null).map(() => [])// 处理每行columnsFilter?.forEach((item, index) => {const columnIndex = index % colsgroupedColumns[columnIndex].push(item)})// 处理每列const maxColumnWidths = groupedColumns.map(column => {return column.reduce((maxWidth, item) => {const label = item?.searchTitle ?? item?.titlereturn label ? Math.max(maxWidth, getTextWidth(label)) : maxWidth}, 0)})// 处理每列标签宽度const resColumns = columnsFilter?.map((item, index) => {const columnIndex = index % colsitem.width = `${maxColumnWidths[columnIndex]}px`return { ...item, width: `${maxColumnWidths[columnIndex]}px` }})setFormList(() => [...resColumns])}// 此方法 实际计算出来结果 会比手动计算大8px左右const getTextWidth = (text, font = '14px Microsoft YaHei') => {const canvas = document.createElement('canvas')let context = canvas.getContext('2d')context.font = fontlet textmetrics = context.measureText(`${text}:`)return textmetrics.width}/*** 组件类型* @param {object} params 仅需要搜索组件参数* @param {string} params.searchType 搜索组件类型 - Input|Select|* @param {array} params.options 搜索参数数组展示* @param {string} params.placeholder 占位符* @param {string} params.title 名称* @param {string} params.searchTitle 指定搜索名称* @param {string} params.mode 搜索多选模式* @param {string} params.picker 日期选择模式* @param {object} params.DatePickerOptions 日期时间参数* @param {array} params.RangePickerOptions 日期区间默认时间* @param {object} params.presets 快捷键设置* @param {string} params.searchIndex 搜索参数* @param {string} params.dataIndex 搜索&table参数* @param {object} params.selectOptions 选择框参数* @param {string} params.relevanceIndex 日期关联参数,用于日期限制* @param {string} params.relevanceTitle 日期关联名称,用于选择提示* */const componentsFormItem = params => {const {searchType,placeholder,searchTitle,title,selectOptions,picker,rangePickerOptions,datePickerOptions,presets = defaultPresets,renderExtraFooterText,searchIndex,dataIndex,timeRangeDay = 31,} = paramsswitch (searchType) {case 'Select':return (<Select{...selectOptions}mode={selectOptions?.mode ?? ''}allowClearkey='value'options={selectOptions?.options? selectOptions.options?.map(item => ({value: item[selectOptions?.props?.value ?? 'value'],label: item[selectOptions?.props?.label ?? 'desc'],})): []}onChange={selectOptions?.onChange}placeholder={placeholder ?? `请选择${searchTitle ?? title}`}style={{ width: '100%' }}/>)case 'DatePicker':return (<DatePicker{...datePickerOptions}picker={picker}placeholder={placeholder ?? `请选择${searchTitle ?? title}`}style={{ width: '100%' }}/>)case 'RangePicker':return (<RangePicker{...rangePickerOptions}renderExtraFooter={() =>renderExtraFooterText ?? (<div style={{ color: 'red' }}>注:最长可选择时间范围 {timeRangeDay} 天</div>)}presets={presets}picker={picker}disabledDate={timeRangeDay? current =>handleDisabledDateRangePicker(current, searchIndex ?? dataIndex, timeRangeDay): null}onChange={val => handleRangePickerChange(val, searchIndex ?? dataIndex)}onCalendarChange={val => handleOnCalendarChange(val, searchIndex ?? dataIndex)}onOpenChange={open => handleOnOpenChange(open, searchIndex ?? dataIndex)}placeholder={placeholder ?? ['开始时间', '结束时间']}style={{ width: '100%' }}/>)default:return (<InputallowClearplaceholder={placeholder ?? `请输入${searchTitle ?? title}`}style={{ width: '100%' }}/>)}}/*** 日期组件打开时操作* @function handleOnOpenChange* @param {boolean} open 是否打开了参数* @param {string | T | any} searchIndex 搜索参数* */const handleOnOpenChange = (open, searchIndex) => {if (open) {setTimeout(() => {form.setFieldsValue({ [`${searchIndex}`]: [null, null] })})} else {const date = form.getFieldValue(searchIndex)if ((!date || !date[0] || !date[1]) && initialValues && initialValues[`${searchIndex}`]) {form.setFieldsValue({ [`${searchIndex}`]: [...initialValues[`${searchIndex}`]] })}}}/*** 待选日期发生变化时回调* @function handleOnCalendarChange* @param {array[dayjs]} values 时间选择参数* @param {string | T | any} searchIndex 搜索参数* */const handleOnCalendarChange = (values, searchIndex) => {form.setFieldValue(searchIndex, values)}/*** 时间区间选择设置关联参数,返回可选择范围* @function handleDisabledDateRangePicker* @param {dayjs | any} current 时间* @param {string | T | any} searchIndex 搜索参数* @param {number} timeRangeDay 禁用范围天数* */const handleDisabledDateRangePicker = (current, searchIndex, timeRangeDay) => {if (!form.getFieldValue(searchIndex) || !form.getFieldValue(searchIndex)[0]) {return current && current > dayjs().endOf('day')}let tooLate =form.getFieldValue(searchIndex)[0] &&current?.diff(form.getFieldValue(searchIndex)[0], 'days') >= timeRangeDaylet tooEarly =form.getFieldValue(searchIndex)[1] &&form.getFieldValue(searchIndex)[1].diff(current, 'days') >= timeRangeDayreturn !!tooEarly || !!tooLate || (current && current > dayjs().endOf('day'))}/*** 时间选择格式化输出* @function handleRangePickerChange* @param {array} values 时间框输出时间* @param {string | T | any} searchIndex 输出搜索参数// * @param {string} format 日期格式化 , format = 'YYYY-MM-DD'* */const handleRangePickerChange = (values, searchIndex) => {form.setFieldValue(searchIndex, values)}// FormItem子组件内容展示const renderFormItemChildren = () => {return (<>{formList?.map(item => {const { renderFormItem, title, searchTitle, dataIndex, searchIndex, width } = itemif (renderFormItem) {return (<Col {...rowCols} key={searchIndex ?? dataIndex} style={{ marginTop: 10 }}><Form.Itemlabel={searchTitle ?? title}name={searchIndex ?? dataIndex}labelCol={{ style: { minWidth: width } }}key={searchIndex ?? dataIndex}>{renderFormItem()}</Form.Item></Col>)}return (<Col {...rowCols} key={searchIndex ?? dataIndex} style={{ marginTop: 10 }}><Form.Itemlabel={searchTitle ?? title}name={searchIndex ?? dataIndex}labelCol={{ style: { minWidth: width } }}key={searchIndex ?? dataIndex}>{componentsFormItem(item)}</Form.Item></Col>)})}</>)}const handleIsShow = () => {return renderFormItemChildren()?.props?.children?.length >= 3}// 搜索const handleFormSearch = values => {handleSearch({...values,pageSize: pageSizeOptions?.pageSize ?? 20,current: pageSizeOptions?.current ?? 1,isSearch: true,})}// 重置const handleFormReset = () => {form.resetFields()handleSearch({...initialValues,pageSize: pageSizeOptions?.pageSize ?? 20,current: pageSizeOptions?.current ?? 1,})}// DOMreturn (<Formlayout='inline'form={form}name='advanced_search'onFinish={handleFormSearch}labelAlign={labelAlign}colon={colon}initialValues={{ ...initialValues }}className='search-form'><Row gutter={[16, 16]} className='row-search'><Row style={{ width: '100%' }}><Row style={{ display: expand ? 'inline-flex' : 'none' }}>{renderFormItemChildren()?.props?.children?.map(item => item)}</Row><Row style={{ display: !expand ? 'inline-flex' : 'none' }}>{renderFormItemChildren()?.props?.children?.slice(0, 2)?.map(item => item)}</Row></Row>{(!expand || renderFormItemChildren()?.props?.children?.length % 3 !== 0) && (<Col {...rowCols} className='col-left__one' style={{ bottom: 0 }}><Space size='small'><ButtononClick={handleFormReset}disabled={buttonProps.resetDisabled}style={{ display: handleIsShow() ? 'flex' : 'none' }}>{buttonProps.searchResetText}</Button><Button type='primary' htmlType='submit' disabled={buttonProps.searchDisabled}>{buttonProps.searchButtonText}</Button><aonClick={() => {setExpand(!expand)setPuckOrOpen(expand ? '展开' : '收起')}}className='button-open'style={{ display: handleIsShow() ? 'flex' : 'none' }}><DownOutlined rotate={expand ? 180 : 0} /> {puckOrOpen}</a></Space></Col>)}</Row>{expand && renderFormItemChildren()?.props?.children?.length % 3 === 0 && (<Row className='row-button' style={{ marginTop: expand ? 16 : -32 }}><Col span={24} className='col-left__two'><Space size='small'><Button onClick={handleFormReset} disabled={buttonProps.resetDisabled}>{buttonProps.searchResetText}</Button><Button type='primary' htmlType='submit' disabled={buttonProps.searchDisabled}>{buttonProps.searchButtonText}</Button><aonClick={() => {setExpand(!expand)setPuckOrOpen(expand ? '展开' : '收起')}}className='button-open'><DownOutlined rotate={expand ? 180 : 0} /> {puckOrOpen}</a></Space></Col></Row>)}</Form>)
}export default SearchForm

这里改变了FormItem的label宽度,是计算的,这里是每行三列,切每列的字数最多的为这列的label的宽度,这里看大家需求去改变就可以了

less文件

// index.less
.pro-table {.table-card {margin-top: 10px;.ant-card-body {padding: 10px;}.ant-card-extra{width: 100%;}}.search-form {position: relative;.row-search {width: 100%;.ant-row{width: 100%;}.col-left__one {position: absolute;right: 10px;display: flex;justify-content: flex-end;}}.row-button {width: 100%;margin-top: 10px;.col-left__two {display: flex;justify-content: flex-end;}}}.button-open {font-size: 12px;color: #2e85dd;}
}

代码就这么多,基本上都写了,备注也有,大家自己看吧

不嫌弃可以进啦看看点击

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

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

相关文章

SpringSecurity(11)——核心组件和认证流程

获取用户信息 // 获取安全上下文对象&#xff0c;就是那个保存在 ThreadLocal 里面的安全上下文对象 // 总是不为null(如果不存在&#xff0c;则创建一个authentication属性为null的empty安全上下文对象) SecurityContext securityContext SecurityContextHolder.getContext(…

微信轰炸-python实现方法

新手&#xff0c;一般都需要执行以下命令&#xff0c;用来导入对应模块 pip install -i Simple Index pynput 键盘winr进入输入cmd 执行该命令即可&#xff1a;pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pynput 打开pycharm,输入代码如下 from pynput.keybo…

AI视频智能识别技术在智慧农业大棚升级改造管理场景中的应用方案

一、需求分析 随着科技的进步和农业现代化的推进&#xff0c;智能化技术逐渐成为现代农业发展的重要支撑。农业大棚作为现代农业的重要组成部分&#xff0c;其智能化改造对于提高农业生产效率、降低成本、增加收益具有重要意义。利用先进的信息化手段来对农业大棚进行管理&…

NOC总线(2)

1. NoC的路由 在NoC交换信息时&#xff0c;需要确定从源节点到目标节点所经过的路径&#xff0c;这时就需要路由算法来确定该路径。路由算法分为静态路由算法和动态路由算法两种。 静态路由算法对于两节点之间的路径是固定的&#xff0c;结构简单&#xff0c;便于硬件实…

【算法分析与设计】二叉树的层序遍历

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;算法分析与设计 ⛺️稳中求进&#xff0c;晒太阳 题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xf…

idea插件开发

1&#xff0c; file-new project 如图&#xff0c;选择了安装路径&#xff0c;报错【select home directory for intellij platform plugin sdk】。&#xff08;注意是安装路径最外层的文件夹&#xff0c;不是里面的lib&#xff0c;jbr这一层级&#xff09; 2&#xff0c;点击了…

HTML前端CSS实现只显示1行或者2行、3行剩余显示省略号

想要做的效果: 文本只一行显示 /**实现思路&#xff1a;1.设置inline-block属相2.强制不换行3.固定高度4.隐藏超出部分5.显示“……”*/ {display: inline-block;white-space: nowrap; width: 100%; overflow: hidden;text-overflow:ellipsis; }文本只多行显示 /** 实现思路&…

spring boot集成redis,以及配置database不生效问题

备注&#xff1a;记录一次spring-boot redis 配置redis.database后&#xff0c;仍然使用db0默认库的情况。 springboot集成redis及相关问题 1. spring boot集成redisredis集成依赖&#xff1a;redis配置序列化 2. 集成redission redis分布式锁等快捷管理工具集成依赖配置注入…

【Java发送邮箱】spring boot 发送邮箱

导入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId> </dependency> 2.在properties配置邮箱 # 发件人QQ号 spring.mail.username2508575653qq.com # QQ邮箱授权码 sp…

分享一个asio下使用channel来实现无需队列的安全的连续async_write的方法

分享一个asio下使用channel来实现无需队列的安全的连续async_write的方法 问题&#xff1a;不能直接用asio::async_write连续发送数据 下面这段代码是错误的(为了代码的可读性和易理解&#xff0c;请先忽略函数调用中参数不正确的问题)&#xff1a; asio::async_write(sock,…

xshell配置隧道转移规则

钢铁知识库&#xff0c;一个学习python爬虫、数据分析的知识库。人生苦短&#xff0c;快用python。 xshell是什么 通俗点说就是一款强大ssh远程软件&#xff0c;可以方便运维人员对服务器进行管理操作&#xff0c;功能很多朋友们自行探索&#xff0c;今天只聊其中一个功能点那…

Numpy笔记:安装Numpy+ndarray基本属性+常用方法+索引和切片+广播+轴+范数

Numpy Python库&#xff0c;用于数组快速操作的各种API 支持常见的数组和矩阵操作ndarray处理多维数组 安装Numpy 检查PyCharm的Python运行环境 File–>Settings–>Project–>Python Interpreter检查Python Interpreter环境&#xff0c;例如base 点击Anaconda Prom…

从0开始学习C++ 第三十课 插入排序和快速排序

插入排序 (Insertion Sort) 概念&#xff1a; 插入排序是一种简单直观的排序算法&#xff0c;它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。 逐步分析&#xff1a; 从数组第二个元素开…

HNU-数据挖掘-实验2-数据降维与可视化

数据挖掘课程实验实验2 数据降维与可视化 计科210X 甘晴void 202108010XXX 文章目录 数据挖掘课程实验<br>实验2 数据降维与可视化实验背景实验目标实验数据集说明实验参考步骤实验过程1.对数据进行初步降维2.使用无监督数据降维方法&#xff0c;比如PCA&#xff0c;I…

既是API调试平台也是自动化测试工具?Apipost

Apipost提供可视化的API自动化测试功能&#xff0c;使用Apipost研发人员可以设计、调试接口&#xff0c;测试人员可以基于同一数据源进行测试&#xff0c;Apipost 接口自动化功能在上次更新中进行了逻辑调整&#xff0c;带来更好的交互操作、更多的控制器选择&#xff0c;同时新…

代码随想录算法训练营第四十一天 | 343.整数拆分、66.不同的二叉搜索树

343.整数拆分 题目链接&#xff1a;343.整数拆分 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 文章讲解/视频讲解&#xff1a;https://programmerca…

SpringMvc中拦截器的配置及应用

拦截器原理 在 Spring MVC 中&#xff0c;拦截器&#xff08;Interceptor&#xff09;是一种机制&#xff0c;用于拦截请求并在处理程序&#xff08;Controller&#xff09;执行之前或之后执行一些操作。拦截器允许您在请求的不同阶段&#xff08;如处理程序执行前、处理程序执…

AI大模型中的Bert

1.全方位上下文理解&#xff1a;与以前的模型&#xff08;例如GPT&#xff09;相比&#xff0c;BERT能够双向理解上下文&#xff0c;即同时考虑一个词 的左边和右边的上下文。这种全方位的上下文理解使得BERT能够更好地理解语言&#xff0c;特别是在理解词义、 消歧等复杂任务上…

智慧安防GB28181视频监控EasyCVR v3.5系统增加录像保存地址的配置

智慧安防监控EasyCVR视频管理平台能在复杂的网络环境中&#xff0c;将前端设备统一集中接入。在网络传输上&#xff0c;平台支持设备通过4G、5G、WIFI、有线等方式进行视频流的快捷传输&#xff0c;视频流经平台处理后可对外进行多格式的分发&#xff0c;实现多展示终端观看&am…

消息中间件之Kafka(二)

1.Kafka线上常见问题 1.1 为什么要对topic下数据进行分区存储? 1.commit log文件会受到所在机器的文件系统大小的限制&#xff0c;分区之后可以将不同的分区放在不同的机器上&#xff0c; 相当于对数据做了分布式存储&#xff0c;理论上一个topic可以处理任意数量的数据2.提…