copyconfirm.ui.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. window.changeProduct = function(e)
  2. {
  3. const oldProductID = e.item.oldProductID;
  4. const productID = e.key;
  5. if(productID == 0)
  6. {
  7. $(`#dropdownToggle${oldProductID}`).closest('tbody').find(`tr.product-${oldProductID}`).addClass('hidden');
  8. $(`#dropdownToggle${oldProductID}`).closest('tr').find(`input[name="productIdList[]"]`).val(0);
  9. }
  10. else
  11. {
  12. $(`#dropdownToggle${oldProductID}`).closest('tbody').find(`tr.product-${oldProductID}`).removeClass('hidden');
  13. $(`#dropdownToggle${oldProductID}`).closest('tr').find(`input[name="productIdList[]"]`).val(productID);
  14. }
  15. $('#dropdownToggle' + oldProductID + ' .text').text(e.item.text);
  16. }
  17. window.renderRowData = function($row, index, row)
  18. {
  19. if(row.grade > 1) $row.find('td[data-name="name"]').css('padding-left', `${row.grade * 10}px`); // 子阶段缩进
  20. $row.attr('data-parent', row.parent);
  21. $row.attr('data-id', row.id);
  22. if(['waterfall', 'waterfallplus', 'ipd'].includes(projectModel))
  23. {
  24. if(row.stageBy == 'product' && row.isFirst == 1 && !isTpl)
  25. {
  26. const currentProduct = JSON.parse(productPairs)[row.productID];
  27. const productItems = [];
  28. productItems.push({text: currentProduct, key: row.productID, oldProductID: row.productID});
  29. productItems.push({text: notCopyStage, key: 0, oldProductID: row.productID});
  30. chosenProductStage = chosenProductStage.replace('%s', currentProduct);
  31. $row.before(`<tr>
  32. <td colspan='4'><span class="text-sm text-secondary-500">${chosenProductStage}</span><button class="gray-300-outline size-sm rounded-full ml-2 btn" type="button" id="dropdownToggle${row.productID}"><span class="text">${currentProduct}</span><span class="caret"></span></button></td>
  33. <input type="hidden" name="productIdList[]" value="${row.productID}">
  34. </tr>`);
  35. new zui.Dropdown(`#dropdownToggle${row.productID}`, {
  36. menu: {
  37. className: 'change-product-menu',
  38. items: productItems,
  39. onClickItem: changeProduct
  40. }
  41. });
  42. }
  43. $row.addClass(`product-${row.productID}`);
  44. $row.find('[data-name="id"] input').attr('name', `executionIDList[${row.productID}][${row.id}]`);
  45. $row.find('[data-name="parent"] input').attr('name', `parent[${row.productID}][${row.id}]`);
  46. $row.find('[data-name="name"] input').attr('name', `name[${row.productID}][${row.id}]`);
  47. $row.find('[data-name="begin"] input').attr('name', `begin[${row.productID}][${row.id}]`);
  48. $row.find('[data-name="end"] input').attr('name', `end[${row.productID}][${row.id}]`);
  49. $row.find('[data-name="percent"] input').attr('name', `percent[${row.productID}][${row.id}]`);
  50. $row.find('[data-name="milestone"]').find('input').attr('name', `milestone[${row.productID}][${row.id}]`);
  51. $row.find('[data-name="begin"]').find('.form-group-wrapper').on('inited', function(e, info)
  52. {
  53. info[0].render({name: `begin[${row.productID}]`});
  54. info[0].$.setValue(row.begin);
  55. });
  56. $row.find('[data-name="end"]').find('.form-group-wrapper').on('inited', function(e, info)
  57. {
  58. info[0].render({name: `end[${row.productID}]`});
  59. info[0].$.setValue(row.end);
  60. });
  61. $row.find('[data-name="PM"]').find('.picker-box').on('inited', function(e, info)
  62. {
  63. info[0].render({name: `PM[${row.productID}]`});
  64. info[0].$.setValue(row.PM);
  65. });
  66. $row.find('[data-name="attribute"]').find('.picker-box').on('inited', function(e, info)
  67. {
  68. const disabled = row.parentAttr != 'mix' && row.grade > 1 ? true : false;
  69. info[0].render({name: `attribute[${row.productID}]`, disabled: disabled});
  70. info[0].$.setValue(row.attribute);
  71. });
  72. $row.find('[data-name="acl"]').find('.picker-box').on('inited', function(e, info)
  73. {
  74. info[0].render({name: `acl[${row.productID}]`});
  75. info[0].$.setValue(row.acl);
  76. });
  77. /* 看板和迭代类型不支持百分比。*/
  78. if(row.type == 'kanban' || row.type == 'sprint')
  79. {
  80. $row.find('[data-name="percent"]').attr('readonly', true);
  81. }
  82. }
  83. else
  84. {
  85. $row.find('[data-name="id"] input').attr('name', `executionIDList[]`);
  86. }
  87. }
  88. /**
  89. * Compute work days.
  90. *
  91. * @access public
  92. * @return void
  93. */
  94. window.computeWorkDays = function(currentID)
  95. {
  96. isBatchEdit = false;
  97. if(currentID && typeof currentID != 'object')
  98. {
  99. index = currentID.replace(/[a-zA-Z]*\[|\]/g, '');
  100. if(!isNaN(index)) isBatchEdit = true;
  101. }
  102. let beginDate, endDate;
  103. if(isBatchEdit)
  104. {
  105. beginDate = $("input[name=begin\\[" + index + "\\]]").val();
  106. endDate = $("input[name=end\\[" + index + "\\]]").val();
  107. }
  108. else
  109. {
  110. beginDate = $('input[name=begin]').val();
  111. endDate = $('input[name=end]').val();
  112. }
  113. if(beginDate && endDate)
  114. {
  115. if(isBatchEdit) $("input[name=days\\[" + index + "\\]]").val(computeDaysDelta(beginDate, endDate));
  116. if(!isBatchEdit) $('[name=days]').val(computeDaysDelta(beginDate, endDate));
  117. }
  118. else if($('input[checked="true"]').val())
  119. {
  120. computeEndDate();
  121. }
  122. }
  123. /**
  124. * Compute the end date for project.
  125. *
  126. * @param int $delta
  127. * @access public
  128. * @return void
  129. */
  130. function computeEndDate()
  131. {
  132. let delta = $('input[name^=delta]:checked').val();
  133. let beginDate = $('input[name=begin]').val();
  134. if(!beginDate) return;
  135. delta = currentDelta = parseInt(delta);
  136. beginDate = convertStringToDate(beginDate);
  137. if((delta == 7 || delta == 14) && (beginDate.getDay() == 1))
  138. {
  139. delta = (weekend == 2) ? (delta - 2) : (delta - 1);
  140. }
  141. let endDate = formatDate(beginDate, delta - 1);
  142. $('input[name=end]').zui('datePicker').$.setValue(endDate);
  143. computeWorkDays();
  144. setTimeout(function(){$('[name=delta]').val(`${currentDelta}`)}, 0);
  145. }
  146. /**
  147. * 给指定日期加上具体天数,并返回格式化后的日期.
  148. *
  149. * @param string dateString
  150. * @param int days
  151. * @access public
  152. * @return date
  153. */
  154. function formatDate(dateString, days)
  155. {
  156. const date = new Date(dateString);
  157. date.setDate(date.getDate() + days);
  158. const year = date.getFullYear();
  159. const month = String(date.getMonth() + 1).padStart(2, '0');
  160. const day = String(date.getDate()).padStart(2, '0');
  161. return `${year}-${month}-${day}`;
  162. }
  163. /**
  164. * Convert a date string like 2011-11-11 to date object in js.
  165. *
  166. * @param string $date
  167. * @access public
  168. * @return date
  169. */
  170. function convertStringToDate(dateString)
  171. {
  172. dateString = dateString.split('-');
  173. return new Date(dateString[0], dateString[1] - 1, dateString[2]);
  174. }
  175. /**
  176. * Compute delta of two days.
  177. *
  178. * @param string $date1
  179. * @param string $date2
  180. * @access public
  181. * @return int
  182. */
  183. function computeDaysDelta(date1, date2)
  184. {
  185. date1 = convertStringToDate(date1);
  186. date2 = convertStringToDate(date2);
  187. delta = (date2 - date1) / (1000 * 60 * 60 * 24) + 1;
  188. let weekEnds = 0;
  189. for(i = 0; i < delta; i++)
  190. {
  191. if((weekend == 2 && date1.getDay() == 6) || date1.getDay() == 0) weekEnds ++;
  192. date1 = date1.valueOf();
  193. date1 += 1000 * 60 * 60 * 24;
  194. date1 = new Date(date1);
  195. }
  196. return delta - weekEnds;
  197. }
  198. window.changeAttribute = function(e)
  199. {
  200. const attribute = e.target.value;
  201. const currentRowID = $(e.target).closest('tr').attr('data-id');
  202. if(attribute == 'mix')
  203. {
  204. $('tr[data-parent="' + currentRowID + '"]').each(function()
  205. {
  206. $(this).find('[name^="attribute"]').zui('picker').render({disabled: false});
  207. });
  208. }
  209. else
  210. {
  211. $('tr[data-parent="' + currentRowID + '"]').each(function()
  212. {
  213. $(this).find('[name^="attribute"]').zui('picker').render({disabled: true});
  214. $(this).find('[name^="attribute"]').zui('picker').$.setValue(attribute);
  215. });
  216. }
  217. }