task_detail.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. {{include "com/inc.html"}}
  2. <!-- Main Header -->
  3. {{include "com/header.html"}}
  4. <!-- Left side column. 权限菜单 -->
  5. {{include "com/menu.html"}}
  6. <div class="content-wrapper">
  7. <section class="content-header">
  8. <h1><small></small></h1>
  9. <ol class="breadcrumb">
  10. {{if .T.pid}}
  11. <li><a href="/front/project"><i class="fa fa-dashboard"></i> 项目列表</a></li>
  12. <li><a href="/front/project/task/list?pid={{ .T.pid }}"><i class="fa fa-dashboard"></i> 项目分发</a></li>
  13. <li><a href="#"><i class="fa fa-dashboard"></i> 任务分发</a></li>
  14. {{else if .T.jy}}
  15. <li><a href="/front/group/admin/task/list"><i class="fa fa-dashboard"></i> 剑鱼任务列表</a></li>
  16. <li><a href="#"><i class="fa fa-dashboard"></i> 用户任务分发</a></li>
  17. {{else if .T.group}}
  18. <li><a href="/front/group/task/list"><i class="fa fa-dashboard"></i> 用户组任务列表</a></li>
  19. <li><a href="#"><i class="fa fa-dashboard"></i> 用户任务分发</a></li>
  20. {{end}}
  21. </ol>
  22. </section>
  23. <!-- Main content -->
  24. <section class="content">
  25. <div class="row">
  26. <div class="col-xs-12">
  27. <div class="box">
  28. <div class="box-body">
  29. <div class="box-body margin">
  30. <h4><i class="glyphicon glyphicon-exclamation-sign" style="margin-right: 6px"></i>数据情况</h4>
  31. <div class="form-group" style="margin-left: 10px;margin-top: 10px">
  32. <div class="col-xs-5" style="width: auto">
  33. <label class="form-inline">数据总量:
  34. <input type="text" class="form-control" style="width: 80px" readonly value="{{.T.allNum}}"></label>
  35. <label class="form-inline" style="margin-left: 5px">已分发:
  36. <input type="text" class="form-control" style="width: 80px" readonly value="{{.T.isGiveNum}}"></label>
  37. <label class="form-inline" style="margin-left: 5px">待分发:
  38. <input type="text" class="form-control" style="width: 80px" readonly value="{{.T.isNotGiveNum}}"></label>
  39. <label class="form-inline" style="margin-left: 5px">已标注:
  40. <input type="text" class="form-control" style="width: 80px" readonly value="{{.T.isTagNum}}"></label>
  41. <label class="form-inline" style="margin-left: 5px">未标注:
  42. <input type="text" class="form-control" style="width: 80px" readonly value="{{.T.isNotTagNum}}"></label>
  43. <label class="form-inline">操作:
  44. <input type="button" class="btn btn-sm btn-primary" onclick="dispatchTask('0')" value="分发">
  45. <!-- <a type="button" class="btn btn-sm btn-primary">质检</a>-->
  46. <!-- <input type="button" class="btn btn-sm btn-primary" value="质检结果">-->
  47. </label>
  48. </div>
  49. <div class="col-xs-4 form-group">
  50. </div>
  51. </div>
  52. </div>
  53. <div id="status-div" class="col-xs-1" style="width: auto;float: right">
  54. <label for="statusSelect">状态:
  55. <select class="form-control selectpicker" id="statusSelect">
  56. <option value="-1">全部</option>
  57. <option value="未开始">未开始</option>
  58. <option value="进行中">进行中</option>
  59. <option value="已完成">已完成</option>
  60. <option value="已关闭">已关闭</option>
  61. </select></label>
  62. </div>
  63. <div class="box-body margin">
  64. <h4><i class="glyphicon glyphicon-tasks" style="margin-right: 6px"></i>数据清洗任务列表</h4>
  65. <table id="dataTable" class="table table-bordered table-hover">
  66. <thead>
  67. <tr>
  68. <th></th>
  69. <th>用户账号</th>
  70. <th>项目名称</th>
  71. <th>数据量</th>
  72. <th>任务状态</th>
  73. <th>完成进度</th>
  74. <th>开始时间</th>
  75. <th>完成时间</th>
  76. <th>操作</th>
  77. </tr>
  78. </thead>
  79. </table>
  80. </div>
  81. </div>
  82. <!-- /.box-body -->
  83. </div>
  84. <!-- /.box -->
  85. </div>
  86. </div>
  87. </section>
  88. </div>
  89. <div class="modal fade" id="modal-create-task" tabindex="-1" role="dialog" aria-hidden="true">
  90. <div class="modal-dialog" style="width: 60%">
  91. <div class="modal-content">
  92. <div class="modal-header">
  93. <div class="modal-header">
  94. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
  95. <div class="edit-info">
  96. <span class="glyphicon glyphicon-tasks" aria-hidden="true"></span>
  97. <span class="h3">新建任务</span>
  98. </div>
  99. <div class="edit-form">
  100. <form id="modal-form-task" class="form-horizontal">
  101. <div class="modal-body modal-task">
  102. <div class="form-group margin-bottom" style="margin-left: 15px">
  103. <label class="control-label form-inline h4">待分发数据总量(条):
  104. <span id="modal-num">{{.T.isNotGiveNum}}</span>
  105. </label>
  106. </div>
  107. <hr>
  108. <div class="form-group" style="margin-left: 15px">
  109. <label class="radio-inline">
  110. <input type="radio" name="stype" value="man" checked>手动分发
  111. </label>
  112. <label class="radio-inline">
  113. <input type="radio" name="stype" value="auto">自动分发
  114. </label>
  115. </div>
  116. <div id="task-man">
  117. <div id="TaskDiv">
  118. <div id="itemDiv" class="form-group" style="margin-left: 10px;display: none">
  119. <select id="group-select-clone"></select>
  120. <label class="control-label form-inline" style="margin-left: 20px">数据量(条):
  121. <input type="number" class="form-control"></label>
  122. </div>
  123. <div class="form-group group-item" style="margin-left: 10px;">
  124. <select class="selectpicker" id="group-select"></select>
  125. <label class="control-label form-inline" style="margin-left: 20px">数据量(条):
  126. <input type="number" class="form-control"></label>
  127. <input type="button" class="btn btn-info btn-sm" onclick="addTaskSelect()" value="新增">
  128. </div>
  129. </div>
  130. </div>
  131. <div id="task-auto" style="display: none">
  132. <label class="control-label form-inline" style="margin-left: 20px">用户数量:
  133. <input type="number" class="form-control" id="modal-user-num"></label>
  134. <label class="control-label form-inline" style="margin-left: 20px">分配总量(条):
  135. <input type="number" class="form-control" id="modal-data-num"></label>
  136. </div>
  137. </div>
  138. </form>
  139. </div>
  140. </div>
  141. </div>
  142. <div class="modal-footer">
  143. <input type="button" onclick="saveTask()" class="btn btn-primary" value="保存">
  144. <input type="button" onclick="cancelModel()" class="btn btn-default" value="取消">
  145. </div>
  146. </div>
  147. </div><!-- /.modal -->
  148. </div>
  149. {{include "com/footer.html"}}
  150. <script>
  151. if ({{ .T.pid }}) {
  152. menuActive("project");
  153. }else if ({{ .T.jy }}) {
  154. menuActive("/front/group/admin/task/list");
  155. }else {
  156. menuActive("group/task/list");
  157. }
  158. let gid = {{ .T.gid }}
  159. let grouptaskid = {{ .T.grouptaskid }}
  160. let isNotGiveNum = {{ .T.isNotGiveNum }}
  161. let userList = []
  162. let stype = "man"
  163. $(function () {
  164. ttable = $('#dataTable').dataTable({
  165. "paging": true,
  166. "lengthChange": false,
  167. "searching": true,
  168. "ordering": false,
  169. "info": true,
  170. "autoWidth": false,
  171. "language": {
  172. "url": "/dist/js/dataTables.chinese.lang"
  173. },
  174. "fnDrawCallback": function () {
  175. $("ul.pagination").prepend("&nbsp;&nbsp;&nbsp;转到第 <input type='text' id='changePage' style='width:20px;'> 页 <a type='text' href='javascript:void(0);' id='dataTable-btn' style='text-align:center'>GO</a>");
  176. $('#dataTable-btn').click(function (e) {
  177. var redirectpage = 0
  178. if ($("#changePage").val() && $("#changePage").val() > 0) {
  179. var redirectpage = $("#changePage").val() - 1;
  180. }
  181. ttable.api().page(redirectpage).draw(false);
  182. });
  183. this.api().column(0).nodes().each(function (cell, i) {
  184. cell.innerHTML = i + 1;
  185. });
  186. },
  187. "columns": [
  188. {"data": null, width: "1%"},
  189. {"data": "s_login", width: "5%"},
  190. {"data": "s_projectname", width: "4%"},
  191. {"data": "i_givenum", width: "4%"},
  192. {"data": "s_status", width: "4%"},
  193. {"data": "s_progress", width: "4%"},
  194. {"data": "i_starttime", width: "4%", render: function (val) {
  195. if (val === undefined) {
  196. return "未开始"
  197. }else {
  198. var dt = new Date()
  199. dt.setTime(parseInt(val) * 1000);
  200. return dt.format("yyyy-MM-dd hh:mm:ss")
  201. }
  202. }},
  203. {"data": "i_completetime", width: "4%", render: function (val) {
  204. if (val === undefined) {
  205. return "未完成"
  206. }else {
  207. var dt = new Date()
  208. dt.setTime(parseInt(val) * 1000);
  209. return dt.format("yyyy-MM-dd hh:mm:ss")
  210. }
  211. }},
  212. {
  213. "data": "_id", width: "11%", render: function (val, a, row, pos) {
  214. tmp = '<div>' +
  215. '<a class="btn btn-sm btn-primary" onclick="retrieveTask(\''+val+'\',\''+row.appid+'\',\''+row.s_status+'\')">收回</a>&nbsp;&nbsp;' +
  216. '<a class="btn btn-sm btn-primary" onclick="checkMethod(\'' + row.s_projectid + '\',\'' + val + '\',\'' + row.appid + '\')">质检</a>&nbsp;&nbsp;' +
  217. '<a class="btn btn-sm btn-primary" onclick="closeTask(\'' + val + '\',\'' + row.s_status + '\',\''+row.appid+'\')">打回</a>&nbsp;&nbsp;' +
  218. '</div>';
  219. return tmp
  220. }
  221. }
  222. ],
  223. "initComplete": function () {
  224. $("#dataTable_filter").append($('#status-div'))
  225. },
  226. "fnServerParams": function (e) {
  227. e.s_status = $("#statusSelect option:selected").val()
  228. }
  229. });
  230. $.ajax({
  231. url: "/front/group/user/task/list",
  232. type: "POST",
  233. data: {"grouptaskid": grouptaskid, "s_status": "-1", "s_login": "-1"},
  234. success: function (r) {
  235. if (r.data.length > 0) {
  236. ttable.fnClearTable();
  237. ttable.fnAddData(r.data);
  238. }
  239. }
  240. })
  241. $.ajax({
  242. url: "/front/group/user/list",
  243. type: "POST",
  244. data: {"gid": gid},
  245. success: function (r) {
  246. if (r.rep) {
  247. userList = r.data
  248. }
  249. }
  250. })
  251. $('input[type=radio][name=stype]').change(function () {
  252. if (this.value === 'man') {
  253. stype = "man"
  254. $("#task-man").attr("style", "display:block;")
  255. $("#task-auto").attr("style", "display:none;")
  256. } else if (this.value === 'auto') {
  257. stype = "auto"
  258. $("#task-man").attr("style", "display:none;")
  259. $("#task-auto").attr("style", "display:block;")
  260. }
  261. });
  262. $('#statusSelect').on('changed.bs.select', function () {
  263. $.ajax({
  264. url: "/front/group/user/task/list",
  265. type: "POST",
  266. data: {"grouptaskid": grouptaskid, "s_status": $(this).val(), "s_login": "-1"},
  267. success: function (r) {
  268. if (r.data.length > 0) {
  269. ttable.fnClearTable();
  270. ttable.fnAddData(r.data);
  271. }else {
  272. ttable.fnClearTable();
  273. }
  274. }
  275. })
  276. })
  277. });
  278. function cancelModel() {
  279. $("#task-man").attr("style", "display:block;")
  280. $("#task-auto").attr("style", "display:none;")
  281. $('#TaskDiv .group-item.clone-template').remove()
  282. $("#modal-create-task").modal('hide')
  283. document.getElementById("modal-form-task").reset();
  284. }
  285. function dispatchTask() {
  286. if (isNotGiveNum === 0) {
  287. showTip("没有可分发的数据")
  288. return
  289. }
  290. $('#modal-create-task').modal('show')
  291. let text = document.getElementById("modal-user-num");
  292. text.setAttribute("max", userList.length.toString())
  293. text.onkeyup = function(){
  294. this.value=this.value.replace(/\D/g,'');
  295. if(text.value > userList.length){
  296. text.value = userList.length;
  297. }
  298. }
  299. let num = document.getElementById("modal-data-num");
  300. num.setAttribute("max", isNotGiveNum)
  301. num.onkeyup = function(){
  302. this.value=this.value.replace(/\D/g,'');
  303. if(num.value > isNotGiveNum){
  304. num.value = isNotGiveNum;
  305. }
  306. }
  307. if ($('#group-select option').length === 0) {
  308. for (var i in userList) {
  309. var opt = document.createElement('option');
  310. opt.innerText = userList[i]["s_login"];
  311. opt.value = userList[i]["_id"];
  312. $('#group-select')[0].appendChild(opt)
  313. }
  314. $("#group-select").selectpicker("refresh");
  315. }
  316. }
  317. function addTaskSelect() {
  318. let tNode = $('#itemDiv').clone().addClass('group-item').addClass('clone-template').show()
  319. let st = $(tNode).find('select')
  320. $(st).addClass('selectpicker')
  321. for (var i in userList) {
  322. var opt = document.createElement('option');
  323. opt.innerText = userList[i]["s_login"];
  324. opt.value = userList[i]["_id"];
  325. $(st)[0].appendChild(opt)
  326. }
  327. $(st).selectpicker("refresh");
  328. $('#TaskDiv').append($(tNode))
  329. }
  330. function saveTask() {
  331. let arr = []
  332. let valNum = 0
  333. let num = parseInt($('#modal-num').html())
  334. if (stype === "man") {
  335. $('.group-item').each(function () {
  336. var selectId = $(this).find("select option:checked").val()
  337. var inputVal = $(this).find("input").val()
  338. valNum += parseInt(inputVal)
  339. if (selectId === undefined) {
  340. showTip("未选择分发用户")
  341. return
  342. }
  343. if (inputVal === ""|| valNum > num) {
  344. showTip("分发数量有问题")
  345. return
  346. }
  347. let tmp = {}
  348. for (let v in userList) {
  349. if (userList[v]["_id"] === selectId) {
  350. tmp["s_userid"] = selectId
  351. tmp["s_login"] = userList[v]["s_login"]
  352. tmp["s_name"] = userList[v]["s_name"]
  353. tmp["i_givenum"] = inputVal
  354. break
  355. }
  356. }
  357. arr.push(tmp)
  358. })
  359. }else if (stype === "auto") {
  360. let userNum = parseInt($('#modal-user-num').val())
  361. let dataNum = parseInt($('#modal-data-num').val())
  362. if (userNum > 0 && dataNum > 0 && dataNum >= userNum) {
  363. if (dataNum%userNum === 0) {
  364. // 整除
  365. let avg = dataNum/userNum
  366. for (let i = 0; i < userNum; i++) {
  367. let tmp = {}
  368. tmp["s_userid"] = userList[i]["_id"]
  369. tmp["s_login"] = userList[i]["s_login"]
  370. tmp["s_name"] = userList[i]["s_name"]
  371. tmp["i_givenum"] = avg
  372. arr.push(tmp)
  373. }
  374. }else {
  375. // 没有整除
  376. let quo = Math.floor(dataNum/userNum) // 商数
  377. let rem = dataNum%userNum // 余数
  378. for (let i = 0; i < userNum; i++) {
  379. let tmp = {}
  380. tmp["s_userid"] = userList[i]["_id"]
  381. tmp["s_login"] = userList[i]["s_login"]
  382. tmp["s_name"] = userList[i]["s_name"]
  383. if (i === (userNum-1)) {
  384. tmp["i_givenum"] = quo + rem
  385. }else {
  386. tmp["i_givenum"] = quo
  387. }
  388. arr.push(tmp)
  389. }
  390. }
  391. }else {
  392. showTip("请设置有效数字")
  393. return;
  394. }
  395. }
  396. if (arr.length > 0) {
  397. $.ajax({
  398. url: "/front/user/task/save",
  399. type: "POST",
  400. data: {"grouptaskid": grouptaskid, "usernums": JSON.stringify(arr)},
  401. success: function (r) {
  402. if (r.success) {
  403. location.reload()
  404. }else {
  405. showTip(r.msg)
  406. }
  407. }
  408. })
  409. }
  410. }
  411. // 收回
  412. function retrieveTask(id, appid, status) {
  413. if (status === "未开始" || status === "进行中") {
  414. showConfirm("确认要收回当前任务吗?", function () {
  415. $.ajax({
  416. url: "/front/user/task/retrieve",
  417. type: 'POST',
  418. data: {"appid": appid, "taskid": id},
  419. success: function (r) {
  420. if (r.success) {
  421. let msg = r.msg+"<br>"+"共收回"+r.count+"数据。"
  422. showTip(msg, 1500);
  423. location.reload()
  424. } else {
  425. showTip(r.msg);
  426. }
  427. }
  428. })
  429. })
  430. }else {
  431. showTip("操作不允许")
  432. }
  433. }
  434. function closeTask(id, status, appid) {
  435. if (status === "已完成" || status === "进行中") {
  436. showConfirm("确认要打回当前任务吗?", function () {
  437. $.ajax({
  438. url: "/front/user/task/close",
  439. type: 'POST',
  440. data: {"appid": appid, "taskid": id},
  441. success: function (r) {
  442. if (r.success) {
  443. location.reload()
  444. } else {
  445. showTip(r.msg);
  446. }
  447. }
  448. })
  449. })
  450. }else {
  451. showTip("操作不允许")
  452. }
  453. }
  454. function checkMethod(pid, tid, appid) {
  455. window.location.href = "/front/user/check/data?pid=" + pid + "&tid=" + tid + "&appid=" + appid
  456. }
  457. </script>