customTable.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. // 字母列标
  2. export function getColumnHeaderCode(len) {
  3. let tag_arr = [];
  4. for(let i=0;i<len;i++) tag_arr.push(String.fromCharCode(65+i));
  5. return tag_arr;
  6. }
  7. // 行标
  8. export function getRowHeaderCode(len) {
  9. let tag_arr = [];
  10. for(let i=0;i<len;i++) tag_arr.push(String(1+i));
  11. return tag_arr;
  12. }
  13. //过滤输入空格
  14. export function filterInput(input) {
  15. return input.replace(/\s+/g, '');
  16. }
  17. //从公式中提取因数
  18. export function extractFactorsFromFormula(str) {
  19. let pattern = /[A-Za-z]+\d+/g;
  20. let factors = str.match(pattern);
  21. // 提取括号内的内容作为因数
  22. let parenthesesPattern = /\([^()]+\)/g; // 匹配括号内的内容
  23. let parenthesesMatches = str.match(parenthesesPattern);
  24. if (parenthesesMatches) {
  25. for (let i = 0; i < parenthesesMatches.length; i++) {
  26. let parenthesesContent = parenthesesMatches[i].slice(1, -1); // 去除括号
  27. let subFactors = extractFactorsFromFormula(parenthesesContent);
  28. factors = factors.concat(subFactors);
  29. }
  30. }
  31. return factors.filter ((value, index, self) => self.indexOf(value) === index);
  32. }
  33. //根据因数找元素值
  34. export function findCellByFactor (str) {
  35. let newStr = splitString(toUpperCase(str));
  36. let table = document.querySelector('.table');
  37. let el = table.querySelector("td span[data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']") || table.querySelector("td input[data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']");
  38. return el ? (el.innerText||el.value||'') : null;
  39. }
  40. //转大写
  41. export function toUpperCase(str) {
  42. let uppercaseStr = str.toUpperCase();
  43. return uppercaseStr;
  44. }
  45. //拆分A1为['A','1']
  46. export function splitString(str) {
  47. let letter = str.match(/[A-Z]+/)[0];
  48. let number = str.match(/\d+/)[0];
  49. return [letter, number];
  50. }
  51. //选中整行整列样式
  52. export function selectMoreCellStyle(e,type=null) {
  53. let table = document.querySelector('.table');
  54. resetStyle();
  55. if($(e.target).hasClass('th-col')) { //点击列
  56. // 指标列 日期列显示显示有所区分
  57. const columnIndex = Array.from(e.target.parentNode.children).indexOf(e.target);
  58. table.rows.forEach((cell,index)=> {
  59. if(index !==0) {
  60. if(type === 1) index === 2 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
  61. if(type === 2) index === 1 ? $(cell.children[columnIndex-1]).addClass('td-col-select') : $(cell.children[columnIndex]).addClass('td-col-select');
  62. if(!type) $(cell.children[columnIndex]).addClass('td-col-select');
  63. }
  64. })
  65. }else if($(e.target).hasClass('th-row')) { //点击行
  66. e.target.parentNode.children.forEach((cell,index)=> {
  67. if(index !==0) {
  68. index === 2 ? $(cell).addClass('td-row-select') : $(cell).addClass('td-row-select');
  69. }
  70. })
  71. }
  72. }
  73. // 选中格子样式
  74. export function selectCellStyle(e) {
  75. let table = document.querySelector('.table');
  76. resetStyle();
  77. if (table.querySelectorAll(".td-chose").length == 0) {
  78. e.target.nodeName==='TD' && $(e.target).addClass("td-chose")
  79. e.target.parentNode.nodeName==='TD' && $(e.target.parentNode).addClass("td-chose")
  80. e.target.parentNode.parentNode.nodeName==='TD' && $(e.target.parentNode.parentNode).addClass("td-chose")
  81. e.target.parentNode.parentNode.parentNode.nodeName==='TD' && $(e.target.parentNode.parentNode.parentNode).addClass("td-chose")
  82. }
  83. }
  84. export function resetStyle() {
  85. let table = document.querySelector('.table');
  86. table.querySelectorAll(".td-chose").forEach(el => {
  87. el.classList.remove('td-chose')
  88. })
  89. table.querySelectorAll(".td-col-select").forEach(el => {
  90. el.classList.remove('td-col-select')
  91. })
  92. table.querySelectorAll(".td-row-select").forEach(el => {
  93. el.classList.remove('td-row-select')
  94. })
  95. table.querySelectorAll(".td-relation").forEach(el => {
  96. el.classList.remove('td-relation')
  97. })
  98. }
  99. //单击聚焦
  100. export function setFocus(e) {
  101. if(e.target.nodeName==='TD') {
  102. let input = e.target.querySelector('input');
  103. input && input.focus();
  104. }
  105. }
  106. // 插入值或公式有插值后设置背景色
  107. export function setCellBg(e) {
  108. e.target.parentNode.nodeName==='TD' && $(e.target.parentNode).addClass("insert")
  109. e.target.parentNode.parentNode.nodeName==='TD' && $(e.target.parentNode.parentNode).addClass("insert")
  110. }
  111. //右键菜单
  112. export function getRightClickMenu(pos,canEdit=false) {
  113. let cellMenu = [
  114. { label: "根据日期选择指标值", key: "choose-target" },
  115. // { label: "插入指标值", key: "insert-value" },
  116. { label: "导入日期", key: "insert-date" },
  117. // { label: "导入指标日期", key: "insert-edb-date" },
  118. { label: "日期计算", key: "insert-date-calculate" },
  119. { label: "指标计算",
  120. key: "insert-edb-calculate",
  121. children: [
  122. { label: '累计值转月/季值',source: 1,fromEdbKey:5 },
  123. { label: '同比值',source: 3,fromEdbKey:6 },
  124. { label: '同差值',source: 4,fromEdbKey:7 },
  125. { label: 'N期移动均值',source: 5,fromEdbKey:8 },
  126. { label: 'N期环比值',source: 6,fromEdbKey:12 },
  127. { label: 'N期环差值',source: 7,fromEdbKey:13 },
  128. { label: '升频',source: 8,fromEdbKey:14 },
  129. { label: '时间移位',source: 10,fromEdbKey:22 },
  130. { label: '超季节性',source: 11,fromEdbKey:35 },
  131. { label: '年化值',source: 12,fromEdbKey:52 },
  132. { label: '降频',source: 9,fromEdbKey:51 },
  133. { label: '累计值',source: 13,fromEdbKey:62 },
  134. { label: '指数修匀',source: 15,fromEdbKey:'alpha' },
  135. { label: '日均值',source: 16,fromEdbKey:75 },
  136. ]
  137. },
  138. { label: "清空", key: "reset" },
  139. ]
  140. const menuMap = {
  141. 'col': [
  142. { label: "向左插入列", key: "insert-col-left" },
  143. { label: "向右插入列", key: "insert-col-right" },
  144. { label: "删除", key: "del" },
  145. ],
  146. 'row': [
  147. { label: "向上插入行", key: "insert-row-up" },
  148. { label: "向下插入行", key: "insert-row-down" },
  149. { label: "删除", key: "del" },
  150. ],
  151. 'cell': canEdit
  152. ? [{ label: '编辑',key: 'cell-edit' },...cellMenu]
  153. : cellMenu
  154. }
  155. return menuMap[pos];
  156. }
  157. //日期格式识别转换
  158. export function checkDateFormat(str) {
  159. const dateRegex = /^(?:(?:19|20)\d\d)([-/.])(0?[1-9]|1[0-2])\1(0?[1-9]|[12][0-9]|3[01])$/;
  160. //也支持年-月
  161. const dateMonthRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])$/;
  162. if(dateRegex.test(str)) {
  163. const date = new Date(str);
  164. if (!isNaN(date.getTime())) {
  165. const year = date.getFullYear();
  166. const month = String(date.getMonth() + 1).padStart(2, '0');
  167. const day = String(date.getDate()).padStart(2, '0');
  168. return `${year}-${month}-${day}`;
  169. } else {
  170. return false;
  171. }
  172. } else if(dateMonthRegex.test(str)){
  173. return str
  174. } else {
  175. return false
  176. }
  177. }
  178. /* 根据key找到格子 设置格子样式 */
  179. export function setRelationStyle(query,classname="td-relation") {
  180. const { key } = query;
  181. let table = document.querySelector('.table');
  182. let el = table.querySelector("td[data-key='" + key + "']");
  183. el.nodeName==='TD' && $(el).addClass(classname)
  184. }
  185. //根据cell key找到cell数据
  186. export function findCellByKey(arr,key) {
  187. let cell = null;
  188. for (let i = arr.length - 1; i >= 0; i--) {
  189. if(!cell) {
  190. for(let j = arr[i].length-1;j>=0;j--) {
  191. if(arr[i][j].Uid===key) {
  192. cell = arr[i][j];
  193. break
  194. }
  195. }
  196. }
  197. }
  198. // console.log(cell)
  199. return cell
  200. }
  201. /* 清空插入单元格重置关联样式 */
  202. export function resetRelationStyle() {
  203. let table = document.querySelector('.table');
  204. table.querySelectorAll(".td-relation").forEach(el => {
  205. el.classList.remove('td-relation')
  206. })
  207. }
  208. /* 重置右键选择指标时的单元格标识样式 弹窗消失样式就消失 */
  209. export function resetDialogCellStyle() {
  210. let table = document.querySelector('.table');
  211. table.querySelectorAll(".td-choose-insert-target").forEach(el => {
  212. el.classList.remove('td-choose-insert-target')
  213. })
  214. }
  215. // 根据行头列头位置找key
  216. export function findCellKeyByFactor(str) {
  217. let newStr = splitString(toUpperCase(str));
  218. let table = document.querySelector('.table');
  219. let el = table.querySelector("td [data-rindex='" + newStr[1] + "'][data-cindex='" + newStr[0] + "']");
  220. return el ? (el.dataset.key||'') : null;
  221. }
  222. /* 判断值是否是一个数字或数字字符串 */
  223. export function isNumberVal(value) {
  224. let reg = /^[-]?(?:\d*\.?\d+|\d+%|\d*\.\d+%)$/;
  225. return reg.test(value);
  226. }
  227. /* 增加减少小数点位数 */
  228. export function transDecimalPlace(str,decimalNum) {
  229. console.log(str,decimalNum)
  230. let s = str.replace(/%/,''), decimalPlaces = getDecimalPlaces(str);
  231. //后缀 百分号
  232. let suffix = str.endsWith('%') ? '%' : '';
  233. if(decimalPlaces===0) { //整数
  234. // 补零
  235. const zerosToAdd = Math.max(0, decimalNum);
  236. return zerosToAdd > 0
  237. ? `${s}.${'0'.repeat(zerosToAdd)}${suffix}`
  238. : `${s}${suffix}`;
  239. }
  240. let integerStr = str.split('.')[0],
  241. decimalStr = str.split('.')[1];
  242. if(decimalNum>0) {
  243. return `${s}${'0'.repeat(decimalNum)}${suffix}`
  244. } else {
  245. return decimalNum+decimalPlaces > 0
  246. ? `${integerStr}.${decimalStr.substring(0,decimalNum+decimalPlaces)}${suffix}`
  247. : `${integerStr}${suffix}`
  248. }
  249. }
  250. /* 计算小数点位数 */
  251. export function getDecimalPlaces(numStr) {
  252. // 移除百分号,如果有的话
  253. numStr = numStr.replace('%', '');
  254. // 如果没有小数点,说明小数点位数为 0
  255. if (!numStr.includes('.')) {
  256. return 0;
  257. }
  258. // 获取当前小数点后的位数
  259. const decimalPlaces = numStr.split('.')[1].length;
  260. return decimalPlaces;
  261. }
  262. /* 格式化单元格值 显示转换 */
  263. export function transNumPercentType(str,type) {
  264. console.log(str,type)
  265. let isPercent = str.endsWith('%'),s=str.replace(/%/,''),decimalPlaces = getDecimalPlaces(str);
  266. if(isPercent && type==='percent') { //百分数转百分
  267. return str
  268. }
  269. if(!isPercent && type==='number') { //数字转数字
  270. return str
  271. }
  272. let num = parseFloat(s)
  273. if(type==='percent') {
  274. const percenStr = (num * 100).toFixed(2) + '%';
  275. return percenStr;
  276. }else {
  277. return (num/100).toFixed(2);
  278. }
  279. }
  280. export function transValueFormat(str,{nt,pn}) {
  281. let str1 = '',str2 = '';
  282. str1 = nt ? transNumPercentType(str,nt) : str;
  283. str2 = pn!==0 ? transDecimalPlace(str1,pn) : str1;
  284. return str2;
  285. }