TP屏幕适配--UI篇
文章目录
- 前言
- TP的上报处理流程
- LCD屏内函数处理
- DispatchMSGTpDown
- DispatchMSGTpUp
- DispatchMSGTpMove
- UI界面
- 主菜单界面
- Softkey界面
前言
上一篇文章TP屏幕适配–驱动篇 介绍了TP屏幕底层驱动处理以及按键处理上报,这篇文章主要讲到UI界面如何对TP底层上报的按键手势等信息响应处理。
TP的上报处理流程
TP触屏信息上报的函数处理流程如下图所示:
LCD屏内函数处理
分析下各个函数内部,实现了哪些操作
DispatchMSGTpDown
LOCAL void DispatchMSGTpDown(uint16 x, uint16 y)
{MMI_HANDLE_T win_handle = 0;MMI_HANDLE_T root_handle = 0;MMI_HANDLE_T ctrl_handle = 0;GUI_POINT_T point = {0};MMI_MULTI_KEY_TP_MSG_PARAM_T para = {0};MMI_RESULT_E tp_handle_result = MMI_RESULT_FALSE;MMI_MESSAGE_ID_E msg_id = MSG_TP_PRESS_DOWN;MMI_HANDLE_T focus_win = MMK_GetFocusWinHandle();MMI_HANDLE_T old_handle = MMK_GetProcMsgHandle();s_tp_status = MMI_TP_DOWN;point.x = x;point.y = y;para.cur_tp_point.x = x;para.cur_tp_point.y = y;GetMultiKeyParam(¶); //处理同时多个按下//根据点击的坐标点 获取当前窗口句柄if (!MMK_GetHandleByPos(point, TRUE, &win_handle, &ctrl_handle, 0)){s_tp_dblclk_state = TP_DBLCLK_NONE;return;}MMK_SetTPDownWin(win_handle);if (MMK_GetWinDisplayStyleState(MMK_GerFocusMainWinHandle(), WS_NEED_DBLCLK)){if (TP_DBLCLK_NONE == s_tp_dblclk_state){MMK_ReInitDblClkState(TRUE);}#if !defined RELEASE_INFO{static uint32 s_tp_down_tick = 0;uint32 cur_tp_down_tick = SCI_GetTickCount();SCI_TRACE_ID(TRACE_TOOL_CONVERT, MMK_TP_690_112_2_18_3_22_47_27, (uint8 *)"u",cur_tp_down_tick - s_tp_down_tick);s_tp_down_tick = cur_tp_down_tick;}#endif//双击功能实现if (TP_DBLCLK_NONE == s_tp_dblclk_state){msg_id = MSG_TP_PRESS_DOWN;s_tp_dblclk_state = TP_DBLCLK_PRE;}else if (TP_DBLCLK_PRE == s_tp_dblclk_state && focus_win == s_tp_down_win &&abs(x - s_tp_point_x) <= MMI_TP_DBLCLK_MOVE && abs(y - s_tp_point_y) <= MMI_TP_DBLCLK_MOVE){//如果两次点击在一定的区域范围内 认为是双击MMK_ReInitDblClkState(FALSE);msg_id = MSG_TP_PRESS_DOUBLE;s_tp_dblclk_state = TP_DBLCLK_DONE;}else{MMK_ReInitDblClkState(TRUE);msg_id = MSG_TP_PRESS_DOWN;s_tp_dblclk_state = TP_DBLCLK_PRE;}s_tp_down_win = focus_win;}// set tp Tigger modeMMITHEME_SetTiggerMode(MMITHEME_TRIGGER_MODE_TP);MMK_SetProcMsgHandle(win_handle);// check whether user hook handlertp_handle_result = MMK_RunWinHookProc(win_handle, msg_id, (DPARAM)¶);if (MMI_RESULT_FALSE != tp_handle_result){SetTPDownCtrl(0);}else{// get root form control handleroot_handle = MMK_GetRootFormCtrlHandle(win_handle);if (!(MMK_PosIsCtrl(root_handle, point) && MMK_IsResponseToClick(root_handle))){root_handle = 0;}if (0 != root_handle){SetTPDownCtrl(root_handle);tp_handle_result = MMK_RunCtrlProc(root_handle, msg_id, (DPARAM)¶);}}//以下分别通知UI控件进行处理if (MMI_RESULT_FALSE == tp_handle_result){if (0 != ctrl_handle){SetTPDownCtrl(ctrl_handle);MMK_SetAtvCtrl(win_handle, ctrl_handle);tp_handle_result = MMK_RunCtrlProc(ctrl_handle, msg_id, (DPARAM)¶);}else{SetTPDownCtrl(0);// call the default proces function totp_handle_result = DefaultProcessWinTPMsg(win_handle, msg_id, (DPARAM)¶);}}// check window callback handlerif (MMI_RESULT_FALSE == tp_handle_result){// dispatch the windowtp_handle_result = MMK_RunWinProc(win_handle, msg_id, (DPARAM)¶);}MMK_SetProcMsgHandle(old_handle);}
DispatchMSGTpUp
LOCAL void DispatchMSGTpUp(uint16 x, uint16 y)
{MMI_HANDLE_T win_handle = 0;GUI_POINT_T point = {0};MMI_RESULT_E tp_handle_result = MMI_RESULT_FALSE;MMI_MULTI_KEY_TP_MSG_PARAM_T para = {0};MMI_MESSAGE_ID_E msg_id = MSG_TP_PRESS_UP;MMI_HANDLE_T old_handle = MMK_GetProcMsgHandle();s_tp_status = MMI_TP_NONE;s_is_tp_move = FALSE;s_is_delay_tp_move = FALSE;point.x = x;point.y = y;para.cur_tp_point.x = x;para.cur_tp_point.y = y;//获取同时按下的 多个按键参数GetMultiKeyParam(¶);//根据坐标 获取当前窗口的句柄if (!MMK_GetHandleByPos(point, TRUE, &win_handle, PNULL, 0)){// 如果没有找到 则返回NONEs_tp_dblclk_state = TP_DBLCLK_NONE;return;}//检查TP是否成对if (!CheckTPPair(win_handle)){return;}// 检查判断是不是双击if (MMK_GetWinDisplayStyleState(MMK_GerFocusMainWinHandle(), WS_NEED_DBLCLK)){if (TP_DBLCLK_DONE == s_tp_dblclk_state){msg_id = MSG_TP_PRESS_DBLCLK_UP;s_tp_dblclk_state = TP_DBLCLK_NONE;// SCI_TRACE_LOW:"@DBLCLK, MSG_TP_PRESS_DBLCLK_UP"SCI_TRACE_ID(TRACE_TOOL_CONVERT, MMK_TP_881_112_2_18_3_22_47_34, (uint8 *)"");}else{// SCI_TRACE_LOW:"@DBLCLK, MSG_TP_PRESS_UP"SCI_TRACE_ID(TRACE_TOOL_CONVERT, MMK_TP_885_112_2_18_3_22_47_35, (uint8 *)"");}}//设置需要处理消息的窗口 s_proc_msg_handleMMK_SetProcMsgHandle(win_handle);// check whether user hook handlertp_handle_result = MMK_RunWinHookProc(win_handle, msg_id, (DPARAM)¶);// check ctrl handlerif (MMI_RESULT_FALSE == tp_handle_result){tp_handle_result = DefaultProcessTPMsg(win_handle, msg_id, (DPARAM)¶);}//关掉TP按下控制 即成对处理完成SetTPDownCtrl(0);MMK_SetTPDownWin(0);//以下分别通知UI控件进行处理if (MMI_RESULT_FALSE == tp_handle_result){// dispatch the windowtp_handle_result = MMK_RunWinProc(win_handle, msg_id, (DPARAM)¶);if (MMI_RESULT_FALSE == tp_handle_result){tp_handle_result = DefaultProcessWinTPMsg(win_handle, msg_id, (DPARAM)¶);}}MMK_SetProcMsgHandle(old_handle);
}
DispatchMSGTpMove
LOCAL void DispatchMSGTpMove(uint16 pre_point_x, uint16 pre_point_y, uint16 cur_point_x, uint16 cur_point_y)
{MMI_HANDLE_T win_handle = 0;GUI_POINT_T point = {0};MMI_RESULT_E tp_handle_result = MMI_RESULT_FALSE;MMI_MULTI_KEY_TP_MSG_PARAM_T para = {0};MMI_HANDLE_T old_handle = MMK_GetProcMsgHandle();s_is_tp_move = TRUE;// set pointpoint.x = cur_point_x;point.y = cur_point_y;// set parameterpara.cur_tp_point.x = cur_point_x;para.cur_tp_point.y = cur_point_y;para.pre_tp_point.x = pre_point_x;para.pre_tp_point.y = pre_point_y;GetMultiKeyParam(¶);//获取坐标所在的句柄if (!MMK_GetHandleByPos(point, TRUE, &win_handle, PNULL, 0)){return;}//检查是否成对if (!CheckTPPair(win_handle)){return;}//设置当前使用的句柄MMK_SetProcMsgHandle(win_handle);//以下分别通知UI控件进行处理tp_handle_result = MMK_RunWinHookProc(win_handle, MSG_TP_PRESS_MOVE, (DPARAM)¶);// check ctrl handlerif (MMI_RESULT_FALSE == tp_handle_result){tp_handle_result = DefaultProcessTPMsg(win_handle, MSG_TP_PRESS_MOVE, (DPARAM)¶);}// check window callback handlerif (MMI_RESULT_FALSE == tp_handle_result){tp_handle_result = MMK_RunWinProc(win_handle, MSG_TP_PRESS_MOVE, (DPARAM)¶);}MMK_SetProcMsgHandle(old_handle);
}
UI界面
主菜单界面
主菜单界面的实现由mmi_mainmenu_matrix.c里面MatrixMenuHandle函数来处理
LOCAL MMI_RESULT_E MatrixMenuHandle(void *pm_data_ptr, MMI_MESSAGE_ID_E msg_id, DPARAM param)
{#ifdef UI_MULTILAYER_SUPPORTGUI_LCD_DEV_INFO lcd_dev_info = {0};#endifMMI_RESULT_E result = MMI_RESULT_TRUE;MMIMAINMENU_MATRIX_DATA_T *menu_ctrl_ptr = (MMIMAINMENU_MATRIX_DATA_T *)pm_data_ptr;GUI_POINT_T point = {0};if (PNULL == menu_ctrl_ptr){return MMI_RESULT_FALSE;}switch (msg_id){//... 省略部分代码#if defined(TOUCH_PANEL_SUPPORT) || defined(TOUCH_PANEL_CTRL_SUPPORT_MMI)case MSG_TP_PRESS_DOWN:point.x = MMK_GET_TP_X(param);point.y = MMK_GET_TP_Y(param);MMITheme_StopControlText();//进行区域计算等处理HandleMatrixMenuTpDown(&point, menu_ctrl_ptr);HandleTextToSpeech(menu_ctrl_ptr);break;case MSG_TP_PRESS_UP:point.x = MMK_GET_TP_X(param);point.y = MMK_GET_TP_Y(param);HandleMatrixMenuTpUp(&point, menu_ctrl_ptr);HandleTextToSpeech(menu_ctrl_ptr);break;case MSG_TP_PRESS_MOVE:point.x = MMK_GET_TP_X(param);point.y = MMK_GET_TP_Y(param);HandleMatrixMenuTpMove(&point, menu_ctrl_ptr);break;case MSG_TP_PRESS_LONG:case MSG_TP_PRESS_SHORT:// 处理tp short 消息HandleMatrixMenuSpecialMsg(menu_ctrl_ptr, msg_id, param);break;#endif//... 省略部分代码default:result = MMI_RESULT_FALSE;break;}return result;}
Softkey界面
Softkey界面由ctrlsoftkey.c里面的GUISOFTKEY_HandleMsg函数来进行处理
LOCAL MMI_RESULT_E GUISOFTKEY_HandleMsg(CTRLBASE_OBJ_T *ctrl_ptr, MMI_MESSAGE_ID_E msg_id, DPARAM param)
{#if defined(TOUCH_PANEL_SUPPORT) || defined(TOUCH_PANEL_CTRL_SUPPORT_MMI)GUI_POINT_T point = {0};
#endifint16 i = 0;CTRLSOFTKEY_OBJ_T *softkey_ptr = PNULL;MMI_RESULT_E recode = MMI_RESULT_TRUE;if (PNULL == ctrl_ptr){return MMI_RESULT_FALSE;}softkey_ptr = (CTRLSOFTKEY_OBJ_T *)ctrl_ptr;if (!softkey_ptr->is_visible){return MMI_RESULT_FALSE;}switch (msg_id){case MSG_CTL_OPEN:break;case MSG_CTL_PAINT:DrawSoftkey(softkey_ptr);break;case MSG_NOTIFY_UPDATE:if (IsButtonStyle(softkey_ptr->style)){GUIBUTTONSOFTKEY_DrawBg(softkey_ptr, (GUI_RECT_T *)param);}break;case MSG_CTL_LOSE_FOCUS:if (!IsButtonStyle(softkey_ptr->style)){for (i = 0; i < GUISOFTKEY_BUTTON_NUM; i++){SetWinSKBButtonPressed(softkey_ptr, i, FALSE);}SetWinSKBPressed(softkey_ptr, FALSE);}break;
#if defined(TOUCH_PANEL_SUPPORT) || defined(TOUCH_PANEL_CTRL_SUPPORT_MMI)case MSG_TP_PRESS_DOWN:case MSG_TP_PRESS_UP:case MSG_TP_PRESS_LONG:case MSG_TP_PRESS_MOVE:if (!IsButtonStyle(softkey_ptr->style)){point.x = MMK_GET_TP_X(param);point.y = MMK_GET_TP_Y(param);//传入坐标,处理TP事件recode = HandleSoftkeyBarTPMsg(softkey_ptr, msg_id, point);}break;
#endifdefault:recode = MMI_RESULT_FALSE;break;}return recode;
}
// HandleSoftkeyBarTPMsg 对按下,移动,抬起 进行详细处理
LOCAL MMI_RESULT_E HandleSoftkeyBarTPMsg(CTRLSOFTKEY_OBJ_T *softkey_ptr, MMI_MESSAGE_ID_E msg_id, GUI_POINT_T point)
{MMI_RESULT_E result = MMI_RESULT_FALSE;
#if defined(TOUCH_PANEL_SUPPORT) || defined(TOUCH_PANEL_CTRL_SUPPORT_MMI)BOOLEAN is_send_msg = FALSE;MMI_MESSAGE_ID_E send_msg_id = 0;int16 i = 0;GUI_RECT_T softkey_rect = {0};MMI_RESULT_E pre_result = MMI_RESULT_FALSE;MMI_HANDLE_T win_handle = 0;MMI_HANDLE_T ctrl_handle = 0;BOOLEAN is_press_long = FALSE;CTRLBASE_OBJ_T *ctrl_ptr = (CTRLBASE_OBJ_T *)softkey_ptr;static BOOLEAN s_tplong_handle = FALSE; //如果tp long消息被处理了,则tp up消息不再处理if (PNULL == softkey_ptr){return MMI_RESULT_FALSE;}win_handle = softkey_ptr->win_handle;softkey_rect = ctrl_ptr->rect;//因为窗口表里面定义了Txt_null,表明不需要softkey的,但是系统已经把区域给了,所以这里特殊处理下。(使系统不处理tp)if (MSG_TP_PRESS_DOWN == msg_id && GUI_PointIsInRect(point, MMITHEME_GetSoftkeyRect(MIDDLE_BUTTON)) &&GUISK_DATA_TEXT_ID == softkey_ptr->button_arr[MIDDLE_BUTTON].content.data_type &&MMITHEME_IsMidkeyNull(softkey_ptr->button_arr[MIDDLE_BUTTON].content.data_u.text_id)){return MMI_RESULT_FALSE;}//先确认按键是否可见if (!softkey_ptr->tp_disable){//如果tp long消息被窗口处理了,则tp up消息不再处理if (MSG_TP_PRESS_DOWN == msg_id){s_tplong_handle = FALSE;}else if (MSG_TP_PRESS_UP == msg_id && s_tplong_handle){s_tplong_handle = FALSE;return MMI_RESULT_TRUE;}if (MSG_TP_PRESS_DOWN == msg_id){if (GUI_PointIsInRect(point, softkey_rect)){SetWinSKBPressed(softkey_ptr, TRUE);}else{//点击区域不在softkey内return MMI_RESULT_FALSE;}}else if (!GetWinSKBPressed(softkey_ptr)){// softkey 未按下return MMI_RESULT_FALSE;}}else{//窗口无softkeyreturn MMI_RESULT_FALSE;}switch (msg_id){case MSG_TP_PRESS_DOWN:SetWinSKBPressed(softkey_ptr, TRUE);//是否点中软键区的某个button 图标for (i = 0; i < GUISOFTKEY_BUTTON_NUM; i++){//处理按下了 左中右哪个按键SetWinSKBButtonPressed(softkey_ptr, i, FALSE);if (softkey_ptr->button_arr[i].is_show && GUI_PointIsInRect(point, softkey_ptr->button_arr[i].rect) &&!softkey_ptr->button_arr[i].is_gray){//画按下的效果DrawPressedSoftkey(softkey_ptr, point, TRUE);SetWinSKBButtonPressed(softkey_ptr, i, TRUE);break;}}result = MMI_RESULT_TRUE;break;case MSG_TP_PRESS_UP:if (GetWinSKBPressed(softkey_ptr)){result = HandleSoftkeyBar(softkey_ptr, point); // handle the softkeyfor (i = 0; i < GUISOFTKEY_BUTTON_NUM; i++){if (softkey_ptr->button_arr[i].is_show && softkey_ptr->button_arr[i].is_pressed){SetWinSKBButtonPressed(softkey_ptr, i, FALSE);DrawSoftkeyByIndex(softkey_ptr, i, FALSE);}}SetWinSKBPressed(softkey_ptr, FALSE);if (MMI_RESULT_FALSE == result){result = MMI_RESULT_TRUE;}}break;case MSG_TP_PRESS_LONG:if (GetWinSKBPressed(softkey_ptr)){//是否在软键区内,并进行处理result = HandleSoftkeyBar(softkey_ptr, point); // handle the softkeyfor (i = 0; i < GUISOFTKEY_BUTTON_NUM; i++){if (softkey_ptr->button_arr[i].is_pressed &&GUI_PointIsInRect(point, softkey_ptr->button_arr[i].rect) &&softkey_ptr->button_arr[i].is_long_press){SetWinSKBButtonPressed(softkey_ptr, i, FALSE);DrawSoftkeyByIndex(softkey_ptr, i, FALSE);s_tplong_handle = TRUE;SetWinSKBPressed(softkey_ptr, FALSE);}}if (!s_tplong_handle){result = MMI_RESULT_TRUE;}}break;case MSG_TP_PRESS_MOVE:if (GetWinSKBPressed(softkey_ptr)){for (i = 0; i < GUISOFTKEY_BUTTON_NUM; i++){if (softkey_ptr->button_arr[i].is_pressed &&!GUI_PointIsInRect(point, softkey_ptr->button_arr[i].rect)){SetWinSKBButtonPressed(softkey_ptr, i, FALSE);DrawSoftkeyByIndex(softkey_ptr, i, FALSE);}else if (softkey_ptr->button_arr[i].is_show &&GUI_PointIsInRect(point, softkey_ptr->button_arr[i].rect) &&!softkey_ptr->button_arr[i].is_pressed && !softkey_ptr->button_arr[i].is_gray){DrawPressedSoftkey(softkey_ptr, point, TRUE);SetWinSKBButtonPressed(softkey_ptr, i, TRUE);}}result = MMI_RESULT_TRUE;}break;default:result = MMI_RESULT_FALSE;break;}if (MMI_RESULT_FALSE != result && MSG_TP_PRESS_LONG == msg_id){is_press_long = TRUE;}// handle the softkey barpre_result = result;switch (result){case GUI_RESULT_CTLOK:if (!is_press_long){is_send_msg = TRUE;send_msg_id = MSG_APP_OK;}break;case GUI_RESULT_CTLCANCEL:is_send_msg = TRUE;if (!is_press_long){send_msg_id = MSG_APP_CANCEL;}else{send_msg_id = MSG_KEYLONG_CANCEL;}break;case GUI_RESULT_CTLMDL:if (!is_press_long){is_send_msg = TRUE;send_msg_id = MSG_APP_WEB;}break;default:break;}// get active control handlectrl_handle = MMK_GetActiveCtrl(win_handle);if ((0 != ctrl_handle) && (is_send_msg)){result = MMK_RunCtrlProc(ctrl_handle, send_msg_id, PNULL);if (!result){// get parent handlectrl_handle = MMK_GetParentCtrlHandle(ctrl_handle);while (0 != ctrl_handle){result = MMK_RunCtrlProc(ctrl_handle, send_msg_id, PNULL);if (result){break;}ctrl_handle = MMK_GetParentCtrlHandle(ctrl_handle);}}}if ((MMI_RESULT_FALSE == result) || (pre_result == result)){result = MMK_RunWinProc(win_handle, send_msg_id, PNULL);}
#endifreturn result;
}
TP屏幕适配--UI篇相关推荐
- TP屏幕适配--驱动篇
文章目录 前言 硬件构成 TP原理 主要硬件组成 通讯流程 引脚配置 通讯方式(IIC) 中断初始化 TP屏幕逻辑主线程 TP触屏信息进行记录和上报 读取TP触屏信息并解析 TP触屏信息进行分析处理 ...
- Android高手笔记-屏幕适配 UI优化
Android高手笔记-屏幕适配 & UI优化 屏幕与适配 由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高: 屏幕适配究其根本 ...
- IOS 屏幕适配理论篇
@[TOC](IOS 屏幕适配(一)理论篇) 1. IOS 屏幕适配基本概念 1.1 IOS 设备的尺寸和分辨率 1.1.1 分辨率相关概念 点(Points): 是iOS开发中引入的抽象单位,称作点 ...
- 鸿蒙OS屏幕适配UI设计图解决方案
先上图 这仨赏金猎人App解决方案 赏金猎人开发日志地址https://harmonyos.51cto.com/posts/3203,我想问问谁有办法替换系统默认的尺寸计算方案求大佬告知 这个是实现渲 ...
- html 手机浏览器:屏幕适配 - 代码篇
重要代码: <!-- apple强制全屏,显示在状态栏下方 --> <meta name="apple-mobile-web-app-capable" conte ...
- Android dp方式的屏幕适配-原理(后期补充完整讲解)
Android dp方式的屏幕适配-原理 传统所说的屏幕适配,其实是针对不同屏幕的UI尺寸适配,即在编写页面时使用了具体的dp.sp值后导致的其他问题. 我之前写过一些相关的文章和工具插件,也收到了很 ...
- android ui布局适配,Android适配全面总结(一)----屏幕适配
前言 Android适配是一个老生常谈的问题,很多程序员觉得很恶心,不愿意做适配,但是又不得不做.然后老板说,这位兄弟,做好了,今天晚饭给你加个鸡腿,然后程序员开始找各种资料,忙活起来了,最终在苦逼的 ...
- IOS 屏幕适配(一)理论篇
IOS 屏幕适配(一)理论篇 1. IOS 屏幕适配基本概念 1.1 IOS 设备的尺寸和分辨率 1.1.1 分辨率相关概念 1.1.2 IOS 各个设备对应的分辨率 1.2 设计和开发之间的多屏适配 ...
- Android 万能适配方案和UI屏幕适配 不同分辨率 最全面 最易懂的
文章目录 1.屏幕尺寸 2.屏幕分辨率 3.屏幕像素密度 4.图片的适配方案 1.屏幕尺寸 屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米(下面有图文介绍) 比如常见的屏幕尺寸有2.4 ...
最新文章
- javax.swing.jFrame
- SQL Server温故系列(1):SQL 数据操作 CRUD 之增删改合
- Windows Server 2003显示中文为乱码(方框)的问题
- MyBatis与Hibernate比较
- 数据库开发技术java方向_Java开发工程师(Web方向) - 03.数据库开发 - 第5章.MyBatis...
- [源码学习]调试Razor从哪里开始
- python中plot是什么意思_python中的plot函数是什么?
- BZOJ-2456-mode(思维题)
- 计算机的五笔咋么学,电脑五笔输入法怎么学
- 用x360ce,北通蓝牙手柄成功玩双人成行
- 关于win10桌面图标位置错乱的原因及解决办法
- 穷人思维」过渡到「富人思维」
- win10蓝牙功能不见了_Win10 2004更新了什么?新功能新特性汇总
- 服务器无备份位置可用,云服务器备份区域和可用区
- 索引失效的情况及解决(超详细)
- 免费视频播放器Video.js介绍
- 如何将MATLAB程序插入到.net(C#)中(流程以及常见错误总结)
- 微服务架构实践心得小结
- 比较出名的视频分享网站
- 微信公众号找不到模板消息