diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index 029e88d..97ad353 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -78,6 +78,8 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 是否限制工作表名长度 [limitSheetNameLength](#limitSheetNameLength) - 默认允许工作表名的最大长度 [defaultSheetNameMaxLength](#defaultSheetNameMaxLength) - 分页器 [pager](#pager) +- 自定义图片上传 [uploadImage](#uploadImage) +- 自定义图片地址处理 [imageUrlHandle](#imageUrlHandle) ### container - 类型:String @@ -714,6 +716,79 @@ Luckysheet开放了更细致的自定义配置选项,分别有 } ``` +### uploadImage + +用于自定义图片的上传,默认情况下,插入的图片是以base64的形式放入sheet数据中,如果需要单独上传图片,仅在sheet中引用图片地址可使用此配置。 + +- 类型: `function (file) => Promise(imgUrl)`,接受file对象,返回Promise,值为上传完成的图片url +- 默认值: `undefined` + +:::details 查看示例配置 + +```js +{ + uploadImage: function (file) { + return new Promise(function (resolve, reject) { + var xhr = new XMLHttpRequest(); + xhr.open('POST', 'http://192.168.210.159/miniuiServer/imageUploader.php'); + + // 额外的请求头 + var headers = {}; + if (headers) { + Object.keys(headers).forEach(function (k) { + xhr.setRequestHeader(k, headers[k]); + }); + } + var data = new FormData(); + // 要上传的图片文件 + data.append('file', file, file.name || ''); + + xhr.send(data); + xhr.onreadystatechange = function () { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + var res = JSON.parse(xhr.responseText); + var url = res.downloadUrl; + if (url) { + resolve(url); // 给上传的后的地址 + } else { + reject('image upload error'); + } + } else { + reject('image upload error'); + } + } + }; + }); + } +} + +``` + +::: + +### imageUrlHandle + +图片上传的路径处理函数,和 [uploadImage](#uploadImage) 相关,一般只有使用自定义图片上传才需要此配置。 + +- 类型: `function (string) => string`,接受原始路径,返回新路径 +- 默认值: `undefined` +- 作用,处理图片显示时的路径。 + 如上传返回地址为接口地址,如: `rest/attach/[fileguid]`, 则需要处理为 `http://localhost:8080/xxx/rest/attach/[fileguid]` 才能显示,但将前面域名信息写入数据,后续使用可能会有问题,因此可使用此方法处理路径,全路径仅在展示使用,数据内仅存储 `rest/attach/[fileguid]` + +```js +{ + // 处理上传图片的地址 + imageUrlHandle: function (url) { + // 已经是 // http data 开头则不处理 + if (/^(?:\/\/|(?:http|https|data):)/i.test(url)) { + return url; + } + return location.origin + url; + } +} +``` + ------------ ## 钩子函数 @@ -1461,6 +1536,33 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - 作用:工作表从活动状态转为非活动状态后 - 参数: - {Number} [i]: sheet页的`index` + +### imageDeleteBefore + +- 类型:Function +- 默认值:null +- 作用:图片删除前触发 +- 参数: + - {Object} [imageItem]: 要删除的图片配置对象 + +### imageDeleteAfter + +- 类型:Function +- 默认值:null +- 作用:图片删除后触发,如果自定义了图片上传,可在此处发请求删除图片 +- 参数: + - {Object} [imageItem]: 删除的图片配置对象 + +```js +{ + hook: { + imageDeleteAfter: function (imageItem) { + var src = imgItem.src; + $.post('/rest/file/deletebyurl', {downloadUrl: src}); + } + } +} +``` ------------ diff --git a/src/controllers/handler.js b/src/controllers/handler.js index d98c7ab..73c011d 100644 --- a/src/controllers/handler.js +++ b/src/controllers/handler.js @@ -1476,13 +1476,7 @@ export default function luckysheetHandler() { if(!checkProtectionAuthorityNormal(Store.currentSheetIndex, "editObjects")){ return; } - let render = new FileReader(); - render.readAsDataURL(files[0]); - - render.onload = function(event){ - let src = event.target.result; - imageCtrl.inserImg(src); - } + imageCtrl.insertImg(files[0]); } handleCellDragStopEvent(e); }, false); @@ -3174,17 +3168,20 @@ export default function luckysheetHandler() { "left": left, "top": top }); + + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let imgSrc = typeof imageUrlHandle === 'function' ? imageUrlHandle(imgItem.src) : imgItem.src; $("#luckysheet-modal-dialog-cropping .cropping-mask").css({ "width": imgItem.default.width, "height": imgItem.default.height, - "background-image": "url(" + imgItem.src + ")", + "background-image": "url(" + imgSrc + ")", "left": -offsetLeft, "top": -offsetTop }) $("#luckysheet-modal-dialog-cropping .cropping-content").css({ - "background-image": "url(" + imgItem.src + ")", + "background-image": "url(" + imgSrc + ")", "background-size": imgItem.default.width + "px " + imgItem.default.height + "px", "background-position": -offsetLeft + "px " + -offsetTop + "px" }) @@ -4886,14 +4883,7 @@ export default function luckysheetHandler() { return; } let file = e.currentTarget.files[0]; - let render = new FileReader(); - render.readAsDataURL(file); - - render.onload = function(event){ - let src = event.target.result; - imageCtrl.inserImg(src); - $("#luckysheet-imgUpload").val(""); - } + imageCtrl.insertImg(file); }); //菜单栏 插入链接按钮 @@ -5620,12 +5610,7 @@ export default function luckysheetHandler() { } //复制的是图片 else if(clipboardData.files.length == 1 && clipboardData.files[0].type.indexOf('image') > -1){ - let render = new FileReader(); - render.readAsDataURL(clipboardData.files[0]); - render.onload = function(event){ - let src = event.target.result; - imageCtrl.inserImg(src); - } + imageCtrl.insertImg(clipboardData.files[0]); return; } diff --git a/src/controllers/imageCtrl.js b/src/controllers/imageCtrl.js index 949c13e..3120654 100644 --- a/src/controllers/imageCtrl.js +++ b/src/controllers/imageCtrl.js @@ -8,6 +8,8 @@ import { setluckysheet_scroll_status } from '../methods/set'; import { replaceHtml } from '../utils/util'; import Store from '../store'; import locale from '../locale/locale'; +import tooltip from '../global/tooltip'; +import method from '../global/method'; const imageCtrl = { imgItem: { @@ -49,7 +51,29 @@ const imageCtrl = { cropChangeXY: null, cropChangeObj: null, copyImgItemObj: null, - inserImg: function(src){ + insertImg: function (file) { + const uploadImage = Store.toJsonOptions && Store.toJsonOptions['uploadImage']; + if (typeof uploadImage === 'function') { + // 上传形式 + uploadImage(file).then(url => { + imageCtrl._insertImg(url); + }).catch(error => { + tooltip.info('', '图片上传失败'); + }); + } else { + // 内部base64形式 + let render = new FileReader(); + render.readAsDataURL(file); + + render.onload = function(event){ + let src = event.target.result; + imageCtrl._insertImg(src); + $("#luckysheet-imgUpload").val(""); + } + } + }, + + _insertImg: function(src){ let _this = this; let last = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1]; @@ -73,7 +97,8 @@ const imageCtrl = { _this.addImgItem(img); } - image.src = src; + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + image.src = typeof imageUrlHandle === 'function' ? imageUrlHandle(src) : src; }, generateRandomId: function(prefix) { if(prefix == null){ @@ -95,7 +120,8 @@ const imageCtrl = { modelHtml: function(id, imgItem) { let _this = this; - let src = imgItem.src; + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let src = typeof imageUrlHandle === 'function' ? imageUrlHandle(imgItem.src) : imgItem.src; let imgItemParam = _this.getImgItemParam(imgItem); let width = imgItemParam.width * Store.zoomRatio; @@ -368,9 +394,10 @@ const imageCtrl = { "top": top, "position": position }); - + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let imgUrl = typeof imageUrlHandle === 'function' ? imageUrlHandle(item.src) : item.src; $("#luckysheet-modal-dialog-activeImage .luckysheet-modal-dialog-content").css({ - "background-image": "url(" + item.src + ")", + "background-image": "url(" + imgUrl + ")", "background-size": item.default.width * Store.zoomRatio + "px " + item.default.height * Store.zoomRatio + "px", "background-position": -item.crop.offsetLeft * Store.zoomRatio + "px " + -item.crop.offsetTop * Store.zoomRatio + "px" }) @@ -747,16 +774,19 @@ const imageCtrl = { "position": position }); + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let imgSrc = typeof imageUrlHandle === 'function' ? imageUrlHandle(item.src) : item.src; + $("#luckysheet-modal-dialog-cropping .cropping-mask").css({ "width": item.default.width, "height": item.default.height, - "background-image": "url(" + item.src + ")", + "background-image": "url(" + imgSrc + ")", "left": -item.crop.offsetLeft, "top": -item.crop.offsetTop }) $("#luckysheet-modal-dialog-cropping .cropping-content").css({ - "background-image": "url(" + item.src + ")", + "background-image": "url(" + imgSrc + ")", "background-size": item.default.width + "px " + item.default.height + "px", "background-position": -item.crop.offsetLeft + "px " + -item.crop.offsetTop + "px" }) @@ -794,9 +824,11 @@ const imageCtrl = { "top": top, "position": position }); + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let imgSrc = typeof imageUrlHandle === 'function' ? imageUrlHandle(item.src) : item.src; $("#luckysheet-modal-dialog-activeImage .luckysheet-modal-dialog-content").css({ - "background-image": "url(" + item.src + ")", + "background-image": "url(" + imgSrc + ")", "background-size": item.default.width + "px " + item.default.height + "px", "background-position": -item.crop.offsetLeft + "px " + -item.crop.offsetTop + "px" }) @@ -842,8 +874,11 @@ const imageCtrl = { "position": position }); + let imageUrlHandle = Store.toJsonOptions && Store.toJsonOptions['imageUrlHandle']; + let imgSrc = typeof imageUrlHandle === 'function' ? imageUrlHandle(imgItem.src) : imgItem.src; + $("#luckysheet-modal-dialog-activeImage .luckysheet-modal-dialog-content").css({ - "background-image": "url(" + imgItem.src + ")", + "background-image": "url(" + imgSrc + ")", "background-size": imgItem.default.width + "px " + imgItem.default.height + "px", "background-position": -imgItem.crop.offsetLeft + "px " + -imgItem.crop.offsetTop + "px" }) @@ -852,15 +887,24 @@ const imageCtrl = { }, removeImgItem: function() { let _this = this; + let imgItem = _this.images[_this.currentImgId]; + + // 钩子 imageDeleteBefore + if(!method.createHookFunction('imageDeleteBefore', imgItem)){ + return; + } $("#luckysheet-modal-dialog-activeImage").hide(); $("#luckysheet-modal-dialog-cropping").hide(); $("#luckysheet-modal-dialog-slider-imageCtrl").hide(); $("#" + _this.currentImgId).remove(); + delete _this.images[_this.currentImgId]; _this.currentImgId = null; + // 钩子 imageDeleteAfter + method.createHookFunction('imageDeleteAfter', imgItem); _this.ref(); }, copyImgItem: function(e) {