1. 项目使用:数据大屏
2. 使用场景
- 封装派发器,定时对页面进行数据派发,页面根据接收到的数据,进行实时更新,实现炫酷效果
3. 实现效果
-
显示单个组件的控制器场景(控制器下可能有N个组件,但是同时只展示单个组件)
-
显示列表组件的控制器场景(列表恒定只展示10条数据,每新增一条就需要移除一条)
4. 代码结构
5. bean.ts代码
// 接口数据请求定义
export enum DataTypeCode {
UserSituation = 'UserSituation'
}
// 派发的数据结构
export class DataBo {
data: []
}
// 派发回调
export interface IDispatchCallback {
(data: any[]):void
}
// 数据派发器参数
export class Options {
//首次派发数据量
firstDispatch: number
//非首次派发数据量
nextDispatch: number
//是否循环派发
loop?: boolean = true
// 派发数据类型
dataType: DataTypeCode
// 循环派发时间 秒
loopTime?: number = 1
//派发回调函数
callback: IDispatchCallback
key?: string
// 重新派发?
noRepeatDispatch?: boolean = false
}
export interface totalData {
dayNum: number
weekNum: number
}
export declare class DataProvider<T> {
/**
* 数据
*/
private data;
/**
* promise队列,用于后续回调
*/
private promises;
/**
* 异步获取信息
* @returns
*/
getData(): Promise<T>;
/**
* @param data
*/
setData(data: T): void;
/**
* 是否准备好回调
* @returns
*/
protected isReady(): boolean;
/**
* 获取data对象
* @returns
*/
protected getObj(): T;
private handle;
}
6. data-dispatch 控制器代码
import { Options } from './bean'
export class Dispatch {
//配置信息
private opts: Options
//需要派发的数据,如果loop=true,在派发完后会重新派发
private data: any
private dispatchData: any[]
private timer
constructor(opts: Options) {
clearTimeout(this.timer)
//TODO 可以初始化的时候,传入callback
this.opts = opts
}
// 调用start即开始派发数据
// 数据中心定时刷新数据以后,只需要调用start,即可刷新data,重新派发数据
start(data: any[]):void {
clearTimeout(this.timer)
this.data = data
// 派发数据为数组时
if (Array.isArray(this.data)) {
this.dispatchData = this.data.slice(0, this.opts.firstDispatch)
this.timeoutDispatch(this.opts.firstDispatch)
}
// 派发数据为非数组时
else {
console.error('非数组数据无法进行派发')
}
}
// 数据派发
disPatch():void {
this.opts.callback(this.dispatchData)
}
// 根据页面设置进行数据循环派发
timeoutDispatch(num: number):void {
this.disPatch()
// 支持循环且数据长度大于首次派发数据长度,才支持循环派发
if (!this.data || !this.data.length || (this.data.length <= this.opts.firstDispatch) || (num >= this.data.length && !this.opts.loop)) {
return
}
this.timer = setTimeout(() => {
num = num + 1
// 数据长度超过实际长度,从新开始派发 或者根据字段noRepeatDispatch决定是否接着派发
if (num > this.data.length) {
num = this.opts.noRepeatDispatch ? this.opts.nextDispatch : this.opts.firstDispatch
}
// num长度等于首次派发长度,派发数据量 = 首次派发数据量
if (num === this.opts.firstDispatch && num !== 1) {
this.dispatchData = this.data.slice(0, this.opts.firstDispatch)
}
// 否则,按照 非首次派发数据量 进行派发
else {
this.dispatchData = this.data.slice(num - this.opts.nextDispatch, num)
}
clearTimeout(this.timer)
this.timeoutDispatch(num)
}, this.opts.loopTime * 1000)
}
}
7. data-center 数据中心代码
import { Dispatch } from './data-dispatch'
import { DataTypeCode, Options, totalData, DataProvider } from './bean'
import api from '@/api/api'
// 平台运营总量
const getUserSituation = () => {
return api.getUserSituation().then(res => {
return Promise.resolve({ data: [res.data] })
})
}
const dataApiMap = {}
// 平台运营总量
dataApiMap[DataTypeCode.UserSituation] = getUserSituation
// 数据中心获取数据触发派发器
export class DataCenter {
private dispatch
// 请求接口类型
private type: DataTypeCode
private timer
constructor(opts: Options) {
this.dispatch = new Dispatch(opts)
clearTimeout(this.timer)
}
// 获取接口数据
private getData() {
dataApiMap[this.type]().then(res => {
// 触发派发器
this.dispatch.start(res.data)
})
}
// 定时获取数据,每隔5分钟请求一次接口
private initData(type: DataTypeCode) {
clearTimeout(this.timer)
this.type = type
this.getData()
this.timer = setTimeout(() => {
clearTimeout(this.timer)
this.initData(type)
}, 5 * 60 * 1000)
}
}
8. 页面中数据获取
getData() {
const options = {
firstDispatch: 7,
nextDispatch: 1,
callback: (data) => {
// 每隔一秒派发器会派发数据到页面,页面接收后,可以根据需要对数据进行处理
console.log(data)
}
}
const data = new DataCenter(options)
data.initData('UserSituation')
}