超漂亮的Bootstrap 富文本编辑器summernote


Posted in Javascript onApril 05, 2016

 Summernote 是一个简单,灵活,所见即所得(WYSIWYG)的编辑器,基于 jQuery 和 Bootstrap 构建。Summernote 所有主要的操作都支持快捷键,有一个功能强大的 API,它提供了大量的自定义选项的设计(宽,高,有效的项目等等)和功能。对于主要的脚本语言或框架(PHP,Ruby,Django,NodeJS),该项目有提供了集成示例。

Bootstrap summernote,用其官网上的介绍就是“Super Simple WYSIWYG editor”,不过在我看来,与bootstrap中文官网上提供的“bootstrap-wysiwyg”要更simple,更漂亮,更好用!

虽然我之前尝试过使用bootstrap-wysiwyg,可参照Bootstrap wysiwyg富文本数据如何保存到mysql,但事后诸葛亮的经验告诉我,summernote绝对是更佳的富文本编辑器,这里对其工作team点三十二个赞!!!!!

经过一天时间的探索,对summernote有所掌握,那么为了更广大前端爱好者提供便利,我将费劲一番心血来介绍一下summernote,超级福利啊。

一、官方API和源码下载

工欲善其事必先利其器,首先把summernote的源码拿到以及对应官方API告诉大家是首个任务!

官网(demo和api)

github源码下载,注意下载开发版

二、效果图

效果图1

超漂亮的Bootstrap 富文本编辑器summernote

效果图2

超漂亮的Bootstrap 富文本编辑器summernote

效果图3

超漂亮的Bootstrap 富文本编辑器summernote

三、开讲内容

大的方向为以下三个内容:

summernote的页面布局(资源引入、初始参数)
summernote从本地上传图片方法(前端onImageUpload方法、后端springMVC文件保存)
summernote所在form表单的数据提交

①、summernote的页面布局

<!DOCTYPE html>
<html lang="zh-CN">
<%@ include file="/components/common/taglib.jsp"%>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>summernote - bs3fa4</title>
<!-- include jquery -->
<script type="text/javascript" src="${ctx}/components/jquery/jquery.js"></script>
<!-- include libs stylesheets -->
<link type="text/css" rel="stylesheet" href="${ctx}/components/bootstrap/css/bootstrap.css" />
<script type="text/javascript" src="${ctx}/components/bootstrap/js/bootstrap.min.js"></script>
<!-- include summernote -->
<link type="text/css" rel="stylesheet" href="${ctx}/components/summernote/summernote.css" />
<script type="text/javascript" src="${ctx}/components/summernote/summernote.js"></script>
<script type="text/javascript" src="${ctx}/components/summernote/lang/summernote-zh-CN.js"></script>
<script type="text/javascript">
$('div.summernote').each(function() {
var $this = $(this);
var placeholder = $this.attr("placeholder") || '';
var url = $this.attr("action") || '';
$this.summernote({
lang : 'zh-CN',
placeholder : placeholder,
minHeight : 300,
dialogsFade : true,// Add fade effect on dialogs
dialogsInBody : true,// Dialogs can be placed in body, not in
// summernote.
disableDragAndDrop : false,// default false You can disable drag
// and drop
callbacks : {
onImageUpload : function(files) {
var $files = $(files);
$files.each(function() {
var file = this;
var data = new FormData();
data.append("file", file);
$.ajax({
data : data,
type : "POST",
url : url,
cache : false,
contentType : false,
processData : false,
success : function(response) {
var json = YUNM.jsonEval(response);
YUNM.debug(json);
YUNM.ajaxDone(json);
if (json[YUNM.keys.statusCode] == YUNM.statusCode.ok) {
// 文件不为空
if (json[YUNM.keys.result]) {
var imageUrl = json[YUNM.keys.result].completeSavePath;
$this.summernote('insertImage', imageUrl, function($image) {
});
}
}
},
error : YUNM.ajaxError
});
});
}
}
});
});
</script>
</head>
<body>
<div class="container">
<form class="form-horizontal required-validate" action="#" enctype="multipart/form-data" method="post" onsubmit="return iframeCallback(this, pageAjaxDone)">
<div class="form-group">
<label for="" class="col-md-2 control-label">项目封面</label>
<div class="col-md-8 tl th">
<input type="file" name="image" class="projectfile" value="${deal.image}"/>
<p class="help-block">支持jpg、jpeg、png、gif格式,大小不超过2.0M</p>
</div>
</div>
<div class="form-group">
<label for="" class="col-md-2 control-label">项目详情</label>
<div class="col-md-8">
<div class="summernote" name="description" placeholder="请对项目进行详细的描述,使更多的人了解你的" action="${ctx}/file">${deal.description}</div>
</div>
</div>
</form>
</div>
</body>
</html>

<!DOCTYPE html>html5的标记是必须的,注意千万不能是<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">这种doctype,否则summernote的组件显示怪怪的,按钮的大小布局不一致,这里就不再上图了,但是千万注意!
bootstrap 的版本号最好为v3.3.5

1、布局div

<div class="summernote" name="description" placeholder="请对项目进行详细的描述,使更多的人了解你的" action="${ctx}/file">${deal.description}</div>

相信你也看到了我为div加上的三个属性name、placeholder、action,那么我们来详细介绍一下三个属性的作用:

name,为外层form表单提供summernote数据保存时的数据模型的属性名,和input标签的name属性作用一致,稍候在form提交的时候具体介绍。

placeholder,很直白,为summernote提供初始状态的文本描述,当然还需要后续加工,div显然是不支持placeholder属性的。

action,为图片上传提供后端接收地址,稍候在介绍图片上传onImageUpload会再次用到。
另外${deal.description}其实你不需要太多关注,和textarea的赋值的用法一致,就是单纯的显示保存后的内容。

2、summernote初始化

$('div.summernote').each(function() {
var $this = $(this);
var placeholder = $this.attr("placeholder") || '';
var url = $this.attr("action") || '';
$this.summernote({
lang : 'zh-CN',
placeholder : placeholder,
minHeight : 300,
dialogsFade : true,// Add fade effect on dialogs
dialogsInBody : true,// Dialogs can be placed in body, not in
// summernote.
disableDragAndDrop : false,// default false You can disable drag
// and drop
});
});

使用jquery获取到页面上的summernote,对其进行初始化,我们来详细介绍列出参数的用法(先不介绍图片上传的onImageUpload 方法)。

lang ,指定语言为中文简体

placeholder ,summernote初始化显示的内容。

minHeight,最小高度为300,注意这里没有使用height,是有原因的,这里稍作解释,就不上图了。当使用height指定高度后,假如上传比height高的图片,summernote就不会自动调整高度,并且前文中“效果图3”中标出的红色区域会不贴着图片,而溢出到summernote外部。

dialogsFade,增加summernote上弹出窗口滑进滑出的动态效果。
dialogsInBody,这个属性也很关键,默认为false,字面上的意思是summernote的弹出框是否在body中(in嘛),设置为false时,dialog的式样会继承其上一级外部(如上文中的form-horizontal)容器式样,那么显示的效果就很别扭,这里也不再上图;那么设置为true时,就不会继承上一级外部div的属性啦,从属于body嘛。

disableDragAndDrop,设置为false吧,有的时候拖拽会出点问题,你可实践。

②、summernote从本地上传图片方法

1、前端onImageUpload方法

假如问度娘如下的话:“onImageUpload方法怎么写?”,度娘大多会为你找到如下回答:

$(\'.summernote\').summernote({
height:300,
onImageUpload: function(files, editor, welEditable) {
sendFile(files[0],editor,welEditable);
}
});
});
function sendFile(file, editor, welEditable) {
data = new FormData();
data.append("file", file);
url = "http://localhost/spichlerz/uploads";
$.ajax({
data: data,
type: "POST",
url: url,
cache: false,
contentType: false,
processData: false,
success: function (url) {
editor.insertImage(welEditable, url);
}
});
}
</script>

以上资源来自于stackoverflow。

但其实呢,summernote-develop版本的summernote已经不支持这种onImageUpload写法,那么如今的写法是什么样子呢?参照summernote的官网例子。

onImageUpload

Override image upload handler(default: base64 dataURL on IMG tag). You can upload image to server or AWS S3: more…
// onImageUpload callback
$('#summernote').summernote({
callbacks: {
onImageUpload: function(files) {
// upload image to server and create imgNode...
$summernote.summernote('insertNode', imgNode);
}
}
});
// summernote.image.upload
$('#summernote').on('summernote.image.upload', function(we, files) {
// upload image to server and create imgNode...
$summernote.summernote('insertNode', imgNode);
});

那么此时onImageUpload的具体写法呢?(后端为springMVC):

callbacks : {
// onImageUpload的参数为files,summernote支持选择多张图片
onImageUpload : function(files) {
var $files = $(files);
// 通过each方法遍历每一个file
$files.each(function() {
var file = this;
// FormData,新的form表单封装,具体可百度,但其实用法很简单,如下
var data = new FormData();
// 将文件加入到file中,后端可获得到参数名为“file”
data.append("file", file);
// ajax上传
$.ajax({
data : data,
type : "POST",
url : url,// div上的action
cache : false,
contentType : false,
processData : false,
// 成功时调用方法,后端返回json数据
success : function(response) {
// 封装的eval方法,可百度
var json = YUNM.jsonEval(response);
// 控制台输出返回数据
YUNM.debug(json);
// 封装方法,主要是显示错误提示信息
YUNM.ajaxDone(json);
// 状态ok时
if (json[YUNM.keys.statusCode] == YUNM.statusCode.ok) {
// 文件不为空
if (json[YUNM.keys.result]) {
// 获取后台数据保存的图片完整路径
var imageUrl = json[YUNM.keys.result].completeSavePath;
// 插入到summernote
$this.summernote('insertImage', imageUrl, function($image) {
// todo,后续可以对image对象增加新的css式样等等,这里默认
});
}
}
},
// ajax请求失败时处理
error : YUNM.ajaxError
});
});
}
}

注释当中加的很详细,这里把其他关联的代码一并贴出,仅供参照。

debug : function(msg) {
if (this._set.debug) {
if (typeof (console) != "undefined")
console.log(msg);
else
alert(msg);
}
},
jsonEval : function(data) {
try {
if ($.type(data) == 'string')
return eval('(' + data + ')');
else
return data;
} catch (e) {
return {};
}
},
ajaxError : function(xhr, ajaxOptions, thrownError) {
if (xhr.responseText) {
$.showErr("<div>" + xhr.responseText + "</div>");
} else {
$.showErr("<div>Http status: " + xhr.status + " " + xhr.statusText + "</div>" + "<div>ajaxOptions: " + ajaxOptions + "</div>"
+ "<div>thrownError: " + thrownError + "</div>");
}
},
ajaxDone : function(json) {
if (json[YUNM.keys.statusCode] == YUNM.statusCode.error) {
if (json[YUNM.keys.message]) {
YUNM.debug(json[YUNM.keys.message]);
$.showErr(json[YUNM.keys.message]);
}
} else if (json[YUNM.keys.statusCode] == YUNM.statusCode.timeout) {
YUNM.debug(json[YUNM.keys.message]);
$.showErr(json[YUNM.keys.message] || YUNM.msg("sessionTimout"), YUNM.loadLogin);
}
},

2、后端springMVC文件保存

2.1、为springMVC增加文件的配置

<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8">
<property name="maxUploadSize" value="1024000000"></property>
</bean>
<mvc:annotation-driven conversion-service="conversionService" />
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="converters">
<list>
<!-- 这里使用string to date可以将dao在jsp到controller转换的时候直接将string格式的日期转换为date类型 -->
<bean class="com.honzh.common.plugin.StringToDateConverter" />
<!-- 为type为file类型的数据模型增加转换器 -->
<bean class="com.honzh.common.plugin.CommonsMultipartFileToString" />
</list>
</property>
</bean>

这里就不做过多介绍了,可参照我之前写的SpringMVC之context-dispatcher.xml,了解基本的控制器

2.2、FileController.java

package com.honzh.spring.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.honzh.common.base.UploadFile;
import com.honzh.spring.service.FileService;
@Controller
@RequestMapping(value = "/file")
public class FileController extends BaseController {
private static Logger logger = Logger.getLogger(FileController.class);
@Autowired
private FileService fileService;
@RequestMapping("")
public void index(HttpServletRequest request, HttpServletResponse response) {
logger.debug("获取上传文件...");
try {
UploadFile uploadFiles = fileService.saveFile(request);
renderJsonDone(response, uploadFiles);
} catch (Exception e) {
logger.error(e.getMessage());
logger.error(e.getMessage(), e);
renderJsonError(response, "文件上传失败");
}
}
}

2.3、FileService.java

package com.honzh.spring.service;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.honzh.common.Variables;
import com.honzh.common.base.UploadFile;
import com.honzh.common.util.DateUtil;
@Service
public class FileService {
private static Logger logger = Logger.getLogger(FileService.class);
public UploadFile saveFile(HttpServletRequest request) throws IOException {
logger.debug("获取上传文件...");
// 转换为文件类型的request
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// 获取对应file对象
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
Iterator<String> fileIterator = multipartRequest.getFileNames();
// 获取项目的相对路径(http://localhost:8080/file)
String requestURL = request.getRequestURL().toString();
String prePath = requestURL.substring(0, requestURL.indexOf(Variables.ctx));
while (fileIterator.hasNext()) {
String fileKey = fileIterator.next();
logger.debug("文件名为:" + fileKey);
// 获取对应文件
MultipartFile multipartFile = fileMap.get(fileKey);
if (multipartFile.getSize() != 0L) {
validateImage(multipartFile);
// 调用saveImage方法保存
UploadFile file = saveImage(multipartFile);
file.setPrePath(prePath);
return file;
}
}
return null;
}
private UploadFile saveImage(MultipartFile image) throws IOException {
String originalFilename = image.getOriginalFilename();
logger.debug("文件原始名称为:" + originalFilename);
String contentType = image.getContentType();
String type = contentType.substring(contentType.indexOf("/") + 1);
String fileName = DateUtil.getCurrentMillStr() + new Random().nextInt(100) + "." + type;
// 封装了一个简单的file对象,增加了几个属性
UploadFile file = new UploadFile(Variables.save_directory, fileName);
file.setContentType(contentType);
logger.debug("文件保存路径:" + file.getSaveDirectory());
// 通过org.apache.commons.io.FileUtils的writeByteArrayToFile对图片进行保存
FileUtils.writeByteArrayToFile(file.getFile(), image.getBytes());
return file;
}
private void validateImage(MultipartFile image) {
}
}

2.4、UploadFile.java

package com.honzh.common.base;
import java.io.File;
import com.honzh.common.Variables;
public class UploadFile {
private String saveDirectory;
private String fileName;
private String contentType;
private String prePath;
private String completeSavePath;
private String relativeSavePath;
public UploadFile(String saveDirectory, String filesystemName) {
this.saveDirectory = saveDirectory;
this.fileName = filesystemName;
}
public String getFileName() {
return fileName;
}
public String getSaveDirectory() {
return saveDirectory;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getPrePath() {
if (prePath == null) {
return "";
}
return prePath;
}
public void setPrePath(String prePath) {
this.prePath = prePath;
setCompleteSavePath(prePath + getRelativeSavePath());
}
public String getCompleteSavePath() {
return completeSavePath;
}
public void setCompleteSavePath(String completeSavePath) {
this.completeSavePath = completeSavePath;
}
public String getRelativeSavePath() {
return relativeSavePath;
}
public void setRelativeSavePath(String relativeSavePath) {
this.relativeSavePath = relativeSavePath;
}
public void setSaveDirectory(String saveDirectory) {
this.saveDirectory = saveDirectory;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public File getFile() {
if (getSaveDirectory() == null || getFileName() == null) {
return null;
} else {
setRelativeSavePath(Variables.ctx + "/" + Variables.upload + "/" + getFileName());
return new File(getSaveDirectory() + "/" + getFileName());
}
}
}

后端文件保存方法也非常简单,懂java的同学都可以看得懂,那么对于后端不使用springmvc的同学,你可以再找找方法。

辛苦的介绍完前两节后,我们来一个动态图看一下效果吧!

超漂亮的Bootstrap 富文本编辑器summernote

③. summernote所在form表单的数据提交

这里,我们再回顾一下summernote所在的form表单,其中还包含了一个普通file的input标签,也就是说,该form还需要上传一张项目封面。

<form class="form-horizontal required-validate" action="#" enctype="multipart/form-data" method="post" onsubmit="return iframeCallback(this, pageAjaxDone)">

先看一下form的属性:

enctype:”multipart/form-data”,表明为文件类型的form保存

iframeCallback方法,稍候详细介绍,主要是对有文件上传的form表单进行封装。

1、iframeCallback

function iframeCallback(form, callback) {
YUNM.debug("带文件上传处理");
var $form = $(form), $iframe = $("#callbackframe");
var data = $form.data('bootstrapValidator');
if (data) {
if (!data.isValid()) {
return false;
}
}
// 富文本编辑器
$("div.summernote", $form).each(function() {
var $this = $(this);
if (!$this.summernote('isEmpty')) {
var editor = "<input type='hidden' name='" + $this.attr("name") + "' value='" + $this.summernote('code') + "' />";
$form.append(editor);
} else {
$.showErr("请填写项目详情");
return false;
}
});
if ($iframe.size() == 0) {
$iframe = $("<iframe id='callbackframe' name='callbackframe' src='about:blank' style='display:none'></iframe>").appendTo("body");
}
if (!form.ajax) {
$form.append('<input type="hidden" name="ajax" value="1" />');
}
form.target = "callbackframe";
_iframeResponse($iframe[0], callback || YUNM.ajaxDone);
}
function _iframeResponse(iframe, callback) {
var $iframe = $(iframe), $document = $(document);
$document.trigger("ajaxStart");
$iframe.bind("load", function(event) {
$iframe.unbind("load");
$document.trigger("ajaxStop");
if (iframe.src == "javascript:'%3Chtml%3E%3C/html%3E';" || // For
// Safari
iframe.src == "javascript:'<html></html>';") { // For FF, IE
return;
}
var doc = iframe.contentDocument || iframe.document;
// fixing Opera 9.26,10.00
if (doc.readyState && doc.readyState != 'complete')
return;
// fixing Opera 9.64
if (doc.body && doc.body.innerHTML == "false")
return;
var response;
if (doc.XMLDocument) {
// response is a xml document Internet Explorer property
response = doc.XMLDocument;
} else if (doc.body) {
try {
response = $iframe.contents().find("body").text();
response = jQuery.parseJSON(response);
} catch (e) { // response is html document or plain text
response = doc.body.innerHTML;
}
} else {
// response is a xml document
response = doc;
}
callback(response);
});
}

贴上全部代码以供参考,但是这里我们只讲以下部分:

// 富文本编辑器
$("div.summernote", $form).each(function() {
var $this = $(this);
if (!$this.summernote('isEmpty')) {
var editor = "<input type='hidden' name='" + $this.attr("name") + "' value='" + $this.summernote('code') + "' />";
$form.append(editor);
} else {
$.showErr("请填写项目详情");
return false;
}
});

通过form获取到summernote对象$this 后,通过!$this.summernote('isEmpty')来判断用户是否对富文本编辑器有内容上的填写,保证不为空,为空时,就弹出提示信息。

$this.summernote('code')可获得summernote编辑器的html内容,将其封装到input对象中,name为前文中div提供的name,供后端使用。

这里其他地方就不做多解释了,详细可参照Bootstrap wysiwyg富文本数据如何保存到mysql。

保存到数据库中是什么样子呢?

<p><img src="http://localhost:8080/ymeng/upload/2016033117093076.jpeg" style=""></p><p><br></p><p>你好,有兴趣可以加入到沉默王二的群啊<br></p>

页面效果为:

超漂亮的Bootstrap 富文本编辑器summernote

好了,好了,终于写完了,没想到写的这么累,如果你有什么新鲜的玩意,也可以联系我啊,欢迎你的指导!

关于Bootstrap 富文本编辑器summernote小编就给大家介绍到这里,希望对大家有所帮助!有不同见解欢迎提出宝贵意见,共同学习进步!

Javascript 相关文章推荐
JS获取dom 对象 ajax操作 读写cookie函数
Nov 18 Javascript
js中实现多态采用和继承类似的方法
Aug 22 Javascript
node.js中的console.assert方法使用说明
Dec 10 Javascript
jQuery拖动元素并对元素进行重新排序
Dec 30 Javascript
老生常谈Javascript中的原型和this指针
Oct 09 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
Mar 21 jQuery
jQuery插件imgAreaSelect基础讲解
May 26 jQuery
详解React Native开源时间日期选择器组件(react-native-datetime)
Sep 13 Javascript
arcgis for js栅格图层叠加(Raster Layer)问题
Nov 22 Javascript
详解vue移动端项目的适配(以mint-ui为例)
Aug 17 Javascript
Layui数据表格之单元格编辑方式
Oct 26 Javascript
react使用antd的上传组件实现文件表单一起提交功能(完整代码)
Jun 29 Javascript
jQuery技巧之让任何组件都支持类似DOM的事件管理
Apr 05 #Javascript
JS+CSS实现闪烁字体效果代码
Apr 05 #Javascript
js拖拽的原型声明和用法总结
Apr 04 #Javascript
javascript如何实现360度全景照片问题汇总
Apr 04 #Javascript
javascript制作照片墙及制作过程中出现的问题
Apr 04 #Javascript
javascript拖拽效果延伸学习
Apr 04 #Javascript
javascript事件委托的用法及其好处简析
Apr 04 #Javascript
You might like
PHP中使用数组实现堆栈数据结构的代码
2012/02/05 PHP
基于PHP中的常用函数回顾
2013/07/11 PHP
Parse正式发布开源PHP SDK
2014/08/11 PHP
用 Composer构建自己的 PHP 框架之使用 ORM
2014/10/30 PHP
DOM基础及php读取xml内容操作的方法
2015/01/23 PHP
如何利用http协议发布博客园博文评论
2015/08/03 PHP
zend framework重定向方法小结
2016/05/28 PHP
php抽象方法和抽象类实例分析
2016/12/07 PHP
PHP通过get方法获得form表单数据方法总结
2018/09/12 PHP
PHP Ajax跨域问题解决方案代码实例
2020/08/01 PHP
JavaScript 事件记录使用说明
2009/10/20 Javascript
JavaScript编程中window的location与history对象详解
2015/10/26 Javascript
JS图片定时翻滚效果实现方法
2016/06/21 Javascript
总结在前端排序中遇到的问题
2016/07/19 Javascript
Angular.js中用ng-repeat-start实现自定义显示
2016/10/18 Javascript
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
2017/05/09 Javascript
微信小程序支付及退款流程详解
2017/11/30 Javascript
angularJs中ng-model-options设置数据同步的方法
2018/09/30 Javascript
微信小程序发送短信验证码完整实例
2019/01/07 Javascript
Vue的生命周期操作示例
2019/09/17 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
2019/09/19 Javascript
如何在vue中使用video.js播放m3u8格式的视频
2021/02/01 Vue.js
Python3使用requests登录人人影视网站的方法
2016/05/11 Python
TensorFlow数据输入的方法示例
2018/06/19 Python
python selenium 获取标签的属性值、内容、状态方法
2018/06/22 Python
python遍历文件夹找出文件夹后缀为py的文件方法
2018/10/21 Python
详解Python Qt的窗体开发的基本操作
2019/07/14 Python
python 实现视频 图像帧提取
2019/12/10 Python
python图形用户接口实例详解
2019/12/16 Python
TensorFlow的环境配置与安装方法
2021/02/20 Python
国培教师自我鉴定
2014/02/12 职场文书
《从现在开始》教学反思
2014/04/15 职场文书
三八妇女节活动总结
2014/05/04 职场文书
2014大学班主任工作总结
2014/11/08 职场文书
2016年五一促销广告语
2016/01/28 职场文书
2016年小学党支部创先争优活动总结
2016/04/05 职场文书