Create.cshtml
@model SN.Models.ProductModel
@{
ViewBag.Title = "产品立项";
Layout = "../Shared/_LayoutAdminLTE.cshtml";
}
<head>
<!--summernote-->
<link href="~/Content/summernote/summernote.css" rel="stylesheet" />
<script src="~/Content/summernote/summernote.js"></script>
<script src="~/Content/summernote/summernote-zh-CN.js"></script>
</head>
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<!-- 内容标题 -->
<section class="content-header">
<h1>
创建新产品
<small>产品管理</small>
</h1>
<!-- 导航地图 -->
<ol class="breadcrumb">
<li><a href="../Product/Index"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">产品管理</li>
</ol>
</section>
<!-- 内容Panel -->
<section class="content">
<!-- Default box -->
<div class="box">
@*<div class="box-header with-border">
<h3 class="box-title">创建新产品</h3>
</div>*@
<div class="box-body">
<!-- 这是写入要展示的内容 -->
<div class="form-group">
@Html.EditorFor(model => model.ProductName, new { htmlAttributes = new { @class = "form-control", placeholder = "请输入产品名称" } })
@Html.ValidationMessageFor(model => model.ProductName, "", new { @class = "text-danger" })
</div>
@Html.HiddenFor(model => model.Productlogic)@*定义一个隐藏表用单于接收summernote数据*@
<div class="form-group">
<div id="summernote" placeholder="请输入产品逻辑说明"></div>
@Html.ValidationMessageFor(model => model.Productlogic, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.EditorFor(model => model.Interactive, new { htmlAttributes = new { @class = "form-control", placeholder = "请输入交互需求" } })
@Html.ValidationMessageFor(model => model.Interactive, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.EditorFor(model => model.DateRep, new { htmlAttributes = new { @class = "form-control", placeholder = "请输入数据需求" } })
@Html.ValidationMessageFor(model => model.DateRep, "", new { @class = "text-danger" })
</div>
<div class="form-group">
@Html.EditorFor(model => model.OtherRep, new { htmlAttributes = new { @class = "form-control", placeholder = "请输入非功能需求" } })
@Html.ValidationMessageFor(model => model.OtherRep, "", new { @class = "text-danger" })
</div>
<div class="btn-group pull-right">
<button type="submit" class="btn btn-primary" id="btnLogin">保存</button>
<button type="button" class="btn btn-default" id="btnRegister">取消</button>
</div>
<!-- 这是写入要展示的内容 -->
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</section>
}
@section scripts{
<!-- 内部javascript -->
<script>
$(document).ready(function () {
var placeholder = $("#summernote").attr("placeholder") || '';//设置输入提示
var url = $("#summernote").attr("action") || '';//设置上传图片的url
$("#summernote").summernote({
lang: 'zh-CN',
placeholder: placeholder,
minHeight: 300,
maxHeight: 800,
dialogsFade: true,// 设置滑动效果Add fade effect on dialogs
dialogsInBody: true,// 设置窗口显示位置Dialogs can be placed in body, not in
disableDragAndDrop: false,//设置拖拽
callbacks: {
onImageUpload: function (files) {
$(files).each(function () {
var file = this;
var data = new FormData();
data.append("file", file);
//ajax上传图片
$.ajax({
url: url,
type: "post",
data: data,
dataType: "json",
cache: false,
contentType: false,
processData: false,
success: function (response) {
var jsonObj = JSON.parse(response); // JSON.parse(); 方法
var jsonObj = JSON.parse(response); // JSON.parse(); 方法
var imgNode = document.createElement('img');
imgNode.setAttribute('src', jsonObj.result);
$("#summernote").summernote('insertNode', imgNode);
},
error: function (response) {
}
});
});
}
}
});
//初始化summernote的值
var encodevalue = $("#Productlogic").val();
//var decodevalue = htmlDecode(encodevalue);
$('#summernote').summernote('code', encodevalue);
});
//设置表单数值
$("form").submit(function (e) {
var makrup = $("#summernote").summernote('code');
//将文档编辑器的内容赋给要存储的属性(如Productlogic)
$("#Productlogic").val(makrup);
});
</script>
}
summernote-zh-CN.js
(function ($) {
$.extend($.summernote.lang, {
'zh-CN': {
font: {
bold: '粗体',
italic: '斜体',
underline: '下划线',
clear: '清除格式',
height: '行高',
name: '字体',
strikethrough: '删除线',
subscript: '下标',
superscript: '上标',
size: '字号'
},
image: {
image: '图片',
insert: '插入图片',
resizeFull: '缩放至 100%',
resizeHalf: '缩放至 50%',
resizeQuarter: '缩放至 25%',
floatLeft: '靠左浮动',
floatRight: '靠右浮动',
floatNone: '取消浮动',
shapeRounded: '形状: 圆角',
shapeCircle: '形状: 圆',
shapeThumbnail: '形状: 缩略图',
shapeNone: '形状: 无',
dragImageHere: '将图片拖拽至此处',
selectFromFiles: '从本地上传',
maximumFileSize: '文件大小最大值',
maximumFileSizeError: '文件大小超出最大值。',
url: '图片地址',
remove: '移除图片'
},
video: {
video: '视频',
videoLink: '视频链接',
insert: '插入视频',
url: '视频地址',
providers: '(优酷, Instagram, DailyMotion, Youtube等)'
},
link: {
link: '链接',
insert: '插入链接',
unlink: '去除链接',
edit: '编辑链接',
textToDisplay: '显示文本',
url: '链接地址',
openInNewWindow: '在新窗口打开'
},
table: {
table: '表格'
},
hr: {
insert: '水平线'
},
style: {
style: '样式',
p: '普通',
blockquote: '引用',
pre: '代码',
h1: '标题 1',
h2: '标题 2',
h3: '标题 3',
h4: '标题 4',
h5: '标题 5',
h6: '标题 6'
},
lists: {
unordered: '无序列表',
ordered: '有序列表'
},
options: {
help: '帮助',
fullscreen: '全屏',
codeview: '源代码'
},
paragraph: {
paragraph: '段落',
outdent: '减少缩进',
indent: '增加缩进',
left: '左对齐',
center: '居中对齐',
right: '右对齐',
justify: '两端对齐'
},
color: {
recent: '最近使用',
more: '更多',
background: '背景',
foreground: '前景',
transparent: '透明',
setTransparent: '透明',
reset: '重置',
resetToDefault: '默认'
},
shortcut: {
shortcuts: '快捷键',
close: '关闭',
textFormatting: '文本格式',
action: '动作',
paragraphFormatting: '段落格式',
documentStyle: '文档样式',
extraKeys: '额外按键'
},
history: {
undo: '撤销',
redo: '重做'
},
help: {
insertParagraph: '插入段落',
undo: '撤销',
redo: '重做',
tab: '增加缩进',
untab: '减少缩进',
bold: '粗体',
italic: '斜体',
underline: '下划线',
strikethrough: '删除线',
removeFormat: '清除格式',
justifyLeft: '左对齐',
justifyCenter: '居中对齐',
justifyRight: '右对齐',
justifyFull: '两端对齐',
insertUnorderedList: '无序列表',
insertOrderedList: '有序列表',
outdent: '减少缩进',
indent: '增加缩进',
formatPara: '设置选中内容样式为 普通',
formatH1: '设置选中内容样式为 标题1',
formatH2: '设置选中内容样式为 标题2',
formatH3: '设置选中内容样式为 标题3',
formatH4: '设置选中内容样式为 标题4',
formatH5: '设置选中内容样式为 标题5',
formatH6: '设置选中内容样式为 标题6',
insertHorizontalRule: '插入水平线',
'linkDialog.show': '显示链接对话框'
}
}
});
})(jQuery);
如图
summernote.js
插入图片,默认会生成base64数据
/**
* insertImages
* @param {File[]} files
*/
this.insertImages = function (files) {
$.each(files, function (idx, file) {
var filename = file.name;
if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {
context.triggerEvent('image.upload.error', lang.image.maximumFileSizeError);
} else {
async.readFileAsDataURL(file).then(function (dataURL) {
return self.insertImage(dataURL, filename);
}).fail(function () {
context.triggerEvent('image.upload.error');
});
}
});
};
//插入视频相关
this.createVideoNode = function (url) {
// video url patterns(youtube, instagram, vimeo, dailymotion, youku, mp4, ogg, webm)
var ytRegExp = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
var ytMatch = url.match(ytRegExp);
var igRegExp = /(?:www\.|\/\/)instagram\.com\/p\/(.[a-zA-Z0-9_-]*)/;
var igMatch = url.match(igRegExp);
var vRegExp = /\/\/vine\.co\/v\/([a-zA-Z0-9]+)/;
var vMatch = url.match(vRegExp);
var vimRegExp = /\/\/(player\.)?vimeo\.com\/([a-z]*\/)*([0-9]{6,11})[?]?.*/;
var vimMatch = url.match(vimRegExp);
var dmRegExp = /.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/;
var dmMatch = url.match(dmRegExp);
var youkuRegExp = /\/\/v\.youku\.com\/v_show\/id_(\w+)=*\.html/;
var youkuMatch = url.match(youkuRegExp);
var mp4RegExp = /^.+.(mp4|m4v)$/;
var mp4Match = url.match(mp4RegExp);
var oggRegExp = /^.+.(ogg|ogv)$/;
var oggMatch = url.match(oggRegExp);
var webmRegExp = /^.+.(webm)$/;
var webmMatch = url.match(webmRegExp);
var $video;
if (ytMatch && ytMatch[1].length === 11) {
var youtubeId = ytMatch[1];
$video = $('<iframe>')
.attr('frameborder', 0)
.attr('src', '//www.youtube.com/embed/' + youtubeId)
.attr('width', '640').attr('height', '360');
} else if (igMatch && igMatch[0].length) {
$video = $('<iframe>')
.attr('frameborder', 0)
.attr('src', 'https://instagram.com/p/' + igMatch[1] + '/embed/')
.attr('width', '612').attr('height', '710')
.attr('scrolling', 'no')
.attr('allowtransparency', 'true');
} else if (vMatch && vMatch[0].length) {
$video = $('<iframe>')
.attr('frameborder', 0)
.attr('src', vMatch[0] + '/embed/simple')
.attr('width', '600').attr('height', '600')
.attr('class', 'vine-embed');
} else if (vimMatch && vimMatch[3].length) {
$video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
.attr('frameborder', 0)
.attr('src', '//player.vimeo.com/video/' + vimMatch[3])
.attr('width', '640').attr('height', '360');
} else if (dmMatch && dmMatch[2].length) {
$video = $('<iframe>')
.attr('frameborder', 0)
.attr('src', '//www.dailymotion.com/embed/video/' + dmMatch[2])
.attr('width', '640').attr('height', '360');
} else if (youkuMatch && youkuMatch[1].length) {
$video = $('<iframe webkitallowfullscreen mozallowfullscreen allowfullscreen>')
.attr('frameborder', 0)
.attr('height', '498')
.attr('width', '510')
.attr('src', '//player.youku.com/embed/' + youkuMatch[1]);
} else if (mp4Match || oggMatch || webmMatch) {
$video = $('<video controls>')
.attr('src', url)
.attr('width', '640').attr('height', '360');
} else {
// this is not a known video link. Now what, Cat? Now what?
return false;
}
$video.addClass('note-video-clip');
return $video[0];
};
this.show = function () {
var text = context.invoke('editor.getSelectedText');
context.invoke('editor.saveRange');
this.showVideoDialog(text).then(function (url) {
// [workaround] hide dialog before restore range for IE range focus
ui.hideDialog(self.$dialog);
context.invoke('editor.restoreRange');
// build node
var $node = self.createVideoNode(url);
if ($node) {
// insert video node
context.invoke('editor.insertNode', $node);
}
}).fail(function () {
context.invoke('editor.restoreRange');
});
};
Summernote.cshtml
@model RepDetailedModel
@{
ViewBag.Title = "Summernote";
}
<div id="summernote">这是Summernote富文本框</div>
@*<script type="text/javascript">
//加载编辑器
$(document).ready(function () {
$("#summernote").summernote({
height: 400,
minHeight: 300,
maxHeight: 500,
focus: true,
lang: "zh-CN",
//重写图片上传
onImageUpload: function (files, editor, $editable) {
sendFile(files[0], editor, $editable);
}
});
});
//图片上传
function sendFile(file, editor, $editable) {
var filename = false;
try{
filename=false['name'];
} catch (e) {
filename = false;
}
if (!filename) {
$(".note-alarm").remove();
}
//以上防止在编辑器内拖拽引发第二次上传导致的提示错误
data = new FormData();
data.append("file", "file");
data.append("key", "filename");//唯一性参数
$.ajax({
data: data,
type: "POST",
url: "",
cache: false,
contentType: false,
success: function (url) {
if (url == '200') {
alert("上传失败!")
return;
} else {
alert("上传成功!")
}
//alert(url);
editor.insertImage($editable, url)
//setTimeout(funtion(){$(".note-alarm").remove();},3000);
},
error: function () {
alert("上传失败!");
return;
//setTimeout(funtion(){$(".note-alarm").remove();},3000);
}
});
}
//var encodevalue = $("#RepDescribe").val();
var decodevalue = htmlDecode(encodevalue);
//$("#summernote").summernote('code', encodevalue);
给编辑器赋值
//var makrup = $('#summernote').summernote('code');
var encodevalue = htmlEncode(makrup);
//$("#RepDescribe").val(makrup);
</script>*@
@*<script>
$(document).ready(function () {
$('.summernote').summernote();
})
</script>*@
<script type="text/javascript">
$(document).ready(function () {
/* function sendFile(file, editor,welEditable) {
console.log("file="+file);
console.log("editor="+editor);
console.log("welEditable="+welEditable);
data = new FormData();
data.append("blog_image[image]", file);
$.ajax({
url: 'blog_images.jsp',
data: data,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
editor.insertImage(welEditable, data.url);
}
});
}
*/
$('#summernote').summernote({
height: 300, /*高さを指定*/
lang: 'zh-CN', // default: 'en-US'
focus: true,
toolbar: [
['style', ['bold', 'italic', 'underline', 'clear']],
['fontsize', ['fontsize']],
['color', ['color']],
['para', ['ul', 'ol', 'paragraph']],
['height', ['height']],
['insert', ['picture', 'video']]
],
/* image: {
selectFromFiles: '选择文件'
}, */
/*onImageUpload: function(files, editor, welEditable) {
sendFile(files[0], editor,welEditable);
}*/
onImageUpload: function (files, editor, $editable) {
sendFile(files[0], editor, $editable);
}
});
});
function sendFile(file, editor, $editable) {
$(".note-toolbar.btn-toolbar").append('正在上传图片');
var filename = false;
try {
filename = file['name'];
alert(filename);
} catch (e) { filename = false; }
if (!filename) { $(".note-alarm").remove(); }
//以上防止在图片在编辑器内拖拽引发第二次上传导致的提示错误
var ext = filename.substr(filename.lastIndexOf("."));
ext = ext.toUpperCase();
var timestamp = new Date().getTime();
var name = timestamp + "_" + $("#summernote").attr('aid') + ext;
//name是文件名,自己随意定义,aid是我自己增加的属性用于区分文件用户
data = new FormData();
data.append("file", file);
data.append("key", name);
data.append("token", $("#summernote").attr('token'));
$.ajax({
data: data,
type: "POST",
url: "/summernote/fileupload", //图片上传出来的url,返回的是图片上传后的路径,http格式
contentType: "json",
cache: false,
processData: false,
success: function (data) {
//data是返回的hash,key之类的值,key是定义的文件名
alert(data);
//把图片放到编辑框中。editor.insertImage 是参数,写死。后面的http是网上的图片资源路径。
//网上很多就是这一步出错。
$('#summernote').summernote('editor.insertImage', "http://res.cloudinary.com/demo/image/upload/butterfly.jpg");
$(".note-alarm").html("上传成功,请等待加载");
setTimeout(function () { $(".note-alarm").remove(); }, 3000);
},
error: function () {
$(".note-alarm").html("上传失败");
setTimeout(function () { $(".note-alarm").remove(); }, 3000);
}
});
}
</script>
<script>
var HelloButton = function (context) {
var ui = $.summernote.ui;
// create button
var button = ui.button({
contents: '<i class="fa fa-child" /> Hello',
tooltip: 'hello',
click: function () {
// invoke insertText method with 'hello' on editor module.
context.invoke('editor.insertText', 'hello');
}
});
return button.render(); // return button as jquery object
}
</script>