protection.js 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. import Store from '../store';
  2. import locale from '../locale/locale';
  3. import { modelHTML } from './constant';
  4. import { getSheetIndex } from '../methods/get';
  5. import { setluckysheet_scroll_status } from '../methods/set';
  6. import sheetmanage from './sheetmanage';
  7. import luckysheetsizeauto from './resize';
  8. import dataVerificationCtrl from './dataVerificationCtrl';
  9. import { replaceHtml,transformRangeToAbsolute,openSelfModel } from '../utils/util';
  10. import { selectionCopyShow } from './select';
  11. import tooltip from '../global/tooltip';
  12. import cleargridelement from '../global/cleargridelement';
  13. let isInitialProtection = false, isInitialProtectionAddRang = false, rangeItemListCache=[], isAddRangeItemState=true, updateRangeItemIndex = null, validationAuthority=null, updatingSheetFile=null, firstInputSheetProtectionPassword = true;
  14. let sqrefMapCache = {}, inputRangeProtectionPassword = {}, initialRangePasswordHtml=false;
  15. const authorityItemArr = [
  16. "selectLockedCells",
  17. "selectunLockedCells",
  18. "formatCells",
  19. "formatColumns",
  20. "formatRows",
  21. "insertColumns",
  22. "insertRows",
  23. "insertHyperlinks",
  24. "deleteColumns",
  25. "deleteRows",
  26. "sort",
  27. "filter",
  28. "usePivotTablereports",
  29. "editObjects",
  30. "editScenarios"
  31. ]
  32. function addRangeItem(item){
  33. const _locale = locale();
  34. const local_protection = _locale.protection;
  35. const locale_button = _locale.button;
  36. let title = item.name, sqref = item.sqref, password = item.password;
  37. let passwordTxt = "";
  38. if(password!=null && password.length>0){
  39. passwordTxt = '<i class="icon iconfont luckysheet-iconfont-bianji2" title="'+ local_protection.rangeItemHasPassword+'"></i>';
  40. }
  41. let rangeItemTemplate = `
  42. <div class="luckysheet-protection-rangeItem" title="${local_protection.rangeItemDblclick}">
  43. <div class="luckysheet-protection-rangeItem-del" title="${locale_button.delete}">
  44. <i class="icon iconfont luckysheet-iconfont-shanchu"></i>
  45. </div>
  46. <div class="luckysheet-protection-rangeItem-name" title="${title}">
  47. ${title}${passwordTxt}
  48. </div>
  49. <div class="luckysheet-protection-rangeItem-range" title="${sqref}">
  50. ${sqref}
  51. </div>
  52. <div class="luckysheet-protection-rangeItem-update" title="${locale_button.update}">
  53. <i class="icon iconfont luckysheet-iconfont-bianji"></i>
  54. </div>
  55. </div>
  56. `;
  57. $("#luckysheet-protection-rangeItem-container").append(rangeItemTemplate);
  58. }
  59. function initialEvent(file){
  60. const _locale = locale();
  61. const local_protection = _locale.protection;
  62. const locale_button = _locale.button;
  63. //confirm protection
  64. $("#luckysheet-slider-protection-ok").click(function(){
  65. let password = $("#protection-password").val();
  66. let sheet = $("#protection-swichProtectionState").is(":checked");
  67. let hint = $("#protection-hint").val();
  68. let file = updatingSheetFile, aut = {};
  69. if(file!=null && file.config!=null && file.config.authority!=null){
  70. aut = file.config.authority;
  71. }
  72. let authorityData = {
  73. }
  74. let algorithmName = "None";
  75. if(password!="••••••••"){
  76. authorityData.password = password;
  77. authorityData.algorithmName = "None";
  78. authorityData.saltValue = null;
  79. }
  80. else if(aut!=null){
  81. authorityData.algorithmName = aut.algorithmName;
  82. authorityData.saltValue = aut.saltValue;
  83. authorityData.password = aut.password;
  84. }
  85. else {
  86. authorityData.algorithmName = "None";
  87. authorityData.saltValue = null;
  88. authorityData.password = "";
  89. }
  90. authorityData.hintText = hint;
  91. authorityData.sheet = sheet==true?1:0;
  92. for(let i=0;i<authorityItemArr.length;i++){
  93. let name = authorityItemArr[i];
  94. let checkId = "luckysheet-protection-check-" + name;
  95. let authorityValue = $("#"+checkId).is(':checked');
  96. authorityData[name] = authorityValue==true?1:0;
  97. }
  98. authorityData.allowRangeList = rangeItemListCache;
  99. rangeItemListCache = [];
  100. firstInputSheetProtectionPassword = true;
  101. if(file.config==null){
  102. file.config = {};
  103. }
  104. file.config.authority = authorityData;
  105. inputRangeProtectionPassword = {};
  106. closeProtectionModal();
  107. });
  108. //cancel protection
  109. $("#luckysheet-slider-protection-cancel, #luckysheet-modal-dialog-protection-close").click(function(){
  110. closeProtectionModal();
  111. });
  112. //Add allow edit range
  113. $("#luckysheet-slider-protection-addRange").click(function(){
  114. initialProtectionRangeModal();
  115. isAddRangeItemState = true;
  116. $("#luckysheet-protection-rangeItem-confirm").html(locale_button.insert);
  117. openSelfModel("luckysheet-protection-rangeItem-dialog");
  118. $("#protection-allowRangeAdd-title").val("Default"+rangeItemListCache.length);
  119. $("#protection-allowRangeAdd-range input").val("");
  120. $("#protection-allowRangeAdd-password").val("");
  121. $("#protection-allowRangeAdd-hint").val("");
  122. });
  123. //update allow edit range
  124. $(document).off("click.luckysheetProtection.rangeItemUpdate").on("click.luckysheetProtection.rangeItemUpdate","#luckysheet-protection-rangeItem-container .luckysheet-protection-rangeItem-update", function(e){
  125. initialProtectionRangeModal();
  126. isAddRangeItemState = false;
  127. $("#luckysheet-protection-rangeItem-confirm").html(locale_button.update);
  128. openSelfModel("luckysheet-protection-rangeItem-dialog");
  129. let $rangeItem = $(e.target).closest(".luckysheet-protection-rangeItem");
  130. let $rangeItemContainer = $("#luckysheet-protection-rangeItem-container");
  131. let index = $rangeItemContainer.find("> div.luckysheet-protection-rangeItem").index($rangeItem);
  132. let item = rangeItemListCache[index];
  133. updateRangeItemIndex = index;
  134. $("#protection-allowRangeAdd-title").val(item.name);
  135. $("#protection-allowRangeAdd-range input").val(item.sqref);
  136. if(item.algorithmName=="None"){
  137. $("#protection-allowRangeAdd-password").val(item.password);
  138. }
  139. else{
  140. $("#protection-allowRangeAdd-password").val("••••••••");
  141. }
  142. $("#protection-allowRangeAdd-hint").val(item.hintText);
  143. });
  144. //delete allow edit range
  145. $(document).off("click.luckysheetProtection.rangeItemDelete").on("click.luckysheetProtection.rangeItemDelete","#luckysheet-protection-rangeItem-container .luckysheet-protection-rangeItem-del", function(e){
  146. let $rangeItem = $(e.target).closest(".luckysheet-protection-rangeItem");
  147. let $rangeItemContainer = $("#luckysheet-protection-rangeItem-container");
  148. let index = $rangeItemContainer.find("> div.luckysheet-protection-rangeItem").index($rangeItem);
  149. let item = rangeItemListCache[index];
  150. rangeItemListCache.splice(index, 1);
  151. $rangeItem.remove();
  152. });
  153. //confirm allow edit range
  154. $(document).off("click.luckysheetProtection.rangeItemConfirm").on("click.luckysheetProtection.rangeItemConfirm","#luckysheet-protection-rangeItem-confirm", function(){
  155. let name = $("#protection-allowRangeAdd-title").val(),
  156. rangeText = $("#protection-allowRangeAdd-range input").val(),
  157. password = $("#protection-allowRangeAdd-password").val(),
  158. hint = $("#protection-allowRangeAdd-hint").val();
  159. if(name.length==0){
  160. alert(local_protection.rangeItemErrorTitleNull);
  161. return;
  162. }
  163. let range = dataVerificationCtrl.getRangeByTxt(rangeText);
  164. if(rangeText.length==0){
  165. alert(local_protection.rangeItemErrorRangeNull);
  166. return;
  167. }
  168. if(range.length==0){
  169. alert(local_protection.rangeItemErrorRange);
  170. return;
  171. }
  172. rangeText = transformRangeToAbsolute(rangeText);
  173. if(isAddRangeItemState){
  174. let item = {
  175. name:name,
  176. password:password,
  177. hintText:hint,
  178. algorithmName:"None",//MD2,MD4,MD5,RIPEMD-128,RIPEMD-160,SHA-1,SHA-256,SHA-384,SHA-512,WHIRLPOOL
  179. saltValue:null,
  180. checkRangePasswordUrl:null,
  181. sqref:rangeText
  182. }
  183. addRangeItem(item);
  184. rangeItemListCache.push(item);
  185. }
  186. else{
  187. let index = updateRangeItemIndex;
  188. let item = rangeItemListCache[index];
  189. item.name = name;
  190. item.sqref = rangeText;
  191. item.hintText = hint;
  192. if(password!="••••••••"){
  193. item.password = password;
  194. item.algorithmName = "None";
  195. }
  196. let $rangeItemContainer = $("#luckysheet-protection-rangeItem-container");
  197. let $rangeitem = $rangeItemContainer.find("> div.luckysheet-protection-rangeItem").eq(index);
  198. let $name = $rangeitem.find(".luckysheet-protection-rangeItem-name");
  199. let passwordTxt = "";
  200. if(password!=null && password.length>0){
  201. passwordTxt = '<i class="icon iconfont luckysheet-iconfont-bianji2" title="'+ local_protection.rangeItemHasPassword+'"></i>';
  202. }
  203. $name.html(name+passwordTxt).attr("title",name);
  204. let $range = $rangeitem.find(".luckysheet-protection-rangeItem-range");
  205. $range.html(rangeText).attr("title",rangeText);
  206. }
  207. $("#luckysheet-protection-rangeItem-dialog").hide();
  208. $("#luckysheet-modal-dialog-mask").hide();
  209. });
  210. //sheet validation check passWord
  211. $(document).off("click.luckysheetProtection.validationConfirm").on("click.luckysheetProtection.validationConfirm","#luckysheet-protection-sheet-validation-confirm", function(e){
  212. let $validation = $("#luckysheet-protection-sheet-validation");
  213. let aut = validationAuthority;
  214. if(aut==null){
  215. restoreProtectionConfig(validationAuthority);
  216. $validation.hide();
  217. $("#luckysheet-modal-dialog-mask").hide();
  218. $("#luckysheet-modal-dialog-slider-protection").show();
  219. luckysheetsizeauto();
  220. return;
  221. }
  222. let $input = $validation.find("input");
  223. let password = $input.val();
  224. if(password==null || password.length==0){
  225. alert(local_protection.checkPasswordNullalert);
  226. return;
  227. }
  228. if(aut.algorithmName!=null && aut.algorithmName!="None"){
  229. if(aut.saltValue!=null && aut.saltValue.length>0){
  230. var hasher = CryptoApi.getHasher(aut.algorithmName);
  231. password =CryptoApi.hmac(aut.saltValue, password, hasher);
  232. }
  233. else{
  234. password = CryptoApi.hash(aut.algorithmName, password);
  235. }
  236. }
  237. if(password==aut.password){
  238. restoreProtectionConfig(validationAuthority);
  239. $validation.hide();
  240. $("#luckysheet-modal-dialog-mask").hide();
  241. $("#luckysheet-modal-dialog-slider-protection").show();
  242. luckysheetsizeauto();
  243. firstInputSheetProtectionPassword = false;
  244. }
  245. else{
  246. alert(local_protection.checkPasswordWrongalert);
  247. }
  248. });
  249. $("#luckysheet-protection-check-selectLockedCells").change(function() {
  250. let $selectLockedCells = $("#luckysheet-protection-check-selectLockedCells"), $selectunLockedCells = $("#luckysheet-protection-check-selectunLockedCells");
  251. let selectLockedCellsChecked = $selectLockedCells.is(":checked"), selectunLockedCellsChecked = $selectunLockedCells.is(":checked");
  252. if(selectLockedCellsChecked){
  253. $selectunLockedCells.prop('checked', true);
  254. }
  255. });
  256. $("#luckysheet-protection-check-selectunLockedCells").change(function() {
  257. let $selectLockedCells = $("#luckysheet-protection-check-selectLockedCells"), $selectunLockedCells = $("#luckysheet-protection-check-selectunLockedCells");
  258. let selectLockedCellsChecked = $selectLockedCells.is(":checked"), selectunLockedCellsChecked = $selectunLockedCells.is(":checked");
  259. if(!selectunLockedCellsChecked){
  260. $selectLockedCells.prop('checked', false);
  261. }
  262. });
  263. //Cell range select controll
  264. $(document).off("click.luckysheetProtection.dvRange").on("click.luckysheetProtection.dvRange", "#protection-allowRangeAdd-range .fa-table", function(e) {
  265. $("#luckysheet-protection-rangeItem-dialog").hide();
  266. let dataSource = "0";
  267. let txt = $(this).siblings("input").val().trim();
  268. dataVerificationCtrl.rangeDialog(dataSource, txt);
  269. dataVerificationCtrl.selectRange = [];
  270. let range = dataVerificationCtrl.getRangeByTxt(txt);
  271. if(range.length > 0){
  272. for(let s = 0; s < range.length; s++){
  273. let r1 = range[s].row[0], r2 = range[s].row[1];
  274. let c1 = range[s].column[0], c2 = range[s].column[1];
  275. let row = Store.visibledatarow[r2],
  276. row_pre = r1 - 1 == -1 ? 0 : Store.visibledatarow[r1 - 1];
  277. let col = Store.visibledatacolumn[c2],
  278. col_pre = c1 - 1 == -1 ? 0 : Store.visibledatacolumn[c1 - 1];
  279. dataVerificationCtrl.selectRange.push({
  280. "left": col_pre,
  281. "width": col - col_pre - 1,
  282. "top": row_pre,
  283. "height": row - row_pre - 1,
  284. "left_move": col_pre,
  285. "width_move": col - col_pre - 1,
  286. "top_move": row_pre,
  287. "height_move": row - row_pre - 1,
  288. "row": [r1, r2],
  289. "column": [c1, c2],
  290. "row_focus": r1,
  291. "column_focus": c1
  292. });
  293. }
  294. }
  295. selectionCopyShow(dataVerificationCtrl.selectRange);
  296. });
  297. $(document).off("click.luckysheetProtection.dvRange2").on("click.luckysheetProtection.dvRange2", "#luckysheet-protection-rangeItem-dialog .show-box-item-dropdown .range .fa-table", function(e) {
  298. $("#luckysheet-protection-rangeItem-dialog").hide();
  299. let dataSource = "1";
  300. let txt = $(this).siblings("input").val().trim();
  301. dataVerificationCtrl.rangeDialog(dataSource, txt);
  302. dataVerificationCtrl.selectRange = [];
  303. let range = dataVerificationCtrl.getRangeByTxt(txt);
  304. if(range.length > 0){
  305. for(let s = 0; s < range.length; s++){
  306. let r1 = range[s].row[0], r2 = range[s].row[1];
  307. let c1 = range[s].column[0], c2 = range[s].column[1];
  308. let row = Store.visibledatarow[r2],
  309. row_pre = r1 - 1 == -1 ? 0 : Store.visibledatarow[r1 - 1];
  310. let col = Store.visibledatacolumn[c2],
  311. col_pre = c1 - 1 == -1 ? 0 : Store.visibledatacolumn[c1 - 1];
  312. dataVerificationCtrl.selectRange.push({
  313. "left": col_pre,
  314. "width": col - col_pre - 1,
  315. "top": row_pre,
  316. "height": row - row_pre - 1,
  317. "left_move": col_pre,
  318. "width_move": col - col_pre - 1,
  319. "top_move": row_pre,
  320. "height_move": row - row_pre - 1,
  321. "row": [r1, r2],
  322. "column": [c1, c2],
  323. "row_focus": r1,
  324. "column_focus": c1
  325. });
  326. }
  327. }
  328. selectionCopyShow(dataVerificationCtrl.selectRange);
  329. });
  330. $(document).off("click.luckysheetProtection.dvRangeConfirm").on("click.luckysheetProtection.dvRangeConfirm", "#luckysheet-dataVerificationRange-dialog-confirm", function(e) {
  331. let txt = $(this).parents("#luckysheet-dataVerificationRange-dialog").find("input").val();
  332. let $input = $("#protection-allowRangeAdd-range input"), inputValue = $input.val();
  333. if(inputValue.substr(inputValue.length-1, 1)==","){
  334. $input.val(inputValue + txt);
  335. }
  336. else{
  337. $input.val(txt);
  338. }
  339. $("#luckysheet-dataVerificationRange-dialog").hide();
  340. $("#luckysheet-modal-dialog-mask").show();
  341. $("#luckysheet-protection-rangeItem-dialog").show();
  342. let range = [];
  343. selectionCopyShow(range);
  344. });
  345. $(document).off("click.luckysheetProtection.dvRangeClose").on("click.dvRangeClose", "#luckysheet-dataVerificationRange-dialog-close", function(e) {
  346. $("#luckysheet-dataVerificationRange-dialog").hide();
  347. $("#luckysheet-modal-dialog-mask").show();
  348. $("#luckysheet-protection-rangeItem-dialog").show();
  349. let range = [];
  350. selectionCopyShow(range);
  351. });
  352. $(document).on("click.luckysheetProtection.luckysheetProtection", "#luckysheet-dataVerificationRange-dialog .luckysheet-modal-dialog-title-close", function(e) {
  353. $("#luckysheet-dataVerificationRange-dialog").hide();
  354. $("#luckysheet-modal-dialog-mask").show();
  355. $("#luckysheet-protection-rangeItem-dialog").show();
  356. let range = [];
  357. selectionCopyShow(range);
  358. });
  359. }
  360. //protect range config
  361. function initialProtectionRangeModal(file){
  362. if(isInitialProtectionAddRang){
  363. return;
  364. }
  365. isInitialProtectionAddRang = true;
  366. let _locale = locale();
  367. let local_protection = _locale.protection;
  368. const locale_button = _locale.button;
  369. $("body").first().append(replaceHtml(modelHTML, {
  370. "id": "luckysheet-protection-rangeItem-dialog",
  371. "addclass": "luckysheet-protection-rangeItem-dialog",
  372. "title": local_protection.allowRangeTitle,
  373. "content": `
  374. <div class="luckysheet-protection-rangeItem-content">
  375. <div class="luckysheet-slider-protection-row">
  376. <div class="luckysheet-slider-protection-column luckysheet-protection-column-3x">
  377. ${local_protection.allowRangeAddTitle}
  378. </div>
  379. <div class="luckysheet-slider-protection-column luckysheet-protection-column-7x" style="left:30%">
  380. <input class="luckysheet-protection-rangeItemiInput" id="protection-allowRangeAdd-title" placeHolder="${local_protection.allowRangeAddtitleDefault}">
  381. </div>
  382. </div>
  383. <div class="luckysheet-slider-protection-row">
  384. <div class="luckysheet-slider-protection-column luckysheet-protection-column-3x">
  385. ${local_protection.allowRangeAddSqrf}
  386. </div>
  387. <div class="luckysheet-slider-protection-column luckysheet-protection-column-7x" style="left:30%">
  388. <div id="protection-allowRangeAdd-range" class="range">
  389. <input class="formulaInputFocus" spellcheck="false" placeHolder="${local_protection.selectCellRangeHolder}">
  390. <i class="fa fa-table" aria-hidden="true" title="${local_protection.selectCellRange}"></i>
  391. </div>
  392. </div>
  393. </div>
  394. <div class="luckysheet-slider-protection-row">
  395. <div class="luckysheet-slider-protection-column luckysheet-protection-column-3x">
  396. ${local_protection.allowRangeAddTitlePassword}
  397. </div>
  398. <div class="luckysheet-slider-protection-column luckysheet-protection-column-7x" style="left:30%">
  399. <input class="luckysheet-protection-rangeItemiInput" id="protection-allowRangeAdd-password" placeHolder="${local_protection.enterPassword}">
  400. </div>
  401. </div>
  402. <div class="luckysheet-slider-protection-row">
  403. <div class="luckysheet-slider-protection-column luckysheet-protection-column-3x">
  404. ${local_protection.allowRangeAddTitleHint}
  405. </div>
  406. <div class="luckysheet-slider-protection-column luckysheet-protection-column-7x" style="left:30%">
  407. <textarea class="luckysheet-protection-rangeItemTextarea" id="protection-allowRangeAdd-hint" placeHolder="${local_protection.allowRangeAddTitleHintTitle}"></textarea>
  408. </div>
  409. </div>
  410. </div>
  411. `,
  412. "botton": `<button id="luckysheet-protection-rangeItem-confirm" class="btn btn-primary">${locale_button.insert}</button>
  413. <button class="btn btn-default luckysheet-model-close-btn">${locale_button.cancel}</button>`,
  414. "style": "z-index:100003"
  415. }));
  416. }
  417. //Protect sheet initial
  418. function initialProtectionRIghtBar(file){
  419. const _locale = locale();
  420. const local_protection = _locale.protection;
  421. const locale_button = _locale.button;
  422. let authorityItemHtml = "";
  423. for(let i=0;i<authorityItemArr.length;i++){
  424. let name = authorityItemArr[i];
  425. authorityItemHtml += `
  426. <div class="luckysheet-slider-protection-row" style="height:18px;">
  427. <div class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  428. <label for="luckysheet-protection-check-${name}"><input id="luckysheet-protection-check-${name}" name="luckysheet-protection-check-${name}" type="checkbox">${local_protection[name]}</label>
  429. </div>
  430. </div>
  431. `;
  432. }
  433. const protectionModalHtml = `
  434. <div id="luckysheet-modal-dialog-slider-protection" class="luckysheet-modal-dialog-slider luckysheet-modal-dialog-slider-pivot" style="display:none;">
  435. <div class="luckysheet-modal-dialog-slider-title"> <span>${local_protection.protectiontTitle}</span> <span id="luckysheet-modal-dialog-protection-close" title="${locale_button.close}"><i class="fa fa-times" aria-hidden="true"></i></span> </div>
  436. <div class="luckysheet-modal-dialog-slider-content">
  437. <div class="luckysheet-slider-protection-config" style="top:10px;height:115px">
  438. <div class="luckysheet-slider-protection-row">
  439. <div class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  440. <label for="protection-swichProtectionState"><input id="protection-swichProtectionState" name="protection-swichProtectionState" type="checkbox">${local_protection.swichProtectionTip}</label>
  441. </div>
  442. </div>
  443. <div class="luckysheet-slider-protection-row" style="height:23px;">
  444. <div class="luckysheet-slider-protection-column" style="width:98%;">
  445. <input class="luckysheet-protection-input" id="protection-password" placeHolder="${local_protection.enterPassword}">
  446. </div>
  447. </div>
  448. <div class="luckysheet-slider-protection-row" style="height:47px;margin-top:4px;">
  449. <div class="luckysheet-slider-protection-column" style="width:98%;">
  450. <textarea class="luckysheet-protection-textarea" id="protection-hint" placeHolder="${local_protection.enterHint}"></textarea>
  451. </div>
  452. </div>
  453. </div>
  454. <div class="luckysheet-slider-protection-config" style="top:130px;height:290px;border-top:1px solid #c5c5c5">
  455. <div class="luckysheet-slider-protection-row" style="height:20px;">
  456. ${local_protection.authorityTitle}
  457. </div>
  458. ${authorityItemHtml}
  459. </div>
  460. <div class="luckysheet-slider-protection-config" style="top:440px;bottom:45px;border-top:1px solid #c5c5c5">
  461. <div class="luckysheet-slider-protection-row" style="height:25px;">
  462. <div class="luckysheet-slider-protection-column luckysheet-protection-column-7x" style="left:0px;line-height: 25px;">
  463. ${local_protection.allowRangeTitle}
  464. </div>
  465. <div class="luckysheet-slider-protection-column luckysheet-protection-column-3x" style="left:70%;">
  466. <div class="luckysheet-slider-protection-ok luckysheet-slider-protection-addRange" id="luckysheet-slider-protection-addRange">
  467. ${local_protection.allowRangeAdd}
  468. </div>
  469. </div>
  470. </div>
  471. <div id="luckysheet-protection-rangeItem-container" class="luckysheet-slider-protection-row" style="top:25px;bottom:0px;position:absolute">
  472. </div>
  473. </div>
  474. <div class="luckysheet-slider-protection-config" style="bottom:0px;height:45px">
  475. <div class="luckysheet-slider-protection-column luckysheet-protection-column-5x" style="left:0px;">
  476. <div class="luckysheet-slider-protection-ok" id="luckysheet-slider-protection-ok">
  477. ${locale_button.confirm}
  478. </div>
  479. </div>
  480. <div class="luckysheet-slider-protection-column luckysheet-protection-column-5x" style="left:50%;">
  481. <div class="luckysheet-slider-protection-cancel" id="luckysheet-slider-protection-cancel">
  482. ${locale_button.cancel}
  483. </div>
  484. </div>
  485. </div>
  486. </div>
  487. </div>
  488. `;
  489. $("body").first().append(protectionModalHtml);
  490. //Password input initial for sheet Protection
  491. $("body").first().append(replaceHtml(modelHTML, {
  492. "id": "luckysheet-protection-sheet-validation",
  493. "addclass": "luckysheet-protection-sheet-validation",
  494. "title": local_protection.validationTitle,
  495. "content": `
  496. <div class="luckysheet-slider-protection-row">
  497. <div class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  498. ${local_protection.validationTips}
  499. </div>
  500. </div>
  501. <div class="luckysheet-slider-protection-row" style="margin-top:20px">
  502. <div class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  503. <input type="password" class="luckysheet-protection-rangeItemiInput" placeHolder="${local_protection.validationInputHint}">
  504. </div>
  505. </div>
  506. `,
  507. "botton": `<button id="luckysheet-protection-sheet-validation-confirm" class="btn btn-primary">${locale_button.confirm}</button>
  508. <button class="btn btn-default luckysheet-model-close-btn">${locale_button.cancel}</button>`,
  509. "style": "z-index:100003"
  510. }));
  511. }
  512. function restoreProtectionConfig(aut){
  513. if(aut==null){
  514. aut = {};
  515. }
  516. for(let i=0;i<authorityItemArr.length;i++){
  517. let name = authorityItemArr[i];
  518. let checkId = "luckysheet-protection-check-" + name;
  519. let authorityValue = aut[name];
  520. if(authorityValue==null){
  521. authorityValue = 0;
  522. }
  523. if(authorityValue==null && name in {selectLockedCells:1, selectunLockedCells:1}){
  524. authorityValue = 1;
  525. }
  526. $("#"+checkId).prop('checked',authorityValue==1?true:false);
  527. }
  528. if(aut.password!=null && aut.password.length>0){
  529. if(aut.algorithmName=="None" || aut.algorithmName==null){
  530. $("#protection-password").val(aut.password);
  531. }
  532. else{
  533. $("#protection-password").val("••••••••");
  534. }
  535. }
  536. else{
  537. $("#protection-password").val("");
  538. }
  539. let sheet = aut.sheet;
  540. if(aut.sheet==null){
  541. sheet = 0;
  542. }
  543. $("#protection-swichProtectionState").prop('checked',sheet==1?true:false);
  544. let hintText = aut.hintText;
  545. if(hintText==null){
  546. hintText = "";
  547. }
  548. $("#protection-hint").val(hintText);
  549. rangeItemListCache = [];
  550. $("#luckysheet-protection-rangeItem-container").empty();
  551. let allowRangeList = aut.allowRangeList;
  552. if(allowRangeList!=null && allowRangeList.length>0){
  553. for(let i=0;i<allowRangeList.length;i++){
  554. let item = allowRangeList[i];
  555. addRangeItem(item);
  556. rangeItemListCache.push(item);
  557. }
  558. }
  559. }
  560. export function openProtectionModal(file){
  561. if(!isInitialProtection){
  562. initialProtectionRIghtBar(file);
  563. initialEvent(file);
  564. isInitialProtection = true;
  565. }
  566. updatingSheetFile = file;
  567. if(file!=null && file.config!=null && file.config.authority!=null){
  568. let aut = file.config.authority;
  569. if(firstInputSheetProtectionPassword && aut.sheet==1 && aut.password!=null && aut.password.length>0){
  570. validationAuthority = aut;
  571. $("#luckysheet-protection-sheet-validation input").val("");
  572. openSelfModel("luckysheet-protection-sheet-validation");
  573. return;
  574. }
  575. else{//retore protection config
  576. restoreProtectionConfig(aut);
  577. }
  578. }
  579. else{//protection initial config
  580. $("#luckysheet-protection-check-selectLockedCells").prop('checked',true);
  581. $("#luckysheet-protection-check-selectunLockedCells").prop('checked',true);
  582. }
  583. $("#luckysheet-modal-dialog-slider-protection").show();
  584. luckysheetsizeauto();
  585. }
  586. export function closeProtectionModal(){
  587. $("#luckysheet-protection-rangeItem-dialog").hide();
  588. $("#luckysheet-modal-dialog-slider-protection").hide();
  589. luckysheetsizeauto();
  590. }
  591. function checkProtectionLockedSqref(r, c, aut, local_protection, isOpenAlert=true, isLock=true){
  592. let isPass = false;
  593. let rangeAut = aut.allowRangeList;
  594. if(rangeAut!=null && rangeAut.length>0){
  595. let isExists = false;
  596. for(let i=0;i<rangeAut.length;i++){
  597. let ra = rangeAut[i];
  598. let sqref = ra.sqref;
  599. let range = dataVerificationCtrl.getRangeByTxt(sqref);
  600. if(range.length > 0){
  601. for(let s = 0; s < range.length; s++){
  602. let r1 = range[s].row[0], r2 = range[s].row[1];
  603. let c1 = range[s].column[0], c2 = range[s].column[1];
  604. if(r>=r1 && r<=r2 && c>=c1 && c<=c2){
  605. isExists = true;
  606. break;
  607. }
  608. }
  609. }
  610. if(isExists){
  611. let password = ra.password;
  612. if(password!=null && password.length>0 && !(sqref in inputRangeProtectionPassword)){
  613. if(isOpenAlert){
  614. openRangePasswordModal(ra);
  615. $("#luckysheet-selection-copy .luckysheet-selection-copy").hide();
  616. }
  617. return false;
  618. }
  619. else{
  620. isPass = true;
  621. }
  622. break;
  623. }
  624. }
  625. }
  626. if (!isPass && !isLock) isPass = true
  627. if(!isPass && isOpenAlert){
  628. let ht;
  629. if(aut.hintText != null && aut.hintText.length>0){
  630. ht = aut.hintText;
  631. }
  632. else{
  633. ht = local_protection.defaultSheetHintText;
  634. }
  635. tooltip.info("", ht);
  636. $("#luckysheet-selection-copy .luckysheet-selection-copy").hide();
  637. }
  638. return isPass;
  639. }
  640. function openRangePasswordModal(rangeAut) {
  641. const _locale = locale();
  642. const local_protection = _locale.protection;
  643. const locale_button = _locale.button;
  644. if(!initialRangePasswordHtml){
  645. //Password input initial for range
  646. $("body").first().append(replaceHtml(modelHTML, {
  647. "id": "luckysheet-protection-range-validation",
  648. "addclass": "luckysheet-protection-sheet-validation",
  649. "title": local_protection.validationTitle,
  650. "content": `
  651. <div class="luckysheet-slider-protection-row">
  652. <div id="luckysheet-protection-range-validation-hint" class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  653. </div>
  654. </div>
  655. <div class="luckysheet-slider-protection-row" style="margin-top:20px">
  656. <div class="luckysheet-slider-protection-column luckysheet-protection-column-10x">
  657. <input type="password" class="luckysheet-protection-rangeItemiInput" placeHolder="${local_protection.validationInputHint}">
  658. </div>
  659. </div>
  660. `,
  661. "botton": `<button id="luckysheet-protection-range-validation-confirm" class="btn btn-primary">${locale_button.confirm}</button>
  662. <button class="btn btn-default luckysheet-model-close-btn">${locale_button.cancel}</button>`,
  663. "style": "z-index:100003"
  664. }));
  665. }
  666. initialRangePasswordHtml = true;
  667. openSelfModel("luckysheet-protection-range-validation");
  668. let $hint = $("#luckysheet-protection-range-validation-hint");
  669. if(rangeAut.hintText != null && rangeAut.hintText.length>0){
  670. $hint.html(rangeAut.hintText);
  671. }
  672. else{
  673. $hint.html(local_protection.defaultRangeHintText);
  674. }
  675. let $rangeV = $("#luckysheet-protection-range-validation");
  676. let $input = $rangeV.find("input");
  677. $input.val("");
  678. $("#luckysheet-protection-range-validation-confirm").off("click").on("click", function(){
  679. let password = $input.val();
  680. if(password==null || password.length==0){
  681. alert(local_protection.checkPasswordNullalert);
  682. return;
  683. }
  684. if(rangeAut.algorithmName!=null && rangeAut.algorithmName!="None"){
  685. // password = CryptoApi.hash(rangeAut.algorithmName, password);
  686. if(rangeAut.saltValue!=null && rangeAut.saltValue.length>0){
  687. var hasher = CryptoApi.getHasher(rangeAut.algorithmName);
  688. password =CryptoApi.hmac(rangeAut.saltValue, password, hasher);
  689. }
  690. else{
  691. password = CryptoApi.hash(rangeAut.algorithmName, password);
  692. }
  693. }
  694. if(password==rangeAut.password){
  695. inputRangeProtectionPassword[rangeAut.sqref] = 1;
  696. $rangeV.hide();
  697. $("#luckysheet-modal-dialog-mask").hide();
  698. alert(local_protection.checkPasswordSucceedalert);
  699. }
  700. else{
  701. alert(local_protection.checkPasswordWrongalert);
  702. }
  703. });
  704. }
  705. //protection state
  706. export function checkProtectionNotEnable(sheetIndex){
  707. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  708. if(sheetFile==null){
  709. return true;
  710. }
  711. if(sheetFile.config==null || sheetFile.config.authority==null){
  712. return true;
  713. }
  714. let aut = sheetFile.config.authority;
  715. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  716. return true;
  717. }
  718. const _locale = locale();
  719. const local_protection = _locale.protection;
  720. let ht;
  721. if(aut.hintText != null && aut.hintText.length>0){
  722. ht = aut.hintText;
  723. }
  724. else{
  725. ht = local_protection.defaultSheetHintText;
  726. }
  727. tooltip.info("", ht);
  728. return false;
  729. }
  730. //cell locked state
  731. export function checkProtectionLocked(r, c, sheetIndex, isOpenAlert=true, isLock=true){
  732. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  733. if(sheetFile==null){
  734. return true;
  735. }
  736. if(sheetFile.config==null || sheetFile.config.authority==null){
  737. return true;
  738. }
  739. let data=sheetFile.data, cell=data[r][c], aut = sheetFile.config.authority;
  740. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  741. return true;
  742. }
  743. if(cell && cell.lo === 0){ // lo为0的时候才是可编辑
  744. return true;
  745. }
  746. const _locale = locale();
  747. const local_protection = _locale.protection;
  748. return checkProtectionLockedSqref(r, c , aut, local_protection, isOpenAlert, isLock);
  749. }
  750. //cell hidden state
  751. export function checkProtectionCellHidden(r, c, sheetIndex){
  752. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  753. if(!sheetFile || (sheetFile.data && !sheetFile.data[r]) || (sheetFile.data && !sheetFile.data[r][c])){
  754. return true;
  755. }
  756. if(sheetFile.config==null || sheetFile.config.authority==null){
  757. return true;
  758. }
  759. let data=sheetFile.data, cell=data[r][c], aut = sheetFile.config.authority;
  760. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  761. return true;
  762. }
  763. if(cell==null || cell.hi==null || cell.hi==0){
  764. return true;
  765. }
  766. return false;
  767. }
  768. //cell range locked state
  769. export function checkProtectionLockedRangeList(rangeList, sheetIndex){
  770. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  771. if(sheetFile==null){
  772. return true;
  773. }
  774. if(sheetFile.config==null || sheetFile.config.authority==null){
  775. return true;
  776. }
  777. let aut = sheetFile.config.authority;
  778. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  779. return true;
  780. }
  781. if(rangeList==null || rangeList.length==0){
  782. return true;
  783. }
  784. const _locale = locale();
  785. const local_protection = _locale.protection;
  786. for(let s = 0; s < rangeList.length; s++){
  787. let r1 = rangeList[s].row[0], r2 = rangeList[s].row[1];
  788. let c1 = rangeList[s].column[0], c2 = rangeList[s].column[1];
  789. for(let r=r1;r<=r2;r++){
  790. for(let c=c1;c<=c2;c++){
  791. const cell = sheetFile.data[r][c] || {}
  792. let isLock = cell.lo === undefined || cell.lo === 1, // 单元格是否锁定
  793. isPass = checkProtectionLockedSqref(r, c , aut, local_protection, true, isLock);
  794. if(!isPass){
  795. return false;
  796. }
  797. }
  798. }
  799. }
  800. return true;
  801. }
  802. //selectLockedCells , selectunLockedCells and cell state
  803. export function checkProtectionSelectLockedOrUnLockedCells(r, c, sheetIndex){
  804. const _locale = locale();
  805. const local_protection = _locale.protection;
  806. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  807. if(sheetFile==null){
  808. return true;
  809. }
  810. if(sheetFile.config==null || sheetFile.config.authority==null){
  811. return true;
  812. }
  813. let data=sheetFile.data, cell=data[r][c], aut = sheetFile.config.authority;
  814. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  815. return true;
  816. }
  817. if(cell && cell.lo === 0){ // lo为0的时候才是可编辑
  818. if(aut.selectunLockedCells==1 || aut.selectunLockedCells==null){
  819. return true;
  820. }
  821. else{
  822. return false;
  823. }
  824. }
  825. else{//locked??
  826. let isAllEdit = checkProtectionLockedSqref(r, c , aut, local_protection, false);//dont alert password model
  827. if(isAllEdit){//unlocked
  828. if(aut.selectunLockedCells==1 || aut.selectunLockedCells==null){
  829. return true;
  830. }
  831. else{
  832. return false;
  833. }
  834. }
  835. else{//locked
  836. if(aut.selectLockedCells==1 || aut.selectLockedCells==null){
  837. return true;
  838. }
  839. else{
  840. return false;
  841. }
  842. }
  843. }
  844. }
  845. //selectLockedCells or selectunLockedCells authority, highlight cell
  846. export function checkProtectionAllSelected(sheetIndex){
  847. const _locale = locale();
  848. const local_protection = _locale.protection;
  849. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  850. if(sheetFile==null){
  851. return true;
  852. }
  853. if(sheetFile.config==null || sheetFile.config.authority==null){
  854. return true;
  855. }
  856. let aut = sheetFile.config.authority;
  857. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  858. return true;
  859. }
  860. let selectunLockedCells = false;
  861. if(aut.selectunLockedCells==1 || aut.selectunLockedCells==null){
  862. selectunLockedCells = true;
  863. }
  864. let selectLockedCells = false;
  865. if(aut.selectLockedCells==1 || aut.selectLockedCells==null){
  866. selectLockedCells = true;
  867. }
  868. if(selectunLockedCells && selectLockedCells){
  869. return true;
  870. }
  871. return false;
  872. }
  873. //formatCells authority, bl cl fc fz ff ct border etc.
  874. export function checkProtectionFormatCells(sheetIndex){
  875. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  876. if(sheetFile==null){
  877. return true;
  878. }
  879. if(sheetFile.config==null || sheetFile.config.authority==null){
  880. return true;
  881. }
  882. let aut = sheetFile.config.authority;
  883. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  884. return true;
  885. }
  886. if(aut.formatCells==1 || aut.formatCells==null){
  887. return true;
  888. }
  889. const _locale = locale();
  890. const local_protection = _locale.protection;
  891. let ht;
  892. if(aut.hintText != null && aut.hintText.length>0){
  893. ht = aut.hintText;
  894. }
  895. else{
  896. ht = local_protection.defaultSheetHintText;
  897. }
  898. tooltip.info("", ht);
  899. return false;
  900. }
  901. //formatColumns authority: controll column hidden and width
  902. //formatRows authority: controll row hidden and height
  903. //insertColumns authority
  904. //insertRows authority
  905. //insertHyperlinks authority:Hyperlinks is not incomplete
  906. //deleteColumns authority
  907. //deleteRows authority
  908. //sort authority
  909. //filter authority
  910. //usePivotTablereports authority
  911. //editObjects authority: insert,delete,update for image, chart, comment,shape etc.
  912. //editScenarios authority: Scenarios features is uncompleted
  913. export function checkProtectionAuthorityNormal(sheetIndex, type="formatColumns", isAlert=true){
  914. let sheetFile = sheetmanage.getSheetByIndex(sheetIndex);
  915. if(sheetFile==null){
  916. return true;
  917. }
  918. if(sheetFile.config==null || sheetFile.config.authority==null){
  919. return true;
  920. }
  921. let aut = sheetFile.config.authority;
  922. if(aut==null || aut.sheet==null || aut.sheet==0 ){
  923. return true;
  924. }
  925. if(aut[type]==1 || aut[type]==null){
  926. return true;
  927. }
  928. if(isAlert){
  929. const _locale = locale();
  930. const local_protection = _locale.protection;
  931. let ht;
  932. if(aut.hintText != null && aut.hintText.length>0){
  933. ht = aut.hintText;
  934. }
  935. else{
  936. ht = local_protection.defaultSheetHintText;
  937. }
  938. tooltip.info("", ht);
  939. }
  940. return false;
  941. }