Browse Source

Merge pull request #831 from cdswyda/feat/image-upload

新增图片单独上传,sheet中引入图片地址的实现,解决图片较大或较多时,数据过大的问题
master
Dushusir 4 years ago
committed by GitHub
parent
commit
074b1c331e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 102
      docs/zh/guide/config.md
  2. 31
      src/controllers/handler.js
  3. 62
      src/controllers/imageCtrl.js

102
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;
}
}
```
------------
## 钩子函数
@ -1462,6 +1537,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});
}
}
}
```
------------
## 工作簿

31
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);
@ -3175,16 +3169,19 @@ export default function luckysheetHandler() {
"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;
}

62
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('<i class="fa fa-exclamation-triangle"></i>', '图片上传失败');
});
} 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) {

Loading…
Cancel
Save