From b2a46171c2cfcd9682537a801a1ea68e7e2d3ba0 Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Tue, 20 Oct 2020 17:26:29 +0800 Subject: [PATCH 1/9] feat(api add): setSheetOrder refresh getScreenshot setWorkbookName undo redo --- docs/zh/guide/api.md | 27 +--- src/controllers/constant.js | 3 - src/global/api.js | 304 +++++++++++++++++++++++++++++++++++- src/global/setdata.js | 5 +- 4 files changed, 305 insertions(+), 34 deletions(-) diff --git a/docs/zh/guide/api.md b/docs/zh/guide/api.md index 514f736..9bb9790 100644 --- a/docs/zh/guide/api.md +++ b/docs/zh/guide/api.md @@ -1651,8 +1651,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### getAllSheets() -[todo] - - **说明**: 返回所有工作表配置,格式同工作表配置,得到的结果可用于表格初始化时作为options.data使用。 @@ -1922,9 +1920,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### setSheetOrder(orderList [,setting]) -[todo] - - - **参数**: - {Array} [orderList]: 工作表顺序,设置工作表的index和order来指定位置,如: @@ -2019,9 +2014,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### refresh([setting]) -[todo] - - - **参数**: - {PlainObject} [setting]: 可选参数 @@ -2078,27 +2070,22 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### getScreenshot([setting]) -[todo] - - **参数**: - {PlainObject} [setting]: 可选参数 - + {Array | Object | String} [range]: 选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 - + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Object | String} [range]: 选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 - **说明**: - 返回指定选区截图后生成的base64格式的图片 + 返回当前表格指定选区截图后生成的base64格式的图片 ------------ ### setWorkbookName(name [,setting]) -[todo] - - **参数**: - - {Number} [name]: 工作簿名称 + - {String} [name]: 工作簿名称 - {PlainObject} [setting]: 可选参数 + {Function} [success]: 操作结束的回调函数 @@ -2110,9 +2097,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### undo([setting]) -[todo] - - - **参数**: - {PlainObject} [setting]: 可选参数 @@ -2126,9 +2110,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### redo([setting]) -[todo] - - - **参数**: - {PlainObject} [setting]: 可选参数 @@ -2257,8 +2238,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### transToData(celldata [,setting])
-[todo] - - **参数**: - {Array} [celldata]: data数据 diff --git a/src/controllers/constant.js b/src/controllers/constant.js index 5cd11a7..8899d90 100644 --- a/src/controllers/constant.js +++ b/src/controllers/constant.js @@ -530,9 +530,6 @@ function rightclickHTML(){ -
-
${rightclick.generateNewMatrix}
-
`; } diff --git a/src/global/api.js b/src/global/api.js index f861cc4..bd68992 100644 --- a/src/global/api.js +++ b/src/global/api.js @@ -1,5 +1,5 @@ import Store from "../store"; -import { replaceHtml, getObjType, chatatABC } from "../utils/util"; +import { replaceHtml, getObjType, chatatABC, luckysheetactiveCell } from "../utils/util"; import { getSheetIndex, getluckysheet_select_save, getluckysheetfile } from "../methods/get"; import locale from "../locale/locale"; @@ -20,6 +20,7 @@ import { luckysheetDeleteCell, luckysheetextendtable, luckysheetdeletetable } fr import { isRealNull, valueIsError, isRealNum, isEditMode, hasPartMC } from "./validate"; import { isdatetime, diff } from "./datecontroll"; import { getBorderInfoCompute } from './border'; +import { luckysheetDrawMain } from './draw'; import server from "../controllers/server"; import menuButton from '../controllers/menuButton'; @@ -31,8 +32,9 @@ import sheetmanage from '../controllers/sheetmanage'; import conditionformat from '../controllers/conditionformat'; import { luckysheet_searcharray } from "../controllers/sheetSearch"; import { selectHightlightShow, selectIsOverlap } from '../controllers/select'; -import { sheetHTML } from '../controllers/constant'; +import { sheetHTML, luckysheetdefaultstyle } from '../controllers/constant'; import { createFilterOptions } from '../controllers/filter'; +import controlHistory from '../controllers/controlHistory'; const IDCardReg = /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i; @@ -4662,6 +4664,64 @@ export function setSheetMove(type, options = {}) { } +/** + * 重新排序所有工作表的位置,指定工作表顺序的数组。 + * @param {Array} orderList 工作表顺序,设置工作表的index和order来指定位置 + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setSheetOrder(orderList, options = {}) { + if(orderList == null || orderList.length == 0){ + return tooltip.info("Type orderList not available", ""); + } + + let orderListMap = {}; + orderList.forEach((item) => { + orderListMap[item.index.toString()] = item.order; + }) + + Store.luckysheetfile.sort((x, y) => { + let order_x = orderListMap[x.index.toString()]; + let order_y = orderListMap[y.index.toString()]; + + if(order_x != null && order_y != null){ + return order_x - order_y; + } + else if(order_x != null){ + return -1; + } + else if(order_y != null){ + return 1; + } + else{ + return 1; + } + }) + + let orders = {}; + + Store.luckysheetfile.forEach((item, i, arr) => { + arr[i].order = i; + orders[item.index.toString()] = i; + + if(i > 0){ + let preIndex = arr[i - 1].index; + $("#luckysheet-sheets-item" + item.index).insertAfter($("#luckysheet-sheets-item" + preIndex)); + } + }) + + server.saveParam("shr", null, orders); + + let { + success + } = {...options} + + if (success && typeof success === 'function') { + success(); + } +} + + /** * 显示指定下标工作表的网格线,返回操作的工作表对象 * @param {Object} options 可选参数 @@ -4738,6 +4798,24 @@ export function hideGridLines(options = {}){ } +/** + * 刷新canvas + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function refresh(options = {}) { + luckysheetrefreshgrid(); + + let { + success + } = {...options} + + if (success && typeof success === 'function') { + success(); + } +} + + /** * 滚动当前工作表位置 * @param {Object} options 可选参数 @@ -4801,7 +4879,6 @@ export function scroll(options = {}){ /** * 根据窗口大小自动resize画布 - * * @param {Object} options 可选参数 * @param {Function} options.success 操作结束的回调函数 */ @@ -4818,6 +4895,200 @@ export function resize(options = {}){ } +/** + * 返回指定选区截图后生成的base64格式的图片 + * @param {Object} options 可选参数 + * @param {Object | String} options.range 选区范围,只能为单个选区;默认为当前选区 + */ +export function getScreenshot(options = {}) { + let { + range = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1], + } = {...options} + + if(getObjType(range) == 'string'){ + if(!formula.iscelldata(range)){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let cellrange = formula.getcellrange(range); + range = { + "row": cellrange.row, + "column": cellrange.column + }; + } + + if(getObjType(range) != 'object' || range.row == null || range.column == null){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let str = range.row[0], + edr = range.row[1], + stc = range.column[0], + edc = range.column[1]; + + let has_PartMC = hasPartMC(Store.config, str, edr, stc, edc); + + if(has_PartMC){ + return tooltip.info('Cannot perform this operation on partially merged cells', ''); + } + + let visibledatarow = Store.visibledatarow; + let visibledatacolumn = Store.visibledatacolumn; + + let scrollHeight, rh_height; + if (str - 1 < 0) { + scrollHeight = 0; + rh_height = visibledatarow[edr]; + } + else { + scrollHeight = visibledatarow[str - 1]; + rh_height = visibledatarow[edr] - visibledatarow[str - 1]; + } + + let scrollWidth, ch_width; + if (stc - 1 < 0) { + scrollWidth = 0; + ch_width = visibledatacolumn[edc]; + } + else { + scrollWidth = visibledatacolumn[stc - 1]; + ch_width = visibledatacolumn[edc] - visibledatacolumn[stc - 1]; + } + + let newCanvas = $("").attr({ + width: Math.ceil(ch_width * Store.devicePixelRatio), + height: Math.ceil(rh_height * Store.devicePixelRatio) + }).css({ width: ch_width, height: rh_height }); + + luckysheetDrawMain(scrollWidth, scrollHeight, ch_width, rh_height, 1, 1, null, null, newCanvas); + let ctx_newCanvas = newCanvas.get(0).getContext("2d"); + + //补上 左边框和上边框 + ctx_newCanvas.beginPath(); + ctx_newCanvas.moveTo( + 0, + 0 + ); + ctx_newCanvas.lineTo( + 0, + Store.devicePixelRatio * rh_height + ); + ctx_newCanvas.lineWidth = Store.devicePixelRatio * 2; + ctx_newCanvas.strokeStyle = luckysheetdefaultstyle.strokeStyle; + ctx_newCanvas.stroke(); + ctx_newCanvas.closePath(); + + ctx_newCanvas.beginPath(); + ctx_newCanvas.moveTo( + 0, + 0 + ); + ctx_newCanvas.lineTo( + Store.devicePixelRatio * ch_width, + 0 + ); + ctx_newCanvas.lineWidth = Store.devicePixelRatio * 2; + ctx_newCanvas.strokeStyle = luckysheetdefaultstyle.strokeStyle; + ctx_newCanvas.stroke(); + ctx_newCanvas.closePath(); + + let url = newCanvas.get(0).toDataURL("image/png"); + + return url; +} + + +/** + * 设置工作簿名称 + * @param {String} name 工作簿名称 + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setWorkbookName(name, options = {}) { + if(name == null || name.toString().length == 0){ + return tooltip.info("The name parameter is invalid.", ""); + } + + $("#luckysheet_info_detail_input").val(name); + + let { + success + } = {...options} + + if (success && typeof success === 'function') { + success(); + } +} + + +/** + * 撤销当前操作,返回刚刚撤销的操作对象 + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function undo(options = {}) { + let ctr = $.extend(true, {}, Store.jfredo[Store.jfredo.length - 1]); + + controlHistory.redo(new Event('custom')); + luckysheetactiveCell(); + + let { + success + } = {...options} + + setTimeout(() => { + if (success && typeof success === 'function') { + success(); + } + }, 1); + + return ctr; +} + + +/** + * 重做当前操作,返回刚刚重做的操作对象 + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function redo(options = {}) { + let ctr = $.extend(true, {}, Store.jfundo[Store.jfundo.length - 1]); + + controlHistory.undo(new Event('custom')); + luckysheetactiveCell(); + + let { + success + } = {...options} + + setTimeout(() => { + if (success && typeof success === 'function') { + success(); + } + }, 1); + + return ctr; +} + + +/** + * 返回所有工作表配置 + */ +export function getAllSheets() { + let data = $.extend(true, [], Store.luckysheetfile); + + data.forEach((item, index, arr) => { + if(item.data != null && item.data.length > 0){ + item.celldata = sheetmanage.getGridData(item.data); + } + + delete item.load; + }) + + return data; +} + + /** * 根据index获取sheet页配置 * @@ -4948,18 +5219,39 @@ export function getLuckysheetfile(){ * @param {Function} options.success 操作结束的回调函数 */ export function transToCellData(data, options = {}){ - let { success } = {...options} setTimeout(()=>{ - if (success && typeof success === 'function') { success(); } - },0) return sheetmanage.getGridData(data) } + + +/** + * celldata => data ,celldata一维数组数据转化成表格所需二维数组 + * + * @param {Array} celldata 二维数组数据 + * @param {Object} options 可选参数 + * @param {Function} options.success 操作结束的回调函数 + */ +export function transToData(celldata, options = {}){ + let { + success + } = {...options} + + setTimeout(()=>{ + if (success && typeof success === 'function') { + success(); + } + },0) + + return sheetmanage.buildGridData({ + celldata: celldata + }) +} diff --git a/src/global/setdata.js b/src/global/setdata.js index 7de4e66..460a2b3 100644 --- a/src/global/setdata.js +++ b/src/global/setdata.js @@ -15,13 +15,16 @@ function setcellvalue(r, c, d, v) { let vupdate; if(getObjType(v) == "object"){ - if(cell==null){ + if(cell == null){ cell = v; } else{ if(v.f != null){ cell.f = v.f; } + else{ + delete cell.f; + } if(v.spl != null){ cell.spl = v.spl; From 047dfeebd4d93a5aceb9a387fb1f62de20c5e389 Mon Sep 17 00:00:00 2001 From: mengshukeji Date: Wed, 21 Oct 2020 14:36:38 +0800 Subject: [PATCH 2/9] docs(api): api 1.add api docs:setRowHeight/setColumnWidth/setSheetZoom/setDataVerification/deleteDataVerification/setProtection --- docs/guide/api.md | 131 +++++++++++++++++++++++++++++++++++++++ docs/guide/config.md | 19 ++++++ docs/zh/guide/api.md | 132 ++++++++++++++++++++++++++++++++++++++++ docs/zh/guide/config.md | 19 ++++++ 4 files changed, 301 insertions(+) diff --git a/docs/guide/api.md b/docs/guide/api.md index 927b12b..f9a95c9 100644 --- a/docs/guide/api.md +++ b/docs/guide/api.md @@ -541,6 +541,54 @@ Use note: ------------ +### setRowHeight(rowInfo [,setting]) + +(TODO) + +- **Parameter**: + + - {Object} [rowInfo]: Correspondence between number of rows and height + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Set the height of the specified ~~row~~ + +- **Usage**: + + - Set the height of the first row to 50px and the height of the second row to 60px + + `luckysheet.setRowHeight({0:50,1:60})` + +------------ + +### setColumnWidth(columnInfo [,setting]) + +(TODO) + +- **Parameter**: + + - {Number} [columnInfo]: Correspondence between the number of columns and the width + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Set the width of the specified column + +- **Usage**: + + - Set the width of the first column to 50px and the width of the second column to 60px + + `luckysheet.setColumnWidth({0:50,1:60})` + +------------ + ## Selection operation ### getRange() @@ -2013,6 +2061,32 @@ Use note: ------------ +### setSheetZoom(zoom [,setting]) + +[todo] + + +- **Parameter**: + + - {Number} [zoom]: Worksheet zoom ratio + + - {PlainObject} [setting]: optional parameters + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Set worksheet zoom ratio + + +- **Usage**: + + - Set the current worksheet zoom ratio to 0.5 + ```js + luckysheet.setSheetZoom(0.5) + ``` + +------------ + ### showGridLines([setting]) - **Parameter**: @@ -2295,6 +2369,63 @@ Use note: ------------ +## Data Verification + +### setDataVerification(option, [setting]) + +[todo] + +- **Parameter**: + + - {Object} [option]: Configuration information for data verification + - {PlainObject} [setting]: optional parameters + + {Array | Object | String} [range]: The selection area for data verification, The format of the supported selection is `"A1:B2"`, `"sheetName!A1:B2"` or `{row:[0,1] ,column:[0,1]}`, can only be a single selection; the default is the current selection + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Specify the worksheet range to set the data verification function and set the parameters + +------------ + +### deleteDataVerification([setting]) + +[todo, to be confirmed whether it is reasonable] + +- **Parameter**: + + - {PlainObject} [setting]: optional parameters + + {Array | Object | String} [range]: The selection area for data verification, The format of the supported selection is `"A1:B2"`, `"sheetName!A1:B2"` or `{row:[0,1] ,column:[0,1]}`, can only be a single selection; the default is the current selection + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Specify the worksheet range to delete the data verification function + +------------ + +## Worksheet Protection + + +### setProtection(option, [setting]) + +[todo] + +- **Parameter**: + + - {Object} [option]: Configuration information for worksheet protection + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Specify the worksheet to set the worksheet protection + +------------ + ## Public method ### transToCellData(data [,setting])
diff --git a/docs/guide/config.md b/docs/guide/config.md index a1c016c..4d9e44d 100644 --- a/docs/guide/config.md +++ b/docs/guide/config.md @@ -743,6 +743,25 @@ The hook functions are uniformly configured under ʻoptions.hook`, and configura - {String} [oldColor]: Before modification, the current worksheet color - {String} [newColor]: After modification, the current worksheet color +------------ +### sheetZoomBefore +- Type: Function +- Default: null +- Usage: Before worksheet zoom +- Parameter: + - {Number} [i]: `index` of current worksheet + - {String} [zoom]: Current worksheet zoom ratio + +------------ +### sheetZoomAfter +- Type: Function +- Default: null +- Usage: After worksheet zoom +- Parameter: + - {Number} [i]: `index` of current worksheet + - {String} [oldZoom]: Before modification, the current worksheet zoom ratio + - {String} [newZoom]: After modification, the current worksheet zoom ratio + ------------ ## Workbook diff --git a/docs/zh/guide/api.md b/docs/zh/guide/api.md index 40ca681..3926831 100644 --- a/docs/zh/guide/api.md +++ b/docs/zh/guide/api.md @@ -543,6 +543,54 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ +### setRowHeight(rowInfo [,setting]) + +(TODO) + +- **参数**: + + - {Object} [rowInfo]: 行数和高度对应关系 + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 设置指定行的高度 + +- **示例**: + + - 设置第一行高度为50px,第二行高度为60px + + `luckysheet.setRowHeight({0:50,1:60})` + +------------ + +### setColumnWidth(columnInfo [,setting]) + +(TODO) + +- **参数**: + + - {Number} [columnInfo]: 列数和宽度对应关系 + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 设置指定列的宽度 + +- **示例**: + + - 设置第一列宽度为50px,第二列宽度为60px + + `luckysheet.setColumnWidth({0:50,1:60})` + +------------ + ## 选区操作 ### getRange() @@ -1960,6 +2008,32 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ +### setSheetZoom(zoom [,setting]) + +[todo] + + +- **参数**: + + - {Number} [zoom]: 工作表缩放比例 + + - {PlainObject} [setting]: 可选参数 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 设置工作表缩放比例 + + +- **示例**: + + - 设置当前工作表缩放比例为0.5 + ```js + luckysheet.setSheetZoom(0.5) + ``` + +------------ + ### showGridLines([setting]) - **参数**: @@ -2242,6 +2316,63 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ +## 数据验证 + +### setDataVerification(option, [setting]) + +[todo] + +- **参数**: + + - {Object} [option]: 数据验证的配置信息 + - {PlainObject} [setting]: 可选参数 + + {Array | Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 指定工作表范围设置数据验证功能,并设置参数 + +------------ + +### deleteDataVerification([setting]) + +[todo,待确认是否合理] + +- **参数**: + + - {PlainObject} [setting]: 可选参数 + + {Array | Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 指定工作表范围删除数据验证功能 + +------------ + +## 工作表保护 + + +### setProtection(option, [setting]) + +[todo] + +- **参数**: + + - {Object} [option]: 工作表保护的配置信息 + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 指定工作表设置工作表保护功能 + +------------ + ## 公共方法 ### transToCellData(data [,setting])
@@ -2286,6 +2417,7 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ + ## 旧版API ::: warning diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index 0d804e0..b3d54bd 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -744,6 +744,25 @@ Luckysheet开放了更细致的自定义配置选项,分别有 - {String} [oldColor]: 修改前当前sheet页颜色 - {String} [newColor]: 修改后当前sheet页颜色 +------------ +### sheetZoomBefore +- 类型:Function +- 默认值:null +- 作用:sheet缩放前 +- 参数: + - {Number} [i]: sheet页的`index` + - {String} [zoom]: 当前sheet页缩放比例 + +------------ +### sheetZoomAfter +- 类型:Function +- 默认值:null +- 作用:sheet缩放后 +- 参数: + - {Number} [i]: sheet页的`index` + - {String} [oldZoom]: 修改前当前sheet页缩放比例 + - {String} [newZoom]: 修改后当前sheet页缩放比例 + ------------ ## 工作簿 From 37c56ac416c79c7dddae01dfe8f8293e2dfec115 Mon Sep 17 00:00:00 2001 From: mengshukeji Date: Wed, 21 Oct 2020 14:52:16 +0800 Subject: [PATCH 3/9] docs(demo): demo demo add feature js --- docs/guide/README.md | 1 + docs/zh/guide/README.md | 1 + src/demoData/demoFeature.js | 0 src/index.html | 7 +++++-- 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 src/demoData/demoFeature.js diff --git a/docs/guide/README.md b/docs/guide/README.md index 272dcb4..9e8f407 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -136,6 +136,7 @@ After `npm run build`, all files in the `dist` folder are copied to the project + ``` diff --git a/docs/zh/guide/README.md b/docs/zh/guide/README.md index 950d613..0659af5 100644 --- a/docs/zh/guide/README.md +++ b/docs/zh/guide/README.md @@ -137,6 +137,7 @@ npm run build + ``` diff --git a/src/demoData/demoFeature.js b/src/demoData/demoFeature.js new file mode 100644 index 0000000..e69de29 diff --git a/src/index.html b/src/index.html index 4ea429d..727a4b4 100644 --- a/src/index.html +++ b/src/index.html @@ -16,6 +16,9 @@ + + + @@ -55,7 +58,7 @@ ], data: [sheetCell,sheetFormula,sheetConditionFormat,sheetSparkline,sheetTable,sheetComment,sheetPivotTableData,sheetPivotTable,sheetChart,sheetPicture,sheetDataVerification] - /*[{"name":"Sheet1","config":{"columnlen":{"0":241},"rowlen":{"0":81,"17":100}},"index":"1","status":"1","order":"0","luckysheet_select_save":[{"row":[0,0],"column":[4,4],"sheetIndex":1}],"zoomRatio":1,"showGridLines":"1","defaultColWidth":72,"defaultRowHeight":18,"celldata":[ + /*[{"name":"Sheet1","config":{"columnlen":{"0":241},"rowlen":{"0":81}},"index":"1","status":"1","order":"0","luckysheet_select_save":[{"row":[0,0],"column":[4,4],"sheetIndex":1}],"zoomRatio":1,"showGridLines":"1","defaultColWidth":72,"defaultRowHeight":18,"celldata":[ {"r":0,"c":0, "v":{ "ct":{ @@ -93,7 +96,7 @@ "qp":1, } }, - {"r":17,"c":2,"v":{"v":"Luckysheet is good project, this is true","ct":{"fa":"General","t":"g"},"bg":null,"bl":0,"it":0,"ff":0,"fs":"11","fc":"rgb(51, 51, 51)","ht":1,"vt":1,tb:2,"m":"Luckysheet"}} + {"r":17,"c":2,"v":{"v":"Luckysheet","ct":{"fa":"General","t":"g"},"bg":null,"bl":0,"it":0,"ff":0,"fs":"11","fc":"rgb(51, 51, 51)","ht":1,"vt":1,"m":"Luckysheet"}} ],"calcChain":[]}]*/ /* From 76dbb5cc613c8290696e917c554aff934050b6a2 Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Wed, 21 Oct 2020 14:54:26 +0800 Subject: [PATCH 4/9] fix(bug): postil image zoom --- src/controllers/imageCtrl.js | 64 ++++++++++++++++++------------------ src/controllers/postil.js | 50 +++++++++++++++------------- src/controllers/zoom.js | 4 +++ src/global/draw.js | 8 ++--- 4 files changed, 68 insertions(+), 58 deletions(-) diff --git a/src/controllers/imageCtrl.js b/src/controllers/imageCtrl.js index 3144047..eb31e58 100644 --- a/src/controllers/imageCtrl.js +++ b/src/controllers/imageCtrl.js @@ -97,19 +97,19 @@ const imageCtrl = { let src = imgItem.src; let imgItemParam = _this.getImgItemParam(imgItem); - let width = imgItemParam.width*Store.zoomRatio; - let height = imgItemParam.height*Store.zoomRatio; - let left = imgItemParam.left*Store.zoomRatio; - let top = imgItemParam.top*Store.zoomRatio; + let width = imgItemParam.width * Store.zoomRatio; + let height = imgItemParam.height * Store.zoomRatio; + let left = imgItemParam.left * Store.zoomRatio; + let top = imgItemParam.top * Store.zoomRatio; let position = imgItemParam.position; let borderWidth = imgItem.border.width; return `
- +
-
+
`; }, getSliderHtml: function() { @@ -354,10 +354,10 @@ const imageCtrl = { let item = _this.images[id]; let imgItemParam = _this.getImgItemParam(item); - let width = imgItemParam.width*Store.zoomRatio; - let height = imgItemParam.height*Store.zoomRatio; - let left = imgItemParam.left*Store.zoomRatio; - let top = imgItemParam.top*Store.zoomRatio; + let width = imgItemParam.width * Store.zoomRatio; + let height = imgItemParam.height * Store.zoomRatio; + let left = imgItemParam.left * Store.zoomRatio; + let top = imgItemParam.top * Store.zoomRatio; let position = imgItemParam.position; $("#luckysheet-modal-dialog-activeImage").show().css({ @@ -370,19 +370,19 @@ const imageCtrl = { $("#luckysheet-modal-dialog-activeImage .luckysheet-modal-dialog-content").css({ "background-image": "url(" + item.src + ")", - "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" + "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" }) $("#luckysheet-modal-dialog-activeImage .luckysheet-modal-dialog-border").css({ - "border-width": item.border.width*Store.zoomRatio, + "border-width": item.border.width * Store.zoomRatio, "border-style": item.border.style, "border-color": item.border.color, - "border-radius": item.border.radius*Store.zoomRatio, - "left": -item.border.width*Store.zoomRatio, - "right": -item.border.width*Store.zoomRatio, - "top": -item.border.width*Store.zoomRatio, - "bottom": -item.border.width*Store.zoomRatio, + "border-radius": item.border.radius * Store.zoomRatio, + "left": -item.border.width * Store.zoomRatio, + "right": -item.border.width * Store.zoomRatio, + "top": -item.border.width * Store.zoomRatio, + "bottom": -item.border.width * Store.zoomRatio, }) _this.sliderHtmlShow(); @@ -591,10 +591,10 @@ const imageCtrl = { let imgItem = _this.images[_this.currentImgId]; let imgItemParam = _this.getImgItemParam(imgItem); - let width = imgItemParam.width*Store.zoomRatio; - let height = imgItemParam.height*Store.zoomRatio; - let left = imgItemParam.left*Store.zoomRatio; - let top = imgItemParam.top*Store.zoomRatio; + let width = imgItemParam.width * Store.zoomRatio; + let height = imgItemParam.height * Store.zoomRatio; + let left = imgItemParam.left * Store.zoomRatio; + let top = imgItemParam.top * Store.zoomRatio; let position = imgItemParam.position; $("#" + _this.currentImgId).show().css({ @@ -605,20 +605,20 @@ const imageCtrl = { "position": position }); $("#" + _this.currentImgId + " img").css({ - "width": imgItem.default.width*Store.zoomRatio, - "height": imgItem.default.height*Store.zoomRatio, - "left": -imgItem.crop.offsetLeft*Store.zoomRatio, - "top": -imgItem.crop.offsetTop*Store.zoomRatio + "width": imgItem.default.width * Store.zoomRatio, + "height": imgItem.default.height * Store.zoomRatio, + "left": -imgItem.crop.offsetLeft * Store.zoomRatio, + "top": -imgItem.crop.offsetTop * Store.zoomRatio }); $("#" + _this.currentImgId + " .luckysheet-modal-dialog-border").css({ - "border-width": imgItem.border.width*Store.zoomRatio, + "border-width": imgItem.border.width * Store.zoomRatio, "border-style": imgItem.border.style, "border-color": imgItem.border.color, - "border-radius": imgItem.border.radius*Store.zoomRatio, - "left": -imgItem.border.width*Store.zoomRatio, - "right": -imgItem.border.width*Store.zoomRatio, - "top": -imgItem.border.width*Store.zoomRatio, - "bottom": -imgItem.border.width*Store.zoomRatio, + "border-radius": imgItem.border.radius * Store.zoomRatio, + "left": -imgItem.border.width * Store.zoomRatio, + "right": -imgItem.border.width * Store.zoomRatio, + "top": -imgItem.border.width * Store.zoomRatio, + "bottom": -imgItem.border.width * Store.zoomRatio, }) _this.currentImgId = null; diff --git a/src/controllers/postil.js b/src/controllers/postil.js index 4ae1daa..40bd3cc 100644 --- a/src/controllers/postil.js +++ b/src/controllers/postil.js @@ -208,18 +208,21 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let fromX = toX + 18; - let fromY = toY - 18; + let fromX = toX + 18 * Store.zoomRatio; + let fromY = toY - 18 * Store.zoomRatio; if(fromY < 0){ fromY = 2; } + let width = _this.defaultWidth * Store.zoomRatio + let height = _this.defaultHeight * Store.zoomRatio + let size = _this.getArrowCanvasSize(fromX, fromY, toX, toY); let html = '
' + '' + - '
'+ value +'
' + + '
'+ value +'
' + '
'; $(html).appendTo($("#luckysheet-cell-main")); @@ -349,10 +352,10 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let left = postil["left"] == null ? toX + 18 : postil["left"]; - let top = postil["top"] == null ? toY - 18 : postil["top"]; - let width = postil["width"] == null ? _this.defaultWidth : postil["width"]; - let height = postil["height"] == null ? _this.defaultHeight : postil["height"]; + let left = postil["left"] == null ? toX + 18 * Store.zoomRatio : postil["left"] * Store.zoomRatio; + let top = postil["top"] == null ? toY - 18 * Store.zoomRatio : postil["top"] * Store.zoomRatio; + let width = postil["width"] == null ? _this.defaultWidth * Store.zoomRatio : postil["width"] * Store.zoomRatio; + let height = postil["height"] == null ? _this.defaultHeight * Store.zoomRatio : postil["height"] * Store.zoomRatio; let value = postil["value"] == null ? "" : postil["value"]; if(top < 0){ @@ -418,18 +421,21 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let fromX = toX + 18; - let fromY = toY - 18; + let fromX = toX + 18 * Store.zoomRatio; + let fromY = toY - 18 * Store.zoomRatio; if(fromY < 0){ fromY = 2; } + let width = _this.defaultWidth * Store.zoomRatio; + let height = _this.defaultHeight * Store.zoomRatio; + let size = _this.getArrowCanvasSize(fromX, fromY, toX, toY); let html = '
' + '' + - '
' + + '
' + '
' + '
' + '
' + @@ -507,10 +513,10 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let left = postil["left"] == null ? toX + 18 : postil["left"]; - let top = postil["top"] == null ? toY - 18 : postil["top"]; - let width = postil["width"] == null ? _this.defaultWidth : postil["width"]; - let height = postil["height"] == null ? _this.defaultHeight : postil["height"]; + let left = postil["left"] == null ? toX + 18 * Store.zoomRatio : postil["left"] * Store.zoomRatio; + let top = postil["top"] == null ? toY - 18 * Store.zoomRatio : postil["top"] * Store.zoomRatio; + let width = postil["width"] == null ? _this.defaultWidth * Store.zoomRatio : postil["width"] * Store.zoomRatio; + let height = postil["height"] == null ? _this.defaultHeight * Store.zoomRatio : postil["height"] * Store.zoomRatio; let value = postil["value"] == null ? "" : postil["value"]; if(top < 0){ @@ -609,10 +615,10 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let left = postil["left"] == null ? toX + 18 : postil["left"]; - let top = postil["top"] == null ? toY - 18 : postil["top"]; - let width = postil["width"] == null ? _this.defaultWidth : postil["width"]; - let height = postil["height"] == null ? _this.defaultHeight : postil["height"]; + let left = postil["left"] == null ? toX + 18 * Store.zoomRatio : postil["left"] * Store.zoomRatio; + let top = postil["top"] == null ? toY - 18 * Store.zoomRatio : postil["top"] * Store.zoomRatio; + let width = postil["width"] == null ? _this.defaultWidth * Store.zoomRatio : postil["width"] * Store.zoomRatio; + let height = postil["height"] == null ? _this.defaultHeight * Store.zoomRatio : postil["height"] * Store.zoomRatio; let value = postil["value"] == null ? "" : postil["value"]; if(top < 0){ @@ -723,10 +729,10 @@ const luckysheetPostil = { let toX = col; let toY = row_pre; - let left = postil["left"] == null ? toX + 18 : postil["left"]; - let top = postil["top"] == null ? toY - 18 : postil["top"]; - let width = postil["width"] == null ? _this.defaultWidth : postil["width"]; - let height = postil["height"] == null ? _this.defaultHeight : postil["height"]; + let left = postil["left"] == null ? toX + 18 * Store.zoomRatio : postil["left"] * Store.zoomRatio; + let top = postil["top"] == null ? toY - 18 * Store.zoomRatio : postil["top"] * Store.zoomRatio; + let width = postil["width"] == null ? _this.defaultWidth * Store.zoomRatio : postil["width"] * Store.zoomRatio; + let height = postil["height"] == null ? _this.defaultHeight * Store.zoomRatio : postil["height"] * Store.zoomRatio; let value = postil["value"] == null ? "" : postil["value"]; if(top < 0){ diff --git a/src/controllers/zoom.js b/src/controllers/zoom.js index 34d3569..711e395 100644 --- a/src/controllers/zoom.js +++ b/src/controllers/zoom.js @@ -5,6 +5,7 @@ import sheetmanage from './sheetmanage'; import {changeSheetContainerSize} from './resize'; import { jfrefreshgrid_rhcw } from '../global/refresh'; import server from './server'; +import luckysheetPostil from './postil'; import imageCtrl from './imageCtrl'; @@ -31,6 +32,9 @@ export function zoomChange(ratio){ let currentSheet = sheetmanage.getSheetByIndex(); + //批注 + luckysheetPostil.buildAllPs(currentSheet.data); + //图片 imageCtrl.images = currentSheet.images; imageCtrl.allImagesShow(); diff --git a/src/global/draw.js b/src/global/draw.js index 2ad7da4..e62fb50 100644 --- a/src/global/draw.js +++ b/src/global/draw.js @@ -1112,7 +1112,7 @@ let nullCellRender = function(r, c, start_r, start_c, end_r, end_c,luckysheetTab //若单元格有批注 if(Store.flowdata[r][c] != null && Store.flowdata[r][c].ps != null){ - let ps_w = 5*Store.zoomRatio, ps_h = 5*Store.zoomRatio; + let ps_w = 8*Store.zoomRatio, ps_h = 8*Store.zoomRatio; luckysheetTableContent.beginPath(); luckysheetTableContent.moveTo( (end_c + offsetLeft - 1- ps_w), (start_r + offsetTop)); luckysheetTableContent.lineTo( (end_c + offsetLeft - 1), (start_r + offsetTop)); @@ -1338,17 +1338,17 @@ let cellRender = function(r, c, start_r, start_c, end_r, end_c, value, luckyshee let verticalAlignPos_text = (pos_y + verticalCellHeight - space_height) ; //文本垂直方向基准线 luckysheetTableContent.textBaseline = "bottom"; - let verticalAlignPos_checkbox = verticalAlignPos_text - 13; + let verticalAlignPos_checkbox = verticalAlignPos_text - 13 * Store.zoomRatio; if(verticalAlign == "0"){ //居中对齐 verticalAlignPos_text = (pos_y + verticalCellHeight / 2); luckysheetTableContent.textBaseline = "middle"; - verticalAlignPos_checkbox = verticalAlignPos_text - 6; + verticalAlignPos_checkbox = verticalAlignPos_text - 6 * Store.zoomRatio; } else if(verticalAlign == "1"){ //上对齐 verticalAlignPos_text = (pos_y + space_height); luckysheetTableContent.textBaseline = "top"; - verticalAlignPos_checkbox = verticalAlignPos_text + 1; + verticalAlignPos_checkbox = verticalAlignPos_text + 1 * Store.zoomRatio; } horizonAlignPos = horizonAlignPos / Store.zoomRatio; From 00b351fa0dc01c32cf9c6b8852937e7d2ceb292d Mon Sep 17 00:00:00 2001 From: liuyang Date: Wed, 21 Oct 2020 15:07:08 +0800 Subject: [PATCH 5/9] fix(setcellvalue delete function fix): fix it --- src/controllers/cellFormat.js | 22 ++++++++++++++++------ src/global/formula.js | 4 +++- src/global/setdata.js | 6 +++--- src/index.html | 4 ++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/controllers/cellFormat.js b/src/controllers/cellFormat.js index 87c69c9..415b794 100644 --- a/src/controllers/cellFormat.js +++ b/src/controllers/cellFormat.js @@ -6,6 +6,7 @@ import menuButton from './menuButton'; import {checkProtectionNotEnable} from './protection'; import { jfrefreshgrid } from '../global/refresh'; import locale from '../locale/locale'; +import { setcellvalue } from '../global/setdata'; let isInitialCellFormatModel = false; @@ -22,9 +23,17 @@ function initialCellFormatModelEvent(){ hidden = hidden==true?1:0; let d = recycleSeletion( - function(cell){ - cell.lo = locked; - cell.hi = hidden; + function(cell, r, c, data){ + if(cell==null){ + setcellvalue(r, c, data, { + lo:locked, + hi:hidden + }); + } + else{ + cell.lo = locked; + cell.hi = hidden; + } }, function(){ alert(local_cellFormat.sheetDataIsNullAlert); @@ -79,7 +88,8 @@ function recycleSeletion(cycleFunction, dataIsNullFunction){ // } // count++; - cycleFunction(cell); + + cycleFunction(cell, r, c, data); } } } @@ -152,12 +162,12 @@ export function openCellFormatModel(){ recycleSeletion( function(cell){ // let cell = data[r][c]; - if(cell.lo==null || cell.lo==1){ + if(cell==null || cell.lo==null || cell.lo==1){ locked = true; lockedCount++; } - if(cell.hi==1){ + if(cell!=null && cell.hi==1){ hidden = true; hiddenCount++; } diff --git a/src/global/formula.js b/src/global/formula.js index 0e97a90..706d31a 100644 --- a/src/global/formula.js +++ b/src/global/formula.js @@ -1238,7 +1238,7 @@ const luckysheetformula = { } if(!checkProtectionLocked(r, c, Store.currentSheetIndex)){ - return + return; } //数据验证 输入数据无效时禁止输入 @@ -5188,6 +5188,7 @@ const luckysheetformula = { "r": u.r, "c": u.c, "v": v[1], + "f": v[2], "spe":v[3], "index": u.index }); @@ -5226,6 +5227,7 @@ const luckysheetformula = { } } updateValue.v = item.v; + updateValue.f = item.f; setcellvalue(item.r, item.c, data, updateValue); server.saveParam("v", item.index, item.v, { "r": item.r, diff --git a/src/global/setdata.js b/src/global/setdata.js index 460a2b3..2f968a1 100644 --- a/src/global/setdata.js +++ b/src/global/setdata.js @@ -22,9 +22,9 @@ function setcellvalue(r, c, d, v) { if(v.f != null){ cell.f = v.f; } - else{ - delete cell.f; - } + // else{ + // delete cell.f; + // } if(v.spl != null){ cell.spl = v.spl; diff --git a/src/index.html b/src/index.html index 4ea429d..7c5aa2c 100644 --- a/src/index.html +++ b/src/index.html @@ -53,8 +53,8 @@ "url":"./assets/iconfont/Pacifico-Regular.ttf" } ], - data: - [sheetCell,sheetFormula,sheetConditionFormat,sheetSparkline,sheetTable,sheetComment,sheetPivotTableData,sheetPivotTable,sheetChart,sheetPicture,sheetDataVerification] + // data: + // [sheetCell,sheetFormula,sheetConditionFormat,sheetSparkline,sheetTable,sheetComment,sheetPivotTableData,sheetPivotTable,sheetChart,sheetPicture,sheetDataVerification] /*[{"name":"Sheet1","config":{"columnlen":{"0":241},"rowlen":{"0":81,"17":100}},"index":"1","status":"1","order":"0","luckysheet_select_save":[{"row":[0,0],"column":[4,4],"sheetIndex":1}],"zoomRatio":1,"showGridLines":"1","defaultColWidth":72,"defaultRowHeight":18,"celldata":[ {"r":0,"c":0, "v":{ From 0fd06cc4d7f465967b3bcc91e0b2484ba61b71f6 Mon Sep 17 00:00:00 2001 From: wpxp123456 <2677556700@qq.com> Date: Wed, 21 Oct 2020 17:49:55 +0800 Subject: [PATCH 6/9] feat(api add): setRowHeight setColumnWidth setSheetZoom setDataVerification deleteDataVerification --- docs/zh/guide/api.md | 30 ++- src/global/api.js | 447 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 461 insertions(+), 16 deletions(-) diff --git a/docs/zh/guide/api.md b/docs/zh/guide/api.md index 9fed4d3..2cf2df8 100644 --- a/docs/zh/guide/api.md +++ b/docs/zh/guide/api.md @@ -544,8 +544,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### setRowHeight(rowInfo [,setting]) -(TODO) - - **参数**: - {Object} [rowInfo]: 行数和高度对应关系 @@ -568,8 +566,6 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### setColumnWidth(columnInfo [,setting]) -(TODO) - - **参数**: - {Number} [columnInfo]: 列数和宽度对应关系 @@ -2004,14 +2000,12 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### setSheetZoom(zoom [,setting]) -[todo] - - - **参数**: - - {Number} [zoom]: 工作表缩放比例 + - {Number} [zoom]: 工作表缩放比例,值范围为0.1 ~ 4; - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + {Function} [success]: 操作结束的回调函数 - **说明**: @@ -2295,15 +2289,21 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ## 数据验证 -### setDataVerification(option, [setting]) - -[todo] +### setDataVerification(optionItem, [setting]) - **参数**: - - {Object} [option]: 数据验证的配置信息 + - {Object} [optionItem]: 数据验证的配置信息 + + {String} [type]: 类型;值可为`"dropdown"`(下拉列表)、`"checkbox"`(复选框)、`"number"`(数字)、`"number_integer"`(数字-整数)、`"number_decimal"`(数字-小数)、`"text_content"`(文本-内容)、`"text_length"`(文本-长度)、`"date"`(日期)、`"validity"`(有效性); + + {String | Null} [type2]: 条件类型;类型`type`值为`"dropdown"`、`"checkbox"`时,`type2`值可为`null`;类型`type`值为`"number"`、`"number_integer"`、`"number_decimal"`、`"text_length"`时,`type2`值可为`"bw"`(介于)、`"nb"`(不介于)、`"eq"`(等于)、`"ne"`(不等于)、`"gt"`(大于)、`"lt"`(小于)、`"gte"`(大于等于)、`"lte"`(小于等于);类型`type`值为`"text_content"`时,`type2`值可为`"include"`(包括)、`"exclude"`(不包括)、`"equal"`(等于);类型`type`值为`"date"`时,`type2`值可为`"bw"`(介于)、`"nb"`(不介于)、`"eq"`(等于)、`"ne"`(不等于)、`"bf"`(早于)、`"nbf"`(不早于)、`"af"`(晚于)、`"naf"`(不晚于);类型`type`值为`"validity"`时,`type2`值可为`"card"`(身份证号码)、`"phone"`(手机号); + + {String | Number} [value1]: 条件值1;类型`type`值为`"dropdown"`时,`value1`值可为选区或以英文逗号隔开的字符串,如`"1,2,3"`或者`"A1:B2"`;类型`type`值为`"validity"`时,`value1`值可为空;其他类型时`value1`值为数值或字符串; + + {String | Number} [value2]: 条件值2;类型`type`值为`"checkbox"`或者条件类型`type2`值为`"bw"`、`"nb"`时有`value2`值,条件值为数值或日期时,条件值2要大于等于条件值1;其它情况可为空; + + {Boolean} [remote]: 自动远程获取选项;默认为`false`; + + {Boolean} [prohibitInput]: 输入数据无效时禁止输入;默认为`false`; + + {Boolean} [hintShow]: 选中单元格时显示提示语;默认为`false`; + + {String} [hintText]: 提示语文本;`hintShow`为`true`时需配置; - {PlainObject} [setting]: 可选参数 - + {Array | Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + + {Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + {Number} [order]: 工作表下标;默认值为当前工作表下标 + {Function} [success]: 操作结束的回调函数 @@ -2315,12 +2315,10 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ### deleteDataVerification([setting]) -[todo,待确认是否合理] - - **参数**: - {PlainObject} [setting]: 可选参数 - + {Array | Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + + {Object | String} [range]: 数据验证的选区范围,支持选区的格式为`"A1:B2"`、`"sheetName!A1:B2"`或者`{row:[0,1],column:[0,1]}`,只能为单个选区;默认为当前选区 + {Number} [order]: 工作表下标;默认值为当前工作表下标 + {Function} [success]: 操作结束的回调函数 diff --git a/src/global/api.js b/src/global/api.js index bd68992..ad26e8b 100644 --- a/src/global/api.js +++ b/src/global/api.js @@ -35,6 +35,8 @@ import { selectHightlightShow, selectIsOverlap } from '../controllers/select'; import { sheetHTML, luckysheetdefaultstyle } from '../controllers/constant'; import { createFilterOptions } from '../controllers/filter'; import controlHistory from '../controllers/controlHistory'; +import { zoomRefreshView, zoomNumberDomBind } from '../controllers/zoom'; +import dataVerificationCtrl from "../controllers/dataVerificationCtrl"; const IDCardReg = /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[12])(0[1-9]|[12]\d|3[01])\d{3}(\d|X)$/i; @@ -1176,6 +1178,113 @@ export function showColumn(startIndex, endIndex, options = {}) { showRowOrColumn('column', startIndex, endIndex, options); } + +/** + * 设置指定行的高度 + * @param {Object} rowInfo 行数和高度对应关系 + * @param {Object} options 可选参数 + * @param {Number} options.order 工作表索引;默认值为当前工作表索引 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setRowHeight(rowInfo, options = {}) { + if(getObjType(rowInfo) != 'object'){ + return tooltip.info("The rowInfo parameter is invalid.", ""); + } + + let { + order = getSheetIndex(Store.currentSheetIndex), + success + } = {...options} + + let file = Store.luckysheetfile[order]; + + if(file == null){ + return tooltip.info("The order parameter is invalid.", ""); + } + + let cfg = $.extend(true, {}, file.config); + if(cfg['rowlen'] == null){ + cfg['rowlen'] = {}; + } + + for(let r in rowInfo){ + if(parseInt(r) >= 0){ + let len = rowInfo[r]; + + if(Number(len) >= 0){ + cfg['rowlen'][parseInt(r)] = Number(len); + } + } + } + + file.config = cfg; + + server.saveParam("cg", file.index, cfg["rowlen"], { "k": "rowlen" }); + + if(file.index == Store.currentSheetIndex){ + Store.config = cfg; + jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length); + } + + if (success && typeof success === 'function') { + success() + } +} + + +/** + * 设置指定列的宽度 + * @param {Object} columnInfo 行数和高度对应关系 + * @param {Object} options 可选参数 + * @param {Number} options.order 工作表索引;默认值为当前工作表索引 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setColumnWidth(columnInfo, options = {}) { + if(getObjType(columnInfo) != 'object'){ + return tooltip.info("The columnInfo parameter is invalid.", ""); + } + + let { + order = getSheetIndex(Store.currentSheetIndex), + success + } = {...options} + + let file = Store.luckysheetfile[order]; + + if(file == null){ + return tooltip.info("The order parameter is invalid.", ""); + } + + let cfg = $.extend(true, {}, file.config); + if(cfg['columnlen'] == null){ + cfg['columnlen'] = {}; + } + + for(let c in columnInfo){ + if(parseInt(c) >= 0){ + let len = columnInfo[c]; + + if(Number(len) >= 0){ + cfg['columnlen'][parseInt(c)] = Number(len); + } + } + } + + file.config = cfg; + + server.saveParam("cg", file.index, cfg["columnlen"], { "k": "columnlen" }); + + if(file.index == Store.currentSheetIndex){ + Store.config = cfg; + jfrefreshgrid_rhcw(Store.flowdata.length, Store.flowdata[0].length); + } + + if (success && typeof success === 'function') { + success() + } +} + + /** * 返回当前选区对象的数组,可能存在多个选区。 * 每个选区的格式为row/column信息组成的对象{row:[0,1],column:[0,1]} @@ -4722,6 +4831,46 @@ export function setSheetOrder(orderList, options = {}) { } +/** + * 设置工作表缩放比例 + * @param {Number} zoom 工作表缩放比例,值范围为0.1 ~ 4; + * @param {Object} options 可选参数 + * @param {Number} options.order 工作表下标;默认值为当前工作表下标 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setSheetZoom(zoom, options = {}) { + if(getObjType(zoom) != 'number' && (zoom < 0.1 || zoom > 4)){ + return tooltip.info("The zoom parameter is invalid.", ""); + } + + let { + order = getSheetIndex(Store.currentSheetIndex), + success + } = {...options} + + let file = Store.luckysheetfile[order]; + + if(file == null){ + return tooltip.info("The order parameter is invalid.", ""); + } + + file["zoomRatio"] = zoom; + + server.saveParam("all", file.index, zoom, { "k": "zoomRatio" }); + + if(file.index == Store.currentSheetIndex){ + Store.zoomRatio = zoom; + + zoomNumberDomBind(); + zoomRefreshView(); + } + + if (success && typeof success === 'function') { + success(); + } +} + + /** * 显示指定下标工作表的网格线,返回操作的工作表对象 * @param {Object} options 可选参数 @@ -5211,6 +5360,304 @@ export function getLuckysheetfile(){ return getluckysheetfile(); } + +/** + * 指定工作表范围设置数据验证功能,并设置参数 + * @param {Object} optionItem 数据验证的配置信息 + * @param {String} optionItem.type 类型 + * @param {String | Null} optionItem.type2 条件类型 + * @param {String | Number} optionItem.value1 条件值1 + * @param {String | Number} optionItem.value2 条件值2 + * @param {Boolean} optionItem.checked 选中状态 + * @param {Boolean} optionItem.remote 自动远程获取选项 + * @param {Boolean} optionItem.prohibitInput 输入数据无效时禁止输入 + * @param {Boolean} optionItem.hintShow 选中单元格时显示提示语 + * @param {String} optionItem.hintText 提示语文本 + * @param {Object} options 可选参数 + * @param {Array | Object | String} options.range 选区范围;默认为当前选区 + * @param {Number} options.order 工作表下标;默认值为当前工作表下标 + * @param {Function} options.success 操作结束的回调函数 + */ +export function setDataVerification(optionItem, options = {}) { + if(getObjType(optionItem) != 'object'){ + return tooltip.info("The optionItem parameter is invalid.", ""); + } + + let { + type, + type2 = null, + value1 = '', + value2 = '', + remote = false, + prohibitInput = false, + hintShow = false, + hintText = '' + } = {...optionItem} + + let typeValues = ["dropdown", "checkbox", "number", "number_integer", "number_decimal", "text_content", "text_length", "date", "validity"]; + let type2Values_1 = ["bw", "nb", "eq", "ne", "gt", "lt", "gte", "lte"]; + let type2Values_2 = ["include", "exclude", "equal"]; + let type2Values_3 = ["bw", "nb", "eq", "ne", "bf", "nbf", "af", "naf"]; + let type2Values_4 = ["card", "phone"]; + + if(!typeValues.includes(type)){ + return tooltip.info("The optionItem.type parameter is invalid.", ""); + } + + let dvText = locale().dataVerification; + + if(type == 'dropdown'){ + if(value1.length == 0){ + tooltip.info('', dvText.tooltipInfo1); + return; + } + } + else if(type == 'checkbox'){ + if(value1.length == 0 || value2.length == 0){ + tooltip.info('', dvText.tooltipInfo2); + return; + } + } + else if(type == 'number' || type == 'number_integer' || type == 'number_decimal'){ + if(!type2Values_1.includes(type2)){ + return tooltip.info("The optionItem.type2 parameter is invalid.", ""); + } + + if(!isRealNum(value1)){ + tooltip.info('', dvText.tooltipInfo3); + return; + } + + if(type2 == 'bw' || type2 == 'nb'){ + if(!isRealNum(value2)){ + tooltip.info('', dvText.tooltipInfo3); + return; + } + + if(Number(value2) < Number(value1)){ + tooltip.info('', dvText.tooltipInfo4); + return; + } + } + } + else if(type == 'text_content'){ + if(!type2Values_2.includes(type2)){ + return tooltip.info("The optionItem.type2 parameter is invalid.", ""); + } + + if(value1.length == 0){ + tooltip.info('', dvText.tooltipInfo5); + return; + } + } + else if(type == 'text_length'){ + if(!type2Values_1.includes(type2)){ + return tooltip.info("The optionItem.type2 parameter is invalid.", ""); + } + + if(!isRealNum(value1)){ + tooltip.info('', dvText.tooltipInfo3); + return; + } + + if(type2 == 'bw' || type2 == 'nb'){ + if(!isRealNum(value2)){ + tooltip.info('', dvText.tooltipInfo3); + return; + } + + if(Number(value2) < Number(value1)){ + tooltip.info('', dvText.tooltipInfo4); + return; + } + } + } + else if(type == 'date'){ + if(!type2Values_3.includes(type2)){ + return tooltip.info("The optionItem.type2 parameter is invalid.", ""); + } + + if(!isdatetime(value1)){ + tooltip.info('', dvText.tooltipInfo6); + return; + } + + if(type2 == 'bw' || type2 == 'nb'){ + if(!isdatetime(value2)){ + tooltip.info('', dvText.tooltipInfo6); + return; + } + + if(diff(value1, value2) > 0){ + tooltip.info('', dvText.tooltipInfo7); + return; + } + } + } + else if(type == 'validity'){ + if(!type2Values_4.includes(type2)){ + return tooltip.info("The optionItem.type2 parameter is invalid.", ""); + } + } + + if(getObjType(remote) != 'boolean'){ + return tooltip.info("The optionItem.remote parameter is invalid.", ""); + } + + if(getObjType(prohibitInput) != 'boolean'){ + return tooltip.info("The optionItem.prohibitInput parameter is invalid.", ""); + } + + if(getObjType(hintShow) != 'boolean'){ + return tooltip.info("The optionItem.hintShow parameter is invalid.", ""); + } + + let { + range = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1], + order = getSheetIndex(Store.currentSheetIndex), + success + } = {...options} + + if(getObjType(range) == 'string'){ + if(!formula.iscelldata(range)){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let cellrange = formula.getcellrange(range); + range = { + "row": cellrange.row, + "column": cellrange.column + }; + } + + if(getObjType(range) != 'object' || range.row == null || range.column == null){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let file = Store.luckysheetfile[order]; + + if(file == null){ + return tooltip.info("The order parameter is invalid.", ""); + } + + let item = { + type: type, + type2: type2, + value1: value1, + value2: value2, + checked: false, + remote: remote, + prohibitInput: prohibitInput, + hintShow: hintShow, + hintText: hintText, + } + + let currentDataVerification = $.extend(true, {}, file.dataVerification); + + let data = $.extend(true, [], file.data); + if(data.length == 0){ + data = sheetmanage.buildGridData(file); + } + + let str = range.row[0], + edr = range.row[1], + stc = range.column[0], + edc = range.column[1]; + + for(let r = str; r <= edr; r++){ + for(let c = stc; c <= edc; c++){ + currentDataVerification[r + '_' + c] = item; + + if(type == 'checkbox'){ + setcellvalue(r, c, data, item.value2); + } + } + } + + if(file.index == Store.currentSheetIndex){ + let historyDataVerification = $.extend(true, {}, file.dataVerification); + + if(type == 'checkbox'){ + dataVerificationCtrl.refOfCheckbox(historyDataVerification, currentDataVerification, Store.currentSheetIndex, data, range); + } + else{ + dataVerificationCtrl.ref(historyDataVerification, currentDataVerification, Store.currentSheetIndex); + } + } + else{ + file.dataVerification = currentDataVerification; + file.data = data; + } + + if (success && typeof success === 'function') { + success(); + } +} + + +/** + * 指定工作表范围删除数据验证功能 + * @param {Object} options 可选参数 + * @param {Array | Object | String} options.range 选区范围;默认为当前选区 + * @param {Number} options.order 工作表下标;默认值为当前工作表下标 + * @param {Function} options.success 操作结束的回调函数 + */ +export function deleteDataVerification(options = {}) { + let { + range = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1], + order = getSheetIndex(Store.currentSheetIndex), + success + } = {...options} + + if(getObjType(range) == 'string'){ + if(!formula.iscelldata(range)){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let cellrange = formula.getcellrange(range); + range = { + "row": cellrange.row, + "column": cellrange.column + }; + } + + if(getObjType(range) != 'object' || range.row == null || range.column == null){ + return tooltip.info("The range parameter is invalid.", ""); + } + + let file = Store.luckysheetfile[order]; + + if(file == null){ + return tooltip.info("The order parameter is invalid.", ""); + } + + let currentDataVerification = $.extend(true, {}, file.dataVerification); + + let str = range.row[0], + edr = range.row[1], + stc = range.column[0], + edc = range.column[1]; + + for(let r = str; r <= edr; r++){ + for(let c = stc; c <= edc; c++){ + delete currentDataVerification[r + '_' + c]; + } + } + + if(file.index == Store.currentSheetIndex){ + let historyDataVerification = $.extend(true, {}, file.dataVerification); + dataVerificationCtrl.ref(historyDataVerification, currentDataVerification, Store.currentSheetIndex); + } + else{ + file.dataVerification = currentDataVerification; + } + + if (success && typeof success === 'function') { + success(); + } +} + + /** * data => celldata ,data二维数组数据转化成 {r, c, v}格式一维数组 * From 30c6c58c0b960df60d1155523971bbe3b9f3351b Mon Sep 17 00:00:00 2001 From: mengshukeji Date: Wed, 21 Oct 2020 20:22:05 +0800 Subject: [PATCH 7/9] docs(api): readme 1.readme add forum 2.api docs add getRowHeight/getColumnWidth/getDefaultRowHeight/getDefaultColumnWidth 3.demo add forum link --- README-zh.md | 9 ++-- README.md | 9 ++-- docs/guide/api.md | 100 ++++++++++++++++++++++++++++++++++++ docs/zh/guide/api.md | 100 ++++++++++++++++++++++++++++++++++++ docs/zh/guide/config.md | 45 ++++++++++++++-- src/demoData/demoFeature.js | 24 +++++++++ src/index.html | 5 +- 7 files changed, 278 insertions(+), 14 deletions(-) diff --git a/README-zh.md b/README-zh.md index 8f055f7..de4e3eb 100644 --- a/README-zh.md +++ b/README-zh.md @@ -10,10 +10,10 @@ 🚀Luckysheet ,一款纯前端类似excel的在线表格,功能强大、配置简单、完全开源。 ## 相关链接 - | 源码 | 文档 | Demo | 插件Demo | - | ------ | -------- | ------ | ------ | - | [Github](https://github.com/mengshukeji/Luckysheet)| [在线文档](https://mengshukeji.github.io/LuckysheetDocs/zh/) | [在线Demo](https://mengshukeji.github.io/LuckysheetDemo) | [导入Excel Demo](https://mengshukeji.github.io/LuckyexcelDemo/) | - | [Gitee镜像](https://gitee.com/mengshukeji/Luckysheet)| [Gitee在线文档](https://mengshukeji.gitee.io/LuckysheetDocs/zh/) | [Gitee在线Demo](https://mengshukeji.gitee.io/luckysheetdemo/) | [Gitee导入Excel Demo](https://mengshukeji.gitee.io/luckyexceldemo/) | + | 源码 | 文档 | Demo | 插件Demo | 论坛 | + | ------ | -------- | ------ | ------ | ------ | + | [Github](https://github.com/mengshukeji/Luckysheet)| [在线文档](https://mengshukeji.github.io/LuckysheetDocs/zh/) | [在线Demo](https://mengshukeji.github.io/LuckysheetDemo) | [导入Excel Demo](https://mengshukeji.github.io/LuckyexcelDemo/) | [中文论坛](https://support.qq.com/product/288322) | + | [Gitee镜像](https://gitee.com/mengshukeji/Luckysheet)| [Gitee在线文档](https://mengshukeji.gitee.io/LuckysheetDocs/zh/) | [Gitee在线Demo](https://mengshukeji.gitee.io/luckysheetdemo/) | [Gitee导入Excel Demo](https://mengshukeji.gitee.io/luckyexceldemo/) | [Gitter](https://gitter.im/mengshukeji/Luckysheet) | ![演示](/docs/.vuepress/public/img/LuckysheetDemo.gif) @@ -200,6 +200,7 @@ npm run build - [@danielcai1987](https://github.com/danielcai1987) - [@qq6690876](https://github.com/qq6690876) - [@javahuang](https://github.com/javahuang) +- [@TimerGang](https://github.com/TimerGang) - [@gsw945](https://github.com/gsw945) - [@swen-xiong](https://github.com/swen-xiong) diff --git a/README.md b/README.md index 84110a3..cfc7507 100644 --- a/README.md +++ b/README.md @@ -16,10 +16,10 @@ English| [简体中文](./README-zh.md) 🚀Luckysheet is an online spreadsheet like excel that is powerful, simple to configure, and completely open source. ## Links - | Source Code | Documentation | Demo | Plugins Demo | - | ------ | -------- | ------ | ------ | - | [Github](https://github.com/mengshukeji/Luckysheet)| [Online Documentation](https://mengshukeji.github.io/LuckysheetDocs/) | [Online Demo](https://mengshukeji.github.io/LuckysheetDemo) | [Import Excel Demo](https://mengshukeji.github.io/LuckyexcelDemo/) | - | [Gitee Mirror](https://gitee.com/mengshukeji/Luckysheet)| [Gitee Online Documentation](https://mengshukeji.gitee.io/LuckysheetDocs/) | [Gitee Online Demo](https://mengshukeji.gitee.io/luckysheetdemo/) | [Gitee Import Excel Demo](https://mengshukeji.gitee.io/luckyexceldemo/) | + | Source Code | Documentation | Demo | Plugins Demo | Forum | + | ------ | -------- | ------ | ------ | ------ | + | [Github](https://github.com/mengshukeji/Luckysheet)| [Online Documentation](https://mengshukeji.github.io/LuckysheetDocs/) | [Online Demo](https://mengshukeji.github.io/LuckysheetDemo) | [Import Excel Demo](https://mengshukeji.github.io/LuckyexcelDemo/) | [Chinese Forum](https://support.qq.com/product/288322) | + | [Gitee Mirror](https://gitee.com/mengshukeji/Luckysheet)| [Gitee Online Documentation](https://mengshukeji.gitee.io/LuckysheetDocs/) | [Gitee Online Demo](https://mengshukeji.gitee.io/luckysheetdemo/) | [Gitee Import Excel Demo](https://mengshukeji.gitee.io/luckyexceldemo/) | [Gitter](https://gitter.im/mengshukeji/Luckysheet) | ![Demo](/docs/.vuepress/public/img/LuckysheetDemo.gif) @@ -196,6 +196,7 @@ Create a table - [@danielcai1987](https://github.com/danielcai1987) - [@qq6690876](https://github.com/qq6690876) - [@javahuang](https://github.com/javahuang) +- [@TimerGang](https://github.com/TimerGang) - [@gsw945](https://github.com/gsw945) - [@swen-xiong](https://github.com/swen-xiong) diff --git a/docs/guide/api.md b/docs/guide/api.md index f9a95c9..c78c051 100644 --- a/docs/guide/api.md +++ b/docs/guide/api.md @@ -589,6 +589,106 @@ Use note: ------------ +### getRowHeight(rowInfo [,setting]) + +(TODO) + +- **Parameter**: + + - {Array} [rowInfo]: The number of rows + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Get the height of the specified row, get the object corresponding to the number of rows and height + +- **Usage**: + + - The height of the first row is 50px, the height of the second row is 60px, get these values + + `luckysheet.getRowHeight([0,1])` + Return to get + `{0:50,1:60}` + +------------ + +### getColumnWidth(columnInfo [,setting]) + +(TODO) + +- **Parameter**: + + - {Array} [columnInfo]: The number of columns + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Get the width of the specified column, get the object of the corresponding relationship between the number of columns and the width + +- **Usage**: + + - The width of the first column is 50px, the width of the second column is 60px, get these values + + `luckysheet.getColumnWidth([0,1])` + Return to get + `{0:50,1:60}` + +------------ + +### getDefaultRowHeight([,setting]) + +(TODO) + +- **Parameter**: + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Get the default row height of the specified worksheet + +- **Usage**: + + - Returns the default row height of the current worksheet + + `luckysheet.getDefaultRowHeight()` + Return to get + `19` + +------------ + +### getDefaultColumnWidth([,setting]) + +(TODO) + +- **Parameter**: + + - {PlainObject} [setting]: optional parameters + + {Number} [order]: Worksheet subscript; the default value is the current worksheet subscript + + {Function} [success]: callback function for the end of the operation + +- **Explanation**: + + Get the default column width of the specified worksheet + +- **Usage**: + + - Returns the default column width of the current worksheet + + `luckysheet.getDefaultColumnWidth()` + Return to get + `73` + +------------ + ## Selection operation ### getRange() diff --git a/docs/zh/guide/api.md b/docs/zh/guide/api.md index 9fed4d3..02701b3 100644 --- a/docs/zh/guide/api.md +++ b/docs/zh/guide/api.md @@ -590,6 +590,106 @@ Luckysheet针对常用的数据操作需求,开放了主要功能的API,开 ------------ +### getRowHeight(rowInfo [,setting]) + +(TODO) + +- **参数**: + + - {Array} [rowInfo]: 行数 + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 获取指定行的高度,得到行数和高度对应关系的对象 + +- **示例**: + + - 第一行高度为50px,第二行高度为60px,获取这些值 + + `luckysheet.getRowHeight([0,1])` + 返回得到 + `{0:50,1:60}` + +------------ + +### getColumnWidth(columnInfo [,setting]) + +(TODO) + +- **参数**: + + - {Array} [columnInfo]: 列数 + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 获取指定列的宽度,得到列数和宽度对应关系的对象 + +- **示例**: + + - 第一列宽度为50px,第二列宽度为60px,获取这些值 + + `luckysheet.getColumnWidth([0,1])` + 返回得到 + `{0:50,1:60}` + +------------ + +### getDefaultRowHeight([,setting]) + +(TODO) + +- **参数**: + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 获取指定工作表的默认行高 + +- **示例**: + + - 返回当前工作表的默认行高 + + `luckysheet.getDefaultRowHeight()` + 返回得到 + `19` + +------------ + +### getDefaultColumnWidth([,setting]) + +(TODO) + +- **参数**: + + - {PlainObject} [setting]: 可选参数 + + {Number} [order]: 工作表下标;默认值为当前工作表下标 + + {Function} [success]: 操作结束的回调函数 + +- **说明**: + + 获取指定工作表的默认列宽 + +- **示例**: + + - 返回当前工作表的默认列宽 + + `luckysheet.getDefaultColumnWidth()` + 返回得到 + `73` + +------------ + ## 选区操作 ### getRange() diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index b3d54bd..07ad1aa 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -106,15 +106,52 @@ Luckysheet开放了更细致的自定义配置选项,分别有 ### loadUrl - 类型:String - 默认值:"" -- 作用:配置`loadUrl`的地址,与`loadSheetUrl`配合使用,一般用于大数据量的时候。也可以不用Luckysheet提供的接口参数,使用[data](#data)参数可以提前准备好所有表格数据用于初始化。 - - Luckysheet会通过ajax请求整个表格数据,默认载入status为1的sheet数据中的所有`celldata`,其余的sheet载入除`celldata`字段外的所有字段。但是考虑到一些公式、图表及数据透视表会引用其他sheet的数据,所以前台会加一个判断,如果该当前sheet引用了其他sheet的数据则会通过`loadSheetUrl`配置的接口地址请求数据,把引用到的sheet的数据一并补全。因为 `loadUrl`只负责当前页数据,所以还需要配置`loadSheetUrl`作为异步加载数据的接口。 +- 作用:配置`loadUrl`的地址,与`loadSheetUrl`配合使用。 + + Luckysheet会通过ajax请求(POST)整个表格的数据,默认载入status为1的sheet数据中的`celldata`,其余的sheet载入除`celldata`字段外的所有配置字段。特别是在数据量大的时候,`loadUrl`只负责当前页单元格数据,配置`loadSheetUrl`作为其它工作表异步加载单元格数据的接口,可以提高性能。 + + 一个合格的接口返回的json数据为: + + ```js + "[ + //status为1的sheet页,重点是需要提供初始化的数据celldata + { + "name": "Cell", + "index": "sheet_001", + "order": 0, + "status": 1, + "celldata": [{"r":0,"c":0,"v":{"bg":null,"bl":0,"it":0,"ff":0,"fs":11,"fc":"rgb(51, 51, 51)","ht":1,"vt":1,"v":1,"ct":{"fa":"General","t":"n"},"m":"1"}}] + }, + //其他status为0的sheet页,无需提供celldata,只需要配置项即可 + { + "name": "Data", + "index": "sheet_002", + "order": 1, + "status": 0 + }, + { + "name": "Picture", + "index": "sheet_003", + "order": 2, + "status": 0 + } + ]" + ``` + 有几个注意点 + + 这是一个字符串,类似于JSON.stringify()处理后的json数据,压缩数据便于传输 + + loadUrl是一个post请求,也是为了支持大数据量 + + 考虑到一些公式、图表及数据透视表会引用其他sheet的数据,所以前台会加一个判断,如果该当前sheet引用了其他sheet的数据则会通过`loadSheetUrl`配置的接口地址请求数据,把引用到的sheet的数据一并补全,而不用等切换到其它页的时候再请求。 + + 当数据量小的时候,也可以不用Luckysheet提供的此接口,直接使用[data](#data)参数可以提前准备好所有表格数据用于初始化。 ------------ ### loadSheetUrl - 类型:String - 默认值:"" -- 作用:配置`loadSheetUrl`的地址,参数为`gridKey`(表格主键) 和 `index`(sheet主键合集,格式为`["sheet_01","sheet_02","sheet_0"]`),返回的数据为sheet的`celldata`字段数据集合。为了加载性能考虑,除了第一次加载当前页的`celldata`数据之外,其余sheet的数据,是在切换到那个sheet页的时候,才会请求那一页的数据。 +- 作用:配置`loadSheetUrl`的地址,参数为`gridKey`(表格主键) 和 `index`(sheet主键合集,格式为`["sheet_01","sheet_02","sheet_0"]`),返回的数据为sheet的`celldata`字段数据集合。 + +为了加载性能考虑,除了第一次加载当前页的`celldata`数据之外,其余sheet的数据,是在切换到那个sheet页的时候,才会请求那一页的数据。 + + 注意:loadSheetUrl是一个post请求,是为了支持大数据量 ------------ ### allowUpdate diff --git a/src/demoData/demoFeature.js b/src/demoData/demoFeature.js index e69de29..329c4b9 100644 --- a/src/demoData/demoFeature.js +++ b/src/demoData/demoFeature.js @@ -0,0 +1,24 @@ + +// Features specially written for demo + +(function() { + + // language + function language(params) { + + var lang = navigator.language||navigator.userLanguage;//常规浏览器语言和IE浏览器 + lang = lang.substr(0, 2);//截取lang前2位字符 + + return lang; + + } + // Tencent Forum Link Button + function supportButton() { + const text = language() === 'zh' ? '反馈' : 'Forum'; + + document.querySelector("body").insertAdjacentHTML('beforeend', `${text}`); + } + + supportButton() + +})() \ No newline at end of file diff --git a/src/index.html b/src/index.html index 727a4b4..d9be04a 100644 --- a/src/index.html +++ b/src/index.html @@ -17,8 +17,6 @@ - - @@ -1790,6 +1788,9 @@ }) + + + \ No newline at end of file From 6ae83196cb50fafbf5657104babd124fac27b818 Mon Sep 17 00:00:00 2001 From: wbfsa Date: Wed, 21 Oct 2020 21:09:34 +0800 Subject: [PATCH 8/9] fix(the bug with first word is space): fix ti --- src/global/getRowlen.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/global/getRowlen.js b/src/global/getRowlen.js index 63e6fd7..816af9c 100644 --- a/src/global/getRowlen.js +++ b/src/global/getRowlen.js @@ -928,14 +928,16 @@ function getCellTextInfo(cell , ctx, option){ let height = textWidth * Math.sin(rt*Math.PI/180) + textHeight * Math.cos(rt*Math.PI/180);//consider text box wdith and line height let lastWord = str.substr(str.length-1,1); if(lastWord==" " || checkWordByteLength(lastWord)==2){ - spaceOrTwoByte = { - index:i, - str:preStr, - width:preTextWidth, - height:preTextHeight, - asc:preMeasureText.actualBoundingBoxAscent, - desc:preMeasureText.actualBoundingBoxDescent, - }; + if(preMeasureText!=null){ + spaceOrTwoByte = { + index:i, + str:preStr, + width:preTextWidth, + height:preTextHeight, + asc:preMeasureText.actualBoundingBoxAscent, + desc:preMeasureText.actualBoundingBoxDescent, + }; + } } // textW_all += textW; From d4cea27d157b7e02072cef1a05238b7a848192e0 Mon Sep 17 00:00:00 2001 From: Dushusir <1414556676@qq.com> Date: Thu, 22 Oct 2020 00:03:35 +0800 Subject: [PATCH 9/9] docs(config): updateUrl update config docs:loadUrl,loadSheetUrl,allowUpdate,updateUrl --- docs/zh/guide/config.md | 72 +++++++++++++++++++++++++++++++++------- docs/zh/guide/operate.md | 2 +- 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/docs/zh/guide/config.md b/docs/zh/guide/config.md index 07ad1aa..94e2a76 100644 --- a/docs/zh/guide/config.md +++ b/docs/zh/guide/config.md @@ -106,11 +106,17 @@ Luckysheet开放了更细致的自定义配置选项,分别有 ### loadUrl - 类型:String - 默认值:"" -- 作用:配置`loadUrl`的地址,与`loadSheetUrl`配合使用。 +- 作用:配置`loadUrl`接口地址,加载所有工作表的配置,并包含当前页单元格数据,与`loadSheetUrl`配合使用。参数为`gridKey`(表格主键)。 + + 源码的请求写法是: + ```js + $.post(loadurl, {"gridKey" : server.gridKey}, function (d) {}) + ``` + > 参见源码 [`src/core.js`](https://github.com/mengshukeji/Luckysheet/blob/master/src/core.js) Luckysheet会通过ajax请求(POST)整个表格的数据,默认载入status为1的sheet数据中的`celldata`,其余的sheet载入除`celldata`字段外的所有配置字段。特别是在数据量大的时候,`loadUrl`只负责当前页单元格数据,配置`loadSheetUrl`作为其它工作表异步加载单元格数据的接口,可以提高性能。 - 一个合格的接口返回的json数据为: + 一个合格的接口返回的json字符串数据为: ```js "[ @@ -120,7 +126,7 @@ Luckysheet开放了更细致的自定义配置选项,分别有 "index": "sheet_001", "order": 0, "status": 1, - "celldata": [{"r":0,"c":0,"v":{"bg":null,"bl":0,"it":0,"ff":0,"fs":11,"fc":"rgb(51, 51, 51)","ht":1,"vt":1,"v":1,"ct":{"fa":"General","t":"n"},"m":"1"}}] + "celldata": [{"r":0,"c":0,"v":{"v":1,"m":"1","ct":{"fa":"General","t":"n"}}}] }, //其他status为0的sheet页,无需提供celldata,只需要配置项即可 { @@ -138,34 +144,76 @@ Luckysheet开放了更细致的自定义配置选项,分别有 ]" ``` 有几个注意点 - + 这是一个字符串,类似于JSON.stringify()处理后的json数据,压缩数据便于传输 + + 这是一个字符串,类似于JSON.stringify()处理后的json数据,压缩后的数据便于传输 + loadUrl是一个post请求,也是为了支持大数据量 - + 考虑到一些公式、图表及数据透视表会引用其他sheet的数据,所以前台会加一个判断,如果该当前sheet引用了其他sheet的数据则会通过`loadSheetUrl`配置的接口地址请求数据,把引用到的sheet的数据一并补全,而不用等切换到其它页的时候再请求。 - + 当数据量小的时候,也可以不用Luckysheet提供的此接口,直接使用[data](#data)参数可以提前准备好所有表格数据用于初始化。 + + 考虑到一些公式、图表及数据透视表会引用其他sheet的数据,所以前台会加一个判断,如果该当前sheet引用了其他sheet的数据则会通过`loadSheetUrl`配置的接口地址请求数据,把引用到的sheet的数据一并补全,而不用等切换到其它页的时候再请求 + + 当数据量小的时候,也可以不用Luckysheet提供的此接口,直接使用[data](#data)参数可以提前准备好所有表格数据用于初始化 ------------ ### loadSheetUrl - 类型:String - 默认值:"" -- 作用:配置`loadSheetUrl`的地址,参数为`gridKey`(表格主键) 和 `index`(sheet主键合集,格式为`["sheet_01","sheet_02","sheet_0"]`),返回的数据为sheet的`celldata`字段数据集合。 +- 作用:配置`loadSheetUrl`接口地址,用于异步加载其它单元格数据。参数为`gridKey`(表格主键) 和 `index`(sheet主键合集,格式为`["sheet_01","sheet_02","sheet_0"]`)。 + + 源码的请求写法是: + ```js + $.post(loadSheetUrl, {"gridKey" : server.gridKey, "index": sheetindex.join(",")}, function (d) {}) + ``` + > 参见源码 [`src/controllers/sheetmanage.js`](https://github.com/mengshukeji/Luckysheet/blob/master/src/controllers/sheetmanage.js) -为了加载性能考虑,除了第一次加载当前页的`celldata`数据之外,其余sheet的数据,是在切换到那个sheet页的时候,才会请求那一页的数据。 + 返回的数据为sheet的`celldata`字段数据集合。 - 注意:loadSheetUrl是一个post请求,是为了支持大数据量 + 一个合格的接口返回的json字符串数据为: + + ```js + "{ + "sheet_01": [ + { + "r": 0, + "c": 0, + "v": { "v": 1, "m": "1", "ct": { "fa": "General", "t": "n" } } + } + ], + "sheet_02": [ + { + "r": 0, + "c": 0, + "v": { "v": 1, "m": "1", "ct": { "fa": "General", "t": "n" } } + } + ], + "sheet_0": [ + { + "r": 0, + "c": 0, + "v": { "v": 1, "m": "1", "ct": { "fa": "General", "t": "n" } } + } + ] + }" + ``` + 同`loadUrl`类似,`loadSheetUrl`也要注意这几点: + + 这是一个字符串格式数据 + + 这是一个post请求 + + 这个接口会在两种情况下自动调用,一是在`loadUrl`加载的当前页数据时发现当前工作表引用了其他工作表,二是切换到一个未曾加载过数据的工作表时 ------------ ### allowUpdate - 类型:Boolean - 默认值:false -- 作用:是否允许操作表格后的后台更新,与`updateUrl`配合使用 +- 作用:是否允许操作表格后的后台更新,与`updateUrl`配合使用。如果要开启共享编辑,此参数必须设置为`true`。 ------------ ### updateUrl - 类型:String - 默认值:"" -- 作用:操作表格后的后台更新地址,在`allowUpdate`为`true`时才会有效,此接口也是共享编辑的接口地址。 +- 作用:操作表格后,实时保存数据的websocket地址,此接口也是共享编辑的接口地址。 + + 有个注意点,要想开启共享编辑,必须满足以下四个条件: + + `allowUpdate`为`true` + + 配置了`loadUrl` + + 配置了`loadSheetUrl` + + 配置了`updateUrl` -注意,还需要配置`loadUrl`和`loadSheetUrl`才能生效 + 通过共享编辑功能,可以实现Luckysheet实时保存数据和多人同步数据,每一次操作都会发送不同的参数到后台,具体的操作类型和参数参见[表格操作](/zh/guide/operate.html) ------------ ### updateImageUrl diff --git a/docs/zh/guide/operate.md b/docs/zh/guide/operate.md index 01802f4..02db446 100644 --- a/docs/zh/guide/operate.md +++ b/docs/zh/guide/operate.md @@ -1,6 +1,6 @@ # 表格操作 -每一次操作都会保存历史记录,用于撤销和重做,如果在表格初始化的时候设置了`allowUpdate`为`true`和`updateUrl`数据更新地址,则会通过websocket将操作实时更新到后台,并且支持共享编辑。 +每一次操作都会保存历史记录,用于撤销和重做,如果在表格初始化的时候开启了[共享编辑](/zh/guide/config.html#updateurl)功能,则会通过websocket将操作实时更新到后台。 > 源码 [`src/controllers/server.js`](https://github.com/mengshukeji/Luckysheet/blob/master/src/controllers/server.js) 模块实现了后台保存功能