layui
.define(['upload', 'laytpl', 'layer'], function (exports) {
var log = console.log // 开发测试时的简写
var upload = layui.upload
var laytpl = layui.laytpl
var layer = layui.layer
var $ = layui.jquery
var domain = location.origin // 自行修改,注意末尾的斜杠
var uploadUrl = domain + '/upload/test' // 同上
/**
* 上传完成后,渲染的 html 元素 模板
* @type {string}
*/
var itemTpl =
'
' +
' {{# if (d.isImage) { }}' +
'
' +
' {{# } else { }}' +
'
已上传文件
' +
' {{# } }}' +
'
' +
' 复制' +
'
' href="{{ d.src }}" target="_blank" title="查看" ' +
' class="up-action {{# if (d.isImage) { }} up-preview {{# } }}"' +
' >查看
' +
' {{# if (!d.readOnly) { }}' +
' 替换' +
' 移除' +
' {{# } }}' +
'
' +
' ' +
'
'
/**
* 简单判断是不是图片地址
* @param {string} path
* @return {boolean}
*/
var isImage = function (path) {
var t = path.toLowerCase().split('.')
var ext = t.length <= 1
? ''
: t[t.length - 1]
var imageExts = [
'jpg', 'jpeg', 'gif', 'png', 'bmp', 'ico', 'webp', 'svg', 'tiff',
]
return imageExts.indexOf(ext) !== -1
}
/**
* 简单判断是不是全路径地址
* @param {string} url
* @return {boolean}
*/
var isFullUrl = function (url) {
url = url.toLowerCase()
return (url.indexOf('https://') === 0) ||
(url.indexOf('http://') === 0)
}
/**
* 复制文本到剪贴板
* @param {string} text
* @return {boolean}
*/
var copyText = function (text) {
var $copyInput = $('')
$('body').append($copyInput)
$copyInput.select()
var res = document.execCommand('copy')
$copyInput.remove()
return res
}
/**
* 手动渲染一个上传器
* @param $wrapper 一个 jQuery 元素
* @param overOptions 可选,覆盖 html 元素中设置的配置
*/
var renderUploader = function ($wrapper, overOptions) {
// 覆盖的配置
if (overOptions) {
var keys = Object.keys(overOptions)
for (var i = 0; i < keys.length; i++) {
var k = keys[i]
$wrapper.data(k, overOptions[k])
}
}
// 可选配置的默认配置
// 有的是 layui upload 的,可参考 layui 文档
var defaultOptions = {
field: 'up_file',
size: 2048,
accept: 'images',
acceptMime: 'image/*',
max: 1, // 最多上传多少张
fullUrl: false, // input 的值,是否设置为全路径
inputName: 'file', // input 的 name 属性,尽量别和前面的 field 一样,虽然没影响
readOnly: false, // 只读情况下,只有查看和复制操作
value: '', // 默认的文件 url 值,用于初始化显示,多个值用英文逗号分隔
}
var options = $.extend(defaultOptions, $wrapper.data())
/**
* layui 上传实例
*/
var uploaderIns
/**
* 获取当前文件已经上传了多少个
*
* @return {number}
*/
var getItemsCount = function () {
return $itemsWrapper.children().length
}
/**
* 判断是否达到最大上传数
* @return {boolean}
*/
var isMax = function () {
return (options.max != 0) && (getItemsCount() >= options.max)
}
/**
* 根据当前已经上传和最大上传,设置选择器的显隐
*/
var setPickerVisible = function () {
isMax() ? $picker.hide() : $picker.show()
}
/**
* 生成上传后新元素的的 html
* @param val 上传后文件的地址
* @param callback html 生成后的回调
*/
var renderItemHtml = function (val, callback) {
var src = isFullUrl(val) ? val : domain + val
laytpl(itemTpl).render({
val: options.fullUrl ? src : val,
src: src,
isImage: isImage(val),
inputName: options.inputName,
readOnly: options.readOnly,
}, function (html) {
var $item = $(html)
// 复制
$item.find('.up-copy').click(function () {
copyText(src)
layer.msg('复制成功', { icon: 1 })
})
// 替换
if (!options.readOnly) {
renderReplaceUploader($item)
}
callback && callback($item)
})
}
/**
* 添加新的已上传元素
* @param {string} val
*/
var appendItem = function (val) {
renderItemHtml(val, function ($item) {
$itemsWrapper.append($item)
setPickerVisible()
})
}
/**
* 替换图片的上传
* @param $item
*/
var renderReplaceUploader = function ($item) {
var replaceOptions = $.extend({}, options, {
elem: $item.find('.up-replace'),
multiple: false,
number: 1,
done: function (res) {
layer.closeAll('loading')
if (res.code !== 0) {
layer.msg(res.msg, { icon: 2 })
return
}
renderItemHtml(res.data.path, function ($newItem) {
$item.replaceWith($newItem)
})
},
error: function () {
layer.closeAll('loading')
},
})
upload.render(replaceOptions)
}
$wrapper.html('
if (!options.readOnly) {
$wrapper.append('
点击上传
')
}
var $picker = $wrapper.find('.up-picker')
var $itemsWrapper = $wrapper.find('.up-items-wrapper')
// 固定配置
options = $.extend(options, {
elem: $picker,
url: uploadUrl,
auto: true,
method: 'post',
multiple: (options.max > 1) || (options.max == 0),
number: options.max,
before: function () {
layer.load(2)
},
done: function (res) {
layer.closeAll('loading')
if (res.code !== 0) {
layer.msg(res.msg, { icon: 2 })
return
}
// layui 的自动上传,好像不能提前终止
// 所以,如果上传数量超过设定的值,只能在这里丢弃返回的结果
if (isMax()) {
return
}
appendItem(res.data.path)
},
error: function () {
layer.closeAll('loading')
},
})
// 初始化默认值的情况
var value = options.value
if (value) {
value = value.split(',')
for (var i = 0; i < value.length; i++) {
if (isMax()) {
break
}
appendItem(value[i])
}
}
// 只读的情况下,不需要渲染上传器
if (!options.readOnly) {
uploaderIns = upload.render(options)
}
$wrapper.on('click', '.up-remove', function () {
$(this).parents('.up-item').remove()
setPickerVisible()
})
}
// 初始化页面上的上传器,使用 .up-uploader 选择器
$('.up-uploader').each(function () {
renderUploader($(this))
})
// 图片弹框预览
$(document).on('click', '.up-preview', function () {
var img = $(this).parents('.up-item').find('.up-image')[0]
var src = img.src
if (!img) {
layer.msg('没有可显示的图片', { icon: 2 })
return
}
var width = img.naturalWidth
var height = img.naturalHeight
if (!width || !height) {
layer.msg('图片尺寸错误', { icon: 2 })
return
}
var hwRatio = height / width
var maxHeight = window.innerHeight * 0.9
var maxWidth = window.innerWidth * 0.9
if (width > maxWidth) {
width = maxWidth
height = width * hwRatio
}
if (height > maxHeight) {
height = maxHeight
width = height / hwRatio
}
layer.open({
type: 1,
title: false,
area: [width + 'px', height + 'px'],
shadeClose: true,
content:
'' +
'
' +
'',
})
return false
})
exports('up-uploader', {
// 导出该函数,可在其他地方,手动渲染动态加入的 html 元素
// 如何导入,可查看 layui 的自定义模块文档
renderUploader: renderUploader,
})
})