ProTable最新配置和数据持久化
<ProTable
headerTitle="用户列表"
actionRef={actionRef}
columns={columns}
dataSource={dataMemo}
toolBarRender={() => [
<Button
key="addNewOne"
type="primary"
icon={<PlusOutlined />}
onClick={addNewOne}
>
新增
</Button>,
]}
editable={{
type: 'multiple',
onSave: (key, record): any => {
onEditRow(key, record);
},
actionRender: (row, config, defaultDoms) => {
return [defaultDoms.save, defaultDoms.cancel];
},
}}
rowKey="id"
search={false}
options={{
reload: () => {
addQueryString({}, { cover: false });
},
density: true,
fullScreen: true,
setting: {
listsHeight: 400,
},
}}
pagination={paginationConfig}
loading={loading}
defaultSize="large"
columnEmptyText="--"
scroll={{ scrollToFirstRowOnChange: false, x: 'max-content' }}
// 列选择持久化
columnsState={{
persistenceKey: 'user_management_columns_state',
persistenceType: 'localStorage',
}}
/>
模糊查询下拉框+labelInValue
<Select
// 原始受控写法(workerValue存储对象形式)
value={workerValue?.map(item=>item?.value)}
onChange={(value,option)=>setWorkerValue(option)}
// 使用labelInValue之后
labelInValue
value={workerValue}
onChange={setWorkerValue}
// 脱离文档流
style={{ width: 200, position: 'absolute', zIndex: 10, left: 0, top: 0 }}
// 由后端模糊查询实现下拉框数据筛选
filterOption={false}
// 搜索防抖
onSearch={(value) => {
getTAMList(value);
}}
// 下拉框的loading
dropdownRender={(originNode) => (
<Spin spinning={loadingSelect}>{originNode}</Spin>
)}
/>
npm i file-loader -S
export default defineConfig({
chainWebpack(memo) {
memo.module
.rule('file-loader')
.test(/.(ogg|mp3|wav|mpe?g)$/i)
.use('file-loader')
.loader('file-loader')
.options({
name: 'audios/[name].[ext]',
limit: 10,
});
},
});
- 播放音乐时,并不需要在页面中添加标签再隐藏,而是直接调用其对象的播放方法。
import NotificationSound from '@/assets/mp3/notification.mp3';
const audio = new Audio(NotificationSound);
audio.play();
- 倒计时刷新中,会出现计时器,为保证调用的函数都是同一个引用,避免反复重新打开新的计时器,需要使用useCallback进行包裹做到缓存。与此同时,倒计时的秒数状态和累计的新增工单条数,都是要在dom中实时更新的。但缓存的函数中又拿不到最新的状态值,这样就出现了的矛盾。但是使用useRef绑定的值不会受到影响,在任何地方都可以拿到它最新的值。所以同步设定好useRef的值即可解决此问题。
const messageNum = useRef(0);
const preMessageNum = useRef(0);
const countDownRef = useRef(10);
const timer = useRef(null);
const preListData = useRef([]);
const onRefeshChange = useCallback((value) => {
setRefreshFlag(value);
localStorage.setItem('auto_refresh_order_detail_checked', JSON.stringify(value));
if (value) {
timer.current = setInterval(() => {
if (countDownRef.current <= 1) {
countDownRef.current = 11;
const tempData = [...preListData.current];
tableDataGet({ ...queryObjRef.current, page: 1 }).then((res) => {
preMessageNum.current = messageNum.current;
res?.data?.content?.forEach((item) => {
if (tempData?.findIndex((val) => val?.vid === item?.vid) === -1) {
messageNum.current += 1;
}
});
if (messageNum.current > 0 && preMessageNum.current !== messageNum.current) {
setNewMessage(messageNum.current > 0);
notification.destroy();
notification.info({
message: `出现了${messageNum.current}条新工单哦`,
placement: 'topRight',
description: '(不关闭将自动累计)',
duration: null,
onClose: () => {
messageNum.current = 0;
},
});
}
});
// setQueryObj((pre) => ({ ...pre }));
}
setActiveMillisecond((countDownRef.current -= 1));
}, 1000);
} else {
countDownRef.current = 10;
setActiveMillisecond(10);
clearInterval(timer.current);
timer.current = null;
}
}, []);
- 使用useEffect在dom挂载执行一次,路由变动会再执行一次,这两次执行时间间隔是非常近的。巧合的是,首次遇到这两次需要的状态值并无区别,导致没有很好的区分方式来避免代码被重复执行一次。最后想到了使用节流的方式,将间隔设置为200ms,避免了多处监听导致短时间内重复请求的问题。
const dataInit = useCallback(
throttle(
() => {
tailingWork();
const orderId = params?.orderId || history?.location?.query?.vid;
if (!orderId) return;
// 客户标签中的数据
setLoading(true);
protoRequest('https://aiops-ssc.alibaba-inc.com/api/customerTag/getTagsByOrderIds', {
method: 'GET',
params: {
ids: orderId,
},
})
.then((res) => {
if (res?.success) {
setTagsValue(res?.fields?.[0]?.knottyResolvers);
} else {
setTagsValue([]);
}
})
.catch(() => {
setTagsValue([]);
})
.finally(() => {
setLoading(false);
});
},
200,
{ leading: true, trailing: false },
),
[],
);