advance_audit.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author lanjianrong
  6. * @date 2020/8/7
  7. * @version
  8. */
  9. $(document).ready(function () {
  10. autoFlashHeight()
  11. let oldVal = null
  12. let timer = null
  13. handleFileList(fileList)
  14. // 控制上报弹窗的文案
  15. function checkModal(isHide) {
  16. if (isHide) {
  17. $('#tm-fail').show()
  18. $('#tm-success').hide()
  19. $('#tm-submit').hide()
  20. } else {
  21. $('#tm-fail').hide()
  22. $('#tm-success').show()
  23. $('#tm-submit').show()
  24. }
  25. }
  26. // 审批人分组选择
  27. $('#account_group').change(function () {
  28. let account_html = '<option value="0">选择审批人</option>'
  29. for (const account of accountList) {
  30. if ((parseInt($(this).val()) === 0 || parseInt($(this).val()) === account.account_group) && account.id !== parseInt(userID)) {
  31. const role = account.role !== '' ? '(' + account.role + ')' : ''
  32. const company = account.company !== '' ? ' -' + account.company : ''
  33. account_html += '<option value="' + account.id + '">' + account.name + role + company + '</option>'
  34. }
  35. }
  36. $('#account_list').html(account_html)
  37. });
  38. // 添加到审批流程中
  39. $('body').on('change', '#account_list', function () {
  40. let id = $(this).val()
  41. id = parseInt(id)
  42. if (id !== 0) {
  43. postData(preUrl + '/audit/add', { auditorId: id }, (data) => {
  44. // <p class="m-0 ml-2"><small class="text-muted">中交第一公路工程局有限公司国道311线满别公路施工一分部</small></p>
  45. const html = []
  46. html.push('<li class="list-group-item" auditorId="'+ data.audit_id +'"><a href="javascript: void(0)" class="text-danger pull-right">移除</a>')
  47. html.push('<span>')
  48. html.push(data.order + ' ')
  49. html.push(data.name + ' ')
  50. html.push('</span>')
  51. html.push('<small class="text-muted">')
  52. html.push(data.role)
  53. html.push('</small>')
  54. html.push(`<p class="m-0 ml-2"><small class="text-muted">${data.company}</small></p></li>`)
  55. $('#auditors').append(html.join(''))
  56. if ($('.fa-stop-circle').length) {
  57. $('.fa-stop-circle').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down')
  58. }
  59. const auditorsHTML = `<li class="list-group-item" data-auditorId='${data.audit_id}'><i class="fa fa fa-stop-circle" ></i> ${data.name} <small class="text-muted">${data.role}</small></li>`
  60. $('#auditors2').append(auditorsHTML)
  61. if ($('#auditors')[0].children.length > 0) {
  62. checkModal(false)
  63. }
  64. });
  65. }
  66. });
  67. // 删除审批人
  68. $('body').on('click', '#auditors li>a', function () {
  69. const li = $(this).parent()
  70. const data = {
  71. auditorId: parseInt(li.attr('auditorId')),
  72. };
  73. postData(preUrl + '/audit/delete', data, (result) => {
  74. li.remove();
  75. for (const rst of result) {
  76. const aLi = $('li[auditorId=' + rst.audit_id + ']');
  77. $('span', aLi).text(rst.order + ' ' + rst.name + ' ')
  78. }
  79. // 删除左边审核人
  80. $(`#auditors2 li[data-auditorId='${data.auditorId}']`).remove()
  81. })
  82. })
  83. $('#au-btn').on('click','a', function() {
  84. const content = $(this).data('target')
  85. switch (content) {
  86. case '#sub-sp':
  87. if ($('#auditors')[0].children.length) {
  88. checkModal(false)
  89. }
  90. break;
  91. default:
  92. break;
  93. }
  94. })
  95. // 上报审批
  96. $('#tm-submit').click(function() {
  97. const pay_ratio = parseFloat($(`.pay-input[data-type=0]`).val())
  98. const cur_amount = parseFloat($(`.pay-input[data-type=1]`).val())
  99. if (!pay_ratio || !cur_amount) {
  100. return toastr.error('请填写本期金额!')
  101. }
  102. const prev_amount = prevAdvance && prevAdvance.prev_total_amount || 0
  103. const prev_total_amount = ZhCalc.add(cur_amount, prev_amount)
  104. const remark = filterText($('#ad-remark').val())
  105. const data = {pay_ratio, cur_amount, prev_amount, prev_total_amount, remark, status: auditConst.status.checking}
  106. postData(preUrl + '/audit/start', data, (data) => {
  107. window.location.reload()
  108. }, () => {
  109. window.location.reload()
  110. })
  111. })
  112. // 重新上报
  113. $('#sp-list2-btn').click(() => {
  114. $('#tm-submit').trigger('click')
  115. })
  116. // 转化成两位小数
  117. function fixedToSub(s, decimal = 2) {
  118. return parseFloat(parseFloat(s).toFixed(decimal))
  119. }
  120. // 自动转换支付比例和本期金额
  121. $('.pay-input').on('input propertychange', function(e) {
  122. let val = parseFloat(e.target.value)
  123. const p_amount = prevAdvance && prevAdvance.prev_total_amount || 0 // 截止本期金额
  124. const re_amount = ZhCalc.sub(advancePayTotal, p_amount) // 剩余未付款的总额
  125. const min = parseFloat($(this).attr('min'))
  126. const max = parseFloat($(this).attr('max'))
  127. const type = parseInt($(this).data('type'))
  128. let pay_ratio = null
  129. let cur_amount = null
  130. if (val < min) {
  131. // 限制最小值为min
  132. $(this).val(min)
  133. val = min
  134. }
  135. if (max && val > max) {
  136. // 限制最大值为max
  137. $(this).val(max)
  138. val = max
  139. }
  140. // 本期金额转化
  141. if (type === 1) {
  142. if (val > re_amount) {
  143. // 限制不能超过最大值
  144. val = re_amount
  145. }
  146. $(this).val(fixedToSub(val, decimal)) // 重新赋值限制只有两位小数
  147. const pay_a_input = $(`.pay-input[data-type=${reverse(type)}]`)
  148. pay_ratio = parseFloat(ZhCalc.mul(ZhCalc.div(val, advancePayTotal), 100).toFixed(2))
  149. cur_amount = val
  150. pay_a_input.val(pay_ratio)
  151. // 截止本期金额文案更新
  152. $('#p_total2').text(formatMoney(ZhCalc.add(val, p_amount), ',', decimal))
  153. } else {
  154. // 支付比例转化
  155. $(this).val(fixedToSub(val)) // 重新赋值限制只有两位小数
  156. const cur_m_input = $(`.pay-input[data-type=${reverse(type)}]`)
  157. cur_amount = ZhCalc.mul(advancePayTotal, ZhCalc.div(val, 100))
  158. pay_ratio = val
  159. cur_m_input.val(cur_amount.toFixed(decimal))
  160. // 截止本期金额文案更新
  161. $('#p_total2').text(formatMoney(ZhCalc.add(cur_amount, p_amount), ',', decimal))
  162. }
  163. const data = {
  164. pay_ratio,
  165. cur_amount,
  166. }
  167. oldVal = {
  168. cur_amount: parseFloat($(`.pay-input[data-type=${1}]`).val()),
  169. remark: filterText($('#ad-remark').val())
  170. }
  171. clearTimeout(timer)
  172. timer = setTimeout(() => {
  173. if (checkInput()) {
  174. update(data)
  175. clearTimeout(timer)
  176. }
  177. }, 2000);
  178. })
  179. function checkInput() {
  180. const newVal = {
  181. cur_amount: parseFloat($(`.pay-input[data-type=${1}]`).val()),
  182. remark: filterText($('#ad-remark').val())
  183. }
  184. return newVal.cur_amount === oldVal.cur_amount && newVal.remark === oldVal.remark
  185. }
  186. $('#ad-remark').on('input propertychange', function(e) {
  187. const remark = filterText(e.target.value);
  188. oldVal = {
  189. pay_ratio: parseFloat($(`.pay-input[data-type=${0}]`).val()),
  190. cur_amount: parseFloat($(`.pay-input[data-type=${1}]`).val()),
  191. remark
  192. }
  193. const data = oldVal
  194. clearTimeout(timer)
  195. timer = setTimeout(() => {
  196. if (checkInput()) {
  197. update(data)
  198. clearTimeout(timer)
  199. }
  200. }, 2000);
  201. })
  202. function filterText(text) {
  203. if (!text) return null
  204. return text.replace(/(\r\n)|(\n)/g, '<br/>').replace(/\s/g, ' ')
  205. }
  206. function update(data) {
  207. postData(preUrl + '/update', data)
  208. }
  209. // $('#file-modal-target').click(function () {
  210. // $('#file-modal').trigger('click')
  211. // })
  212. $('#file-ok').click(function () {
  213. const files = Array.from($('#file-modal')[0].files)
  214. const valiData = files.map(v => {
  215. const ext = v.name.substring(v.name.lastIndexOf('.') + 1)
  216. return {
  217. size: v.size,
  218. ext
  219. }
  220. })
  221. if (validateFiles(valiData)) {
  222. if (files.length) {
  223. const formData = new FormData()
  224. files.forEach(file => {
  225. formData.append('name', file.name)
  226. formData.append('size', file.size)
  227. formData.append('file', file)
  228. })
  229. postDataWithFile(preUrl + '/file/upload', formData, function (result) {
  230. handleFileList(result)
  231. $('#file-cancel').click()
  232. });
  233. }
  234. }
  235. })
  236. function handleFileList(files = []) {
  237. $('#file-content').empty()
  238. const { uncheck, checkNo } = auditConst.status
  239. const newFiles = files.map(file => {
  240. let showDel = false;
  241. if (file.uid === cur_uid) {
  242. if (!curAuditor) {
  243. advance.status === uncheck && cur_uid === advance.uid && (showDel = true)
  244. advance.status === checkNo && cur_uid === advance.uid && (showDel = true)
  245. } else {
  246. curAuditor.audit_id === cur_uid && (showDel = true)
  247. }
  248. }
  249. return {...file, showDel}
  250. })
  251. let html = `<tr><td colspan="3"><a href="#addfujian" data-toggle="modal" class="btn btn-sm btn-light text-primary" data-placement="bottom" title="" data-original-title="添加清单"><i class="fa fa-cloud-upload" aria-hidden="true"></i> 上传附件</a></td></tr>`
  252. newFiles.forEach((file, idx) => {
  253. if (file.showDel) {
  254. html += `<tr><td width="70">${idx + 1}</td><td><a href="/${file.filepath}" target="_blank">${file.filename}</a></td><td width="90"><a href="javascript: void(0);" class="text-danger file-del" data-id="${file.id}">移除</a></td></tr>`
  255. } else {
  256. html += `<tr><td width="70">${idx + 1}</td><td><a href="/${file.filepath}" target="_blank">${file.filename}</a></td><td width="90"></td></tr>`
  257. }
  258. })
  259. $('#file-content').append(html)
  260. }
  261. $('#file-content').on('click', 'a', function () {
  262. if ($(this).hasClass('file-del')) {
  263. const id = $(this).data('id')
  264. postData(preUrl + '/file/del', {id}, (result) => {
  265. handleFileList(result)
  266. })
  267. }
  268. })
  269. })
  270. /**
  271. * 校验文件大小、格式
  272. * @param {Array} files 文件数组
  273. */
  274. function validateFiles(files) {
  275. if (files.length > 10) {
  276. toastr.error('至多同时上传10个文件');
  277. return false
  278. }
  279. return files.every(file => {
  280. if (file.size > 1024 * 1024 * 30) {
  281. toastr.error('文件大小限制为30MB');
  282. return false
  283. }
  284. if (whiteList.indexOf('.' + file.ext) === -1) {
  285. toastr.error('请上传正确的格式文件');
  286. return false
  287. }
  288. return true
  289. })
  290. }
  291. function reverse(num){
  292. return 1^num
  293. }
  294. function formatMoney(s, dot = ',', decimal = 2) {
  295. if (!s) return '0.00';
  296. s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(decimal) + '';
  297. if (!decimal) {
  298. s += '.';
  299. }
  300. let l = s.split('.')[0].split('').reverse(),
  301. r = s.split('.')[1].slice(0, decimal);
  302. let t = '';
  303. for (let i = 0; i < l.length; i++) {
  304. t += l[i] + ((i + 1) % 3 == 0 && (i + 1) != l.length ? dot : '');
  305. }
  306. return t.split('').reverse().join('') + (decimal === 0 ? '' : '.' + r)
  307. }