教育社区简介 教育社区简介
合育宝[音视频]常见问答 合育宝[音视频]常见问答
• 合育宝APP简介
合育宝应用程序是一款流媒体工具软件,支持在Android手机和平板设备上运行,借助这个APP您可以随时随地通过手机开展直播和录播活动,录播视频自动发布到教育资源公共服务平台上,可用于学生自学、教师评价、备课、教研和听课评课等各种日常教学场景。 核心功能 现场直播; 录播视频(支持字幕); 网络播放器. 如何播放网络视频 (直播流或者点播流) ? 进入 播放器 界面; 手工输入或者通过左侧的二维码扫码输入要观看的流媒体网址; 点击播放按钮开始播放. 如何直播 ? 点击屏幕右上角的 头像 图标,进入 我的 界面; 在 登录 栏内用手机免费注册一个账号,并登录; 在 账户与直播 栏内 一次性设置好 直播服务器、直播应用、推流密码和拉流密码四项参数,这些参数只需要设置一次; 在 账户与直播 栏内 填写直播预告内容,包括录播批次,直播预告标题,预告内容介绍,预计开始时间和预计结束时间六项参数,这些参数需要在每次直播前按照需要更改; 完成上述两项参数设置后,点击进入 直播台; 点击直播台底部的直播按钮开始直播. 录播文件在哪里 ? 点击 我的 界面中的 录播 栏目; 点击 标题 开始播放单个视频; 点击 批次 开始播放整批次视频; 点击 右箭头 编辑视频说明文本或者更改视频批次; 点击 分享 图标可以将视频网址通过其它社交软件分享给朋友; 点击 删除 图标可以删除该视频文件; 点击 [字幕] 给视频添加字幕(用本APP账号在合育宝网站登录). 读取更多关于合育宝APP简介 »
• 合育宝APP的目标用户是谁?提供哪些服务项目?
合育宝APP的目标用户是在校老师和在校学生,从来源上分为如下两种类型 第一类、普通个人用户:通过本APP或者合育宝网站注册的个人用户,此类用户没有绑定工作学校或者教育局; 第二类、集团化机构用户:通过释锐数字校园平台单独或者批量创建的学校用户,此类用户都至少绑定了一家工作学校或者教育局,甚至可以绑定有多家工作学校。 这两类用户的类型可以随时按需相互转换:个人用户一旦绑定了工作学校或教育局,就自动转换成机构用户;机构用户一旦取消了跟学校或者教育局的绑定关系,就自动变成个人用户。 合育宝APP为“普通个人用户”提供下列服务项目 主播服务:直播预告、空中直播、分享直播二维码; 观播服务:扫码看直播、扫码看点播; 录播服务:录制视频、人工字幕、VOD视频托管、视频分享。 合育宝APP为“集团化机构用户”提供下列服务项目 主播服务:直播预告、空中直播、分享直播二维码; 观播服务:扫码看直播、扫码看点播; 录播服务:录制视频、人工字幕、VOD视频托管、视频分享; 数字教育资源开发服务:创建视频类教育资源并自动发布到校内资源公共服务平台、资源编目; 数字教育资源应用服务:在线学习、网络备课、主题教研、听课评课、教育评价。 读取更多关于合育宝APP的目标用户是谁?提供哪些服务项目? »
• 合育宝APP 普通个人用户 使用总流程
合育宝APP 普通个人用户 使用总流程 步骤 事项 备注 1 下载并安装合育宝APP* 本APP支持Android5.0及以上版本,并且需要用户同意下列授权: 相机 - 使用摄像头采集视频信号; 麦克风 - 使用麦克风采集音频信号; 存储 - 临时存储二维码图像。 从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。 具体操作详见《如何 下载并安装合育宝APP?》 2 注册主播号* 用本人常用的手机号或者电子邮箱注册一个账号,该账号就是直播和录播视频时必需的主播号。 具体操作详见《如何 注册和登录合育宝APP?》 3 完善账户信息 完善“姓名、性别、邮箱、驻地省份”账户信息。 具体操作详见《如何 在合育宝APP内完善账户信息和修改登录密码?》 4 设置直播参数* 务必正确设置“直播服务器、直播应用、推流密码、拉流密码”这四项关键直播参数,如果这四项参数设置缺失或者有误,都会导致无法按照预期正常开展直播或录播活动。 具体操作详见《如何 设置合育宝APP的直播参数? 如何跟第三方推流和拉流工具对接?》 5 填写直播(含录播)预告 强烈建议用户无论是直播还是录播,都要提前填写直播预告表,直播预告表包括“录播批次、直播预告标题、直播内容、预计开始时间、预计结束时间”共五项。 具体操作详见《如何 在合育宝APP内填写直播(含录播)预告?》 6 音视频参数设置 专业用户可以在“设置”里设置“x264预设、分辨率、帧速率、比特率、聚焦模式、音频质量”这六项参数,这些参数影响直播视频或录播视频的质量。非专业用户可以不用做任何参数设置,系统默认的参数已经能够满足大部分的用户需求。 具体操作详见《如何 设置合育宝APP的音视频参数?》 7 开始直播或录播* 如果上述1,2,4,5四项准备工作都正确无误,这时就能进入“直播台”开启现场直播或录播工作了。 具体操作详见《如何 用合育宝APP或者第三方推流软件开展直播或录播活动?》 8 录播视频管理 只有在第4步“直播应用”启用了“RTMP直播及录播”功能,才能在“录播视频”中看到第7步录制的视频列表。在这里,能够回看视频、编辑“视频介绍文本、录播批次”、创建视频字幕、删除视频、分享视频链接。 具体操作详见《如何 管理和使用录播视频?》 9 播放器* 扫码观看直播视频或者录播视频,不但能看合育宝直播或录播视频源,还能看第三方直播平台提供的直播视频或录播视频。 具体操作详见《如何 使用合育宝自带网络媒体播放器观看直播和点播视频?》 10 分享APP 独乐乐,不如众乐乐,如果您觉得该APP不错,可以通过APP右上角的分享图标将该APP推荐给自己的好朋友。 具体操作详见《如何 分享合育宝APP给好友?》 读取更多关于合育宝APP 普通个人用户 使用总流程 »
• 合育宝APP 学校和教育局用户 使用总流程
合育宝APP 学校和教育局等集团化机构用户 使用总流程 步骤 事项 备注 1 学校或教育局购买释锐®教育资源公共服务平台以及相关应用系统* E01.教育资源公共服务平台,具体操作详见《释锐 教育资源公共服务平台 使用总流程》 E02.网络课程应用系统 E04.主题教研应用系统 E05.听课评课应用系统 释锐老客户可以免费升级至支持合育宝APP的最新版数字校园软件。 2 一次性导入批量创建教师、学生以及家长账号* 建议用手机号或者电子邮箱作为用户名,并且在导入模板的“手机、邮箱”栏填入有效的手机号码和电子邮箱。手机号和电子邮箱必须唯一,今后用于获取验证码和找回忘记的密码。 具体操作详见《释锐 教育资源公共服务平台 使用总流程 步骤9:导入式批量创建在校师生账号》。 3 自动创建合育宝APP账号* 校内用户登录校园平台时自动创建合育宝账号,用该账号就能在合育宝APP上登录了,无需在合育宝APP上再次注册。 4 下载并安装合育宝APP* 本APP支持Android5.0及以上版本,并且需要用户同意下列授权: 相机 - 使用摄像头采集视频信号; 麦克风 - 使用麦克风采集音频信号; 存储 - 临时存储二维码图像。 从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授予。 具体操作详见《如何 下载并安装合育宝APP?》 5 完善账户信息 完善“姓名、性别、邮箱、驻地省份”账户信息。 具体操作详见《如何 在合育宝APP内完善账户信息和修改登录密码?》 6 设置直播参数* 务必正确设置“直播服务器、直播应用、推流密码、拉流密码”这四项关键直播参数,如果这四项参数设置缺失或者有误,都会导致无法按照预期正常开展直播或录播活动; 确保选择本校或本教育局专用直播服务器以及启用“RTMP直播及录播”功能。 具体操作详见《如何 设置合育宝APP的直播参数? 如何跟第三方推流和拉流工具对接?》 7 填写直播(含录播)预告* 强烈建议用户无论是直播还是录播,都要提前填写直播预告表,直播预告表包括“录播批次、直播预告标题、直播内容、预计开始时间、预计结束时间”共五项。 具体操作详见《如何 在合育宝APP内填写直播(含录播)预告?》 8 音视频参数设置 专业用户可以在“设置”里设置“x264预设、分辨率、帧速率、比特率、聚焦模式、音频质量”这六项参数,这些参数影响直播视频或录播视频的质量。非专业用户可以不用做任何参数设置,系统默认的参数已经能够满足大部分的用户需求。 具体操作详见《如何 设置合育宝APP的音视频参数?》 9 开始直播或录播* 如果上述4,6,7三项准备工作都正确无误,这时就能进入“直播台”开启现场直播或录播工作了。 具体操作详见《如何 用合育宝APP或者第三方推流软件开展直播或录播活动?》 10 录播视频管理* 只有在第6步启用了“RTMP直播及录播”功能,才能在“录播视频”中看到第9步录制的视频列表。 在这里,能够回看视频、编辑“视频介绍文本、录播批次”、创建视频字幕、删除视频、分享视频链接。 机构用户专有功能: 每个录播视频会自动即时发布到第1步部署的教育资源公共服务平台上。 用户可以去资源平台的“个人中心”重新编目刚才录制的视频。 具体操作详见《如何 管理和使用录播视频?》以及具体操作详见《释锐 教育资源公共服务平台 使用总流程 步骤20:上传教学资源/专题资源》。 11 播放器* 扫码观看直播视频或者录播视频,不但能看合育宝直播或录播视频源,还能看第三方直播平台提供的直播视频或录播视频。 具体操作详见《如何 使用合育宝自带网络媒体播放器观看直播和点播视频?》 12 分享APP 独乐乐,不如众乐乐,如果您觉得该APP不错,可以通过APP右上角的分享图标将该APP推荐给自己的好朋友。 具体操作详见《如何 分享合育宝APP给好友?》 读取更多关于合育宝APP 学校和教育局用户 使用总流程 »
• 如何 下载并安装合育宝APP?
如何 下载并安装合育宝APP? 从合育宝官网下载(有效); 从下列安卓应用市场:2020年10月1日起陆续发布到下列应用商店 华为 应用市场 搜索 合育宝 安装; vivo 应用商店 搜索 合育宝 安装; oppo 应用商店 搜索 合育宝 安装; 小米 应用商店 搜索 合育宝 安装; 腾讯 应用宝 搜索 合育宝 安装; 360 应用商店 搜索 合育宝 安装; 百度 应用商店 搜索 合育宝 安装。 读取更多关于如何 下载并安装合育宝APP? »
• 如何 注册和登录合育宝APP?
如何 注册和登录合育宝APP? 打开合育宝APP; 点击图标; 点击"注册与登录"; 输入 手机号码 或者 电子邮箱地址,必须是您本人常用的手机号码和电子邮箱; 输入 长度不少于3个字的账号密码,推荐用 数字密码; 点击 “登录或注册账号” 按钮; 如果输入的手机号或电子邮箱已经存在,则登录验证,如果密码不对,自动显示"重置密码"(图2);如果手机号码或者电子邮箱不存在,则发送验证码,请查收手机短信或者邮件收件箱并输入 四位数字 验证码(图1); 再次点击 “登录或注册账号” 按钮,完成账号注册,该账号就是推流和拉流都要用到的主播号。 图1:注册手机号、登录密码、注册验证码 图2:重置密码 读取更多关于如何 注册和登录合育宝APP? »
• 如何 在合育宝APP内完善账户信息和修改登录密码?
打开合育宝APP; 点击图标; 点击"账户与直播"; 点击“密码”行最右侧的图标,修改登录密码,此处要求提供原密码; 点击“姓名”行最右侧的图标,修改姓名; 点击“性别”行最右侧的图标,修改性别; 点击“邮箱”行最右侧的图标,修改电子邮箱,请确保新输入的电子邮箱有效且未被占用; 点击“手机”行最右侧的图标,修改手机号码,请确保新输入的手机号码有效且未被占用; 点击“户籍省份”行最右侧的图标,修改您常住地省份(用户给系统自动分配所在地的直播服务器提供数据参考); 读取更多关于如何 在合育宝APP内完善账户信息和修改登录密码? »
• 如何 设置合育宝APP的直播参数? 如何跟第三方推流和拉流工具对接?
打开合育宝APP; 点击图标; 点击"账户与直播"; 点击“直播服务器”行最右侧的图标,修改直播服务器(直播服务器负责直播和录播服务),请商业用户不要选择 体验用流媒体服务器; 点击“直播应用”行最右侧的图标,修改直播应用(直播应用决定是否开启录播),请有录播需求的商业用户务必选择 RTMP直播及录播 这个应用,无录播需求的用户请选择 RTMP纯直播 应用; 点击“推流密码”行最右侧的图标,修改推流密码,密码长度不要超过6位,而且必须是数字密码(推流密码就是主播将音视频信号推送到直播服务器所需要的鉴权密码,格式 rtmp://直播服务器网址/直播应用名称/主播号?key=推流密码,直播服务器会拒绝推送密码不匹配的数据推送请求;注册账号时,系统会随机生成一个6位数字密码);主播既可以用合育宝APP直接推流,也能用OBS等第三方推流软件推流做直播,用此APP的账号(图1-账号)可以登录合育宝网站,查询本人的推流地址; 点击“拉推流密码”行最右侧的图标,修改拉流密码,密码长度不要超过6位,而且必须是数字密码(拉流密码就是观众看直播时必须输入的密码,格式 rtmp://直播服务器网址/直播应用名称/主播号?key=拉流密码,直播服务器会拒绝拉流密码不匹配的视频观看请求;注册账号时,系统会随机生成一个6位数字密码);主播可以将该拉流网址通过二维码分享给需要观看直播的人,这些人既可以用合育宝APP扫码观看直播,又可以用VLC等第三方网络播放器观看,用此APP的账号(图1第一行)可以登录合育宝网站,查询本人的拉流地址。 图1:设置直播参数 图2:用于OBS等第三方推流工具的推流地址和VLC等第三方拉流工具的拉流地址 读取更多关于如何 设置合育宝APP的直播参数? 如何跟第三方推流和拉流工具对接? »
• 如何 在合育宝APP内填写直播(含录播)预告?
打开合育宝APP; 点击图标; 点击"账户与直播"; 点击“录播批次”行最右侧的图标,修改即将要录播的批次号码,批次相同的视频代表是一组相互关联的视频; 点击“直播预告标题”行最右侧的图标,修改直播活动标题(字数限制64个),如果启用了录播功能,该标题自动成为录播视频的标题,如果部署了教育资源公共服务平台,该标题自动成为教育资源的标题; 点击“直播预告内容”行最右侧的图标,修改直播活动介绍(字数限制256个),如果启用了录播功能,该介绍自动成为录播视频的说明文字,如果部署了教育资源公共服务平台,该介绍自动成为教育资源的介绍; 点击“预计开始时间”行最右侧的图标,修改直播预计开始时间(图1:时间格式 yyyy-MM-dd HH:mm,精确到分钟,请严格按格式要求输入时间); 点击“预计结束时间”行最右侧的图标,修改直播预计结束时间(图2:时间格式 yyyy-MM-dd HH:mm,精确到分钟,请严格按格式要求输入时间)。 图1:预计开始时间 图2:预计结束时间 读取更多关于如何 在合育宝APP内填写直播(含录播)预告? »
• 如何 设置合育宝APP的音视频参数?
打开合育宝APP; 点击图标; 点击"设置"(图1); 点击“选择直播服务器”,修改直播服务器:直播推流所需,必填; 点击“选择直播应用”,修改直播应用:直播推流所需,必填; 点击“主播号”,修改主播号:直播推流所需,必填; 点击“推流码”,修改推流密码:直播推流所需,必填; 点击“拉流(观看)码”,修改拉流密码:直播拉流所需,必填; 点击“启用硬解码”开关,开启或者关闭硬解码模式,如果处于关闭状态,即采用软解码模式;【软编码:使用CPU进行编码和解码;硬编码:使用非CPU进行编码和解码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等】 点击“x264预设”,修改x264预设,详见外站《X264》; 点击“分辨率”,即Output Resolution,修改视频清晰度,详见本站《音视频中常出现的参数解释》; 点击“帧速率”,即Frame per second,修改视频画面每秒出现的帧数,详见本站《音视频中常出现的参数解释》; 点击“比特率”,即Video Bitrate码率,详见本站《音视频中常出现的参数解释》; 点击“聚焦模式”,即Focus Mode,修改摄像机镜头的聚焦模式,默认用“自动连续聚焦模式或自动聚焦模式”,拉伸镜头可以用特写模式; 点击“音频质量”,即Audio Quality,修改声音质量,详见本站《音视频中常出现的参数解释》; 点击“启用第三方RTMP服务器”开关,开启或者关闭使用第三方直播服务器选项,上述第4~8五项参数只对APP内置直播服务器有效,对第三方直播服务器无效,但是第9~15七项参数对第三方直播服务器也有效; 如果启用了第三方RTMP服务器(图2),则只需输入第三方服务器提供的推流地址即可(图3)。 图1:设置 图2:开启第三方RTMP直播服务器状态 图3:输入第三方直播服务器推流地址 读取更多关于如何 设置合育宝APP的音视频参数? »
• 如何 用合育宝APP或者第三方推流软件开展直播或录播活动?
如何 用合育宝APP开展直播或录播活动? 打开合育宝APP(图1); 点击“直播台”,在这里可以直播和录播(图2); 点击或者图标,切换到前置相机或者后置相机; 点击图标,可以拍照并保存照片到本地相册; 点击图标,开始直播或录播:支持横屏直播和竖屏直播,开始直播前请先调整屏幕方向,直播过程中不允许更改屏幕方向;支持镜头拉伸并自动转换成特写聚焦模式;支持人脸检测并自动聚焦到人脸区域;如果直播不能正常工作,请确认是否严格遵守了我们约定的使用流程,并且确认音视频参数是否设置合理; 点击图标,可以暂停直播或录播; 点击图标,恢复直播或录播; 点击图标,停止直播或录播; 点击图标,退出直播台,回到APP默认界面。 图1:合育宝APP中文版 图2:直播台 如何使用OBS等第三方推流软件开展直播或录播活动? 打开PC版OBS软件; 在OBS软件的推流设置处正确设置合育宝提供的推流地址(图3); 其它操作请参考OBS官方网站提供的操作手册。 图3:OBS自定义推流地址设置 读取更多关于如何 用合育宝APP或者第三方推流软件开展直播或录播活动? »
• 如何 管理和使用录播视频?
打开合育宝APP; 点击图标; 点击“录播视频”,这里会列出所有已经录制的视频列表(图1); 点击第一行右侧图标,修改视频简介,字数限制200字; 点击第二行右侧图标,修改录播批次,同一批次的视频可以批量连续播放; 点击图标,给视频添加字幕; 点击图标,通过微信等社交软件分享视频链接给好友; 点击图标,删除录播视频,删除前系统会再次确认,确认无误后系统会删除视频的录播数据,包括VOD服务器上的flv文件和mp4文件; 点击视频标题,调用本APP自带的网络媒体播放器播放本条录播视频; 点击“第1批”文字,调用本APP自带的网络媒体播放器播放本批次所有录播视频。 图1:录播视频列表 读取更多关于如何 管理和使用录播视频? »
• 如何 使用合育宝自带网络媒体播放器观看直播和点播视频?
打开合育宝APP; 点击“播放器”,在这里可以观看直播和录播视频(图1),其中,支持的直播视频有RTMP,HLS和DASH三种格式,点播视频有HLS,MP4和FLV三种格式; 点击图标,扫码输入待观看的视频地址并且直接调用播放器自动播放,可能是一个直播视频拉流地址,也可能是一个VOD视频点播地址,扫入的地址会自动保存到地址输入框内; 如果不用扫码输入,还能直接在输入框内手工输入视频地址,并且按圆形按钮开始播放,如果是VOD点播视频,本播放器能够显示字幕; 长按屏幕底部的二维码图形,可以分享当前用户的直播观看码给好友,好友用APP播放器扫码就可观看本人的直播。 图1:扫二维码或者手工输入待播放视频地址(含直播拉流地址) 图2:二维码扫码界面 读取更多关于如何 使用合育宝自带网络媒体播放器观看直播和点播视频? »
• 如何 分享合育宝APP给好友?
打开合育宝APP; 点击图标,可以选择微信和手机短信等多种方式将该APP的下载网址分享给您的好友; 独乐乐,不如众乐乐,合育宝APP不是一个娱乐性产品,但是能给师生们带来愉悦的工作体验和学习乐趣。 读取更多关于如何 分享合育宝APP给好友? »
• 释锐 教育资源公共服务平台 使用总流程
释锐 教育资源公共服务平台 使用总流程 步骤 事项 备注 1 购买释锐教育资源公共服务平台软件* 厂家直销电话 021-60753206 厂家直销手机 13918751467 厂家直销微信 13918751467 厂家直销QQ 1831571813 网络留言咨询 https://access.threeoa.com/assistant?21 2 创建学年和学期* 【在教育标准系统内操作】学年学期是学校专属时间单位,平台内的所有教职工、学生以及家长这三类用户都要求有特定的时间段,没有时间段的用户账号是没有意义的,所以,在创建平台用户之前,必须创建好学年和学期。 此项工作包括学年管理、学期管理以及学期开学和放假日期的管理,该模块要求强制操作,设置错误或者未设置都会导致系统不能正常运行。 3 设置权限* 【在教育标准系统内操作】控制用户按照需要来使用系统,确保只有被授权的人才能使用被授权的应用和功能,产品提供四种授权方式:应用授权、组织授权、角色授权和用户授权。 4 创建年级* 【在用户与组织系统内操作】从“添加/年级”进入,系统已经内置了从幼儿园托班到博士研究生四年级共44个年级可供选择开通,请按照学校的实际情况勾选相关年级,保存开通即可。 5 创建课程与教研组* 【在教育标准系统内操作】创建各个年级开设的课程信息,该模块要求强制操作,设置错误或者未设置都会导致资源编目等很多系统不能正常工作;选择“学科”视图,可以在此快捷创建各学科对应的教研组。 6 设置当前学年和学期* 【在教育标准系统内操作】指定当前时间是哪个学年和哪个学期。 7 创建学校类组织 【在用户与组织系统内操作】从“添加/学校”进入,按照规定格式逐个创建教育局下辖学校类组织,区域版平台专有功能,学校版平台无此项功能。 8 创建教研组 【在用户与组织系统内操作】从“添加/教研组”进入,按照规定格式逐个创建教研组,也可以在本教程第5步骤内便捷化创建。 9 导入式批量创建在校师生账号* 【在用户与组织系统内操作】从“批量导入”进入,下载Excel格式的导入模板,填写必填用户信息,一次性导入并创建所有用户。导入时可以按教研组和学校分组。 具体操作详见《如何 批量导入用户?》。 10 用户分组 【在用户与组织系统内操作】点击待编入的组织名称,点击“添加”用户,选择要加入的一个或多个用户提交“添加”按钮即可,该操作可以在本教程第9步便捷化完成。 11 指定用户的组织角色* 【在用户与组织系统内操作】对于“教研组长”等在组织内部担任管理类角色的成员,需要单独指定成员角色。 12 学期升级* 每到一个新的学期,需要执行“学生升级到新学期”这项常规工作,一共两个步骤,详见官方教育社区精华帖子《软件到了新学期需要做哪些工作》。 13 学年升级* 每到一个新的学年,需要处理“学生毕业、学生升级、新生入学”三项常规性工作,一共六个步骤,详见官方教育社区精华帖子《软件到了新学年需要做哪些工作》 14 配置资源专用文件服务器 教育资源系统的每一个资源都是一个物理文件,不但文件数量增长快速,而且这些文件普遍较大,尤其是视频资源,小则200MB,大则1GB都是有的,这样,用不了多久,存储容量就满了,因此,需要有添加新存储设备的功能。 为了管理海量资源类文件,必须采用数字化学习专用的文件服务器来管理这些文件,而且要能够随时添加新的存储设备,实现存储规模的不断扩展和文件存取动态管理。 在教育资源后台管理系统中,有一个“FTP服务器管理”模块,在这里按需添加新的FTP服务器,禁用存储空间已满的文件服务器(禁用后的FTP服务器只是不能提供存文件服务,原有的读取文件服务功能还能继续用)。 15 配置教学资源标签 资源标签管理包括“教学资源标签、专题资源标签、主题教研类型、教研任务类型”的维护,系统在首次运行时会初始化内置标签,系统正式上线前,管理员老师务必在此增删改,确保符合学校的本地化需求。 教学资源标签:教学资源编目时用到,用于给教学资源指定一个标签。 专题资源标签:专题资源编目时用到,用于给专题资源指定一个标签。 主题教研类型:创建新的教研活动时用到,用来指明当前创建的教研活动是哪种类型,内置类型有“课例研讨、教学反思、教育教学叙事、专题研讨、临堂会诊、…”等13种类型。 教研任务类型:添加教研任务时用到,用来指明当前教研任务是哪种类型,内置类型有“计划方案、进展记录、完成汇报”。 16 配置专题资源标签 详见本教程第15条。 17 配置教材目录 教材目录(又名知识库)是一个树状分布图,用于给教学资源编目时指定教材章节和知识点,知识库的组织结构从上到下依次为年级、学科、章节和知识点。 其中,年级在“用户与组织系统”中创建;学科和学期在“基础信息管理系统”中创建;在配置教材目录之前,必须先在上述两个系统中把“年级、学科、学期”数据创建好。 如何采用批量导入方式快速创建教材目录? 第1步:点击年级; 第2步:点击学科; 第3步:点击学期; 第4步:点击学期后面的“批量导入”图标; 第5步:下载批量导入模板文件,是一个XML文件; 第6步:用支持XML格式的文本编辑器编辑教材目录; 第7步:选择编辑后的XML文件,然后“提交”。 18 配置专题资源目录 专题资源目录是一个树状分布图,用于专题资源编目时指定专题资源归类,目录采用树形结构,可以按需无限级创建,支持批量导入和导出,模板文件是XML格式。 在上传专题资源前,务必先创建好专题资源目录,否则,无法编目。 19 发布教育资源公共服务平台上线公告 教育资源后台管理系统提供一个简易信息发布模块,用于发布与资源平台相关的通知和公告,例如:资源平台上线公告、资源平台使用方法教程等,这些公告会显示在资源平台首页位置。 20 上传教学资源/专题资源 任何教职工都有权上传自己的教育资源,系统暂时禁止学生和家长类用户上传资源;上传共分为两个操作步骤: 第1步:选择本地电脑上的一个文件,将该文件上传到资源服务器上; 第2步:对文件进行编目标注,只有标注过的文件才能成为一个有用的教育资源。 在编目教育资源时必须指定该资源的共享范围: 私有:该资源只能上传人本人看到和使用; 校内共享:本校所有用户(包括学生和家长用户)都可以看到该资源; 区域共享:整个区域(教育局)的用户都能看到该资源。 在编目教育资源时必须指定教材目录或专题目录,目录越详细越好,标签越准确越好。 在编目教育资源时还可以指定资源价格,价格的单位是“积分”,除了上传者本人之外,其他人需要使用该资源,都必须先购买才能使用,价格为零的资源也需要购买,只不过支付的积分是零而已。 资源编目就是给文件标注数据,常用标注项目如下: 资源标题 资源简介 资源类型 教材章节/教材编目/专题资源编目 存放文件夹 教学/专题资源标签 自定义标签 公开范围 是否原创 资源价格 合育宝音视频专享功能: 如果用户所在的学校或者教育局采用了合育宝录播系统,直播或者录播视频无需上传,自动发布到本教育资源公共服务平台上。 21 视频文件格式自动转换 任何资源文件在完成了上传步骤之后,自动进入系统的文件格式转换队列,排队等待格式转换;只有格式转换成功之后的文件才能在windows平台,android平台以及ios平台平台的多种设备上在线打开和播放。 所有视频文件都会通过FFmpeg转码统一转换成mp4格式,同时打上客户指定的LOGO水印,源文件也保留;所有Flash文件都当作视频文件来处理,但是无需格式转换;所有文档类文件(包括图片)都会统一转换为pdf文件,源文件也保留。 资源压缩文件上传之后,无需格式转换,也无法在线阅读或者在线播放。 视频转码以及文档格式转换等动作都需要占用服务器大量的CPU资源,而服务器资源大多数情况下都是非常有限的,为了应对突然有大量老师同一时间上传了大量的资源文件,防止服务器资源耗尽,系统设计了基于异步消息系统的队列技术,在同一时间,只处理数量有限的文件格式转码,而将其它文件按上传的先后顺序依次排队,系统完成了上一批文件的格式转换之后,会遵守FIFO(First Input First Output)原则,自动处理下一批文件。 如果格式转换不如预期,失败或者其它问题,上传人可以申请“重新转换”,系统会将该文件重新加入到转换队列尾部。 22 资源审核 任何一个资源,在成功上传之后,如果格式转换失败,就不会交付审核,这时需要提醒上传人重新上传,或者重新提交格式转换申请,一旦格式转换成功则会进入教育资源后台管理系统的“资源上线审核”列表,等待学科管理员来审核。审核资源时,审核管理员可以执行下列操作。 在线查看:上线前,审核管理员有权在线阅读或在线播放被审核的资源内容、质量和标注; 同意上线:只有内容充实、质量合格、编目合理的资源才允许公开上线,同意上线后,系统会给上传人发送一封站内信,并且发放一定数额的积分,以资鼓励; 拒绝上线:应该禁止那些内容空洞、质量低劣、编目文不对题的资源上线,资源被拒绝上线后,系统会给上传人发送一封“站内信”说明拒绝理由,并且会扣除一定数额的积分,以示惩罚; 重新转码:如果有需要,审核管理员可以将指定资源申请重新加入转换队列; 取消共享:管理员有权改变资源的区域共享范围,确保区域共享的资源都是精品资源;私有共享范围的文件不在此管理范畴之内。 23 资源上线 任何一条教育资源在通过了审核管理员的审核之后,就代表正式上线了。上线后的资源可以被查找,被搜索,被查看,被播放,被购买,被下载,被引用、被评价。 24 查找资源 系统提供“按目录找资源、关键词搜索、按人找资源、按标签找资源、按时间找资源、按下载量找资源、按格式找资源”等多种查找资源的方式,尽管有那么多查找资源的方式,我们还是首推“按目录找资源”方法,因为这种方法采用树形分支法,跟教材目录配套,操作简单,查找效率最高。 怎样“按目录找教学资源”? 第1步:选定学科; 第2步:选定年级和学期; 第3步:选定课文; 第4步:选定课文的知识点; 第5步:从资源列表中选择一个教学资源,打开预览。 怎样“按目录找专题资源”? 第1步:选定一级目录; 第2步:选定二级目录; 第3步:选定三级目录; 第4步:选定四级目录; 第5步:从专题资源列表中选择一个专题资源,打开预览。 25 在线预览资源 找到资源之后,点击资源标题,就能进入“预览资源”窗口,通过预览资源,可以: 在线查看或者在线播放资源内容,了解资源的用途; 提交访客留言,发表你对该资源的看法和评论; 查看买家提问,了解购买过该资源的用户向卖家提出过哪些问题,卖家又是如何回复的; 查看买家点评,了解每一位买家(买家指花费金币购买了该资源使用权的老师或学生,下同)对该资源的质量评价星级及评分理由,该评价最重要,每位买家有且只有一次机会打分评价,而且该评价会直接影响卖家(卖家是指资源的上传人,下同)的信用总分; 购买该资源,不论资源标价是多少,哪怕免费,如果要用该资源,一定要购买之后才能在线使用,如何使用资源?详见“使用资源”章节。 26 购买资源 在预览资源窗口,如果当前用户不是资源的拥有者(上传人),也还未购买过该资源,就能点击“购买”按钮,用积分购买该资源,每一次成功购买都发生了下面一系列动作: 给买卖双方共同创建一条交易记录,记载了买家、卖家、交易标的资源、交易时间以及交易价格; 给卖家创建了一条收费记录; 给买家创建了一条付费记录; 给买家创建了一条资源评价记录,用于给资源质量评星级; 给买家创建了一条针对卖家的信用评价记录。 27 使用资源 本人上传的资源以及通过购买买过来的其他老师的教学资源和专题资源都可以被使用,资源的主要用途如下。 备课资源:如果要开设网络课程,教育资源是最主要的备课资源之一; 教研文档:如果要参加主题教研活动,教育资源是唯一的教研文档来源; 听课和评课课程:参加优质课评课活动的老师,可以将教育资源直接作为活动作品来提交,供专家评委来听课打分; 作业资源:给学生布置日常作业,也可以将教育资源直接作为作业布置给学生; 下载源文件:将资源的源文件下载到本地电脑,另作他用。 28 评价资源 一个教育资源接受多种方式的评价反馈,其中,最权威的评价来自买家的评价,一个资源好不好,主要由使用者说了算,买家能够从定量和定性两个方面对一个资源进行评价。 定量评价:“好、中、差”信用评价,该评价机会有且只有一次,“好评”给卖家信用加3分,“中评”给卖家信用加1分,“差评”给卖家信用减1分; 定性评价:不限次数的文字点评,可供其他浏览者参考。 读取更多关于释锐 教育资源公共服务平台 使用总流程 »
• 释锐 网络课程应用系统 使用总流程
释锐 网络课程应用系统 使用总流程 步骤 事项 备注 1 考题入库 【在 网络课程频道-我的课程-测验试题 模块内操作】开课教师将常用考题预先录入个人考题库,以供制作考卷时所用。 具体操作详见《如何 添加考题?》 2 制作考卷 【在 网络课程频道-我的课程-测验试卷 模块内操作】开课教师从第1步骤创建的试题库中选择部分考题组成一张试卷,以供备课时所用。 具体操作详见《如何 创建考卷?》 3 教师开课* 在教师个人网络课程管理入口,点击“开设新课”就能开设一门新的网络课程,开课时,请务必指定课程适用的“年级、学科、课文、知识点”,为个性化推送提供线索,网络课程的主要信息如下: 课程标题 课程简介 课程封面图片 课程公开范围 课程适用年级 课程适用学科 课程适用章节(课文) 课程涵盖的知识点 4 教师备课* 开课只是创建了一个课程框架,通过备课才能完成课程教学内容的填充工作,备课流程如下。 第1步:创建课程目录(章节),每一个学习任务必须归属于一个章节,因此,在添加具体的学习任务前,必须先创建好课程的整体任务分段(章节),建议按课时分段,每一段就是一个课时; 第2步:按学习先后顺序添加学习任务,目前系统支持四种学习任务类型,分别是:资源类,测验类,文本类,视频直播类。 如何添加“资源类”学习任务? 从“我上传的资源”或者“我购买的资源”中选择其中的一个教育资源添加为课程的一个学习任务,资源可以是教学资源,也可以是专题资源。 如何添加“文本类”学习任务? 直接在网页编辑器上在线编写学习内容文本和学习要求,将该文章作为一个学习任务添加到课程中。 如何添加“视频直播类”学习任务? 通过添加“文本类”学习任务来实现,将直播时间、直播内容简介以及直播二维码发布到文本框内即可,学生或教师可以用合育宝APP或者VLC等网络流媒体播放软件观看;直播结束后,备课老师务必修改文本内容,将直播网址更改为回看网址。 其中,直播活动由Live视频直播系统提供支持。 如何添加“测验类”学习任务? 在添加“测验类”学习任务前,先按照“制作考卷流程”创建一个在线考卷;然后,进入课程的备课模块,添加“考试测验”类学习任务,选择一个考卷即可。 第3步:预览并发布课程 备课工作做完之后,通过课程预览确认课程学习内容以及学习先后顺序无误后,点击“发布课程,就代表该课程已经正式上线了,只有正式上线的课程才能被学生们看到和选择。 5 推荐课程 备课完成之后,开课老师将课程推荐给学生,被推荐的课程在学生选课时会有红点提示。 推荐课程时以班级为单位批量推送,无需选择一个一个学生,可以同时推荐给多个班级。 网络课程不同于线下课程,推荐学习不等于强制学习,不被推荐的学生也可以选择加入学习;是否选修该课程完全取决于学生的个人意愿和课程质量以及开课老师的声望。 6 在线上课 从数字化学习方式与传统学习方式的对比图可知,在数字化学习方式之下,教师的课堂工作重心从原来的“单向讲课”为主变成“互动课堂和个别化答疑解惑”为主,学习中的问题优先通过学生自主学习和同学间的协作式学习方式来完成,教师通过对学习大数据的分析,找出共性问题进行统一讲解和统一答疑解惑,而个别化学习问题则通过一对一方式来解决,正所谓因材施教教育法,讲解和答疑的方式首推合育宝APP。 下面简述教师上网络课程的工作内容和上课步骤。 第1步,查看课程分析报告,课程报告由五个部分构成,详见后续章节“学习大数据-课程分析报告”; 第2步,根据课程分析报告了解学生的整体学习情况,找出共性问题; 第3步,通过直播教学讲解共性问题,共性问题集体上课; 第4步,通过一对一互动以及一对一直播教学方式,解决个性化学习问题。 学习大数据从教师开课、备课、上课以及学生网上自主学习的过程中自动采集而来,是数字化学习的客观体现;学习大数据通过 “整体学情分析报告、教师开课报告、课程分析报告、课程学习报告、学生学习报告”五个主要报告来分析和呈现学习数据,根据学生在线考试测评结果实现个性化课程推送。学习大数据报告内容另附。 7 学生选老师* 网络课程从选老师开始,老师照片右上角“推荐[3]”代表该教师向“我”推荐了3门课程。 8 学生选课程 选择好老师之后,系统会列出该老师的所有网络课程,学生可以选择其中的任何一门课程,选择并加入该课程,带“荐”标记的课程代表老师推荐过该课程给让我学习;首次进入课程学习窗口前,系统会向学生确认一下是否真的要选修该网络课程。 9 学生自主学习* 学生能够随时点击“待学课程/在学课程”列表,进入课程的在线学习窗口,按顺序通过自主学习和协作式学习来完成老师布置的所有学习任务,完成在线测验,通过测验结果来检验本人的学习效果。 学习过程中,如果碰到困难,可以从“学习讨论,学习笔记,课程群”内寻找答案和帮助,碰到学习问题可以记笔记、提交学习求助问题,寻求老师和同学们的协助。 10 学生自我测验 学习效果如何,不能凭感觉,而需要通过老师布置的在线作业和在线测验来检验,只有测验结果得满分,才能证明自己圆满完成了该课程的学习任务;如果有错题,系统会根据错题集,推荐相关学习资料,请务必继续完成后面的推荐课程,直至该课程覆盖的知识点完全掌握为止(以在线测验无错题为标准)。 11 个性化推送 系统根据第10步骤的测验错题集推荐相关学习资源,含教学资源、专题资源和网络课程。 读取更多关于释锐 网络课程应用系统 使用总流程 »
• 释锐 主题教研应用系统 使用总流程
释锐 主题教研应用系统 使用总流程 步骤 事项 备注 1 教研系统授权 管理教研系统内部权限,包括“年级、教研组、学校”三种教研权限;被授权的“年级”角色能看到归属年级下的所有教研活动, 被授权的“教研组”角色能看到归属教研组下的所有教研活动, 被授权的“学校”角色能看到归属学校的所有教研活动。 教研系统管理员授权不在该模块内,需要在“基础信息管理系统”的权限管理模块中授权。 2 创建教研活动 包括邀请参与人、评价人、负责人。 点击“新建教研”,进入新建教研页面,按照表单提示填写完表单内容就能创建一个新的教研活动。 大部分情况下,教研活动的创建是由学校的教研组长或者教育学院的教研员老师来完成的,但是,系统允许任何老师在教研平台上创建教研活动,唯一的区别是普通老师只能创建自主教研活动,而授权的教研员才能创建校本教研活动和区级教研活动。 “自主教研”活动类型:普通教师发起创建,不需要管理员审核,创建老师可以邀请本校任何老师自由参与该教研活动。 “校本教研”活动类型:教研组负责人发起创建,需要教研管理员审核,可以邀请本校相关教师参与,一般是学校的官方教研活动。 “区域教研”:由教育学院的专业老师发起创建,需要区域教研管理员审核,可以邀请全区域内的相关教师参与,一般是教育局的官方教研活动(学校端的用户可以申请加入区域教研活动)。 活动主题:可在“资源后台管理系统—资源管理—资源标签管理—主题教研类型”模块中统一设置,根据学校或活动实际需要统一修改增删;创建教研活动时需要指定主题。 教研标题:为了方便查找标题名称请按建议格式去做,格式: 时间(X月X日)+范围[如年级、联校]+学科+活动名称,如:7月20日三年级(下)数学《观察物体》。 教研描述:把本次活动的任务和流程等信息公示,让活动的全体参与人员根据描述就知道大体工作计划和安排,如活动流程、时间和人员安排等。 “评价模式”教研模式:在任务结束前,相互不能查看评论,防止相互模仿、复制;校本教研、资源建设要选择这个模式。 “讨论模式”教研模式:参与人提交评论就可相互查看,适用于需要时时交流、讨论式的活动和自主教研。 教研负责人:权限等同发起人,便于组织活动开展,活动的发起人默认就是教研负责人。 教研参与人:参与人负责执行教研任务事件中规定的上传资料、讨论和评价等工作。 教研评价人:评价人有权给教研活动整体质量打分,给每一个任务事件的完成结果打分;一般情况下,除了活动的发起人、负责人和参与人外,其他人是没有权限观看该教研活动的;唯独评价人可以对整个活动过程有查看、监督和评价的权限,主要是方便进行活动考核量化。 3 活动审批 新建的教研活动都需要经过教研管理员的审核方可上线;审核列表会列出教研活动的类型、标题、创建时间、完成时间、负责人、参与人数、审核状况(待审核、通过、关闭、未通过)等信息。 “通过”表示该教研活动已通过审核,允许上线开展活动。 “未通过”表示该教研活动未通过审核,不能上线开展活动。 “关闭”表示该教研活动已通过审核,并且已经结束该教研活动。 “待审核”表示该教研活动正在等待审核过程中。 4 添加任务事件 任务事件是教研活动的核心部分。根据活动内容和流程的不同,将活动拆分成不同的环节,为每个环节建立一个独立的任务事件,教研活动就在任务事件窗口中进行。 在教研活动详情列表点击活动概况下方或右方“任务事件”,可查看到任务事件列表。 举例说明,一个“磨课”教研活动的可以拆分成以下四个环节: 第1环节,第一次备课; 第2环节,第二次备课及第一次评课; 第3环节,第三次备课和第二次评课; 第4环节,总结。 这样就需要先后建立三个任务事件,最后可以根据需要建立第四步的总结和心得体会,并上传教研总结和教师交流的心得体会;如果不需要交流及心得体会,可以直接用教研活动中的总结来替代。 点击“添加任务事件”按钮,开始添加教研任务事件,按要求填写表单内容即可; 注:若无特定任务,任务事件参与人默认与教研活动参与人一致。 5 申请参与 申请参与一个教研活动成为该活动的参与人有两种方式,第一种方式由活动发起人主动邀请加入,第二种方式由申请人申请加入,然后等待活动负责人核准同意。 操作状态显示“申请中....”表示申请请求已发送尚未得到答复; 操作状态显示“进入主题”表示申请已经活动通过,可以参与了; 操作状态显示“申请未通过”表示申请未通过,不能参与此次活动。 6 批准参与 教研活动负责人负责审核“申请加入”请求,点击“操作”,再点击“申请”,进入审核页面。在审核页面可查看申请人员人姓名以及申请时间,点击“同意/不同意”按钮,确定是否允许申请人参与此次教研活动。 7 参与人执行教研活动任务 在教研活动详情页中点击任务事件,展示任务事件列表及其参与人。 红色字体表示此任务还没有完成,点击成员姓名或任务名称,进入任务详情页面,以便完成该任务事件所要求的工作。 在任务详情页面,点击“选择资源”按钮上传教研资源,可以给上传的任务资源和文档定量评分和定性评论,点击“提交”按钮代表该任务事件已经完成。 文档区用于存放活动要求上传的文档,文档格式支持word、excel、ppt、pdf、MP4视频等各种文件(上传的文档自动进入教育资源系统),在文档区可以在线预览、下载和删除这些文档。 8 评价人对教研效果进行评价和讨论 活动评价展示此次教研活动的评价以及各个教研任务事件完成质量的评价。 左侧第一条是教研活动的整体评价和平均评价分,而第二条及后面所有条目则是对各条教研任务事件的质量评价。 当前任务的所有参与者都能通过“群聊”方式参与在线讨论,聊天交流时可以拍照传图,并能导出所有教研讨论记录。 9 负责人总结活动 活动负责人在教研活动结束后,进行活动总结。可在教研活动列表中点击“操作-总结活动”或在教研详情页面点击“总结活动”按钮,填写教研总结表单提交即可。 10 负责人关闭任务和关闭活动 如果一个任务事件的所有工作都完成之后,负责人负责点击“完成任务”按钮来关闭该任务事件,一个任务关闭了之后,就封存不能改动了。 如有需要,可以再次“开启任务”进入编辑和讨论状态。 只有活动的发起者/负责人才能总结活动完成,活动结束后所有的任务事件、文档、在线讨论等可以导出PDF存档。点击完成活动,代表本次教研活动全部结束,不再更新。 读取更多关于释锐 主题教研应用系统 使用总流程 »
• 释锐 听课评课应用系统 使用总流程
释锐 听课评课应用系统 使用总流程 步骤 事项 备注 1 创建评课方案 评课方案就是一套评价课堂的打分标准,由“评估方案和评估技能”构成。 评估方案需要指定方案名称、方案描述和排序序号,可以按需创建多套评估方案,每套评估方案都必须指定合适的评估技能,包括主技能和子技能,每项技能都要有明确的能描述、分值和序号。 2 创建评课活动 开展一次听课评课活动都需要创建一个评课活动,评课活动包含了下列基本信息。 活动主题 报名开始时间 报名截止时间 评估方案,此项特别重要,是量化指标 评选标准,评分标准的文字详细说明 活动说明 3 报名开始 在报名有效期内,受邀老师都能报名参加。 在评课系统首页,选择正在报名中的活动,进入活动之后点击“报名参赛”按钮;报名成功后,务必在规定的时间段内提供参赛作品;参赛作品可以是一门网络课程,也可以是一个教学资源,也可以是一个专题资源;如果要做直播评课,则只能选择一个指定直播地址的在线资源,而不能选择一门网络课程。 4 教师报名参加 在报名有效期内,受邀老师都能报名参加。 在评课系统首页,选择正在报名中的活动,进入活动之后点击“报名参赛”按钮;报名成功后,务必在规定的时间段内提供参赛作品;参赛作品可以是一门网络课程,也可以是一个教学资源,也可以是一个专题资源。 5 报名截止 报名截止日期过后,就不能报名了。 6 评课开始 报名截止之后,自动进入评课时间。 7 评委评课 在评课时间段内(直播评课时间必须跟参赛老师的上课时间一致),受邀评委老师完成“在线听课、在线评课(按评估方案打分)和填写听课记录/评课建议”等评课工作。 每一位评委完成评课后,都会给参赛老师一个评分,系统自动计算该参赛作品的总得分和平均得分。 8 评课结束 评课结束后,评委和参赛老师都能看到听课记录表,记录表内详细记载了每位评委的评课详情以及打分细项。 9 结果公示 评课截止时间到,就代表评课结束,评课结束后,需要由管理员主动执行“结果公示”操作,填写完评课公示之后,才能公示本次活动的最终排名结果。 读取更多关于释锐 听课评课应用系统 使用总流程 »
• 如何 用VLC和微信APP看合育宝直播视频?
如何用电脑版VLC工具观看合育宝直播? 从VLC官网下载并安装好VLC Player软件; 打开VLC Player软件; 点击“媒体-打开网络串流”菜单; 输入 rtmp://live.heyubao.com/live/139****4057?key=06***2 或者 https://heyubao.com/hls/139****4057.m3u8 格式的网络URL,点击播放即可观看合育宝直播视频。 如何用手机版VLC工具观看合育宝直播? 从苹果手机的 app store 或者 安卓 应用商店搜索 VLC for mobile 手机应用程序,并且安装好该APP; 打开VLC应用程序; 点击“网络-打开网络串流”栏目; 输入 rtmp://live.heyubao.com/live/139****4057?key=06***2 或者 https://heyubao.com/hls/139****4057.m3u8 格式的网络URL,点击“打开网络串流”按钮即可观看合育宝直播视频。 如何用微信APP观看合育宝直播? 打开微信APP; 搜索并打开 腾讯视频云 小程序; 点击 直播播放; 扫码 rtmp://live.heyubao.com/live/139****4057?key=06***2 格式的合育宝直播视频源 二维码,好像不支持 m3u8格式的直播视频源; 点击 播放 即可观看合育宝直播视频。 读取更多关于如何 用VLC和微信APP看合育宝直播视频? »
• 如何 发布直播资源并开展在线直播评课活动?
如何 开展网络直播评课活动? 开展网络直播评课活动的总流程跟《释锐 听课评课应用系统 使用总流程》基本一致,但是有两点需要特别注意: 第一点,参赛教师在提交参赛作品时必须【创建一个直播类教育资源】,该资源要预先发布并且完成审核工作; 第二点,由于是直播评课,评委必须在老师上课的时间段内完成评课,评课方式跟录播视频评课完全一样,直播视频可能有20秒左右的时间延迟。 如何创建一个直播视频类在线教育资源? 图1:HLS直播拉流网址 第1步:图1所示,登录云桌面系统,进入“我的个人资料-音视频”栏目,找到您的HLS直播拉流网址(如果空,代表手机号无效,填上有效的手机号即可开通),格式 https://XXX/YYY/ZZZ.m3u8,其中,XXX是直播服务器地址,YYY是直播应用地址(hls代表只直播不录播,hls4vip代表直播结束后自动录播,请在厂家指导下设置音视频参数),ZZZ是流媒体名称,一般是您的注册手机号或者电子邮件地址; 图2:发布一个直播视频类教育资源 第2步:图2所示,进入“教育资源公共服务平台-上传资源”页面,将第1步找到的HLS直播拉流网址填入资源输入框内(切记不要点击“选择一个资源文件”按钮); 图3:发布直播时间预告和活动封面图 第3步:图3所示,进入“ 第2步:首次编目资源”,完善画圈处的内容,尤其是 直播时间预告; 第4步:等待管理员审核通过,上线后即可作为参赛作品报名参赛评课; 图4:直播前评委评课界面(上课直播开始30秒之内,评委就能看到直播画面) 第5步:图4所示,上课的时间,评委远程同步参与评课。 读取更多关于如何 发布直播资源并开展在线直播评课活动? »
最近社区帖子 最近社区帖子
• Ping heyubao.com unknown host
现象:在公司的203.*.*.40服务器上Ping heyubao.com 出现 unknown host,但是ping baidu.com正常。 原因:/etc/resolv.conf 中的 nameserver 设置不对。 解决方案:vi /etc/resolv.conf ,修改dns服务器ip地址即可。 读取更多关于Ping heyubao.com unknown host »
• Nginx CORS 跨域解决方案
Cross Origin Resource Sharing (CORS) is a mechanism that is used by browsers, primarily to validate permissions for access to content from a different origin. What is CORS? When a browser loads a web page, it enforces the Same-origin Policy, which means that it only allows content to be fetched from the same origin as the web page. However, in some cases, a web page might need access to assets from multiple origins that trust that website. This is where CORS comes in. This security mechanism exists only if an application has or is an HTTP client, and if that application implements CORS. Nearly all modern browsers, such as Chrome, Firefox, and Safari, implement CORS. To clarify, an origin with respect to CORS does not have to be the same as a CDN origin. An origin in CORS is defined by a URI scheme, domain, and any possible port number. For example, https://www.example.com:1443 is a different origin than http://www.example.com. And so, a CDN can also be considered as a CORS origin from a browser's perspective. How CORS works CORS can handle two types of requests: simple requests and preflighted requests, which are more complex. Simple requests First request (resource access): Simple requests through CORS are either GET or POST requests from the web page of one origin that's attempting to gain access to the URL of another origin for resources. When making such a request, the browser automatically sets CORS request headers. Primarily, it sets the origin of the web page making the request in the Origin HTTP header, automatically. The CORS request also can contain a set of certain, standard HTTP headers , while maintaining its status as a simple CORS request, from the browser's perspective. The server that receives the CORS request processes the request, and might send a set of CORS response headers back to the browser, with the requested content. These CORS response headers contain values specifying whether the current web page is allowed access to those resources, whether the headers sent are acceptable for that request, and so forth. If the browser is unable to see its CORS request satisfied by the CORS response headers, it automatically prevents the access to and loading of the content. Otherwise, it sees that the CORS origin is giving permission to use the resource, and it allows the access to and loading of the requested content. Preflighted requests First request (preflight): Second request (resource access): For more complex CORS communication between the browser and a CORS origin that's different than the requesting web page, a preflight request is required before an actual resource access. Certain situations might require preflighting CORS requests, such as HTTP methods that are not GET or POST methods, or using non-standard HTTP headers with the request - even if it is a GET or POST request, and so forth. If a preflight request is needed, here's how the events unfold: The browser sends a request using the HTTP OPTIONS method to the server with all of the intended CORS request headers. The server processes those CORS request headers, and can respond with CORS response headers containing no actual content data. The browser checks those CORS response headers to make sure that the CORS request is allowed. If the browser sees that the intended resource request should be allowed by the server, it makes a second request to the browser with the intended HTTP method, whether GET, POST, PUT and so on, with the same CORS request headers. Afterward, the communication between the browser and CORS origin (different than that of the web page) proceeds as if it was a simple CORS request. Similar to a simple CORS request, content and resources are accessible and can be loaded if this second CORS request is allowed. Setting up CORS at your origin As shown in the previous diagrams, CORS is initiated by the requesting HTTP client. However, the effects depend on the requested origin. For your content to be ready for CORS requests, your origin must be configured correctly to respond with the correct CORS response headers and the correct access permissions. The following example shows a basic CORS configuration for a Nginx server: http { # some http context configs server { # some server context configs # URI path to some content location /my-static-content { # some location context configs # Handle simple requests # # Consider only "HTTP GET" requests (content fetching) if ($request_method = 'GET') { # Allows the browser to access data from this server during CORS, # only if the request comes from a web page from the following origin add_header 'Access-Control-Allow-Origin' 'https://www.example.com'; } # Handle preflight requests if ($request_method = 'OPTIONS') { # Allows the browser to access data from this server during CORS, # only if the request comes from a web page from the following origin add_header 'Access-Control-Allow-Origin' 'https://www.example.com'; # Allows only GET requests add_header 'Access-Control-Allow-Methods' 'GET'; # Allows the following headers in the browser's request headers # that may have been added by anything other than what the browser had added automatically add_header 'Access-Control-Allow-Headers' 'pragma'; # Specifies to the browser how long it should cache this preflight response add_header 'Access-Control-Max-Age' 1728000; # HTTP 204 response code means success, # but also that it should expect no content from this (preflight) response return 204; } # more location context configs # If it is not a complex CORS situation requiring a preflight response, # then finally attempt to serve the file whose path falls under this location block's URI path match # # If no such file is found, then present an HTTP 404 code (not found) try_files $uri =404; } # more server context configs } # more http context configs } Generally, the browser should freely load content when it sees a Access-Control-Allow-Origin: * in the server's CORS response headers according to the w3 specification regarding that wildcard value . However, not all browsers support Access-Control-Allow-Origin: *. If the server must support access from multiple web pages, each served from a different origin, a single origin value for Access-Control-Allow-Origin should be dynamically generated per request. The following is a basic example of such a use case for an Nginx server: http { # some http context config ###### # Input from $http_origin, the value in Origin HTTP header # Output to $cors_allowed_origin, a string # # Full string match on the Origin header value # # Attempt to find a match for the value from $http_origin using regex on the left column. # If a match is found, then evaluate $cors_allowed_origin to the same value as $http_origin # Else, default evaluate $cors_allowed_origin to an empty string, so browsers will disallow the CORS request ###### map $http_origin $cors_allowed_origin { default ''; ~^http(s)?://(www|www2|cdn|dev)\.example\.com$ $http_origin; } server { # some server context configs # URI path to some content location /my-static-content { # some location context configs # Handle simple requests if ($request_method = 'GET') { add_header 'Access-Control-Allow-Origin' $cors_allowed_origin; } # Handle preflight requests if ($request_method = 'OPTIONS') { add_header 'Access-Control-Allow-Origin' '$cors_allowed_origin; add_header 'Access-Control-Allow-Methods' 'GET'; add_header 'Access-Control-Allow-Headers' 'pragma'; add_header 'Access-Control-Max-Age' 1728000; return 204; } # more location context configs try_files $uri =404; } # more server context configs } # more http context configs } The previous example uses the map directive to avoid overusing the if Nginx statement. Now, when a CORS request is made to this server and matches that URI path, the server responds with the Access-Control-Allow-Origin header containing the value http://www.example.com, https://cdn.example.com, or http://dev.example.com, when the content is requested from http://www.example.com, https://cdn.example.com, http://dev.example.com, and so forth. Setting up CORS for CDN CDN is largely transparent to the CORS setup of the origin so it does not require a specific CDN configuration. If the CDN Edge server cannot find a cached response for the first request for some content, it forwards the request to the origin host. If the origin host is set up to handle CORS requests, and this request has the Origin header, then it should respond back to the Edge with a CORS header of Access-Control-Allow-Origin and the associated value. The overall response, including that header and value, is cached in the CDN. Any subsequent request for the object at the same URI path is served from the cache and includes the Access-Control-Allow-Origin header value that was originally received from the origin. Multiple CORS origin support In some cases, you can allow a list of specific origins (not all) to access your CDN contents, and need CDN to serve different Access-Control-Allow-Origin response headers for different origins (not wildcard * for any origins). However, CDN caches the headers along with contents, so it might serve the cached Access-Control-Allow-Origin header to the request, which might not match. You can leverage the Cache Key query optimization to add different parameters in the URLs for different origins. This way, the content and headers are cached differently. For example, suppose you've set the CDN cdn.example.com to serve contents for the two origins (abc.com and 123.com), and want to add different parameters for each origin; for example, https://cdn.example.com/test.json?domain=abc.com and https://cdn.example.com/test.json?domain=123.com. CDN would return different Access-Control-Allow-Origin headers that are served by your back-end server: Request from abc.com origin returns access-control-allow-origin: https://abc.com: # curl -H "Origin: https://abc.com" -H "Referer: https://abc.com/" -i https://cdn.example.com/test.json?domain=abc.com HTTP/2 200 access-control-allow-origin: https://abc.com access-control-allow-methods: GET access-control-allow-credentials: true ... Request from 123.com origin returns access-control-allow-origin: https://123.com: # curl -H "Origin: https://123.com" -H "Referer: https://123.com/" -i https://cdn.example.com/test.json?domain=123.com HTTP/2 200 access-control-allow-origin: https://123.com access-control-allow-methods: GET access-control-allow-credentials: true ... Troubleshooting CORS and CORS requests If your origin server is set up for CORS, and you do not see the Access-Control-Allow-Origin header that is returned to the browser’s request, it is possible that the response header cached in CDN was for a request that didn't have the origin header in the request. CDN caches response headers from the origin host. However, the cached headers are based on the request that triggered the request to origin. In that case, the response headers might not include the CORS headers. Clear the cache in CDN for that path using CDN’s purge functionality, and retry the request from the client. The Vary response header from your origin server can also cause unexpected behavior when fetching content through your CDN. Other than one specific exception, the CDN does not cache content (and its associated response header) from your origin server, if the server responds with a Vary header. Currently, our service removes the Vary header from the origin to render the object cacheable, if the object is one of the following file types: aif, aiff, au, avi, bin, bmp, cab, carb, cct, cdf, class, css, doc, dcr, dtd, exe, flv, gcf, gff, gif, grv, hdml, hqx, ico, ini, jpeg, jpg, js, mov, mp3, nc, pct, pdf, png, ppc, pws, swa, swf, txt, vbs, w32, wav, wbmp, wml, wmlc, wmls, wmlsc, xsd, zip, webp, jxr, hdp, wdp, pict, tif, tiff, mid, midi, ttf, eot, woff, otf, svg, svgz, jar, woff2, json. If the object to cache is not one of these file types, remove the Vary header from the origin server's response for that object and try again after using CDN's Purge functions. location /delete*****file/ { # Handle simple requests # # Consider only "HTTP DELETE" requests (content delete) if ($request_method = 'DELETE') { # Allows the browser to access data from this server during CORS, # only if the request comes from a web page from the following origin add_header 'Access-Control-Allow-Origin' 'https://heyubao.com'; } # Handle preflight requests if ($request_method = 'OPTIONS') { # Allows the browser to access data from this server during CORS, # only if the request comes from a web page from the following origin add_header 'Access-Control-Allow-Origin' 'https://heyubao.com'; # Allows only DELETE requests add_header 'Access-Control-Allow-Methods' 'DELETE'; # Allows the following headers in the browser's request headers # that may have been added by anything other than what the browser had added automatically add_header 'Access-Control-Allow-Headers' 'pragma'; # Specifies to the browser how long it should cache this preflight response add_header 'Access-Control-Max-Age' 1728000; # HTTP 204 response code means success, # but also that it should expect no content from this (preflight) response return 204; } # more location context configs # If it is not a complex CORS situation requiring a preflight response, # then finally attempt to serve the file whose path falls under this location block's URI path match # # If no such file is found, then present an HTTP 404 code (not found) try_files $uri =404; alias /usr/local/*****/html/vod/; dav_access user:rw group:rw all:rw; dav_methods DELETE; min_delete_depth 1; } 读取更多关于Nginx CORS 跨域解决方案 »
• Android 回音消除(AcousticEchoCanceler)的使用
回音消除Google 开发文档原文: /** * Acoustic Echo Canceler (AEC). * <p>Acoustic Echo Canceler (AEC) is an audio pre-processor which removes the contribution of the * signal received from the remote party from the captured audio signal. * <p>AEC is used by voice communication applications (voice chat, video conferencing, SIP calls) * where the presence of echo with significant delay in the signal received from the remote party * is highly disturbing. AEC is often used in conjunction with noise suppression (NS). * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC * engine in the audio capture path. * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord}, * specify the audio session ID of this AudioRecord when creating the AcousticEchoCanceler. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, an AEC can be inserted by default in the capture path by the platform * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should * call AcousticEchoCanceler.getEnable() after creating the AEC to check the default AEC activation * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. */ 场景就是在手机播放声音和声音录制同时进行,但是手机播放的声音不会被本机录制,达到了消除的效果。微信对讲的最适合不过了,但是微信的回音消除好像是不是自己弄的。 文档大致意思:创建android.media.AudioRecord 对象的时候,可以通过这个对象获取到一个audio session 的ID,获取方法getAudioSessionId(),这个ID在创建AcousticEchoCanceler的时候要用到(创建对象:AcousticEchoCanceler.create(audioSessionId)),最后播放音频时(这里是用AudioTrack播放)传入这个ID就行了。 1.首先创建AudioRecord对象,里面的参数可以自己查资料知道什么是采样率,声道,位数。 private AudioRecord mRecorder; private byte[] pcm; private int mRecorderBufferSize; /** * 初始化录音 */ public void initRecorder() { mRecorderBufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); pcm = new byte[320]; mRecorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mRecorderBufferSize); } 2.其次,初始化AudioTrack(注意下传入的audioSessionId) private AudioRecord mRecorder; private byte[] pcm; private int mRecorderBufferSize; /** * 初始化录音 */ public void initRecorder() { mRecorderBufferSize = AudioRecord.getMinBufferSize(8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT); pcm = new byte[320]; mRecorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION, 8000, AudioFormat.CHANNEL_IN_MONO, AudioFormat.ENCODING_PCM_16BIT, mRecorderBufferSize); } 3.最后创建AcousticEchoCanceler private AcousticEchoCanceler acousticEchoCanceler; private void initAEC() { if (AcousticEchoCanceler.isAvailable()) { if (acousticEchoCanceler == null) { acousticEchoCanceler = AcousticEchoCanceler.create(audioSessionId); Log.d(TAG, "initAEC: ---->" + acousticEchoCanceler + "\t" + audioSessionId); if (acousticEchoCanceler == null) { Log.e(TAG, "initAEC: ----->AcousticEchoCanceler create fail."); } else { acousticEchoCanceler.setEnabled(true); } } } } 4.最后播放就可以了(OK) public void write(byte[] data) { if (mAudioTrack != null && mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_PLAYING) { mAudioTrack.write(data, 0, data.length); } } 读取更多关于Android 回音消除(AcousticEchoCanceler)的使用 »
• 从MVC原理开始手敲一个MVC框架,体会当大神的乐趣
每一个程序员,在刚入行时学的第一个框架应该就是ssm了,其他的各种学习框架都是后期在工作中,随着业务的不断复杂,在工作和bug中不断成长起来的,但是最经典的应该还是最一开始的时候ssm框架吧 当时刚学习这个时候,就觉得,好牛啊,这样就可以实现一个网站,这群大神是怎么做到的啊,嘿嘿嘿,不知道大家当时有没有这样的问题产生,所以今天就带大家来搭建一个简单的mvc框架,从原理讲起,也能帮助大家更好的理解底层源码 好了,话不多说,我们来看一下 Springmvc基本原理流程 SpringMvc本质上就是对Servlet的封装。 因为创建一个Maven项目,然后在pom文件中增加一个依赖: <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <!-- 部署在服务器时,不使用这个servlet-api 而使用tomcat的--> <scope>provided</scope> </dependency> 2,创建DispatcherServlet,并注册到web.xml中 package com.dxh.edu.mvcframework.servlet; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class DxhDispatcherServlet extends HttpServlet { /** * 接收处理请求 */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { } } web.xml: <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dxhmvc</servlet-name> <servlet-class>com.dxh.edu.mvcframework.servlet.DxhDispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>springmvc.properties</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>dxhmvc</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> 2,注解开发 因为要使用到注解,所以首先要自定义几个注解: 这里就不赘述如何自定义注解了,详情请看:https://www.cnblogs.com/peida/archive/2013/04/24/3036689.html Controller注解: @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DxhController { String value() default ""; } Service注解: @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DxhService { String value() default ""; } RequestMapping注解: @Documented @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface DxhRequestMapping { String value() default ""; } Autowired注解: @Documented @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DxhAutowired { String value() default ""; } 编写测试代码: 测试代码我们放在同项目中的com.dxh.demo包中: package com.dxh.demo.controller; import com.dxh.demo.service.IDemoService; import com.dxh.edu.mvcframework.annotations.DxhAutowired; import com.dxh.edu.mvcframework.annotations.DxhController; import com.dxh.edu.mvcframework.annotations.DxhRequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @DxhController @DxhRequestMapping("/demo") public class DemoController { @DxhAutowired private IDemoService demoService; /** * URL:/demo/query */ @DxhRequestMapping("/query") public String query(HttpServletRequest request, HttpServletResponse response, String name){ return demoService.get(name); } } package com.dxh.demo.service; public interface IDemoService { String get(String name); } package com.dxh.demo.service.impl; import com.dxh.demo.service.IDemoService; import com.dxh.edu.mvcframework.annotations.DxhService; @DxhService("demoService") public class IDemoServiceImpl implements IDemoService { @Override public String get(String name) { System.out.println("Service实现类中的Name:"+ name); return name; } } 目录结构: 3,编写自定义DispatcherServlet中的初始化流程: 在创建好的DxhDispatcherServlet中重写init()方法,并在init方法中做初始化配置: 加载配置文件 springmvc.properties 扫描相关的类——扫描注解 初始化Bean对象(实现IOC容器,基于注解) 实现依赖注入 构造一个handleMapping处理器映射器,将配置好的url和method建立映射关系 @Override public void init(ServletConfig config) throws ServletException { //1. 加载配置文件 springmvc.properties String contextConfigLocation = config.getInitParameter("contextConfigLocation"); doLoadConfig(contextConfigLocation); //2. 扫描相关的类——扫描注解 doScan(""); //3. 初始化Bean对象(实现IOC容器,基于注解) doInstance(); //4. 实现依赖注入 doAutoWired(); //5. 构造一个handleMapping处理器映射器,将配置好的url和method建立映射关系 initHandleMapping(); System.out.println("MVC 初始化完成"); //6. 等待请求进入处理请求 } 以及5个空方法,这篇文章自定义MVC框架其实就是需要对这5个步骤的编写。 //TODO 5,构造一个映射器 private void initHandleMapping() { } //TODO 4,实现依赖注入 private void doAutoWired() { } //TODO 3,IOC容器 private void doInstance() { } //TODO 2,扫描类 private void doScan(String scanPackage) { } //TODO 1,加载配置文件 private void doLoadConfig(String contextConfigLocation) { } 3.1 加载配置文件 首先在resource目录中创建一个配置文件——springmvc.properties 表示要扫描com.dxh.demo下的所有注解。 然后在web.xml中进行配置: 这样,就可以通过config.getInitParameter("contextConfigLocation")获得这个路径。 在DxhDispatcherServlet中定义一个属性,我们把加载后的配置文件中的信息,存储在Properties 中 private Properties properties = new Properties();; //1,加载配置文件 private void doLoadConfig(String contextConfigLocation) { //根据指定路径加载成流: InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(contextConfigLocation); try { properties.load(resourceAsStream); } catch (IOException e) { e.printStackTrace(); } } 3.2 扫描相关的类,扫描注解 上一步骤,我们已经把需要扫描的包存在Properties中,所以这里需要取出: //2. 扫描相关的类——扫描注解 doScan(properties.getProperty("scanPackage")); 把扫描到的类型的全类名存在一个List中缓存起来,等待使用,在DxhDispatcherServlet中定义一个list: //缓存扫描到的类的全类名 private List<String> classNames = new ArrayList<>(); 从配置文件中我们得到了一个需要扫描的包名(com.dxh.demo),我们需要根据classPath+包名,来得到它实际上在磁盘上存的路径,然后递归,直到把所有的该包下(包括子包...)所有的类文件(.class结尾)。然后存在在List classNames中。 //2,扫描类 //scanPackage :com.dxh.demo package--->磁盘的文件夹(File) private void doScan(String scanPackage) { //1.获得classPath路径 String clasPath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); //2.拼接,得到scanPackage在磁盘上的路径 String scanPackagePath= clasPath + scanPackage.replaceAll("\\.","/"); File pack = new File(scanPackagePath); File[] files = pack.listFiles(); for (File file : files) { if (file.isDirectory()){ //子 package //递归 doScan(scanPackage+"."+file.getName()); //com.dxh.demo.controller }else if(file.getName().endsWith(".class")){ String className = scanPackage + "." + file.getName().replace(".class", ""); classNames.add(className); } } } 3.3 初始化Bean对象(实现IOC容器,基于注解) 上一步骤我们把扫描到的类的全类名放到了,list中,那么本次步骤需要遍历整个list: 遍历List,依次得到所有的全类名 通过反射得到类对象 根据类对象判断有没有注解,并区分controller和servicecontroller,它的id此处不做过多处理,不取value了,用类的首字母小写作为id,保存到IOC容器中。service,service层往往是有接口的,再以接口名为id再存入一份bean到ioc,便于后期根据接口类型注入 完成 代码实现: //IOC容器 private Map<String,Object> ioc = new HashMap<>(); //3,IOC容器 //基于classNames缓存的类的全限定类名,以及反射技术,完成对象创建和管理 private void doInstance() { if (classNames.size()==0) return; try{ for (int i = 0; i < classNames.size(); i++) { String className = classNames.get(i); //com.dxh.demo.controller.DemoController //反射 Class<?> aClass = Class.forName(className); //区分controller ,区分service if (aClass.isAnnotationPresent(DxhController.class)){ //controller的id此处不做过多处理,不取value了,用类的首字母小写作为id,保存到IOC容器中 String simpleName = aClass.getSimpleName();//DemoController String lowerFirstSimpleName = lowerFirst(simpleName); //demoController Object bean = aClass.newInstance(); ioc.put(lowerFirstSimpleName,bean); }else if (aClass.isAnnotationPresent(DxhService.class)){ DxhService annotation = aClass.getAnnotation(DxhService.class); //获取注解的值 String beanName = annotation.value(); //指定了id就以指定的id为准 if (!"".equals(beanName.trim())){ ioc.put(beanName,aClass.newInstance()); }else{ //没有指定id ,首字母小写 String lowerFirstSimpleName = lowerFirst(aClass.getSimpleName()); ioc.put(lowerFirstSimpleName,aClass.newInstance()); } //service层往往是有接口的,再以接口名为id再存入一分bean到ioc,便于后期根据接口类型注入 Class<?>[] interfaces = aClass.getInterfaces(); for (Class<?> anInterface : interfaces) { //以接口的类名作为id放入。 ioc.put(anInterface.getName(),aClass.newInstance()); } }else { continue; } } }catch (Exception e){ e.printStackTrace(); } } 3.4 实现依赖注入: 上一步骤把所有需要加载的bean,存入了ioc Map中,此时,我们就需要遍历这个map然后依次得到每个bean对象,然后判断对象中有没有被@****DxhAutowired修饰的属性。 遍历ioc这个map,得到每个对象 获取对象的字段(属性)信息 判断字段是否被@DxhAutowired修饰 判断@DxhAutowired有没有设置value值有,直接从ioc容器中取出,然后设置属性。无,需要根据当前字段的类型注入(接口注入) 代码实现: //4,实现依赖注入 private void doAutoWired() { if (ioc.isEmpty()){return;} //1,判断容器中有没有被@DxhAutowried注解的属性,如果有需要维护依赖注入关系 for (Map.Entry<String,Object> entry: ioc.entrySet()){ //获取bean对象中的字段信息 Field[] declaredFields = entry.getValue().getClass().getDeclaredFields(); for (Field declaredField : declaredFields) { if (!declaredField.isAnnotationPresent(DxhAutowired.class)){ continue; } //有该注解: DxhAutowired annotation = declaredField.getAnnotation(DxhAutowired.class); String beanName = annotation.value(); //需要注入的bean的Id if ("".equals(beanName.trim())){ //没有配置具体的beanId,需要根据当前字段的类型注入(接口注入) IDemoService beanName = declaredField.getType().getName(); } //开启赋值 declaredField.setAccessible(true); try { //字段调用,两个参数:(哪个对象的字段,传入什么) declaredField.set(entry.getValue(),ioc.get(beanName)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } 3.5 构造一个handleMapping处理器映射器 构造一个handleMapping处理器映射器,将配置好的url和method建立映射关系****。 手写MVC框架最关键的环节 假设有一个: 那么如何通过/demo/query定位到 DemoController类中的query这个方法 ? 之前我们所有被@DxhController(自定义Controller注解)的类,都存在了ioc 这个map中。 我们可以遍历这个map,得到每个bean对象 然后判断是否被@DxhController所修饰(排除@DxhService所修饰的bean) 然后判断是否被@DxhRequestMapping所修饰,有的话,就取其value值,作为baseUrl 然后遍历该bean对象中的所有方法,得到被@DxhRequestMapping修饰的方法。得到其value值,作为methodUrl。 baseUrl + methodUrl = url 我们把url和当前method绑定起来,存在map中,也就是建立了url和method建立映射关系。 代码实现: //handleMapping ,存储url和method直接的映射关系 private Map<String,Object> handleMapping = new HashMap<>(); //5,构造一个映射器,将url和method进行关联 private void initHandleMapping() { if (ioc.isEmpty()){return;} for (Map.Entry<String,Object> entry: ioc.entrySet()){ //获取ioc中当前遍历对象的class类型 Class<?> aClass = entry.getValue().getClass(); //排除非controller层的类 if (!aClass.isAnnotationPresent(DxhController.class)){ continue; } String baseUrl = ""; if (aClass.isAnnotationPresent(DxhRequestMapping.class)){ //Controller层 类上 注解@DxhRequestMapping中的value值 baseUrl = aClass.getAnnotation(DxhRequestMapping.class).value(); } //获取方法 Method[] methods = aClass.getMethods(); for (Method method : methods) { //排除没有@DxhRequestMapping注解的方法 if (!method.isAnnotationPresent(DxhRequestMapping.class)){continue;} //Controller层 类中方法上 注解@DxhRequestMapping中的value值 String methodUrl = method.getAnnotation(DxhRequestMapping.class).value(); String url = baseUrl+methodUrl; //建立url和method之间的映射关系,用map缓存起来 handleMapping.put(url,method); } } } 4,测试一下: 到目前位置,还没有完全写完,但是不妨碍我们测试一下看看刚才写的那部分内容有没有什么问题: 完整的pom文件: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.dxh.edu</groupId> <artifactId>mvc</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>mvc Maven Webapp</name> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <!-- 部署在服务器时,不使用这个servlet-api 而使用tomcat的--> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugins> <!-- 编译插件定义编译细节--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.2</version> <configuration> <source>11</source> <target>11</target> <encoding>utf-8</encoding> <!-- 告诉编译器,编译的时候记录下形参的真实名称--> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/</path> </configuration> </plugin> </plugins> </build> </project> pom文件中加入了一个tomcat插件,并设置端口为8080,因此我们通过tomcat启动项目: 启动完成后,打开浏览器url中输入: http://localhost:8080/demo/query 浏览器中什么都没返回(我们的代码还没真正的完成,尚未编写处理请求步骤),同时控制台中打印了MVC初始化完成,可以认为,目前的代码没有明显的缺陷。 我们继续~~~~~ 5,改造initHandleMapping() 5.1 为什么改造? DxhDispatcherServlet这个类继承了HttpServlet,并重写了doGet和doPost方法,在doGet中调用了doPost方法,当我们使用反射调用方法时(method.invoke(......))发现少了一部分参数: 因此我们要改造initHandleMapping(),修改url和method的映射关系(不简简单单的存入map中)。 5.2 新建Handler类 package com.dxh.edu.mvcframework.pojo; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.regex.Pattern; public class Handler { //method.invoke(obj,)需要 private Object controller; private Method method; //spring中url支持正则 private Pattern pattern; //参数的顺序,为了进行参数绑定 ,Key 参数名, Value 代表第几个参数 private Map<String,Integer> paramIndexMapping; public Handler(Object controller, Method method, Pattern pattern) { this.controller = controller; this.method = method; this.pattern = pattern; this.paramIndexMapping = new HashMap<>(); } //getset方法这里省略,实际代码中需要... } 在Handler类中编写了4个属性: private Object controller:method.invoke(obj,)需要 private Method method:与url绑定的方法 private Pattern pattern:可以通过正则匹配,也可以直接写String url。 private Map<String,Integer> paramIndexMapping:参数的顺序,为了进行参数绑定 ,Key 参数名, Value 代表第几个参数 5.3 修改initHandleMapping() 首先,就不能直接通过Map<url,Method>的得方式进行关系映射了,使用一个list,泛型是刚才创建的Handler。 //handleMapping ,存储url和method直接的映射关系 // private Map<String,Method> handleMapping = new HashMap<>(); private List<Handler> handlerMapping = new ArrayList<>(); 改动前,改动后代码对比: 改动后的initHandleMapping(): //5,构造一个映射器,将url和method进行关联 private void initHandleMapping() { if (ioc.isEmpty()){return;} for (Map.Entry<String,Object> entry: ioc.entrySet()){ //获取ioc中当前遍历对象的class类型 Class<?> aClass = entry.getValue().getClass(); //排除非controller层的类 if (!aClass.isAnnotationPresent(DxhController.class)){ continue; } String baseUrl = ""; if (aClass.isAnnotationPresent(DxhRequestMapping.class)){ //Controller层 类上 注解@DxhRequestMapping中的value值 baseUrl = aClass.getAnnotation(DxhRequestMapping.class).value(); } //获取方法 Method[] methods = aClass.getMethods(); for (Method method : methods) { //排除没有@DxhRequestMapping注解的方法 if (!method.isAnnotationPresent(DxhRequestMapping.class)){continue;} //Controller层 类中方法上 注解@DxhRequestMapping中的value值 String methodUrl = method.getAnnotation(DxhRequestMapping.class).value(); String url = baseUrl+methodUrl; //把method所有信息以及url封装为Handler Handler handler = new Handler(entry.getValue(),method, Pattern.compile(url)); //处理计算方法的参数位置信息 Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { Parameter parameter = parameters[i]; //不做太多的参数类型判断,只做:HttpServletRequest request, HttpServletResponse response和基本类型参数 if (parameter.getType()==HttpServletRequest.class||parameter.getType()==HttpServletResponse.class){ //如果时request和response对象,那么参数名称存 HttpServletRequest 和 HttpServletResponse handler.getParamIndexMapping().put(parameter.getType().getSimpleName(),i); }else{ handler.getParamIndexMapping().put(parameter.getName(),i); } } handlerMapping.add(handler); } } } 6, 请求处理开发 doPost(): 上一步骤,我们配置了 uri和method的映射关系,并封装到了Handler中存入list,那么接下来,就要通过HttpServletRequest,取出uri,然后找到具体的Handler: 通过HttpServletRequest取出uri找到具体的Handler 得到将调用方法的参数的数组 根据上述数组长度创建一个新的数组(参数数组,传入反射调用的) 通过req.getParameterMap()得到前台传来的参数parameterMap 遍历parameterMap 通过StringUtils.join方法把name=1&name=2格式的参数变为name[1,2] (需要commons-lang依赖) 参数匹配并设置 private Handler getHandler(HttpServletRequest req) { if (handlerMapping.isEmpty()){return null;} String url = req.getRequestURI(); //遍历 handlerMapping for (Handler handler : handlerMapping) { Matcher matcher = handler.getPattern().matcher(url); if (!matcher.matches()){continue;} return handler; } return null; } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { //根据uri获取到能够处理当前请求的Handler(从handlerMapping中(list)) Handler handler = getHandler(req); if (handler==null){ resp.getWriter().write("404 not found"); return; } //参数绑定 //该方法所有参数得类型数组 Class<?>[] parameterTypes = handler.getMethod().getParameterTypes(); //根据上述数组长度创建一个新的数组(参数数组,传入反射调用的) Object[] paramValues = new Object[parameterTypes.length]; //以下就是为了向参数数组中设值,而且还得保证参数得顺序和方法中形参顺序一致。 Map<String,String[]> parameterMap = req.getParameterMap(); //遍历request中所有的参数 ,(填充除了request、response之外的参数) for (Map.Entry<String,String[]> entry: parameterMap.entrySet()){ //name=1&name=2 name[1,2] String value = StringUtils.join(entry.getValue(), ",");// 如同 1,2 //如果参数和方法中的参数匹配上了,填充数据 if (!handler.getParamIndexMapping().containsKey(entry.getKey())){continue;} //方法形参确实有该参数,找到它得索引位置,对应得把参数值放入paramValues Integer index = handler.getParamIndexMapping().get(entry.getKey()); //把前台传递过来的参数值,填充到对应得位置去 paramValues[index] = value; } Integer requestIndex = handler.getParamIndexMapping().get(HttpServletRequest.class.getSimpleName()); paramValues[requestIndex] = req; Integer responseIndex = handler.getParamIndexMapping().get(HttpServletResponse.class.getSimpleName()); paramValues[responseIndex] = resp; //最终调用handler得method属性 try { Object invoke = handler.getMethod().invoke(handler.getController(), paramValues); //简单操作,把方法返回的数据以字符串的形式写出 resp.getWriter().write(invoke.toString()); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } 7,测试: 打开浏览器,url中输入:http://localhost:8080/demo/query?name=lisi 返回: 控制台中打印出: OK完成~ 转自:https://www.toutiao.com/i6903531694301676035/ 读取更多关于从MVC原理开始手敲一个MVC框架,体会当大神的乐趣 »
• 什么是 Lambda?该如何使用?
什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个“值”。 如果你想把“一块代码”赋给一个Java变量,应该怎么做呢? 比如,我想把右边那块代码,赋给一个叫做aBlockOfCode的Java变量: 在Java 8之前,这个是做不到的。但是Java 8问世之后,利用Lambda特性,就可以做到了。 当然,这个并不是一个很简洁的写法。所以,为了使这个赋值操作更加elegant, 我们可以移除一些没用的声明。 这样,我们就成功的非常优雅的把“一块代码”赋给了一个变量。而“这块代码”,或者说“这个被赋给一个变量的函数”,就是一个Lambda表达式。 但是这里仍然有一个问题,就是变量aBlockOfCode的类型应该是什么? 在Java 8里面,所有的Lambda的类型都是一个接口,而Lambda表达式本身,也就是”那段代码“,需要是这个接口的实现。这是我认为理解Lambda的一个关键所在,简而言之就是,Lambda表达式本身就是一个接口的实现。直接这样说可能还是有点让人困扰,我们继续看看例子。我们给上面的aBlockOfCode加上一个类型: 这种只有一个接口函数需要被实现的接口类型,我们叫它”函数式接口“。为了避免后来的人在这个接口中增加接口函数导致其有多个接口函数需要被实现,变成"非函数接口”,我们可以在这个上面加上一个声明@FunctionalInterface, 这样别人就无法在里面添加新的接口函数了: 这样,我们就得到了一个完整的Lambda表达式声明: Lambda表达式有什么作用? 最直观的作用就是使得代码变得异常简洁。 我们可以对比一下Lambda表达式和传统的Java对同一个接口的实现: 这两种写法本质上是等价的。但是显然,Java 8中的写法更加优雅简洁。并且,由于Lambda可以直接赋值给一个变量,我们就可以直接把Lambda作为参数传给函数, 而传统的Java必须有明确的接口实现的定义,初始化才行: 有些情况下,这个接口实现只需要用到一次。传统的Java 7必须要求你定义一个“污染环境”的接口实现MyInterfaceImpl,而相较之下Java 8的Lambda, 就显得干净很多。 Lambda结合FunctionalInterface Lib, forEach, stream(),method reference等新特性可以使代码变的更加简洁! 直接上例子。 假设Person的定义和List<Person>的值都给定。 现在需要你打印出guiltyPersons List里面所有LastName以"Z"开头的人的FirstName。 原生态Lambda写法:定义两个函数式接口,定义一个静态函数,调用静态函数并给参数赋值Lambda表达式。 这个代码实际上已经比较简洁了,但是我们还可以更简洁么? 当然可以。在Java 8中有一个函数式接口的包,里面定义了大量可能用到的函数式接口(java.util.function (Java Platform SE 8 ))。所以,我们在这里压根都不需要定义NameChecker和Executor这两个函数式接口,直接用Java 8函数式接口包里的Predicate<T>和Consumer<T>就可以了——因为他们这一对的接口定义和NameChecker/Executor其实是一样的。 第一步简化 - 利用函数式接口包: 静态函数里面的for each循环其实是非常碍眼的。这里可以利用Iterable自带的forEach()来替代。forEach()本身可以接受一个Consumer<T> 参数。 第二步简化 - 用Iterable.forEach()取代foreach loop: 由于静态函数其实只是对List进行了一通操作,这里我们可以甩掉静态函数,直接使用stream()特性来完成。stream()的几个方法都是接受Predicate<T>,Consumer<T>等参数的(java.util.stream (Java Platform SE 8 ))。你理解了上面的内容,stream()这里就非常好理解了,并不需要多做解释。 第三步简化 - 利用stream()替代静态函数: 对比最开始的Lambda写法,这里已经非常非常简洁了。但是如果,我们的要求变一下,变成print这个人的全部信息,及p -> System.out.println(p); 那么还可以利用Method reference来继续简化。所谓Method reference, 就是用已经写好的别的Object/Class的method来代替Lambda expression。格式如下: 第四步简化 - 如果是println(p),则可以利用Method reference代替forEach中的Lambda表达式: 这基本上就是能写的最简洁的版本了。 Lambda配合Optional<T>可以使Java对于null的处理变的异常优雅 这里假设我们有一个person object,以及一个person object的Optional wrapper: Optional<T>如果不结合Lambda使用的话,并不能使原来繁琐的null check变的简单。 只有当Optional<T>结合Lambda一起使用的时候,才能发挥出其真正的威力! 我们现在就来对比一下下面四种常见的null处理中,Java 8的Lambda+Optional<T>和传统Java两者之间对于null的处理差异。 情况一 - 存在则开干 情况二 - 存在则返回,无则返回屁 情况三 - 存在则返回,无则由函数产生 情况四 - 夺命连环null检查 由上述四种情况可以清楚地看到,Optional<T>+Lambda可以让我们少写很多ifElse块。尤其是对于情况四那种夺命连环null检查,传统java的写法显得冗长难懂,而新的Optional<T>+Lambda则清新脱俗,清楚简洁。 来源:https://www.zhihu.com/question/20125256/answer/324121308 读取更多关于什么是 Lambda?该如何使用? »
• K12有关学段问题导致学科没有正常显示
现象:巫溪县教育资源公共服务平台【学科】没有正常显示。 原因:添加了三个职业高中学段,而系统默认以学段3为分界点,高于学段3的学校归属高校范畴,而低于等于学段3(即0-12年级)的学校归属k12中小学范畴。 解决方案:修改云桌面系统,将学段分界点从3改到6,即中专含中专及一下的学段都归属为中小学。 读取更多关于K12有关学段问题导致学科没有正常显示 »
• 带你揭开BFC(Block Formatting Context)的神秘面纱
原创黑马程序员2020-07-22 15:55:36 1. 引言 在前端的布局手段中,一直有这么一个知识点,很多前端开发者都知道有它的存在,但是很多人也仅仅是知道它的存在而已,对它的作用也只是将将说得出来,可是却没办法说得非常的清晰。这个知识点,就是BFC。想要了解BFC的规则,前提必须是熟悉前端网页的多种布局手段,例如盒的显示模式display,三种布局手段标准流(normal)、浮动流(float)、定位流(position)等。你只有熟练掌握了这些布局手段之后,才能很好的理解BFC。今天这篇文章,来大家解析一下BFC,希望对各位新老朋友有所帮助。 2. 定义 BFC - Block Formatting Context 块级格式化上下文 BFC的定义,在官方文档到中,是这么介绍BFC的。 A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context. 强行翻译一下吧,简单来说,这句话的意思就是: 一个BFC区域包含创建该上下文元素的所有子元素,但是不包括创建了新的BFC的子元素的内部元素 很显然,哪怕强行翻译了,大部分人依旧是看不懂这句话的。看都看不懂,那自然就没什么能把它说明白。talk is cheap, show me the code.看不懂意思,我用代码来给你演示。 <div class="box1" id="HM_bfc1"> <div class="box2"></div> <div class="box3"></div> <div class="box4"></div> <div class="box5" id="HM_bfc2"> <div class="box6"></div> <div class="box7"></div> <div class="box8"></div> </div> </div> 用这段代码来解释上面那段BFC定义的话,就应该是这个意思:#HM_bfc1是一块BFC区域,这块区域包含了box2、box3、box4、box5,也就是所有#HM_bfc1的子元素。同时#HM_bfc2也创造了一块BFC区域,包含了box6,box7,box8。注意,第一个box1的BFC,只包括box1的子元素box2345,不包括box678。#HM_bfc2这个BFC同样也仅仅是包括自己的子元素box678。 划重点 每一个BFC区域只包括其子元素,不包括其子元素的子元素。(这1点比较容易理解) 每一个BFC区域都是独立隔绝的,互不影响!(这点不太好理解,但是后续会使用代码验证) 看完上面的描述,很多朋友依旧不懂,把第2节用心的再读一遍,相信你会有新的收获。然后往下继续阅读,你会豁然开朗。 3. 触发BFC 并不是任意一个元素都可以被当做BFC,只有当这个元素满足以下任意一个条件的时候,这个元素才会被当做一个BFC。 触发BFC的条件 body根元素 设置浮动,不包括none 设置定位,absoulte或者fixed 行内块显示模式,inline-block 设置overflow,即hidden,auto,scroll 表格单元格,table-cell 弹性布局,flex 上代码说明 首先, body元素是1个BFC,因为它满足我们的第1个条件(body根元素),这个BFC区域包含子元素hm1234,但是不包括两个p标签,需要注意的是,hm3不是一个BFC区域,因为他不满足上面任意1个条件。如果我们希望hm3也是1个BFC区域,只要让hm3满足上面任意一个条件即可。 这个时候,hm3元素被设置为了overflow为hidden,满足上面第5个条件,所以此时,hm3就成为了一个BFC区域,这个BFC区域包含其所有子元素 – 两个p标签。 划重点: 并不是所有的元素都是BFC, 只有满足了上面的任意1个条件之后,这个元素才成为1个BFC。 一个BFC区域,只包含其所有子元素,不包含子元素的子元素. 4. 利用BFC解决问题 在你明白了解BFC的触发规则之后,那么就需要利用BFC的特点来解决我们在布局中遇到的一些问题了,还记得我们之前说过,BFC有一个特点是:**每一个BFC区域都是相互独立,互不影响的。** 4.1 解决外边距的塌陷问题(垂直塌陷) 开发中,前端的布局手段,离不开外边距margin,那么,也会遇到一些问题,例如外边距的垂直塌陷问题。 通过以上的实例,我们会发现,代码给两个div盒子,都添加了四个方向的margin,讲道理,学过数学的都知道,100+100=200.可是,盒子之间的距离,现在却之后100px。这就是很典型的margin的塌陷,两段margin重叠到了一块,互相影响。那么,如何利用BFC,让这个问题得到解决呢。回忆下,上文说过,BFC,就是一个与世隔绝的独立区域,不会互相影响,那么,我们可以将这两个盒子,放到两个BFC区域中,即可解决这个问题。 4.2 利用BFC解决包含塌陷 当父子关系的盒子,给子元素添加margin-top,有可能会把父元素一起带跑 原本,正确的显示方式,应该是粉色盒子与红色盒子的顶部距离为50px,但是由于margin的塌陷问题,导致盒子内部的布局影响到了外部。这个时候,就可以触发BFC,将父盒子变成一个独立的区域,这样在BFC区域内部的任何操作,都不会影响到外部。 4.3 当浮动产生影响的时候,可以利用BFC来清除浮动的影响 以上代码表示,一个没有设置高度的父盒子,包含着七个子元素。如果此时,所有的子元素都浮动的话。 当所有的子元素都浮动了,这个时候,父盒子失去了原有的高度,这就是浮动的影响。这个时候,同样也可用BFC的机制,来清除浮动带来的影响。使用BFC,将所有的浮动元素包裹起来。 4.4 BFC可以阻止标准流元素被浮动元素覆盖 以上情况,红色盒子浮动,蓝色盒子时标准流,默认情况下,浮动元素覆盖了标准流元素。但是,如果将蓝色盒子的BFC触发,那么情况将有所变化。 当蓝色盒子触发了BFC之后,浮动元素再也不能覆盖它了,而且还能利用这个特性,来实现蓝色盒子宽度根据红色盒子的宽度来做自动适应 5. 总结 一个BFC区域只包含其子元素,不包括其子元素的子元素. 并不是所有的元素都能成为一块BFC区域,只有当这个元素满足条件的时候才会成为一块BFC区域 不同的BFC区域之间是相互独立的,互不影响的。利用这个特性我们可以让不同BFC区域之间的布局不产生影响. 读取更多关于带你揭开BFC(Block Formatting Context)的神秘面纱 »
• 解决独立显卡obs捕获显示器后黑屏界面问题
现象:新购2台win10操作系统的华为笔记本电脑上安装的obs直播软件,捕获显示器后是黑屏界面,即推流视频有声音,无图像;捕捉摄像头和窗口正常。 原因:这两台笔记本电脑都有俩显卡(集显和独显),系统默认先看时集成显卡,而obs默认用独立显卡。 解决方案:如下图 读取更多关于解决独立显卡obs捕获显示器后黑屏界面问题 »
• CentOS 8.0在大于2TB的硬盘上安装时需要采用GPT模式
现象:CentOS 8 在 曙光服务器上安装时无法识别硬盘,硬盘容量6TB,大于2TB 原因:安装CentOS 8时,如果硬盘容量小于2TB,系统默认会使用MBR模式来安装,若大于2TB时,需强制使用GPT分割 解决方案:出现安装Centos8引导画面之后,按“TAB”键,将命令行最后追加"inst.gpt"这个参数:>vmlinuz initrd=initrd.img inst.gpt 读取更多关于CentOS 8.0在大于2TB的硬盘上安装时需要采用GPT模式 »
• Android国际化语言代码
中文(中国):values-zh-rCN 中文(台湾):values-zh-rTW 中文(香港):values-zh-rHK 英语(美国):values-en-rUS 英语(英国):values-en-rGB 英文(澳大利亚):values-en-rAU 英文(加拿大):values-en-rCA 英文(爱尔兰):values-en-rIE 英文(印度):values-en-rIN 英文(新西兰):values-en-rNZ 英文(新加坡):values-en-rSG 英文(南非):values-en-rZA 阿拉伯文(埃及):values-ar-rEG 阿拉伯文(以色列):values-ar-rIL 保加利亚文: values-bg-rBG 加泰罗尼亚文:values-ca-rES 捷克文:values-cs-rCZ 丹麦文:values-da-rDK 德文(奥地利):values-de-rAT 德文(瑞士):values-de-rCH 德文(德国):values-de-rDE 德文(列支敦士登):values-de-rLI 希腊文:values-el-rGR 西班牙文(西班牙):values-es-rES 西班牙文(美国):values-es-rUS 芬兰文(芬兰):values-fi-rFI 法文(比利时):values-fr-rBE 法文(加拿大):values-fr-rCA 法文(瑞士):values-fr-rCH 法文(法国):values-fr-rFR 希伯来文:values-iw-rIL 印地文:values-hi-rIN 克罗里亚文:values-hr-rHR 匈牙利文:values-hu-rHU 印度尼西亚文:values-in-rID 意大利文(瑞士):values-it-rCH 意大利文(意大利):values-it-rIT 日文:values-ja-rJP 韩文:values-ko-rKR 立陶宛文:valueslt-rLT 拉脱维亚文:values-lv-rLV 挪威博克马尔文:values-nb-rNO 荷兰文(比利时):values-nl-BE 荷兰文(荷兰):values-nl-rNL 波兰文:values-pl-rPL 葡萄牙文(巴西):values-pt-rBR 葡萄牙文(葡萄牙):values-pt-rPT 罗马尼亚文:values-ro-rRO 俄文:values-ru-rRU 斯洛伐克文:values-sk-rSK 斯洛文尼亚文:values-sl-rSI 塞尔维亚文:values-sr-rRS 瑞典文:values-sv-rSE 泰文:values-th-rTH 塔加洛语:values-tl-rPH 土耳其文:values--r-rTR 乌克兰文:values-uk-rUA 越南文:values-vi-rVN 缅甸语 : values-my(补充一种新语言) 读取更多关于Android国际化语言代码 »
移动办公之[掌上微校]常见问答 移动办公之[掌上微校]常见问答
• 微信服务有哪些项目?
微信服务随着应用的不断深入,会越来越多,截至2018年3月29日,已经支持下列服务,所有消息都通过绑定号校园帐户的用户手机微信传送。 校务办公系统(家校通): 教工内部通知及反馈。 家长通知及反馈。 教职工工资查询。 日程提醒。 会议申请、审核、提醒。 用车,用餐,采购及临时加班的申请、审核、提醒。 电教报修申请、受理、提醒。 总务报修申请、受理、提醒。 文印申请、核准、交印、领取、提醒。 学生成绩系统: 学生本人或者家长接收每次考试的成绩单。 教学管理系统(走班排课系统): 每个星期天下午1点钟系统定时发送下周课表给班主任、任课老师、学生及家长。 一旦有网上选课安排,系统即时发送选课通知给学生或家长,确保学生在规定时间内按时选课。 一旦有调课安排,系统即时发送调课通知给跟调课有关联的班主任,任课老师,学生及家长。 每节课的上课考勤通知给家长和班主任。 一旦任课老师在课堂上给某位同学添加了课堂表现评语,系统即时通知给班主任和家长。 读取更多关于微信服务有哪些项目? »
• 哪些学校可以开通微信服务?
学校需要满足下列2个条件: 只有释锐智慧校园系列软件v7.3.2.0之后的版本才提供微信支持,该版本系2018年2月1日发布,因此只有升级到v7.3.2.0版本及其后续更高版本之后才能开通微信服务。诚邀2018年2月1日之前交付的所有释锐老客户联系申请产品升级!释锐公司技术团队跟您回访确认升级事宜。请点击微信开通申请链接。电话咨询 021-60753206 购买释锐保服务就能升级,或者在产品交付1年之内或还在释锐保运维服务或者SaaS托管服务期内的客户免费升级。点击了解释锐保服务详情。 读取更多关于哪些学校可以开通微信服务? »
• 释锐校园软件终端用户如何绑定微信服务?
释锐校园软件终端用户是指:购买了释锐校园级软件产品学校的在职教职工、在校学生和家长,释锐软件为每一位教职工、学生及家长都提供了一个用户账号和初始密码。如果您属于上述3类用户之一,就能将学校所用的释锐软件平台和您个人微信APP进行绑定。绑定好之后,能够免去每次进系统都需要登录验证的麻烦,并且从微信上就能收到来自学校的各类官方消息和通知(消息类型清单详见 https://access.threeoa.com/bbs/-/message_boards/message/189207),而且新消息时会即时提醒。 释锐校园软件终端用户绑定微信服务的步骤如下(教职工、学生、家长绑定步骤一致,没有区别): 第1步:关注产品研发厂商(上海释锐教育软件有限公司或OEM合作伙伴)的官方微信公众号 上海释锐教育软件有限公司的微信公众号是 threegroup ,二维码 第2步:绑定校园账号 个人中心》绑定校园账号》请选择一所学校》选择贵校所在省份》选择贵校所在地市》“点击查询”列表当前地市开通了微信服务的所有学校列表》选择您所在的学校》系统会自动检测网络是否畅通》如果网络畅通,点击“确定”按钮》系统自动跳往贵校释锐软件平台运行的网址,等待您的输入》请输入正确的用户名和密码(如果您不知道账号和初始密码,请向贵校的网络管理员老师索取)》验证通过代表完成绑定。 第3步:学校信息提醒 第4步:手机微信上查阅来自学校的信息 第5步:手机微信上回复来自学校的信息 点击第4步图中的“编辑留言”或者“留言”即可参与回复。回复的内容不但保存在微信留言列表中,还会自动同步到学校的释锐校务办公平台对应的站内信的留言列表内。 视频教程(请点击播放) 您的浏览器版本不支持video技术,此处视频无法播放,建议用Chrome谷歌浏览器。 绑定过程中,碰到问题或者困难找谁? 首先:找学校的网络管理员老师,学生或者学生家长可以先找到班主任,由班主任告知网络管理员老师的电话; 其次:直接释锐公司工作人员,售后服务咨询电话 021-60753203 ,售后服务咨询QQ 313908888。 读取更多关于释锐校园软件终端用户如何绑定微信服务? »
• 为什么需要关注厂家的微信公众号,而不是学校自己的公众号?
简化上线流程,确保极速上线可用。 如果绑定学校自有公众号,除了厂家要按年收取技术维护费外,一个支持二次开发的公众号还需要经过联系腾讯公司办理付费认证、开发配置、模版消息配置等多个环节,从申请到上线需要1-2周时间。 况且,不论是学校公众号,还是厂家公众号,都是腾讯公司的微信公众号技术,起到的作用就是“消息快递员”的作用,没有本质的区别,好处都是可以快速在手机上收到来自校园平台的各类实用消息。 读取更多关于为什么需要关注厂家的微信公众号,而不是学校自己的公众号? »
• 多校绑定同一个公众号会导致信息错发吗?
不会。释锐微信公众服务系统采用了“释锐校园软件平台、释锐中转分发服务器、腾讯微信服务器、用户手机微信APP”四层架构,微信用户在首次绑定校园账号时也绑定了校园软件网址。 读取更多关于多校绑定同一个公众号会导致信息错发吗? »
• 绑定微信提示“CAS is Unavailable”
现象:微信公众号绑定学校时,提示“CAS is Unavailable”,如下图;但是在浏览器上可以正常登录系统。 [img]https://access.threeoa.com/documents/10182/218667/%E5%BE%AE%E4%BF%A1%E7%BB%91%E5%AE%9A%E6%8A%A5%E9%94%99/ded43bc5-ed3f-4952-8723-ab723bf16b4b?t=1571819536000[/img] 原因:桌面系统-设置-微信服务器栏为空,导致后台报”空值错误”; 解决方案: 登陆网页版桌面系统→设置→启用微信总开关并填写微信服务器地址"[b]http://license.threeoa.com[/b]" 读取更多关于绑定微信提示“CAS is Unavailable” »