paper.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. let configs_count = {}
  2. let config_dialog = 0
  3. define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
  4. var Controller = {
  5. index: function () {
  6. // 初始化表格参数配置
  7. Table.api.init({
  8. extend: {
  9. index_url: 'exam/paper/index' + location.search,
  10. add_url: 'exam/paper/add',
  11. edit_url: 'exam/paper/edit',
  12. del_url: 'exam/paper/del',
  13. multi_url: 'exam/paper/multi',
  14. import_url: 'exam/paper/import',
  15. table: 'exam_paper',
  16. }
  17. });
  18. var table = $("#table");
  19. //在普通搜索渲染后
  20. table.on('post-common-search.bs.table', function (event, table) {
  21. let form = $("form", table.$commonsearch);
  22. $("input[name='cate_id']", form).addClass("selectpage").data("source", "exam/cate/selectpage").data("params", {"custom[kind]": "QUESTION","isTree":true}).data("orderBy", "sort desc");
  23. // $("input[name='exam_type_id']", form).addClass("selectpage").data("source", "exam_type/index").data("orderBy", "sort desc");
  24. Form.events.cxselect(form);
  25. Form.events.selectpage(form);
  26. });
  27. //当内容渲染完成给编辑按钮添加`data-area`属性,点击列表编辑按钮时全屏
  28. table.on('post-body.bs.table', function (e, settings, json, xhr) {
  29. $(".btn-add").data("area", ["100%", "100%"]);
  30. $(".btn-editone").data("area", ["100%", "100%"]);
  31. });
  32. // 初始化表格
  33. table.bootstrapTable({
  34. url: $.fn.bootstrapTable.defaults.extend.index_url,
  35. pk: 'id',
  36. sortName: 'id',
  37. search: false,
  38. showExport: false,//隐藏导出
  39. showToggle: false,//隐藏浏览模式
  40. showColumns: false,//隐藏显示隐藏模式
  41. searchFormVisible: true,//默认显示搜索表单
  42. columns: [
  43. [
  44. {checkbox: true},
  45. {field: 'id', title: __('Id'), operate: false},
  46. {field: 'cate_id', title: __('Cate_id'), autocomplete: false, visible: false},
  47. {field: 'cate.name', title: __('Cate_id'), operate: false},
  48. {field: 'title', title: __('Title'), autocomplete: false, operate: 'LIKE'},
  49. {field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image},
  50. // {field: 'configs', title: __('Configs'), operate: 'LIKE'},
  51. {field: 'quantity', title: __('Quantity'), operate: false},
  52. {field: 'total_score', title: __('Total_score'), operate: false},
  53. {field: 'pass_score', title: __('Pass_score'), operate: false},
  54. {
  55. field: 'mode',
  56. title: __('Mode'),
  57. searchList: {"RANDOM": __('Random'), "FIX": __('Fix')},
  58. formatter: Table.api.formatter.normal
  59. },
  60. {
  61. field: 'limit_time',
  62. title: __('Limit_time'),
  63. operate: false,
  64. autocomplete: false,
  65. formatter: function (value) {
  66. return Controller.api.formatDuring(value)
  67. }
  68. },
  69. {
  70. field: 'start_time',
  71. title: __('Start_time'),
  72. operate: 'RANGE',
  73. addclass: 'datetimerange',
  74. autocomplete: false,
  75. formatter: Table.api.formatter.datetime
  76. },
  77. {
  78. field: 'end_time',
  79. title: __('End_time'),
  80. operate: 'RANGE',
  81. addclass: 'datetimerange',
  82. autocomplete: false,
  83. formatter: Table.api.formatter.datetime
  84. },
  85. // {field: 'is_only_room', title: __('Is_only_room'), searchList: {"1":__('Yes'),"0":__('No')}, formatter: Table.api.formatter.toggle},
  86. {
  87. field: 'status',
  88. title: __('Status'),
  89. searchList: {"NORMAL": __('Normal'), "HIDDEN": __('Hidden')},
  90. formatter: Table.api.formatter.status
  91. },
  92. {
  93. field: 'createtime',
  94. title: __('Createtime'),
  95. operate: 'RANGE',
  96. addclass: 'datetimerange',
  97. autocomplete: false,
  98. formatter: Table.api.formatter.datetime
  99. },
  100. // {field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
  101. {
  102. field: 'operate',
  103. title: __('Operate'),
  104. table: table,
  105. buttons:[
  106. {
  107. name:'grade',
  108. text:'成绩',
  109. title:'成绩',
  110. icon:'fa fa-exclamation-circle',
  111. classname:'btn btn-xs btn-info btn-dialog btn-grade',
  112. url:'exam/grade/index/paper_id/{ids}?dialog=1',
  113. target:'_self',
  114. },
  115. {
  116. name:'nograde',
  117. text:'缺考',
  118. title:'缺考',
  119. icon:'fa fa-exclamation-circle',
  120. classname:'btn btn-xs btn-info btn-dialog btn-nograde',
  121. url:'exam/paper/nograde/id/{ids}',
  122. target:'_self',
  123. }
  124. ],
  125. events: Table.api.events.operate,
  126. formatter: Table.api.formatter.operate
  127. }
  128. ]
  129. ],
  130. onLoadSuccess:function(){
  131. // 这里就是数据渲染结束后的回调函数
  132. $(".btn-grade").data("area", ['90%','90%']);
  133. $(".btn-nograde").data("area", ['90%','90%']);
  134. }
  135. });
  136. // 为表格绑定事件
  137. Table.api.bindevent(table);
  138. },
  139. recyclebin: function () {
  140. // 初始化表格参数配置
  141. Table.api.init({
  142. extend: {
  143. 'dragsort_url': ''
  144. }
  145. });
  146. var table = $("#table");
  147. // 初始化表格
  148. table.bootstrapTable({
  149. url: 'exam/paper/recyclebin' + location.search,
  150. pk: 'id',
  151. sortName: 'id',
  152. columns: [
  153. [
  154. {checkbox: true},
  155. {field: 'id', title: __('Id')},
  156. {field: 'title', title: __('Title'), align: 'left'},
  157. {
  158. field: 'deletetime',
  159. title: __('Deletetime'),
  160. operate: 'RANGE',
  161. addclass: 'datetimerange',
  162. formatter: Table.api.formatter.datetime
  163. },
  164. {
  165. field: 'operate',
  166. width: '130px',
  167. title: __('Operate'),
  168. table: table,
  169. events: Table.api.events.operate,
  170. buttons: [
  171. {
  172. name: 'Restore',
  173. text: __('Restore'),
  174. classname: 'btn btn-xs btn-info btn-ajax btn-restoreit',
  175. icon: 'fa fa-rotate-left',
  176. url: 'exam/paper/restore',
  177. refresh: true
  178. },
  179. {
  180. name: 'Destroy',
  181. text: __('Destroy'),
  182. classname: 'btn btn-xs btn-danger btn-ajax btn-destroyit',
  183. icon: 'fa fa-times',
  184. url: 'exam/paper/destroy',
  185. refresh: true
  186. }
  187. ],
  188. formatter: Table.api.formatter.operate
  189. }
  190. ]
  191. ]
  192. });
  193. // 为表格绑定事件
  194. Table.api.bindevent(table);
  195. },
  196. add: function () {
  197. Controller.api.bindevent()
  198. Controller.api.bindConfigs()
  199. Controller.api.bindTime()
  200. },
  201. nograde: function () {
  202. Controller.api.bindevent()
  203. },
  204. edit: function () {
  205. Controller.api.bindevent()
  206. Controller.api.bindConfigs()
  207. Controller.api.getCountScore()
  208. Controller.api.renderCountScore()
  209. Controller.api.bindTime()
  210. },
  211. api: {
  212. bindevent: function () {
  213. Form.api.bindevent($("form[role=form]"), function () {
  214. }, function () {
  215. }, function () {
  216. let mode = $('input[name="row[mode]"]:checked').val()
  217. console.log('submit mode', mode)
  218. if (mode === 'FIX') {
  219. $('#valid').click()
  220. return valid_result;
  221. } else {
  222. let configs = $('#c-configs').val()
  223. console.log('configs', configs)
  224. if (!configs) {
  225. Layer.alert('请配置试卷出题规则')
  226. return false
  227. }
  228. let quantity = $('.span_quantity').text()
  229. if (quantity !== $('#c-quantity').val()) {
  230. Layer.alert('试卷出题规则的选取题数与试卷题目数量不一致')
  231. return false
  232. }
  233. let total_score = $('.span_total_score').text()
  234. if (total_score !== $('#c-total_score').val()) {
  235. Layer.alert('试卷出题规则的总分与试卷总分不一致')
  236. return false
  237. }
  238. let limit_time_hour = $('#c-limit_time_hour').val()
  239. let limit_time_minute = $('#c-limit_time_minute').val()
  240. let limit_time = (limit_time_hour ? limit_time_hour : 0) * 3600 + (limit_time_minute ? limit_time_minute : 0) * 60
  241. $('#c-limit_time').val(limit_time)
  242. }
  243. return true
  244. });
  245. },
  246. // 选题模式设置
  247. bindConfigs: function () {
  248. // 选题模式弹窗
  249. $('.btn-configs').click(function () {
  250. let quantity = $('#c-quantity').val()
  251. let total_score = $('#c-total_score').val()
  252. if (!quantity || !total_score) {
  253. Layer.msg('请先设置题目数量和试卷总分')
  254. return false
  255. }
  256. config_dialog = Layer.open({
  257. type: 1,
  258. shade: false,
  259. title: '随机选题配置',
  260. area: ['600px', '600px'],
  261. zIndex: 1,
  262. content: $('#configsDialog'),
  263. cancel: function () {
  264. }
  265. })
  266. })
  267. // 选题库获取题数
  268. $(document).on("change", "#config-cate_id", function () {
  269. Controller.api.getCountScore()
  270. })
  271. // 选取题更改
  272. $('.input_count').change(function () {
  273. let type = $(this).data('type')
  274. let count = $(this).val()
  275. let score = $('.input_' + type + '_score').val()
  276. Controller.api.calcCountScore(type, count, score)
  277. })
  278. // 每题分数更改
  279. $('.input_score').change(function () {
  280. let type = $(this).data('type')
  281. let count = Controller.api.formatVal($('.input_' + type).val())
  282. let score = Controller.api.formatVal($(this).val())
  283. Controller.api.calcCountScore(type, count, score)
  284. })
  285. // 分难度更改
  286. $('.checkbox_difficulty').change(function () {
  287. let type = $(this).data('type')
  288. let value = $(this).is(':checked')
  289. let ul = $('.ul_' + type + '_difficulty')
  290. let input_count = Controller.api.formatVal($('.input_' + type))
  291. let input_score = Controller.api.formatVal($('.input_' + type + '_score'))
  292. let span_score = Controller.api.formatVal($('.span_' + type + '_score'))
  293. if (value) {
  294. ul.removeClass('hide').show()
  295. input_count.attr('disabled', 'disabled')
  296. input_score.attr('disabled', 'disabled')
  297. span_score.hide()
  298. // 触发计算
  299. $(ul.find('.input_count')[0]).trigger('change')
  300. } else {
  301. ul.addClass('hide').hide()
  302. input_count.removeAttr('disabled', 'disabled')
  303. input_score.removeAttr('disabled', 'disabled')
  304. span_score.show()
  305. }
  306. // $('.input_count').trigger('change')
  307. })
  308. // 保存选题配置 TODO 弃用
  309. $('#btnSaveConfig').click(function () {
  310. Controller.api.saveConfig()
  311. })
  312. },
  313. // 保存选题配置
  314. saveConfig() {
  315. let configs = {
  316. cate_ids: $('#config-cate_id').val(),
  317. all: {},
  318. judge: {
  319. difficulty: {}
  320. },
  321. single: {
  322. difficulty: {}
  323. },
  324. multi: {
  325. difficulty: {}
  326. },
  327. fill: {
  328. difficulty: {}
  329. },
  330. short: {
  331. difficulty: {}
  332. },
  333. material: {
  334. difficulty: {}
  335. },
  336. }
  337. // 总
  338. $('#divAll').find('span').each(function (index, ele) {
  339. let key = $(ele).attr('class').replace('span_', '')
  340. configs.all[key] = parseInt(Controller.api.formatVal($(ele).text()))
  341. })
  342. // 题型配置
  343. $('.input_kind_count').each(function (index, ele) {
  344. let type = $(ele).data('type')
  345. configs[type]['count'] = parseInt(Controller.api.formatVal($(ele).val()))
  346. configs[type]['score'] = parseInt(Controller.api.formatVal($(ele).next('span').find('.input_score').val()))
  347. configs[type]['total_score'] = configs[type]['count'] * configs[type]['score']
  348. configs[type]['use_difficulty'] = $(ele).parent().find('.checkbox_difficulty').is(':checked')
  349. })
  350. // 难度配置
  351. $('.ul_difficulty').find('.input_count').each(function (index, ele) {
  352. let type_key = $(ele).data('type').split('_')
  353. let type = type_key[0]
  354. let key = type_key[1]
  355. configs[type].difficulty[key] = {
  356. count: parseInt(Controller.api.formatVal($(ele).val())),
  357. score: parseInt(Controller.api.formatVal($(ele).next('.input_score').val()))
  358. }
  359. configs[type].difficulty[key]['total_score'] = configs[type].difficulty[key].count * configs[type].difficulty[key].score
  360. })
  361. console.log('configs', configs)
  362. $('#c-configs').val(JSON.stringify(configs))
  363. Layer.close(config_dialog)
  364. },
  365. // 根据题库设置题数、分数
  366. getCountScore() {
  367. let cate_ids = $('#config-cate_id').val()
  368. if (cate_ids) {
  369. configs_count = {}
  370. Fast.api.ajax({
  371. url: 'exam/question/getCount',
  372. type: 'post',
  373. data: {cate_ids: cate_ids}
  374. }, function (data, ret) {
  375. configs_count = data
  376. if (!configs_count) {
  377. return false
  378. }
  379. let quantity = $('#c-quantity').val()
  380. let total_score = $('#c-total_score').val()
  381. let sing_score = parseInt(total_score / quantity)
  382. for (let key of Object.keys(configs_count)) {
  383. let value = configs_count[key]
  384. $('.span_' + key + '_total').text(value)
  385. $('.input_' + key).attr('max', value)
  386. $('.input_' + key + '_score').attr('max', sing_score)//.val(sing_score)
  387. }
  388. return false
  389. });
  390. }
  391. },
  392. calcCountScore(type, count, score) {
  393. // 计算题型总分
  394. $('.span_' + type + '_total_score').text(count * score)
  395. // 计算分难度的总分
  396. if (type.indexOf('_') > 0) {
  397. let parent_type = type.split('_')[0]
  398. let ul = $('.ul_' + parent_type + '_difficulty')
  399. let parent_count_input = $('.input_' + parent_type)
  400. let parent_score_span = $('.span_' + parent_type + '_total_score')
  401. let sum_count = 0
  402. let sum_score = 0
  403. ul.find('.input_count').each(function (index, ele) {
  404. let single_score = $(ele).next('input').val()
  405. sum_count += parseInt($(ele).val())
  406. sum_score += parseInt($(ele).val()) * single_score
  407. })
  408. parent_count_input.val(sum_count)
  409. parent_score_span.text(sum_score)
  410. }
  411. // 总题数
  412. let kind_total_count = 0
  413. $('.input_kind_count').each(function (index, ele) {
  414. kind_total_count += parseInt($(ele).val())
  415. })
  416. $('.span_quantity').text(kind_total_count)
  417. // 计算总分
  418. let kind_total_score = 0
  419. $('.span_kind_total_score').each(function (index, ele) {
  420. kind_total_score += parseInt($(ele).text())
  421. })
  422. $('.span_total_score').text(kind_total_score)
  423. // 保存配置
  424. Controller.api.saveConfig()
  425. },
  426. // 根据配置设置题数渲染数据
  427. renderCountScore() {
  428. // 考试时间渲染
  429. const limit_time = $('#c-limit_time').val() ? $('#c-limit_time').val() : 0
  430. if (limit_time) {
  431. let hour = Math.floor(limit_time / 3600)
  432. let minute = Math.floor(limit_time / 60) % 60
  433. $('#c-limit_time_hour').val(hour)
  434. $('#c-limit_time_minute').val(minute)
  435. }
  436. let configs_val = $('#c-configs').val()
  437. console.log('configs_val', configs_val)
  438. const config_json = configs_val && typeof configs_val === 'string' ? JSON.parse(configs_val) : {}
  439. if (config_json && config_json.cate_ids) {
  440. for (const key in config_json) {
  441. if (key === 'all') {
  442. $('.span_quantity').text(config_json.all.quantity)
  443. $('.span_total_score').text(config_json.all.total_score)
  444. } else {
  445. const kind_config = config_json[key]
  446. $('.input_count[data-type="' + key + '"]').val(kind_config['count'])
  447. $('.input_score[data-type="' + key + '"]').val(kind_config['score'])
  448. $('.span_' + key + '_total_score').text(kind_config['total_score'])
  449. if (kind_config['use_difficulty'] === true) {
  450. $('.checkbox_' + key).click()
  451. const difficulty_config = kind_config['difficulty']
  452. for (const k in difficulty_config) {
  453. let difficulty_count = difficulty_config[k].count ? difficulty_config[k].count : 0
  454. let difficulty_score = difficulty_config[k].score ? difficulty_config[k].score : 0
  455. let difficulty_total_score = difficulty_count * difficulty_score
  456. $('.input_' + key + '_' + k).val(difficulty_count)
  457. $('.input_' + key + '_' + k + '_score').val(difficulty_score)
  458. $('.span_' + key + '_' + k + '_total_score').text(difficulty_total_score)
  459. }
  460. }
  461. }
  462. }
  463. // 触发计算
  464. // $($('.ul_judge_difficulty').find('.input_count')[0]).trigger('change')
  465. }
  466. },
  467. // 限定时间事件,59分转小时
  468. bindTime() {
  469. $('#c-limit_time_minute').change(function (ele) {
  470. let minute = $(this).val()
  471. if (minute >= 60) {
  472. $('#c-limit_time_minute').val(0)
  473. let hour_ctrl = $('#c-limit_time_hour')
  474. hour_ctrl.val(parseInt(hour_ctrl.val()) + 1)
  475. }
  476. })
  477. },
  478. // 绑定固定选题配置按钮事件
  479. bindFixButton() {
  480. $('.btn-fix-configs').click(function () {
  481. Fast.api.open('exam/question/select', '选择试题', {
  482. area: ['90%', '90%'],
  483. callback: function (data) {
  484. if (!data) {
  485. return
  486. }
  487. }
  488. })
  489. });
  490. },
  491. // 秒数转时分秒格式
  492. formatDuring (second) {
  493. var hours = parseInt((second % (60 * 60 * 24)) / (60 * 60));
  494. var minutes = parseInt((second % (60 * 60)) / (60));
  495. var seconds = (second % (60));
  496. return hours + "时 " + minutes + "分 " + seconds + "秒";
  497. },
  498. // 获取数字值
  499. formatVal (val) {
  500. return isNaN(val) ? 0 : val
  501. },
  502. }
  503. };
  504. return Controller;
  505. });