browse.ui.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. $(document).off('click', '.batch-btn').on('click', '.batch-btn', function()
  2. {
  3. const dtable = zui.DTable.query($(this).target);
  4. const checkedList = dtable.$.getChecks();
  5. if(!checkedList.length) return;
  6. const url = $(this).data('url');
  7. const form = new FormData();
  8. checkedList.forEach((id) => {
  9. const data = dtable.$.getRowInfo(id).data;
  10. if(data.isScene) form.append('sceneIdList[]', data.caseID);
  11. if(!data.isScene) form.append('caseIdList[]', data.caseID);
  12. });
  13. if($(this).hasClass('ajax-btn'))
  14. {
  15. if($(this).hasClass('batch-delete-btn'))
  16. {
  17. zui.Modal.confirm(confirmBatchDeleteSceneCase).then((res) => {if(res) $.ajaxSubmit({url, data:form});});
  18. }
  19. else
  20. {
  21. $.ajaxSubmit({url, data:form});
  22. }
  23. }
  24. else
  25. {
  26. postAndLoadPage(url, form);
  27. }
  28. });
  29. /**
  30. * 拖拽用例或者场景。
  31. * Drag case or scene.
  32. *
  33. * @param from 被拿起的元素
  34. * @param to 放下时的目标元素
  35. * @param type 放在目标元素的上方还是下方
  36. * @access public
  37. * @return bool
  38. */
  39. window.onSortEnd = function(from, to, type)
  40. {
  41. if(!from || !to) return false;
  42. if(!from.data.isScene && !to.data.isScene)
  43. {
  44. if(from.data.parent != to.data.parent) changeScene(from.data.id, to.data.parent);
  45. changeOrder(from.data.caseID, from.data.sort, to.data.caseID, to.data.sort, type, 'case');
  46. }
  47. else if(from.data.isScene && to.data.isScene)
  48. {
  49. if(from.data.parent == to.data.parent)
  50. {
  51. $('#dragModal').attr('data-sourceID', from.data.id);
  52. $('#dragModal').attr('data-targetID', to.data.id);
  53. $('#dragModal').attr('data-sourceSort', from.data.sort);
  54. $('#dragModal').attr('data-targetSort', to.data.sort);
  55. $('#dragModal').attr('data-type', type);
  56. zui.Modal.open({id: 'dragModal'});
  57. }
  58. else
  59. {
  60. changeScene(from.data.id, to.data.id);
  61. }
  62. }
  63. else if(!from.data.isScene && to.data.isScene)
  64. {
  65. changeScene(from.data.id, to.data.id);
  66. }
  67. return true;
  68. }
  69. function changeScene(caseID, sceneID)
  70. {
  71. const url = $.createLink('testcase', 'changeScene');
  72. const form = new FormData();
  73. form.append('sourceID', caseID);
  74. form.append('targetID', sceneID);
  75. $.ajaxSubmit({url, data:form});
  76. }
  77. function changeOrder(sourceID, sourceOrder, targetID, targetOrder, type, module)
  78. {
  79. const url = $.createLink('testcase', 'updateOrder');
  80. const form = new FormData();
  81. form.append('sourceID', sourceID);
  82. form.append('sourceOrder', sourceOrder);
  83. form.append('targetID', targetID);
  84. form.append('targetOrder', targetOrder);
  85. form.append('type', type);
  86. form.append('module', module);
  87. $.ajaxSubmit({url, data:form});
  88. }
  89. /**
  90. * 拖拽的用例或者场景是否允许放下。
  91. * Is it allowed to drop the dragged case or scene.
  92. *
  93. * @param from 被拿起的元素
  94. * @param to 放下时的目标元素
  95. * @access public
  96. * @return bool
  97. */
  98. window.canSortTo = function(from, to)
  99. {
  100. if(!from || !to) return false;
  101. if(!from.data.isScene && !to.data.isScene && from.data.parent != 0 && from.data.parent != to.data.parent) return false;
  102. if(from.data.isScene && !to.data.isScene) return false;
  103. return true;
  104. }
  105. /**
  106. * 切换显示所有用例和自动化用例。
  107. * Toggles between displaying all cases and automation cases.
  108. *
  109. * @param event $event
  110. * @access public
  111. * @return void
  112. */
  113. window.toggleOnlyAutoCase = function(event)
  114. {
  115. const onlyAutoCase = $(event.target).prop('checked') ? 1 : 0;
  116. $.cookie.set('onlyAutoCase', onlyAutoCase, {expires:config.cookieLife, path:config.webRoot});
  117. loadCurrentPage();
  118. }
  119. /**
  120. * 标题列显示额外的内容。
  121. * Display extra content in the title column.
  122. *
  123. * @param object result
  124. * @param object info
  125. * @access public
  126. * @return object
  127. */
  128. window.onRenderCell = function(result, {row, col})
  129. {
  130. if(result)
  131. {
  132. if(col.name == 'caseID' && row.data.isScene)
  133. {
  134. result.shift(); // 移除场景ID
  135. }
  136. if(col.name == 'title')
  137. {
  138. const data = row.data;
  139. const module = this.options.customData.modules[data.module];
  140. if(data.color) result[0].props.style = 'color: ' + data.color;
  141. if(data.isScene) // 场景
  142. {
  143. result.shift(); // 移除带链接的场景名称
  144. result.push({html: data.title}); // 添加不带链接的场景名称
  145. if(module) result.unshift({html: '<span class="label gray-pale rounded-full nowrap">' + module + '</span>'}); // 添加模块标签
  146. result.unshift({html: '<span class="label gray-300-outline text-gray rounded-full nowrap">' + scene + '</span>'}); // 添加场景标签
  147. if(data.hasCase == false) result.push({html: '<span class="text-gray">(' + noCase + ')</span>'}); // 添加暂无用例标签
  148. }
  149. else // 用例
  150. {
  151. if(data.auto == 'auto') result.unshift({html: '<span class="label gray-pale rounded-full nowrap">' + automated + '</span>'}); // 添加自动化标签
  152. if(module) result.unshift({html: '<span class="label gray-pale rounded-full nowrap">' + module + '</span>'}); // 添加模块标签
  153. if(row.data.fromCaseID > 0)
  154. {
  155. if(isFromDoc)
  156. {
  157. result.push({html: `[<i class='icon icon-share'></i> #${row.data.fromCaseID}]`}); // 添加来源用例
  158. }
  159. else if(canImportToLib)
  160. {
  161. let caseLink = $.createLink('testcase', 'view', `id=${row.data.fromCaseID}`);
  162. result.push({html: `[<a href=${caseLink} data-app='qa'><i class='icon icon-share'></i> #${row.data.fromCaseID}</a>]`}); // 添加来源用例链接
  163. }
  164. }
  165. }
  166. }
  167. if(col.name == 'pri' && row.data.isScene)
  168. {
  169. result.shift(); // 移除场景优先级
  170. }
  171. if(col.name == 'status' && row.data.status == 'casechanged')
  172. {
  173. result[0] = {html: '<span style="color:#ff6f42">' + caseChanged + '</span>'};
  174. }
  175. if(col.name == 'story' && row.data.story > 0)
  176. {
  177. result[0] = {html: `<a href="${$.createLink('story', 'view', `storyID=${row.data.story}`)}">${row.data.storyTitle}</a>`};
  178. }
  179. }
  180. if(row.data.lastEditedDate == '0000-00-00 00:00:00') row.data.lastEditedDate = '';
  181. if(row.data.reviewedDate == '0000-00-00') row.data.reviewedDate = '';
  182. return result;
  183. }
  184. /**
  185. * 计算表格信息的统计。
  186. * Set summary for table footer.
  187. *
  188. * @param element element
  189. * @param array checks
  190. * @access public
  191. * @return object
  192. */
  193. window.setStatistics = function(element, checks)
  194. {
  195. if(checks.length)
  196. {
  197. caseCount = 0;
  198. runCaseCount = 0;
  199. checks.forEach((id) => {
  200. const scene = element.getRowInfo(id).data;
  201. if(scene.isScene == false)
  202. {
  203. caseCount ++;
  204. if(scene.lastRunResult != '') runCaseCount ++;
  205. }
  206. });
  207. return zui.formatString(checkedSummary, {
  208. checked: caseCount,
  209. run: runCaseCount
  210. });
  211. }
  212. }
  213. /**
  214. * Get selected case id list.
  215. *
  216. * @param string selector
  217. * @access public
  218. * @return void
  219. */
  220. function getCheckedCaseIdList(selector)
  221. {
  222. let caseIdList = '';
  223. const dtable = zui.DTable.query('#' + selector);
  224. $.each(dtable.$.getChecks(), function(index, caseID)
  225. {
  226. if(index > 0) caseIdList += ',';
  227. caseIdList += caseID;
  228. });
  229. $('#caseIdList').val(caseIdList);
  230. }
  231. /**
  232. * Check ztf script run result.
  233. *
  234. * @param e
  235. * @access public
  236. * @return void
  237. */
  238. window.checkZtf = function(e)
  239. {
  240. e.preventDefault();
  241. e.stopPropagation();
  242. const url = $(this).attr('href');
  243. $.get(url, function(result)
  244. {
  245. const load = result.load;
  246. if(!load || typeof load == 'string')
  247. {
  248. zui.Modal.open({url: load, size: 'lg', replace: true});
  249. return false;
  250. }
  251. zui.Modal.confirm(load.confirm).then((res) => {
  252. if(!res) return loadModal(load.canceled, null, {size: 'lg'});
  253. $.post(load.confirmed, {}, function(result)
  254. {
  255. result = JSON.parse(result);
  256. if(result.result == 'fail') return zui.Modal.alert(result.message);
  257. loadModal(load.canceled, null, {size: 'lg'});
  258. });
  259. });
  260. }, 'json');
  261. }
  262. window.clickChangeScenen = function()
  263. {
  264. const caseID = $('#dragModal').attr('data-sourceID');
  265. const sceneID = $('#dragModal').attr('data-targetID');
  266. changeScene(caseID, sceneID);
  267. }
  268. window.clickChangeOrder = function()
  269. {
  270. const sourceID = $('#dragModal').attr('data-sourceID');
  271. const sourceOrder = $('#dragModal').attr('data-sourceSort');
  272. const targetID = $('#dragModal').attr('data-targetID');
  273. const targetOrder = $('#dragModal').attr('data-targetSort');
  274. const type = $('#dragModal').attr('data-type');
  275. changeOrder(sourceID, sourceOrder, targetID, targetOrder, type, 'scene');
  276. }
  277. $('#dragModal').on('click', '[data-dismiss=modal]', function()
  278. {
  279. loadCurrentPage({cache: false});
  280. });
  281. window.firstRendered = false;
  282. window.toggleCheckRows = function(idList)
  283. {
  284. if(!idList?.length || firstRendered) return;
  285. firstRendered = true;
  286. const dtable = zui.DTable.query($('#testcases'));
  287. dtable.$.toggleCheckRows(idList.split(','), true);
  288. }