From 439dff4330ab5053643331286091d44ae910fb8d Mon Sep 17 00:00:00 2001
From: wpxp123456 <2677556700@qq.com>
Date: Wed, 28 Oct 2020 17:23:41 +0800
Subject: [PATCH] feat(hyperlink): add hyperlink function
---
src/controllers/constant.js | 22 ++-
src/controllers/controlHistory.js | 7 +
src/controllers/handler.js | 22 +++
src/controllers/hyperlinkCtrl.js | 265 ++++++++++++++++++++++++++++++
src/controllers/resize.js | 2 +
src/controllers/sheetmanage.js | 5 +
src/css/luckysheet-core.css | 34 ++++
src/locale/en.js | 16 ++
src/locale/zh.js | 16 ++
9 files changed, 387 insertions(+), 2 deletions(-)
create mode 100644 src/controllers/hyperlinkCtrl.js
diff --git a/src/controllers/constant.js b/src/controllers/constant.js
index d320325..2aacaad 100644
--- a/src/controllers/constant.js
+++ b/src/controllers/constant.js
@@ -384,6 +384,9 @@ function rightclickHTML(){
+
@@ -1229,6 +1232,23 @@ function menuToolBar (){
+
diff --git a/src/controllers/controlHistory.js b/src/controllers/controlHistory.js
index 3a95a4c..d3940df 100644
--- a/src/controllers/controlHistory.js
+++ b/src/controllers/controlHistory.js
@@ -5,6 +5,7 @@ import conditionformat from './conditionformat';
import luckysheetPostil from './postil';
import imageCtrl from './imageCtrl';
import dataVerificationCtrl from './dataVerificationCtrl';
+import hyperlinkCtrl from './hyperlinkCtrl';
import {zoomRefreshView,zoomNumberDomBind} from './zoom';
import { createFilter, createFilterOptions, labelFilterOptionState } from './filter';
import formula from '../global/formula';
@@ -344,6 +345,9 @@ const controlHistory = {
else if (ctr.type == "updateDataVerificationOfCheckbox"){
dataVerificationCtrl.refOfCheckbox(ctr.currentDataVerification, ctr.historyDataVerification, ctr.sheetIndex, ctr.data, ctr.range);
}
+ else if (ctr.type == "updateHyperlink"){
+ hyperlinkCtrl.ref(ctr.currentHyperlink, ctr.historyHyperlink, ctr.sheetIndex, ctr.data, ctr.range);
+ }
else if (ctr.type == "updateCF"){
let historyRules = ctr["data"]["historyRules"];
@@ -650,6 +654,9 @@ const controlHistory = {
else if (ctr.type == "updateDataVerificationOfCheckbox"){
dataVerificationCtrl.refOfCheckbox(ctr.historyDataVerification, ctr.currentDataVerification, ctr.sheetIndex, ctr.curData, ctr.range);
}
+ else if (ctr.type == "updateHyperlink") {
+ hyperlinkCtrl.ref(ctr.historyHyperlink, ctr.currentHyperlink, ctr.sheetIndex, ctr.curData, ctr.range);
+ }
else if (ctr.type == "updateCF"){
let currentRules = ctr["data"]["currentRules"];
diff --git a/src/controllers/handler.js b/src/controllers/handler.js
index 432681d..f7d72fa 100644
--- a/src/controllers/handler.js
+++ b/src/controllers/handler.js
@@ -5,6 +5,7 @@ import pivotTable from './pivotTable';
import luckysheetDropCell from './dropCell';
import luckysheetPostil from './postil';
import imageCtrl from './imageCtrl';
+import hyperlinkCtrl from './hyperlinkCtrl';
import dataVerificationCtrl from './dataVerificationCtrl';
import menuButton from './menuButton';
import conditionformat from './conditionformat';
@@ -338,6 +339,9 @@ export default function luckysheetHandler() {
//数据验证 单元格聚焦
dataVerificationCtrl.cellFocus(row_index, col_index, true);
+ //链接 单元格聚焦
+ hyperlinkCtrl.cellFocus(row_index, col_index);
+
//若点击单元格部分不在视图内
if (col_pre < $("#luckysheet-cell-main").scrollLeft()) {
$("#luckysheet-scrollbar-x").scrollLeft(col_pre);
@@ -4531,6 +4535,24 @@ export default function luckysheetHandler() {
}
});
+ //菜单栏 插入链接按钮
+ $("#luckysheet-insertLink-btn-title").click(function () {
+ if(!checkProtectionNotEnable(Store.currentSheetIndex)){
+ return;
+ }
+
+ if (Store.luckysheet_select_save == null || Store.luckysheet_select_save.length == 0) {
+ return;
+ }
+
+ hyperlinkCtrl.createDialog();
+ hyperlinkCtrl.init();
+ })
+ $("#luckysheetInsertLink").click(function () {
+ $("#luckysheet-insertLink-btn-title").click();
+ $("#luckysheet-rightclick-menu").hide();
+ })
+
//菜单栏 数据验证按钮
$("#luckysheet-dataVerification-btn-title").click(function () {
if(!checkProtectionNotEnable(Store.currentSheetIndex)){
diff --git a/src/controllers/hyperlinkCtrl.js b/src/controllers/hyperlinkCtrl.js
new file mode 100644
index 0000000..a906031
--- /dev/null
+++ b/src/controllers/hyperlinkCtrl.js
@@ -0,0 +1,265 @@
+import { replaceHtml } from '../utils/util';
+import { getcellvalue } from '../global/getdata';
+import { luckysheetrefreshgrid } from '../global/refresh';
+import formula from '../global/formula';
+import tooltip from '../global/tooltip';
+import editor from '../global/editor';
+import { modelHTML } from './constant';
+import server from './server';
+import { getSheetIndex } from '../methods/get';
+import locale from '../locale/locale';
+import Store from '../store';
+
+const hyperlinkCtrl = {
+ item: {
+ linkType: 'external', //链接类型 external外部链接,internal内部链接
+ linkAddress: '', //链接地址 网页地址或工作表单元格引用
+ linkTooltip: '', //提示
+ },
+ hyperlink: null,
+ createDialog: function(){
+ let _this = this;
+
+ const _locale = locale();
+ const hyperlinkText = _locale.insertLink;
+ const toolbarText = _locale.toolbar;
+ const buttonText = _locale.button;
+
+ $("#luckysheet-modal-dialog-mask").show();
+ $("#luckysheet-insertLink-dialog").remove();
+
+ let sheetListOption = '';
+ Store.luckysheetfile.forEach(item => {
+ sheetListOption += ``;
+ })
+
+ let content = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
+
+ $("body").append(replaceHtml(modelHTML, {
+ "id": "luckysheet-insertLink-dialog",
+ "addclass": "luckysheet-insertLink-dialog",
+ "title": toolbarText.insertLink,
+ "content": content,
+ "botton": `
+ `,
+ "style": "z-index:100003"
+ }));
+ let $t = $("#luckysheet-insertLink-dialog").find(".luckysheet-modal-dialog-content").css("min-width", 350).end(),
+ myh = $t.outerHeight(),
+ myw = $t.outerWidth();
+ let winw = $(window).width(),
+ winh = $(window).height();
+ let scrollLeft = $(document).scrollLeft(),
+ scrollTop = $(document).scrollTop();
+ $("#luckysheet-insertLink-dialog").css({
+ "left": (winw + scrollLeft - myw) / 2,
+ "top": (winh + scrollTop - myh) / 3
+ }).show();
+
+ _this.dataAllocation();
+ },
+ init: function (){
+ let _this = this;
+
+ const _locale = locale();
+ const hyperlinkText = _locale.insertLink;
+
+ //链接类型
+ $(document).off("change.linkType").on("change.linkType", "#luckysheet-insertLink-dialog-linkType", function(e){
+ let value = this.value;
+
+ $("#luckysheet-insertLink-dialog .show-box").hide();
+ $("#luckysheet-insertLink-dialog .show-box-" + value).show();
+ })
+
+ //确认按钮
+ $(document).off("click.confirm").on("click.confirm", "#luckysheet-insertLink-dialog-confirm", function(e){
+ let last = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1];
+ let rowIndex = last.row_focus || last.row[0];
+ let colIndex = last.column_focus || last.column[0];
+
+ //文本
+ let linkText = $("#luckysheet-insertLink-dialog-linkText").val();
+
+ let linkType = $("#luckysheet-insertLink-dialog-linkType").val();
+ let linkAddress = $("#luckysheet-insertLink-dialog-linkAddress").val();
+ let linkSheet = $("#luckysheet-insertLink-dialog-linkSheet").val();
+ let linkCell = $("#luckysheet-insertLink-dialog-linkCell").val();
+ let linkTooltip = $("#luckysheet-insertLink-dialog-linkTooltip").val();
+
+ if(linkType == 'external'){
+ if(!/^http[s]?:\/\/([\w\-\.]+)+[\w-]*([\w\-\.\/\?%&=]+)?$/ig.test(linkAddress)){
+ tooltip.info('', hyperlinkText.tooltipInfo1);
+ return;
+ }
+ }
+ else{
+ if(!formula.iscelldata(linkCell)){
+ tooltip.info('', hyperlinkText.tooltipInfo2);
+ return;
+ }
+
+ linkAddress = linkSheet + "!" + linkCell;
+ }
+
+ if(linkText == null || linkText.replace(/\s/g, '') == ''){
+ linkText = linkAddress;
+ }
+
+ let item = {
+ linkType: linkType,
+ linkAddress: linkAddress,
+ linkTooltip: linkTooltip,
+ }
+
+ let historyHyperlink = $.extend(true, {}, _this.hyperlink);
+ let currentHyperlink = $.extend(true, {}, _this.hyperlink);
+
+ currentHyperlink[rowIndex + "_" + colIndex] = item;
+
+ let d = editor.deepCopyFlowData(Store.flowdata);
+ let cell = d[rowIndex][colIndex];
+
+ if(cell == null){
+ cell = {};
+ }
+
+ cell.fc = 'rgb(0, 0, 255)';
+ cell.un = 1;
+ cell.v = linkText;
+
+ d[rowIndex][colIndex] = cell;
+
+ _this.ref(
+ historyHyperlink,
+ currentHyperlink,
+ Store.currentSheetIndex,
+ d,
+ { row: [rowIndex, rowIndex], column: [colIndex, colIndex] }
+ );
+
+ $("#luckysheet-modal-dialog-mask").hide();
+ $("#luckysheet-insertLink-dialog").hide();
+ })
+ },
+ dataAllocation: function(){
+ let _this = this;
+
+ let last = Store.luckysheet_select_save[Store.luckysheet_select_save.length - 1];
+ let rowIndex = last.row_focus || last.row[0];
+ let colIndex = last.column_focus || last.column[0];
+
+ let hyperlink = _this.hyperlink || {};
+ let item = hyperlink[rowIndex + "_" + colIndex] || {};
+
+ //文本
+ let text = getcellvalue(rowIndex, colIndex, null, 'm');
+ $("#luckysheet-insertLink-dialog-linkText").val(text);
+
+ //链接类型
+ let linkType = item.linkType || 'external';
+ $("#luckysheet-insertLink-dialog-linkType").val(linkType);
+
+ $("#luckysheet-insertLink-dialog .show-box").hide();
+ $("#luckysheet-insertLink-dialog .show-box-" + linkType).show();
+
+ //链接地址
+ let linkAddress = item.linkAddress || '';
+
+ if(linkType == 'external'){
+ $("#luckysheet-insertLink-dialog-linkAddress").val(linkAddress);
+ }
+ else{
+ if(formula.iscelldata(linkAddress)){
+ let sheettxt = linkAddress.split("!")[0];
+ let rangetxt = linkAddress.split("!")[1];
+
+ $("#luckysheet-insertLink-dialog-linkSheet").val(sheettxt);
+ $("#luckysheet-insertLink-dialog-linkCell").val(rangetxt);
+ }
+ }
+
+ //提示
+ let linkTooltip = item.linkTooltip || '';
+ $("#luckysheet-insertLink-dialog-linkTooltip").val(linkTooltip);
+ },
+ cellFocus: function(r, c){
+ let _this = this;
+
+ if(_this.hyperlink == null || _this.hyperlink[r + '_' + c] == null){
+ return;
+ }
+
+
+ },
+ ref: function(historyHyperlink, currentHyperlink, sheetIndex, d, range){
+ let _this = this;
+
+ if (Store.clearjfundo) {
+ Store.jfundo = [];
+
+ let redo = {};
+ redo["type"] = "updateHyperlink";
+ redo["sheetIndex"] = sheetIndex;
+ redo["historyHyperlink"] = historyHyperlink;
+ redo["currentHyperlink"] = currentHyperlink;
+ redo["data"] = Store.flowdata;
+ redo["curData"] = d;
+ redo["range"] = range;
+ Store.jfredo.push(redo);
+ }
+
+ _this.hyperlink = currentHyperlink;
+ Store.luckysheetfile[getSheetIndex(sheetIndex)].hyperlink = currentHyperlink;
+
+ Store.flowdata = d;
+ editor.webWorkerFlowDataCache(Store.flowdata);//worker存数据
+ Store.luckysheetfile[getSheetIndex(sheetIndex)].data = Store.flowdata;
+
+ //共享编辑模式
+ if(server.allowUpdate){
+ server.saveParam("all", sheetIndex, currentHyperlink, { "k": "hyperlink" });
+ server.historyParam(Store.flowdata, sheetIndex, range);
+ }
+
+ setTimeout(function () {
+ luckysheetrefreshgrid();
+ }, 1);
+ }
+}
+
+export default hyperlinkCtrl;
\ No newline at end of file
diff --git a/src/controllers/resize.js b/src/controllers/resize.js
index 5ca3935..4e909ca 100644
--- a/src/controllers/resize.js
+++ b/src/controllers/resize.js
@@ -318,6 +318,7 @@ export function menuToolBarWidth() {
$('#luckysheet-icon-textwrap').offset().left,
$('#luckysheet-icon-rotation').offset().left,
$('#luckysheet-insertImg-btn-title').offset().left,
+ $('#luckysheet-insertLink-btn-title').offset().left,
$('#luckysheet-chart-btn-title').offset().left,
$('#luckysheet-icon-postil').offset().left,
$('#luckysheet-pivot-btn-title').offset().left,
@@ -356,6 +357,7 @@ export function menuToolBarWidth() {
['#luckysheet-icon-textwrap','#luckysheet-icon-textwrap-menu'],
['#luckysheet-icon-rotation','#luckysheet-icon-rotation-menu','#toolbar-separator-text-rotate'],
'#luckysheet-insertImg-btn-title',
+ '#luckysheet-insertLink-btn-title',
'#luckysheet-chart-btn-title',
'#luckysheet-icon-postil',
['#luckysheet-pivot-btn-title','#toolbar-separator-pivot-table'],
diff --git a/src/controllers/sheetmanage.js b/src/controllers/sheetmanage.js
index deaaf2f..36cd089 100644
--- a/src/controllers/sheetmanage.js
+++ b/src/controllers/sheetmanage.js
@@ -19,6 +19,7 @@ import luckysheetsizeauto from './resize';
import luckysheetPostil from './postil';
import imageCtrl from './imageCtrl';
import dataVerificationCtrl from './dataVerificationCtrl';
+import hyperlinkCtrl from './hyperlinkCtrl';
import luckysheetFreezen from './freezen';
import { createFilterOptions, labelFilterOptionState } from './filter';
import { selectHightlightShow, selectionCopyShow } from './select';
@@ -930,6 +931,10 @@ const sheetmanage = {
//数据验证
dataVerificationCtrl.dataVerification = file.dataVerification;
dataVerificationCtrl.init();
+
+ //链接
+ hyperlinkCtrl.hyperlink = file.hyperlink;
+ hyperlinkCtrl.init();
createFilterOptions(file["filter_select"], file["filter"]);
},
diff --git a/src/css/luckysheet-core.css b/src/css/luckysheet-core.css
index 6b72126..6068da1 100644
--- a/src/css/luckysheet-core.css
+++ b/src/css/luckysheet-core.css
@@ -7065,6 +7065,40 @@ fieldset[disabled] .btn-danger.focus {
position: absolute;
display: none;
}
+/* 插入链接 */
+#luckysheet-insertLink-dialog{
+ user-select: none;
+}
+#luckysheet-insertLink-dialog .box{
+ font-size: 12px;
+}
+#luckysheet-insertLink-dialog .box-item{
+ height: 30px;
+ line-height: 30px;
+ margin-bottom: 10px;
+}
+#luckysheet-insertLink-dialog .box-item label{
+ display: inline-block;
+ width: 80px;
+ text-align: right;
+ margin-right: 10px;
+}
+#luckysheet-insertLink-dialog .box-item input{
+ width: 200px;
+ height: 30px;
+ padding: 0 10px;
+ border: 1px solid #d4d4d4;
+ outline-style: none;
+ box-sizing: border-box;
+}
+#luckysheet-insertLink-dialog .box-item select{
+ width: 200px;
+ height: 30px;
+ padding: 0 5px;
+ border: 1px solid #d4d4d4;
+ outline-style: none;
+ box-sizing: border-box;
+}
/* 数据验证 */
#luckysheet-dataVerification-dialog{
user-select: none;
diff --git a/src/locale/en.js b/src/locale/en.js
index 05a87fd..b279da0 100644
--- a/src/locale/en.js
+++ b/src/locale/en.js
@@ -8859,6 +8859,7 @@ export default {
screenshot: 'Screenshot',
splitColumn: 'Split text',
insertImage: 'Insert image',
+ insertLink: 'Insert link',
dataVerification: 'Data verification',
protection:"Protect the sheet",
@@ -9689,6 +9690,21 @@ export default {
fiveQuadrantDiagram: 'Five-quadrant diagram',
fiveBoxes: '5 Boxes',
},
+ insertLink: {
+ linkText: "Text",
+ linkType: "Link type",
+ external: "External link",
+ internal: "Internal link",
+ linkAddress: "Link address",
+ linkSheet: "Worksheet",
+ linkCell: "Cell reference",
+ linkTooltip: "Tooltip",
+ placeholder1: "Please enter the web link address",
+ placeholder2: "Please enter the cell to be quoted, example A1",
+ placeholder3: "Please enter the prompt content",
+ tooltipInfo1: "Please enter a valid link",
+ tooltipInfo2: "Please enter the correct cell reference",
+ },
dataVerification: {
cellRange: 'Cell range',
selectCellRange: 'Click to select a cell range',
diff --git a/src/locale/zh.js b/src/locale/zh.js
index 6818780..494f786 100644
--- a/src/locale/zh.js
+++ b/src/locale/zh.js
@@ -9085,6 +9085,7 @@ export default {
screenshot: '截图',
splitColumn: '分列',
insertImage: '插入图片',
+ insertLink: '插入链接',
dataVerification: '数据验证',
protection:"保护工作表内容",
@@ -9933,6 +9934,21 @@ export default {
fiveQuadrantDiagram: '五象限图',
fiveBoxes: '5个框',
},
+ insertLink: {
+ linkText: "文本",
+ linkType: "链接类型",
+ external: "外部链接",
+ internal: "内部链接",
+ linkAddress: "链接地址",
+ linkSheet: "工作表",
+ linkCell: "单元格引用",
+ linkTooltip: "提示",
+ placeholder1: "请输入网页链接地址",
+ placeholder2: "请输入要引用的单元格,例A1",
+ placeholder3: "请输入提示内容",
+ tooltipInfo1: "请输入有效的链接",
+ tooltipInfo2: "请输入正确的单元格引用",
+ },
dataVerification: {
cellRange: '单元格范围',
selectCellRange: '点击选择单元格范围',