大致的需求就是,在客户现场展示几个大屏,而客户可以在管理端控制每个大屏的展示布局。
那么针对这种情况我们应该如何设计呢?
首先我们使用的方案是websocket长连接方案。因为在这个需求总管理端需要知道连接的每个大屏的状态,而客户端需要实时同步大屏数据和上报自身状态同步给客户端。
对此使用长连接通讯相对来讲是比较靠谱的而且很容易实现。
在这里我们虽然展示了不同的大屏,但是每个大屏默认会有一个初始配置,用于首次展示。
那么这种展示方式的连接流程数据交方式是什么?
首先我们的连接流程指的是对接websocket的连接流程,在此我们规定了如下格式
go
type DataMessage struct{
PageId: string `json:pageId`, // 页面唯一标识
PageStatus: int `json:pageStatus` // 页面的类型 1 管理端 | 2 展示端
PageVersion: int `json:pageStatus` // 页面配置版本
Data: string `json: data` // 同步的数据
}
在页面连接之前会自己生成一个md5表示当前的页面ID,这条数据也用于存储该页面对应socket连接的key值,这样设计的关键点是对需要广播的配置页面实现精准控制,保证每个配置的独立性。数据结构如下
go
type pageWebsocket struct {
PageId string `json:pageId` // 唯一标识
PageStatus: int `json:pageStatus` // 页面的类型 1 管理端 | 2 展示端
PageVersion: int `json:pageStatus` // 页面配置版本
ws *websocket.Conn `json:ws` // 版本号
}
var pageWebsocketMap = map[string] pageWebsocket{} // 数据map
假设我们有四个展示端页面一个管理端,在一开始进入的时候会产生5条连接,每个连接均通过上述方式记录,此时,管理端会接收到由四个页面同步过来的数据,并展示在管理页面中,每次配置时端可以批量选择需要同步的页面,被选中的页面的pageId
就会被作为广播的发送者,通过之前pageWebsocketMap
存储的ws
连接句柄来广播数据。
展示端如果需要同步自身数据,需要通过PageStatus找到管理端实现管理端的数据广播(我们目前做的是只有一个管理端页面,不存在多管理端控制同一页面)。
每次窗口关闭时释放pageWebsocketMap
存储的长连接,而针对释放我们采取的是服务端生成一个唯一标识,该标识仅仅标识本次连接是唯一的,用于defer函数回调时使用
对于客户端使用store来做数据管理,格式如下所示
typescript
interface State {
ws: WebSocket | undefined;
isConnect: boolean;
data: any;
}
export default createStore<State>({
state: {
ws: undefined, // ws句柄
isConnect: false, // 是否连接
data: {}, // 数据
},
getters: {},
mutations: {
setData(store, payload: WebSocket) {
store.data = payload;
},
setWs(store, payload: WebSocket) {
store.ws = payload;
},
setState(store, payload: boolean) {
store.isConnect = payload;
},
},
actions: {
initWebsocket(store, userId: string) {
if (
store.state.ws &&
store.state.ws.CLOSED !== 3 &&
store.state.isConnect
) {
store.state.ws.close();
}
const ws = new WebSocket(WS_URL);
store.commit("setWs", ws);
ws.onopen = () => {
store.commit("setState", true);
const params = JSON.stringify({ userId, type: 1 });
store.commit("setData", params);
};
ws.onerror = () => {
store.commit("setState", false);
};
ws.onclose = () => {
store.commit("setState", false);
};
ws.onmessage = (ev: MessageEvent<any>) => {
store.commit("setData");
const data = JSON.parse(ev.data);
console.log(data);
};
},
sendData(store, jsonData: any) {
if (store.state.ws) {
store.state.ws.send(JSON.stringify(jsonData));
}
},
},
modules: {},
});
该函数仅仅起到ws的透传管理,具体的数据发送依靠sendData
实现,而响应则是依靠onmessage
来作为数据的同步,页面使用computed
或直接使用useStore
获取数据即可完成页面的动态刷新操作