refill_quota_stats.index.php 114 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588
  1. <?php defined('InShopNC') or exit('Access Invalid!'); ?>
  2. <style>
  3. th label {
  4. display: inline-block;
  5. width: 60px;
  6. }
  7. .page .fixed-bar .item-title h3 {
  8. margin-top: 18px !important;
  9. margin-bottom: 10px !important;
  10. font-weight: 700 !important;
  11. }
  12. .tab-base li span {
  13. font-size: 12px !important;
  14. }
  15. input::placeholder {
  16. color: #333;
  17. }
  18. .btn-container {
  19. margin-top: 10px;
  20. display: flex;
  21. justify-content: space-between;
  22. padding: 10px;
  23. }
  24. .btn-container div:last-child {
  25. display: flex;
  26. align-items: center;
  27. gap: 10px;
  28. }
  29. .btn-container .layui-input,
  30. .btn-container .layui-btn {
  31. height: 40px;
  32. line-height: 40px;
  33. padding: 0 10px;
  34. margin: 0;
  35. box-sizing: border-box;
  36. }
  37. .btn-container .layui-btn {
  38. background-color: #1E9FFF;
  39. color: white;
  40. border: none;
  41. cursor: pointer;
  42. display: flex;
  43. align-items: center;
  44. justify-content: center;
  45. }
  46. .layui-btn-sm {
  47. height: 28px !important;
  48. line-height: 28px !important;
  49. padding: 0 10px !important;
  50. }
  51. .stats-panel {
  52. margin-top: 40px;
  53. margin-left: 30px;
  54. width: 2240px;
  55. overflow-x: hidden;
  56. }
  57. .ch-tags {
  58. display: block;
  59. padding: 6px 12px;
  60. margin: 5px 0;
  61. background-color: #f0f0f0;
  62. border: 1px solid #dcdcdc;
  63. border-radius: 4px;
  64. font-size: 14px;
  65. line-height: 20px;
  66. color: #333;
  67. position: relative;
  68. transition: background-color 0.3s, border-color 0.3s;
  69. }
  70. .ch-tags:hover {
  71. background-color: #e9e9e9;
  72. border-color: #bbb;
  73. }
  74. .ch-tags .delete-btn {
  75. position: absolute;
  76. top: 0;
  77. right: 5px;
  78. cursor: pointer;
  79. color: #ff4d4f;
  80. font-size: 16px;
  81. transition: color 0.3s;
  82. }
  83. .ch-tags .delete-btn:hover {
  84. color: #d93f3a;
  85. }
  86. .layui-btn {
  87. position: relative;
  88. }
  89. .company-model,
  90. .merchant-model,
  91. .channel-model,
  92. .summary-model{
  93. display: flex;
  94. padding: 20px;
  95. }
  96. .leftmenu-manager-container {
  97. flex: 1;
  98. margin-right: 20px;
  99. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  100. padding: 10px;
  101. }
  102. .model-form {
  103. flex: 2;
  104. box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
  105. padding: 10px;
  106. }
  107. .form-group {
  108. margin-bottom: 20px;
  109. }
  110. .form-group label {
  111. display: inline-block;
  112. width: 100px;
  113. font-weight: bold;
  114. line-height: 32px;
  115. color: #333;
  116. }
  117. .form-group input,
  118. .form-group textarea,
  119. .form-group select {
  120. width: calc(100% - 110px);
  121. padding: 8px 12px;
  122. border: 1px solid #ccc;
  123. border-radius: 4px;
  124. background-color: #fff;
  125. font-size: 14px;
  126. line-height: 1.5;
  127. box-sizing: border-box;
  128. height: 36px;
  129. }
  130. .form-group input:focus,
  131. .form-group textarea:focus,
  132. .form-group select:focus {
  133. border-color: #5cdb95;
  134. box-shadow: 0 0 5px rgba(92, 219, 149, 0.5);
  135. outline: none;
  136. }
  137. .form-group textarea {
  138. resize: vertical;
  139. min-height: 100px;
  140. }
  141. .form-group select {
  142. cursor: pointer;
  143. height: 36px;
  144. }
  145. .layui-btn {
  146. margin-top: 10px;
  147. }
  148. .model-form {
  149. display: flex;
  150. flex-direction: column;
  151. gap: 15px;
  152. }
  153. .model-form .form-group {
  154. display: flex;
  155. align-items: center;
  156. }
  157. .model-form .form-group label {
  158. width: 150px;
  159. }
  160. .model-form .form-group select,
  161. .model-form .form-group input,
  162. .model-form .form-group textarea {
  163. flex: 1;
  164. }
  165. .model-form button {
  166. align-self: flex-end;
  167. width: auto;
  168. }
  169. .quota-tablebar {
  170. display: flex;
  171. align-items: center;
  172. justify-content: flex-start;
  173. padding: 10px 20px;
  174. background-color: #f5f5f5;
  175. border-radius: 5px;
  176. position: relative;
  177. }
  178. .quota-tablebar span {
  179. font-size: 16px;
  180. color: #333;
  181. position: absolute;
  182. left: 120px;
  183. /*transform: translateX(-50%);*/
  184. }
  185. .quota-tablebar button {
  186. padding: 8px 16px;
  187. font-size: 14px;
  188. line-height: 1.5;
  189. border: none;
  190. border-radius: 4px;
  191. cursor: pointer;
  192. background-color: #28a745;
  193. color: white;
  194. transition: background-color 0.3s;
  195. }
  196. .req-flag {
  197. color: red;
  198. display: inline-block;
  199. margin-right: 5px;
  200. }
  201. .layui-form-select input {
  202. width: 100% !important;
  203. }
  204. #rechargeManual {
  205. width: 1110px;
  206. }
  207. #rechargeManualApprove {
  208. display:none;
  209. padding: 20px;
  210. width: 1210px;
  211. }
  212. .reset-bar, .reset-bar-c {
  213. margin: 0 10px;
  214. width: 2230px;
  215. /*overflow-x: auto;*/
  216. white-space: nowrap;
  217. background-color: #fff;
  218. box-sizing: border-box;
  219. position: relative;
  220. }
  221. .reset-bar button, .reset-bar-c button {
  222. height: 28px;
  223. line-height: 28px;
  224. display: inline-block;
  225. vertical-align: middle;
  226. width: 150px;
  227. }
  228. .reset-bar-c button:first-child {
  229. margin-left: 600px;
  230. }
  231. .reset-bar-c button:nth-child(2) {
  232. margin-left: 150px;
  233. }
  234. .reset-bar-c button:nth-child(3) {
  235. margin-left: 0;
  236. }
  237. .company-checkbox {
  238. display: inline-flex;
  239. align-items: center;
  240. margin: 5px 10px 0 0;
  241. padding: 4px 8px;
  242. font-size: 13px;
  243. border: 1px solid #dcdcdc;
  244. border-radius: 4px;
  245. background-color: #fff;
  246. cursor: pointer;
  247. transition: background-color 0.2s, border-color 0.2s;
  248. }
  249. .company-checkbox:hover {
  250. background-color: #f9f9f9;
  251. border-color: #c9c9c9;
  252. }
  253. .company-checkbox input {
  254. margin-right: 6px;
  255. width: 14px;
  256. height: 14px;
  257. }
  258. .company-checkbox span {
  259. color: #333;
  260. line-height: 1.5;
  261. }
  262. .negative-value {
  263. color: red;
  264. }
  265. .chinese-money {
  266. font-size: 12px;
  267. color: red;
  268. display: block;
  269. margin-top: 5px;
  270. }
  271. .btn-badge {
  272. position: absolute;
  273. top: 5px;
  274. right: 5px;
  275. width: 16px;
  276. height: 16px;
  277. background-color: red;
  278. color: white;
  279. border-radius: 50%;
  280. display: flex;
  281. align-items: center;
  282. justify-content: center;
  283. font-size: 10px;
  284. font-weight: bold;
  285. }
  286. .summary-tables-subject {
  287. width: 135px;
  288. line-height: 30px;
  289. font-size: 18px;
  290. background-color: #1E9FFF;
  291. padding-left: 15px;
  292. font-weight: 800;
  293. }
  294. </style>
  295. <div class="page" id="app">
  296. <div class="fixed-bar">
  297. <div class="item-title">
  298. <h3>带票额度统计</h3>
  299. <ul class="tab-base">
  300. <li><a href="JavaScript:void(0);" class="current"><span>带票额度统计</span></a></li>
  301. </ul>
  302. </div>
  303. </div>
  304. <div class="fixed-empty"></div>
  305. <!-- 顶部按钮 -->
  306. <div class="btn-container">
  307. <div>
  308. </div>
  309. <div>
  310. <input class="layui-input query-input" type="text" readonly value="" name="query_month" id="query_month" autocomplete="off" />
  311. <button type="button" class="layui-btn layui-bg-blue" id="btn-update-all">更新数据</button>
  312. <button type="button" class="layui-btn layui-bg-blue" id="btn_refresh_approve">刷新审核</button>
  313. </div>
  314. </div>
  315. <div class="layui-clear"></div>
  316. <!-- 主体 -->
  317. <div class="stats-panel layui-font-14">
  318. <company-set type="KEY_QUOTA_COMPANY" emit="updateCompany"></company-set>
  319. <div class="reset-bar-c">
  320. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-company" data-col="corrected_used_quota">一键清零</button>
  321. <button type="button" class="layui-btn layui-bg-orange ac-batch-invoice" data-table="tb-company">批量提交</button>
  322. <button type="button" class="layui-btn layui-bg-red ac-approve" data-table="tb-company">
  323. 审批
  324. <span class="btn-badge" id="badge-approve-company">0</span>
  325. </button>
  326. </div>
  327. <table class="layui-hide" id="tb-company"></table>
  328. </div>
  329. <!-- 下游(机构) -->
  330. <div class="stats-panel layui-font-14">
  331. <merchant-set type="KEY_QUOTA_MERCHANT" emit="updateMerchant"></merchant-set>
  332. <div class="reset-bar">
  333. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-merchant" data-col="total_invoiced">一键清零</button>
  334. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-merchant" data-col="month_opened">一键清零</button>
  335. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-merchant" data-col="actual_invoice_amount">一键清零</button>
  336. <button type="button" class="layui-btn layui-bg-orange ac-batch-invoice" data-table="tb-merchant">批量提交</button>
  337. <button type="button" class="layui-btn layui-bg-red ac-approve" data-table="tb-merchant">
  338. 审批
  339. <span class="btn-badge" id="badge-approve-mch">0</span>
  340. </button>
  341. </div>
  342. <table class="layui-hide" id="tb-merchant"></table>
  343. </div>
  344. <!-- 上游 -->
  345. <div class="stats-panel layui-font-14">
  346. <channel-set type="KEY_QUOTA_CHANNEL" emit="updateChannel"></channel-set>
  347. <div class="reset-bar">
  348. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-channel" data-col="total_invoiced">一键清零</button>
  349. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-channel" data-col="month_opened">一键清零</button>
  350. <button type="button" class="layui-btn layui-btn-light-yellow reset-col" data-table="tb-channel" data-col="actual_invoice_amount">一键清零</button>
  351. <button type="button" class="layui-btn layui-bg-orange ac-batch-invoice" data-table="tb-channel">批量提交</button>
  352. <button type="button" class="layui-btn layui-bg-red ac-approve" data-table="tb-channel">
  353. 审批
  354. <span class="btn-badge" id="badge-approve-chan">0</span>
  355. </button>
  356. </div>
  357. <table class="layui-hide" id="tb-channel"></table>
  358. </div>
  359. <!-- 综合统计 -->
  360. <div class="stats-panel layui-font-14">
  361. <summary-set type="KEY_QUOTA_SUMMARY" emit="updateSummary"></summary-set>
  362. <div id="summary-tables">
  363. </div>
  364. </div>
  365. <!-- 申请确认 -->
  366. <div id="rechargeManual" style="display:none; padding: 20px;">
  367. <div class="layui-form-item">
  368. <table class="layui-hide" id="tb_apply"></table>
  369. </div>
  370. </div>
  371. <div id="rechargeManualApprove">
  372. <table class="layui-hide" id="tb_approve"></table>
  373. </div>
  374. </div>
  375. <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/laydate/laydate.js"></script>
  376. <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/jquery.ui.js"></script>
  377. <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/i18n/zh-CN.js" charset="utf-8"></script>
  378. <script type="text/javascript" src="<?php echo RESOURCE_SITE_URL;?>/refill/layer.js"></script>
  379. <script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL;?>/js/xm-select.js"></script>
  380. <script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL;?>/layui/layui.js"></script>
  381. <link rel="stylesheet" type="text/css" href="<?php echo ADMIN_TEMPLATES_URL; ?>/layui/css/layui.css"/>
  382. <link rel="stylesheet" type="text/css" href="<?php echo RESOURCE_SITE_URL; ?>/js/jquery-ui/themes/ui-lightness/jquery.ui.css"/>
  383. <script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL;?>/js/stats-utils.js?t=<?php echo time();?>"></script>
  384. <script type="text/javascript" src="<?php echo ADMIN_TEMPLATES_URL;?>/js/stats-quota.js?t=<?php echo time();?>"></script>
  385. <?php session_start(); ?>
  386. <script type="text/javascript">
  387. const systemUserName = '<?php echo $output['admin_info']['name'];?>';
  388. const isAdmin = systemUserName === 'admin';//区分管理员和出纳的权限
  389. $(function () {
  390. const app = new ComponentBase({
  391. el: '#app',
  392. componentData: {
  393. 'company-set': [],
  394. 'merchant-set': [],
  395. 'channel-set': [],
  396. 'summary-set': []
  397. },
  398. components: {
  399. 'company-set': CompanyComponent,
  400. 'merchant-set': MerchantComponent,
  401. 'channel-set': ChannelComponent,
  402. 'summary-set': SummaryComponent
  403. }
  404. });
  405. class CompanyTable extends LayuiTableBase {
  406. constructor() {
  407. super('tb-company');
  408. }
  409. renderTable() {
  410. const that = this;
  411. const tableData = dataHelper.getCompanyList();
  412. tableData.forEach(function (item) {
  413. item.total_quota = formatDecimals(item.total_quota);
  414. item.used_quota = formatDecimals(item.used_quota);
  415. item.left_quota = formatDecimals(item.total_quota - item.used_quota);
  416. item.corrected_used_quota = '0';
  417. item.operator = '';
  418. });
  419. layui.table.render({
  420. elem: '#' + this.tableId,
  421. data: tableData,
  422. limit: tableData.length,
  423. cols: [[
  424. {field: 'name', title: '主体名称', width: 150},
  425. {field: 'total_quota', title: '总额度', width: 200},
  426. {field: 'used_quota', title: '已用额度', width: 110},
  427. {field: 'left_quota', title: '剩余额度', width: 150},
  428. {field: 'corrected_used_quota', title: '已用额度矫正', width: 150},
  429. {field: 'operator', title: '操作人', width: 150},
  430. {field: 'remark', title: '备注', width: 150},
  431. {field: 'action', title: '操作', width: 150, templet: function(d){return '<button class="layui-btn layui-btn-sm invoice-apply-signle" style="margin: 0" data-index="'+d.LAY_TABLE_INDEX+'">矫正</button>';}}
  432. ]],
  433. done: function (res, curr, count) {
  434. const tableItem = $('#' + that.tableId);
  435. const trs = tableItem.next('.layui-table-view').find('.layui-table-body tbody tr');
  436. trs.each(function(i, tr) {
  437. const editNumberColumns = ['corrected_used_quota'];
  438. if (isAdmin === true) {
  439. editNumberColumns.push('total_quota', 'used_quota');
  440. }
  441. for(let col of editNumberColumns) {
  442. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  443. const valDiv = td.find('div');
  444. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  445. valDiv.off('input', handleInputd2)
  446. .off('keypress')
  447. .off('blur')
  448. .on('input', handleInputd2)
  449. .on('keypress', function(e) {
  450. if (e.keyCode === 13) {
  451. e.preventDefault();
  452. $(this).blur();
  453. }
  454. })
  455. .on('blur', async function () {
  456. let val = valDiv.text().trim();
  457. if (!isNumeric(val)) {
  458. valDiv.html('0');
  459. }
  460. val = normalizeAmount(val);//过滤,比如前导 0
  461. valDiv.html(formatDecimals(val));
  462. const index = $(this).parent().parent().data('index');
  463. await that.saveEdit(index);
  464. that.deltaValue('total_quota', 'used_quota', 'left_quota');
  465. that.setValueClass(['left_quota']);
  466. });
  467. }
  468. const editTextColumns = ['remark', 'operator'];
  469. for(let col of editTextColumns) {
  470. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  471. const valDiv = td.find('div');
  472. let val = valDiv.text().trim();
  473. valDiv.html(val);
  474. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  475. valDiv.off('input')
  476. .off('keypress')
  477. .off('blur')
  478. .on('input')
  479. .on('keypress', function(e) {
  480. if (e.keyCode === 13) {
  481. e.preventDefault();
  482. $(this).blur();
  483. }
  484. })
  485. .on('blur', async function () {
  486. const index = $(this).parent().parent().data('index');
  487. await that.saveEdit(index);
  488. that.deltaValue('total_quota', 'used_quota', 'left_quota');
  489. that.setValueClass(['left_quota']);
  490. });
  491. }
  492. });
  493. that.setValueClass(['left_quota']);
  494. tableItem.next('.layui-table-view').off('click', '.invoice-apply-signle').on('click', '.invoice-apply-signle', function (){
  495. const index = $(this).data('index');
  496. that.applyOne(index);
  497. });
  498. }
  499. });
  500. }
  501. deltaValue(firstCloumn, secondCloumn, resultCloumn) {
  502. const trs = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  503. trs.each(function (index, element) {
  504. const firstVal = $(element).find('td[data-field="' + firstCloumn + '"]').find('.layui-table-cell').text().trim();
  505. const secondVal = $(element).find('td[data-field="' + secondCloumn + '"]').find('.layui-table-cell').text().trim();
  506. const resultTd = $(element).find('td[data-field="' + resultCloumn + '"]').find('.layui-table-cell');
  507. const deltaVal = formatDecimals(parseFloat(firstVal) - parseFloat(secondVal), 2);
  508. resultTd.html(deltaVal);
  509. });
  510. }
  511. async saveEdit(index) {
  512. const companyData = dataHelper.getCompanyList();
  513. if (index >= companyData.length) {
  514. console.error('主体数据错误:编辑索引大于主体总数');
  515. return;
  516. }
  517. const tr = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr[data-index="' + index + '"]');
  518. const total_quota = tr.find('td[data-field="total_quota"]').find('div').text().trim();
  519. const used_quota = tr.find('td[data-field="used_quota"]').find('div').text().trim();
  520. const remark = tr.find('td[data-field="remark"]').find('div').text().trim();
  521. let item = companyData[index];
  522. item.total_quota = total_quota || "0";
  523. item.used_quota = used_quota || "0";
  524. item.remark = remark || "";
  525. await dataHelper.addOrUpdateData(CONSTANTS.KEY_QUOTA_COMPANY, item, 1);
  526. renderSummaryTables();
  527. }
  528. applyOne(index) {
  529. batchCorrected.doApplyOne(this.tableId, index);
  530. }
  531. }
  532. class MerchantTable extends LayuiTableBase {
  533. constructor() {
  534. super('tb-merchant');
  535. }
  536. async renderTable() {
  537. const that = this;
  538. const merchantList = dataHelper.getMerchantList();
  539. merchantList.forEach(mItem => {
  540. setEmptyFieldsToZero(mItem, ['total_invoiced', 'month_opened']);
  541. });
  542. const mchIds = merchantList.map(item => item.mch_id).join(',')
  543. const currMonth = getCurrMonthCondition();
  544. const sysData = await statsApi.getSysMchAmounts(mchIds, currMonth);
  545. let sysMchData = [];
  546. if (sysData.state === true) {
  547. sysMchData = sysData.list;
  548. }
  549. let tableData = deepCloneData(merchantList);
  550. tableData.forEach(item => {
  551. const amountsItem = sysMchData.find(aItem => aItem.mch_id === item.mch_id);
  552. if (amountsItem !== undefined) {
  553. item.mch_name = amountsItem.mch_name;
  554. item.total_amounts = formatDecimals(amountsItem.total_amounts, 2);
  555. item.month_amounts = formatDecimals(amountsItem.month_amounts, 2);
  556. } else {
  557. item.mch_name = '';
  558. item.total_amounts = '0';
  559. item.month_amounts = '0';
  560. }
  561. item.total_invoiced = formatDecimals(item.total_invoiced);
  562. Object.assign(item, {
  563. estimated_invoice_amount:0,
  564. available_invoice_amount: 0,
  565. actual_invoice_amount: 0,
  566. invoice_date: '',
  567. operator: ''
  568. });
  569. });
  570. tableData = sortBySubjectContinuity(tableData);
  571. layui.table.render({
  572. elem: '#' + this.tableId,
  573. data: tableData,
  574. limit: tableData.length,
  575. cols: [[
  576. {field: 'subject', title: '对应主体', width: 150},
  577. {field: 'mch_id', title: '机构id', width: 100},
  578. {field: 'mch_name', title: '机构名称', width: 200},
  579. {field: 'total_amounts', title: '充值总计金额', width: 150},
  580. {field: 'month_amounts', title: '本月打款总计', width: 150},
  581. {field: 'total_invoiced', title: '已开票总金额', width: 150},
  582. {field: 'last_invoice_date', title: '上次开票日期', width: 150, templet: function(d){
  583. return '<input type="text" class="layui-input date-input" data-index="' + d.LAY_TABLE_INDEX + '" data-field="last_invoice_date" value="' + d.last_invoice_date + '">';
  584. }},
  585. {field: 'month_opened', title: '本月已开票', width: 150},
  586. {field: 'available_invoice_amount', title: '本月可开票总计', width: 150},
  587. {field: 'estimated_invoice_amount', title: '预计本月开票金额', width: 150},
  588. {field: 'actual_invoice_amount', title: '实际本次开票', width: 150},
  589. {field: 'invoice_date', title: '开票日期', width: 150, templet: function(d){
  590. return '<input type="text" class="layui-input date-input" data-index="' + d.LAY_TABLE_INDEX + '" data-field="invoice_date" value="' + d.invoice_date + '">';
  591. }},
  592. {field: 'operator', title: '操作人', width: 150},
  593. {field: 'remark', title: '备注', width: 150},
  594. {field: 'action', title: '操作', width: 100, templet: function(d){return '<button class="layui-btn layui-btn-sm invoice-apply-signle" style="margin: 0" data-index="'+d.LAY_TABLE_INDEX+'">申请</button>';}}
  595. ]],
  596. done: function (res, curr, count) {
  597. const tableItem = $('#' + that.tableId);
  598. const trs = tableItem.next('.layui-table-view').find('.layui-table-body tbody tr');
  599. trs.each(function(i, tr) {
  600. const subject = tableData[i].subject;
  601. $(tr).attr('subject', subject);
  602. });
  603. that.mergeCells();
  604. const updateTable = () => {
  605. that.deltaValue('total_amounts', 'total_invoiced', 'estimated_invoice_amount');
  606. that.updateAvailableInvoiceAmount();
  607. that.setValueClass(['total_invoiced', 'available_invoice_amount', 'estimated_invoice_amount', 'actual_invoice_amount', 'month_opened', 'total_amounts', 'month_amounts']);
  608. that.updateColumnCnMoney(['total_invoiced']);
  609. };
  610. updateTable();
  611. trs.each(function (i, tr) {
  612. const editNumberColumns = ['total_invoiced', 'actual_invoice_amount'];
  613. if (isAdmin === true) {
  614. editNumberColumns.push('month_opened');
  615. }
  616. for (let col of editNumberColumns) {
  617. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  618. const valDiv = td.find('div');
  619. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  620. valDiv.off('input', handleInputd2)
  621. .off('keypress')
  622. .off('blur')
  623. .on('input', handleInputd2)
  624. .on('keypress', function (e) {
  625. if (e.keyCode === 13) {
  626. e.preventDefault();
  627. $(this).blur();
  628. }
  629. })
  630. .on('blur', async function () {
  631. let val = valDiv.text().trim();
  632. if (!isNumeric(val)) {
  633. valDiv.html('0');
  634. }
  635. val = normalizeAmount(val);//过滤,比如前导 0
  636. valDiv.html(formatDecimals(val));
  637. const index = $(this).parent().parent().data('index');
  638. await that.saveEdit(index);
  639. if (col === 'month_opened') {
  640. const subject = $(tr).find('td[data-field="subject"]').find('div').text();
  641. await that.updateCompanyUsedQuota(subject);
  642. setTimeout(function () {
  643. companyTable.renderTable();
  644. renderSummaryTables()
  645. }, 0);
  646. }
  647. if (col === 'total_invoiced') {
  648. setTimeout(function () {
  649. renderSummaryTables();
  650. }, 0);
  651. }
  652. updateTable();
  653. });
  654. }
  655. const editTextColumns = ['operator', 'remark'];
  656. for (let col of editTextColumns) {
  657. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  658. const valDiv = td.find('div');
  659. let val = valDiv.text().trim();
  660. valDiv.html(val);
  661. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  662. valDiv.off('input')
  663. .off('keypress')
  664. .off('blur')
  665. .on('input')
  666. .on('keypress', function (e) {
  667. if (e.keyCode === 13) {
  668. e.preventDefault();
  669. $(this).blur();
  670. }
  671. })
  672. .on('blur', async function () {
  673. const index = $(this).parent().parent().data('index');
  674. await that.saveEdit(index);
  675. updateTable();
  676. });
  677. }
  678. });
  679. //日期组件
  680. setTimeout(function(){
  681. $('.date-input').each(function(){
  682. const rowIndex = $(this).attr('data-index');
  683. layui.laydate.render({
  684. elem: this,
  685. type: 'date',
  686. done: async function (value, date, endDate) {
  687. await that.saveEdit(rowIndex);
  688. }
  689. });
  690. });
  691. }, 0);
  692. tableItem.next('.layui-table-view').off('click', '.invoice-apply-signle').on('click', '.invoice-apply-signle', function (){
  693. const index = $(this).data('index');
  694. that.applyOne(index);
  695. });
  696. that.setRole();
  697. }
  698. });
  699. }
  700. setRole() {
  701. if (isAdmin === true) {
  702. return;
  703. }
  704. const tbRoot = $('#' + this.tableId);
  705. const bodyTrs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  706. const headerTrs = tbRoot.next('.layui-table-view').find('.layui-table-header thead tr');
  707. const hideColumns = ['total_amounts', 'month_amounts', 'month_opened', 'total_invoiced', 'last_invoice_date'];
  708. for (let col of hideColumns) {
  709. bodyTrs.each(function (i, tr) {
  710. $(tr).find('td[data-field="' + col + '"]').addClass('layui-hide');
  711. });
  712. headerTrs.each(function (i, tr) {
  713. $(tr).find('th[data-field="' + col + '"]').addClass('layui-hide');
  714. });
  715. }
  716. }
  717. updateColumnCnMoney(columns) {
  718. const tableItem = $('#' + this.tableId);
  719. const trs = tableItem.next('.layui-table-view').find('.layui-table-body tbody tr');
  720. trs.each(function(i, tr) {
  721. columns.forEach(column => {
  722. const cell = $(tr).find('td[data-field="' + column + '"]');
  723. let value = cell.find('div').text().trim();
  724. value = parseFloat(value.replace(/[^\d.-]/g, ''));
  725. if (!isNaN(value)) {
  726. const chineseMoney = cnMoneyFormat(value);
  727. cell.find('.chinese-money').remove();
  728. const content = chineseMoney !== '' ? `(${chineseMoney})` : '';
  729. cell.append('<span class="chinese-money">' + content + '</span>');
  730. }
  731. });
  732. });
  733. }
  734. mergeCells() {
  735. const tbRoot = $('#' + this.tableId);
  736. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  737. const groups = {};
  738. trs.each(function(i, tr) {
  739. const group = $(tr).attr('subject');
  740. if (group) {
  741. if (!groups[group]) {
  742. groups[group] = {count: 0, startIndex: i};
  743. }
  744. groups[group].count++;
  745. }
  746. });
  747. for (let group in groups) {
  748. const info = groups[group];
  749. if (info.count > 1) {
  750. const mergeColumns = ['available_invoice_amount'];
  751. for (let col of mergeColumns) {
  752. trs.eq(info.startIndex).find('td[data-field="' + col + '"]').attr('rowspan', info.count);
  753. for (let j = 1; j < info.count; j++) {
  754. trs.eq(info.startIndex + j).find('td[data-field="' + col + '"]').addClass('layui-hide');
  755. }
  756. }
  757. }
  758. }
  759. }
  760. deltaValue(firstCloumn, secondCloumn, resultCloumn) {
  761. const trs = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  762. trs.each(function (index, element) {
  763. const firstVal = $(element).find('td[data-field="' + firstCloumn + '"]').find('.layui-table-cell').text().trim();
  764. const secondVal = $(element).find('td[data-field="' + secondCloumn + '"]').find('.layui-table-cell').text().trim();
  765. const resultTd = $(element).find('td[data-field="' + resultCloumn + '"]').find('.layui-table-cell');
  766. const deltaVal = formatDecimals(parseFloat(firstVal) - parseFloat(secondVal), 2);
  767. resultTd.html(deltaVal);
  768. });
  769. }
  770. updateAvailableInvoiceAmount () {
  771. let groupSum = {};
  772. const trs = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  773. trs.each(function (index, element) {
  774. const amount = $(element).find('td[data-field="estimated_invoice_amount"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  775. const tdGroup = $(element).attr('subject');
  776. if (!tdGroup) {
  777. return;
  778. }
  779. if (!groupSum[tdGroup]) {
  780. groupSum[tdGroup] = 0;
  781. }
  782. if (isNumeric(amount) && amount > 0) { //负数不计入求和
  783. groupSum[tdGroup] += parseFloat(amount);
  784. }
  785. });
  786. trs.each(function (index, element) {
  787. const td = $(element).find('td[data-field="available_invoice_amount"]').not('.layui-hide').find('.layui-table-cell');
  788. const tdGroup = $(element).attr('subject');
  789. if (!tdGroup) {
  790. return;
  791. }
  792. if (td.length > 0) {
  793. const val = groupSum[tdGroup];
  794. td.html(formatDecimals(val));
  795. }
  796. });
  797. }
  798. async saveEdit(index) {
  799. const merchantData = dataHelper.getMerchantList();
  800. if (index >= merchantData.length) {
  801. console.error('主体数据错误:编辑索引大于主体总数');
  802. return;
  803. }
  804. const tr = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr[data-index="' + index + '"]');
  805. const total_invoiced = tr.find('td[data-field="total_invoiced"]').find('div').text().trim();
  806. const month_opened = tr.find('td[data-field="month_opened"]').find('div').text().trim();
  807. const last_invoice_date = tr.find('td[data-field="last_invoice_date"]').find('div').find('input').val().trim();
  808. const remark = tr.find('td[data-field="remark"]').find('div').text().trim();
  809. let item = merchantData[index];
  810. item.total_invoiced = total_invoiced || "0";
  811. item.last_invoice_date = last_invoice_date || "";
  812. item.month_opened = month_opened || "0";
  813. item.remark = remark;
  814. await dataHelper.addOrUpdateData(CONSTANTS.KEY_QUOTA_MERCHANT, item, 2);
  815. }
  816. async updateCompanyUsedQuota(subject) {
  817. const companyList = dataHelper.getCompanyList();
  818. const activeCompany = companyList.find(cItem => cItem.name === subject);
  819. if (activeCompany !== undefined) {//更新当前编辑的主体已用额度
  820. const merchantDataNew = dataHelper.getMerchantList();
  821. const total = merchantDataNew
  822. .filter(mItem => mItem.subject === subject)
  823. .reduce((sum, item) => sum + parseFloat(item.month_opened), 0);
  824. activeCompany.used_quota = total.toString();
  825. }
  826. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_COMPANY, companyList);
  827. }
  828. applyOne(index) {
  829. batchMchInvoice.doApplyOne(this.tableId, index);
  830. }
  831. }
  832. class ChannelTable extends LayuiTableBase {
  833. constructor() {
  834. super('tb-channel');
  835. }
  836. async renderTable() {
  837. const that = this;
  838. const channelList = dataHelper.getChannelList();
  839. channelList.forEach(cItem => {
  840. setEmptyFieldsToZero(cItem, ['total_invoiced', 'month_opened']);
  841. });
  842. const storeIds = channelList.map(item => item.store_id).join(',')
  843. const currMonth = getCurrMonthCondition();
  844. const sysData = await statsApi.getSysChanAmounts(storeIds, currMonth);
  845. let sysChanData = [];
  846. if (sysData.state === true) {
  847. sysChanData = sysData.list;
  848. }
  849. let tableData = deepCloneData(channelList);
  850. tableData.forEach(item => {
  851. const amountsItem = sysChanData.find(aItem => aItem.store_id === item.store_id);
  852. if (amountsItem !== undefined) {
  853. item.store_name = amountsItem.store_name;
  854. item.month_amounts = formatDecimals(amountsItem.month_amounts, 2);
  855. item.total_amounts = formatDecimals(amountsItem.total_amounts, 2);
  856. } else {
  857. item.store_name = '';
  858. item.month_amounts = '0';
  859. item.total_amounts = '0';
  860. }
  861. item.total_invoiced = formatDecimals(item.total_invoiced);
  862. Object.assign(item, {
  863. estimated_invoice_amount:0,
  864. available_invoice_amount: 0,
  865. actual_invoice_amount: 0,
  866. invoice_date: '',
  867. operator: ''
  868. });
  869. });
  870. tableData = sortBySubjectContinuity(tableData);
  871. layui.table.render({
  872. elem: '#' + this.tableId,
  873. data: tableData,
  874. limit: tableData.length,
  875. cols: [[
  876. {field: 'subject', title: '对应主体', width: 150},
  877. {field: 'store_id', title: '通道id', width: 100},
  878. {field: 'store_name', title: '通道名称', width: 200},
  879. {field: 'total_amounts', title: '通道总计金额', width: 150},
  880. {field: 'month_amounts', title: '本月打款总计', width: 150},
  881. {field: 'total_invoiced', title: '已开票总金额', width: 150},
  882. {field: 'last_invoice_date', title: '上次开票日期', width: 150, templet: function(d){
  883. return '<input type="text" class="layui-input date-input" data-index="' + d.LAY_TABLE_INDEX + '" data-field="last_invoice_date" value="' + d.last_invoice_date + '">';
  884. }},
  885. {field: 'month_opened', title: '本月已开票', width: 150},
  886. {field: 'available_invoice_amount', title: '本月可开票总计', width: 150},
  887. {field: 'estimated_invoice_amount', title: '预计本月开票金额', width: 150},
  888. {field: 'actual_invoice_amount', title: '实际本次开票', width: 150},
  889. {field: 'invoice_date', title: '开票日期', width: 150, templet: function(d){
  890. return '<input type="text" class="layui-input date-input" data-index="' + d.LAY_TABLE_INDEX + '" data-field="invoice_date" value="' + d.invoice_date + '">';
  891. }},
  892. {field: 'operator', title: '操作人', width: 150},
  893. {field: 'remark', title: '备注', width: 150},
  894. {field: 'action', title: '操作', width: 100, templet: function(d){return '<button class="layui-btn layui-btn-sm invoice-apply-signle" style="margin: 0" data-index="'+d.LAY_TABLE_INDEX+'">申请</button>';}}
  895. ]],
  896. done: function (res, curr, count) {
  897. const tableItem = $('#' + that.tableId);
  898. const trs = tableItem.next('.layui-table-view').find('.layui-table-body tbody tr');
  899. trs.each(function(i, tr) {
  900. const subject = tableData[i].subject;
  901. $(tr).attr('subject', subject);
  902. });
  903. that.mergeCells();
  904. const updateTable = () => {
  905. that.deltaValue('total_amounts', 'total_invoiced', 'estimated_invoice_amount');
  906. that.updateAvailableInvoiceAmount();
  907. that.setValueClass(['total_invoiced', 'available_invoice_amount', 'estimated_invoice_amount', 'actual_invoice_amount', 'month_opened', 'total_amounts']);
  908. that.updateColumnCnMoney(['total_invoiced']);
  909. };
  910. updateTable();
  911. trs.each(function (i, tr) {
  912. const editNumberColumns = ['total_invoiced', 'actual_invoice_amount'];
  913. if (isAdmin === true) {
  914. editNumberColumns.push('month_opened');
  915. }
  916. for (let col of editNumberColumns) {
  917. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  918. const valDiv = td.find('div');
  919. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  920. valDiv.off('input', handleInputd2)
  921. .off('keypress')
  922. .off('blur')
  923. .on('input', handleInputd2)
  924. .on('keypress', function (e) {
  925. if (e.keyCode === 13) {
  926. e.preventDefault();
  927. $(this).blur();
  928. }
  929. })
  930. .on('blur', async function () {
  931. let val = valDiv.text().trim();
  932. if (!isNumeric(val)) {
  933. valDiv.html('0');
  934. }
  935. val = normalizeAmount(val);//过滤,比如前导 0
  936. valDiv.html(formatDecimals(val));
  937. const index = $(this).parent().parent().data('index');
  938. await that.saveEdit(index);
  939. updateTable();
  940. });
  941. }
  942. const editTextColumns = ['operator', 'remark'];
  943. for (let col of editTextColumns) {
  944. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  945. const valDiv = td.find('div');
  946. let val = valDiv.text().trim();
  947. valDiv.html(val);
  948. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  949. valDiv.off('input')
  950. .off('keypress')
  951. .off('blur')
  952. .on('input')
  953. .on('keypress', function (e) {
  954. if (e.keyCode === 13) {
  955. e.preventDefault();
  956. $(this).blur();
  957. }
  958. })
  959. .on('blur', async function () {
  960. const index = $(this).parent().parent().data('index');
  961. await that.saveEdit(index);
  962. updateTable();
  963. });
  964. }
  965. });
  966. //日期组件
  967. setTimeout(function(){
  968. $('.date-input').each(function(){
  969. const rowIndex = $(this).attr('data-index');
  970. layui.laydate.render({
  971. elem: this,
  972. type: 'date',
  973. done: async function (value, date, endDate) {
  974. await that.saveEdit(rowIndex);
  975. }
  976. });
  977. });
  978. }, 0);
  979. tableItem.next('.layui-table-view').off('click', '.invoice-apply-signle').on('click', '.invoice-apply-signle', function (){
  980. const index = $(this).data('index');
  981. that.applyOne(index);
  982. });
  983. that.setRole();
  984. }
  985. });
  986. }
  987. setRole() {
  988. if (isAdmin === true) {
  989. return;
  990. }
  991. const tbRoot = $('#' + this.tableId);
  992. const bodyTrs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  993. const headerTrs = tbRoot.next('.layui-table-view').find('.layui-table-header thead tr');
  994. const hideColumns = ['total_amounts', 'month_amounts', 'month_opened', 'total_invoiced', 'last_invoice_date'];
  995. for (let col of hideColumns) {
  996. bodyTrs.each(function (i, tr) {
  997. $(tr).find('td[data-field="' + col + '"]').addClass('layui-hide');
  998. });
  999. headerTrs.each(function (i, tr) {
  1000. $(tr).find('th[data-field="' + col + '"]').addClass('layui-hide');
  1001. });
  1002. }
  1003. }
  1004. updateColumnCnMoney(columns) {
  1005. const tableItem = $('#' + this.tableId);
  1006. const trs = tableItem.next('.layui-table-view').find('.layui-table-body tbody tr');
  1007. trs.each(function(i, tr) {
  1008. columns.forEach(column => {
  1009. const cell = $(tr).find('td[data-field="' + column + '"]');
  1010. let value = cell.find('div').text().trim();
  1011. value = parseFloat(value.replace(/[^\d.-]/g, ''));
  1012. if (!isNaN(value)) {
  1013. const chineseMoney = cnMoneyFormat(value);
  1014. cell.find('.chinese-money').remove();
  1015. const content = chineseMoney !== '' ? `(${chineseMoney})` : '';
  1016. cell.append('<span class="chinese-money">' + content + '</span>');
  1017. }
  1018. });
  1019. });
  1020. }
  1021. mergeCells() {
  1022. const tbRoot = $('#' + this.tableId);
  1023. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1024. const groups = {};
  1025. trs.each(function(i, tr) {
  1026. const group = $(tr).attr('subject');
  1027. if (group) {
  1028. if (!groups[group]) {
  1029. groups[group] = {count: 0, startIndex: i};
  1030. }
  1031. groups[group].count++;
  1032. }
  1033. });
  1034. for (let group in groups) {
  1035. const info = groups[group];
  1036. if (info.count > 1) {
  1037. const mergeColumns = ['available_invoice_amount'];
  1038. for (let col of mergeColumns) {
  1039. trs.eq(info.startIndex).find('td[data-field="' + col + '"]').attr('rowspan', info.count);
  1040. for (let j = 1; j < info.count; j++) {
  1041. trs.eq(info.startIndex + j).find('td[data-field="' + col + '"]').addClass('layui-hide');
  1042. }
  1043. }
  1044. }
  1045. }
  1046. }
  1047. deltaValue(firstCloumn, secondCloumn, resultCloumn) {
  1048. const trs = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1049. trs.each(function (index, element) {
  1050. const firstVal = $(element).find('td[data-field="' + firstCloumn + '"]').find('.layui-table-cell').text().trim();
  1051. const secondVal = $(element).find('td[data-field="' + secondCloumn + '"]').find('.layui-table-cell').text().trim();
  1052. const resultTd = $(element).find('td[data-field="' + resultCloumn + '"]').find('.layui-table-cell');
  1053. const deltaVal = formatDecimals(parseFloat(firstVal) - parseFloat(secondVal), 2);
  1054. resultTd.html(deltaVal);
  1055. });
  1056. }
  1057. updateAvailableInvoiceAmount () {
  1058. let groupSum = {};
  1059. const trs = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1060. trs.each(function (index, element) {
  1061. const amount = $(element).find('td[data-field="estimated_invoice_amount"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  1062. const tdGroup = $(element).attr('subject');
  1063. if (!tdGroup) {
  1064. return;
  1065. }
  1066. if (!groupSum[tdGroup]) {
  1067. groupSum[tdGroup] = 0;
  1068. }
  1069. if (isNumeric(amount) && amount > 0) { //负数不计入求和
  1070. groupSum[tdGroup] += parseFloat(amount);
  1071. }
  1072. });
  1073. trs.each(function (index, element) {
  1074. const td = $(element).find('td[data-field="available_invoice_amount"]').not('.layui-hide').find('.layui-table-cell');
  1075. const tdGroup = $(element).attr('subject');
  1076. if (!tdGroup) {
  1077. return;
  1078. }
  1079. if (td.length > 0) {
  1080. const val = groupSum[tdGroup];
  1081. td.html(formatDecimals(val));
  1082. }
  1083. });
  1084. }
  1085. async saveEdit(index) {
  1086. const channelData = dataHelper.getChannelList();
  1087. if (index >= channelData.length) {
  1088. console.error('主体数据错误:编辑索引大于主体总数');
  1089. return;
  1090. }
  1091. const tr = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr[data-index="' + index + '"]');
  1092. const total_invoiced = tr.find('td[data-field="total_invoiced"]').find('div').text().trim();
  1093. const month_opened = tr.find('td[data-field="month_opened"]').find('div').text().trim();
  1094. const last_invoice_date = tr.find('td[data-field="last_invoice_date"]').find('div').find('input').val().trim();
  1095. const remark = tr.find('td[data-field="remark"]').find('div').text().trim();
  1096. let item = channelData[index];
  1097. item.total_invoiced = total_invoiced || "0";
  1098. item.month_opened = month_opened || "0";
  1099. item.last_invoice_date = last_invoice_date || "";
  1100. item.remark = remark;
  1101. await dataHelper.addOrUpdateData(CONSTANTS.KEY_QUOTA_CHANNEL, item, 2);
  1102. setTimeout(function () {
  1103. renderSummaryTables();
  1104. }, 0);
  1105. }
  1106. applyOne(index) {
  1107. batchChanInvoice.doApplyOne(this.tableId, index);
  1108. }
  1109. }
  1110. class SummaryTable extends LayuiTableBase {
  1111. constructor(tableId, subject) {
  1112. super(tableId);
  1113. this.subject = subject;
  1114. this.lines = 0;
  1115. }
  1116. renderTable() {
  1117. const that = this;
  1118. const channelData = this.channelTableData().filter(item => {
  1119. return item.subject === that.subject;
  1120. });
  1121. this.lines = channelData.length;
  1122. const merchantData = this.merchantTableData().filter(item => {
  1123. return item.subject === that.subject;
  1124. });
  1125. const summaryData = dataHelper.getSummaryList().find(item => item.subject === that.subject);
  1126. const invoice_remaining_amount = summaryData === undefined || summaryData.invoice_remaining_amount === '' ? '0' : summaryData.invoice_remaining_amount;
  1127. const remaining_tickets = summaryData === undefined || summaryData.remaining_tickets === '' ? '0' : summaryData.remaining_tickets;
  1128. const invoice_needed_amount = summaryData === undefined || summaryData.invoice_needed_amount === '' ? '0' : summaryData.invoice_needed_amount;
  1129. const ticket_difference = summaryData === undefined || summaryData.ticket_difference === '' ? '0' : summaryData.ticket_difference;
  1130. const adjustment_value = summaryData === undefined || summaryData.adjustment_value === '' ? '0' : summaryData.adjustment_value;
  1131. const receivable_ticket = channelData.reduce((total, item) => {
  1132. return total + parseFloat(item.total_amounts);
  1133. }, 0);
  1134. const total_received_tickets = channelData.reduce((total, item) => {
  1135. return total + parseFloat(item.total_invoiced);
  1136. }, 0);
  1137. const issuable_ticket = merchantData.reduce((total, item) => {
  1138. return total + parseFloat(item.total_amounts);
  1139. }, 0);
  1140. const total_issued_tickets = merchantData.reduce((total, item) => {
  1141. return total + parseFloat(item.total_invoiced);
  1142. }, 0);
  1143. const pending_tickets = merchantData.reduce((total, item) => {
  1144. const estimated_invoice_amount = parseFloat(item.estimated_invoice_amount);
  1145. if (estimated_invoice_amount > 0) {
  1146. return total + estimated_invoice_amount;
  1147. }
  1148. return total;
  1149. }, 0);
  1150. for (const chan of channelData) { //合并的单元格属性,合并项的数值保持一致
  1151. chan.invoice_remaining_amount = formatDecimals(invoice_remaining_amount);
  1152. chan.invoice_needed_amount = formatDecimals(invoice_needed_amount);
  1153. chan.receivable_ticket = formatDecimals(receivable_ticket);
  1154. chan.total_received_tickets = formatDecimals(total_received_tickets);
  1155. chan.issuable_ticket = formatDecimals(issuable_ticket);
  1156. chan.total_issued_tickets = formatDecimals(total_issued_tickets);
  1157. chan.remaining_tickets = formatDecimals(remaining_tickets);
  1158. chan.pending_tickets = formatDecimals(pending_tickets);
  1159. chan.ticket_difference = formatDecimals(ticket_difference);
  1160. chan.adjustment_value = formatDecimals(adjustment_value);
  1161. }
  1162. layui.table.render({
  1163. elem: '#' + this.tableId,
  1164. data: channelData,
  1165. limit: channelData.length,
  1166. cols: [[
  1167. {field: 'store_name', title: '上游', width: 150},
  1168. {field: 'total_amounts', title: '总计', width: 200},
  1169. {field: 'receivable_ticket', title: '应该收票', width: 200},
  1170. {field: 'total_invoiced', title: '已开', width: 150},
  1171. {field: 'total_received_tickets', title: '总计收票', width: 150},
  1172. {field: 'adjustment_value', title: '矫正值(含跨年)', width: 150},
  1173. {field: 'issuable_ticket', title: '应出票', width: 150},
  1174. {field: 'total_issued_tickets', title: '总计出票', width: 150},
  1175. {field: 'remaining_tickets', title: '剩余票', width: 150},
  1176. {field: 'pending_tickets', title: '待开票', width: 150},
  1177. {field: 'ticket_difference', title: '差额', width: 150},
  1178. {field: 'invoice_remaining_amount', title: '现有多少票', width: 150},
  1179. {field: 'invoice_needed_amount', title: '需进票', width: 150},
  1180. ]],
  1181. done: function (res, curr, count) {
  1182. that.mergeCells();
  1183. that.setRole();
  1184. that.setEditCell();
  1185. that.updateTable();
  1186. }
  1187. });
  1188. }
  1189. calcTicketDifference() {
  1190. const tbRoot = $('#' + this.tableId);
  1191. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1192. trs.each(function(i, tr) {
  1193. const pending_tickets = $(tr).find('td[data-field="pending_tickets"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  1194. const remaining_tickets = $(tr).find('td[data-field="remaining_tickets"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  1195. const $ticketDifferenceEl = $(tr).find('td[data-field="ticket_difference"]').not('.layui-hide').find('.layui-table-cell');
  1196. if ($ticketDifferenceEl.length > 0) {
  1197. const ticket_difference = parseFloat(remaining_tickets) - parseFloat(pending_tickets);
  1198. $ticketDifferenceEl.html(formatDecimals(ticket_difference));
  1199. }
  1200. });
  1201. }
  1202. calcInvoiceNeededAmount() {
  1203. const tbRoot = $('#' + this.tableId);
  1204. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1205. trs.each(function(i, tr) {
  1206. const pending_tickets = $(tr).find('td[data-field="pending_tickets"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  1207. const invoice_remaining_amount = $(tr).find('td[data-field="invoice_remaining_amount"]').not('.layui-hide').find('.layui-table-cell').text().trim();
  1208. const $invoiceNeededAmountEl = $(tr).find('td[data-field="invoice_needed_amount"]').not('.layui-hide').find('.layui-table-cell');
  1209. if ($invoiceNeededAmountEl.length > 0) {
  1210. const invoice_needed_amount = parseFloat(invoice_remaining_amount) - parseFloat(pending_tickets);
  1211. $invoiceNeededAmountEl.html(formatDecimals(invoice_needed_amount));
  1212. }
  1213. });
  1214. }
  1215. updateTable() {
  1216. this.setValueClass(['total_amounts', 'receivable_ticket', 'total_invoiced', 'total_received_tickets', 'issuable_ticket', 'total_issued_tickets', 'remaining_tickets', 'pending_tickets', 'ticket_difference', 'invoice_needed_amount']);
  1217. }
  1218. mergeCells() {
  1219. const tbRoot = $('#' + this.tableId);
  1220. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1221. const mergeColumns = ['receivable_ticket', 'total_received_tickets', 'issuable_ticket', 'total_issued_tickets', 'remaining_tickets', 'pending_tickets', 'ticket_difference', 'invoice_remaining_amount', 'adjustment_value', 'invoice_needed_amount'];
  1222. for (let col of mergeColumns) {
  1223. trs.eq(0).find('td[data-field="' + col + '"]').attr('rowspan', this.lines);
  1224. for (let j = 1; j < this.lines; j++) {
  1225. trs.eq(j).find('td[data-field="' + col + '"]').addClass('layui-hide');
  1226. }
  1227. }
  1228. }
  1229. setEditCell() {
  1230. const that = this;
  1231. const tbRoot = $('#' + this.tableId);
  1232. const trs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1233. trs.each(function (i, tr) {
  1234. const editNumberColumns = ['remaining_tickets', 'ticket_difference', 'invoice_remaining_amount', 'adjustment_value', 'invoice_needed_amount'];
  1235. for (let col of editNumberColumns) {
  1236. const td = $(tr).find('td[data-field="' + col + '"]').not('.layui-hide');
  1237. const valDiv = td.find('div');
  1238. valDiv.attr('contenteditable', true).css('background-color', 'lightblue');
  1239. valDiv.off('input', handleInputd2)
  1240. .off('keypress')
  1241. .off('blur')
  1242. .on('input', handleInputd2)
  1243. .on('keypress', function (e) {
  1244. if (e.keyCode === 13) {
  1245. e.preventDefault();
  1246. $(this).blur();
  1247. }
  1248. })
  1249. .on('blur', async function () {
  1250. let val = valDiv.text().trim();
  1251. if (!isNumeric(val)) {
  1252. valDiv.html('0');
  1253. }
  1254. val = normalizeAmount(val);//过滤,比如前导 0
  1255. valDiv.html(formatDecimals(val));
  1256. if (col === 'invoice_remaining_amount' || col === 'adjustment_value') {
  1257. that.calcInvoiceNeededAmount();
  1258. }
  1259. if (col === 'remaining_tickets') {
  1260. that.calcTicketDifference();
  1261. }
  1262. const index = $(this).parent().parent().data('index');
  1263. await that.saveEdit(index);
  1264. that.updateTable();
  1265. });
  1266. }
  1267. });
  1268. }
  1269. async saveEdit(index) {
  1270. const summaryData = dataHelper.getSummaryList();
  1271. if (index >= summaryData.length) {
  1272. console.error('主体数据错误:编辑索引大于主体总数');
  1273. return;
  1274. }
  1275. const tr = $('#' + this.tableId).next('.layui-table-view').find('.layui-table-body tbody tr[data-index="' + index + '"]');
  1276. const invoice_remaining_amount = tr.find('td[data-field="invoice_remaining_amount"]').find('div').not('.layui-hide').text().trim();
  1277. const remaining_tickets = tr.find('td[data-field="remaining_tickets"]').find('div').not('.layui-hide').text().trim();
  1278. const invoice_needed_amount = tr.find('td[data-field="invoice_needed_amount"]').find('div').not('.layui-hide').text().trim();
  1279. const ticket_difference = tr.find('td[data-field="ticket_difference"]').find('div').not('.layui-hide').text().trim();
  1280. const adjustment_value = tr.find('td[data-field="adjustment_value"]').find('div').not('.layui-hide').text().trim();
  1281. let item = dataHelper.getSummaryList().find(item => item.subject === this.subject);
  1282. if (item === undefined) {
  1283. item = {
  1284. sort: 0,
  1285. subject: this.subject,
  1286. invoice_remaining_amount: invoice_remaining_amount,
  1287. remaining_tickets: remaining_tickets,
  1288. invoice_needed_amount: invoice_needed_amount,
  1289. ticket_difference: ticket_difference,
  1290. adjustment_value: adjustment_value
  1291. };
  1292. } else {
  1293. item.invoice_remaining_amount = invoice_remaining_amount;
  1294. item.remaining_tickets = remaining_tickets;
  1295. item.invoice_needed_amount = invoice_needed_amount;
  1296. item.ticket_difference = ticket_difference;
  1297. item.adjustment_value = adjustment_value;
  1298. }
  1299. await dataHelper.addOrUpdateData(CONSTANTS.KEY_QUOTA_SUMMARY, item, 1);
  1300. const that = this;
  1301. setTimeout(function () {
  1302. that.renderTable();
  1303. }, 0);
  1304. }
  1305. channelTableData() {
  1306. const data = [];
  1307. const channelTb = $('#' + channelTable.tableId);
  1308. const channelTrs = channelTb.next('.layui-table-view').find('.layui-table-body tbody tr');
  1309. channelTrs.each(function (i, tr) {
  1310. const subject = $(tr).find('td[data-field="subject"]').find('div').text();
  1311. const store_name = $(tr).find('td[data-field="store_name"]').find('div').text();
  1312. const total_amounts = $(tr).find('td[data-field="total_amounts"]').find('div').text();
  1313. const total_invoiced = $(tr).find('td[data-field="total_invoiced"]').find('div').text();
  1314. const estimated_invoice_amount = $(tr).find('td[data-field="estimated_invoice_amount"]').find('div').text();
  1315. data.push({
  1316. subject,
  1317. store_name,
  1318. total_amounts,
  1319. total_invoiced,
  1320. estimated_invoice_amount
  1321. });
  1322. });
  1323. return data;
  1324. }
  1325. merchantTableData() {
  1326. const data = [];
  1327. const merchantTb = $('#' + merchantTable.tableId);
  1328. const merchantTrs = merchantTb.next('.layui-table-view').find('.layui-table-body tbody tr');
  1329. merchantTrs.each(function (i, tr) {
  1330. const subject = $(tr).find('td[data-field="subject"]').find('div').text();
  1331. const total_amounts = $(tr).find('td[data-field="total_amounts"]').find('div').text();
  1332. const month_amounts = $(tr).find('td[data-field="month_amounts"]').find('div').text();
  1333. const total_invoiced = $(tr).find('td[data-field="total_invoiced"]').find('div').text();
  1334. const month_opened = $(tr).find('td[data-field="month_opened"]').find('div').text();
  1335. const estimated_invoice_amount = $(tr).find('td[data-field="estimated_invoice_amount"]').find('div').text();
  1336. data.push({
  1337. subject,
  1338. total_amounts,
  1339. month_amounts,
  1340. total_invoiced,
  1341. month_opened,
  1342. estimated_invoice_amount
  1343. });
  1344. });
  1345. return data;
  1346. }
  1347. setRole() {
  1348. if (isAdmin === true) {
  1349. return;
  1350. }
  1351. const tbRoot = $('#' + this.tableId);
  1352. const bodyTrs = tbRoot.next('.layui-table-view').find('.layui-table-body tbody tr');
  1353. const headerTrs = tbRoot.next('.layui-table-view').find('.layui-table-header thead tr');
  1354. const hideColumns = ['channel_amounts', 'channel_total_invoiced'];
  1355. for (let col of hideColumns) {
  1356. bodyTrs.each(function (i, tr) {
  1357. $(tr).find('td[data-field="' + col + '"]').addClass('layui-hide');
  1358. });
  1359. headerTrs.each(function (i, tr) {
  1360. $(tr).find('th[data-field="' + col + '"]').addClass('layui-hide');
  1361. });
  1362. }
  1363. }
  1364. }
  1365. class BatchWorkflow extends TaskManager {
  1366. constructor(prefix) {
  1367. super();
  1368. this.initializeGlobalTaskList();
  1369. this.prefix = prefix; //mch/chan
  1370. }
  1371. getTaskType() {
  1372. return 'batch_quota_' + this.prefix;
  1373. }
  1374. getPendingTasksByApprover() {
  1375. const tasks = super.getPendingTasks();
  1376. return tasks.filter(task => task.approver === 'admin');
  1377. }
  1378. getPendingTaskDetails() {
  1379. const worklist = this.getPendingTasksByApprover();
  1380. return worklist.reduce((acc, obj) => {
  1381. const formattedTime = formatDateTime(obj.time);
  1382. const itemsWithTime = obj.data.items.map(item => ({
  1383. ...item,
  1384. time: formattedTime
  1385. }));
  1386. return acc.concat(itemsWithTime);
  1387. }, []);
  1388. }
  1389. async invalidateItem(type, type_id) {
  1390. const tasks = this.getPendingTasksByApprover();
  1391. for (const task of tasks) {
  1392. const updatedItems = task.data.items.filter(item =>
  1393. !(item.type === type && item.type_id === type_id)
  1394. );
  1395. if (updatedItems.length !== task.data.items.length) {
  1396. const newData = { ...task.data, items: updatedItems };
  1397. const updateSuccess = await this.updateTask(
  1398. task.id,
  1399. updatedItems.length > 0 ? newData : {}
  1400. );
  1401. if (!updateSuccess) {
  1402. console.error(`Failed to update task ${task.id} after removing item ${type_id}`);
  1403. return false;
  1404. }
  1405. }
  1406. }
  1407. return true;
  1408. }
  1409. }
  1410. class BatchInvoice {
  1411. constructor(type) {
  1412. this.type = type;
  1413. this.workflow = new BatchWorkflow(type);
  1414. this.dv = 1; //数据版本,作用:由于需求变化导致存储的缓存数据格式发生变化,由该字段标记,审核的时候如果数据版本与当前dv版本不一致,需要手动作废审核重新操作。
  1415. }
  1416. lineData(targetRow) {
  1417. let typeId = '', typeName = '';
  1418. const type = this.type;
  1419. if (type === 'mch') {
  1420. typeId = 'mch_id';
  1421. typeName = 'mch_name';
  1422. } else {
  1423. typeId = 'store_id';
  1424. typeName = 'store_name';
  1425. }
  1426. const subject = targetRow.find('td[data-field="subject"]').find('div').text().trim();
  1427. const type_id = targetRow.find(`td[data-field="${typeId}"]`).find('div').text().trim();
  1428. const type_name = targetRow.find(`td[data-field="${typeName}"]`).find('div').text().trim();
  1429. const amounts = targetRow.find('td[data-field="amounts"]').find('div').text().trim();
  1430. const total_invoiced = targetRow.find('td[data-field="total_invoiced"]').find('div').text().trim();
  1431. const invoice_date = targetRow.find('td[data-field="invoice_date"]').find('div').find('input').val().trim();
  1432. const available_invoice_amount = targetRow.find('td[data-field="available_invoice_amount"]').find('div').text().trim();
  1433. const actual_invoice_amount = targetRow.find('td[data-field="actual_invoice_amount"]').find('div').text().trim();
  1434. const operator = targetRow.find('td[data-field="operator"]').find('div').text().trim();
  1435. const remark = targetRow.find('td[data-field="remark"]').find('div').text().trim();
  1436. return {
  1437. type,
  1438. subject,
  1439. type_id,
  1440. type_name,
  1441. amounts,
  1442. total_invoiced,
  1443. invoice_date,
  1444. available_invoice_amount,
  1445. actual_invoice_amount,
  1446. operator,
  1447. remark
  1448. };
  1449. }
  1450. doApplyOne(tableId, index) {
  1451. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1452. const targetRow = trs.eq(index);
  1453. const taskData = this.lineData(targetRow);
  1454. if (!isNumeric(taskData.actual_invoice_amount)
  1455. || taskData.actual_invoice_amount === '0') {
  1456. showErr(`${taskData.type_name} 金额设置无效`);
  1457. return;
  1458. }
  1459. if (!isValidDate(taskData.invoice_date)) {
  1460. showErr(`${taskData.type_name} 开票日期 设置无效`);
  1461. return;
  1462. }
  1463. if (taskData.operator === '') {
  1464. showErr(`${taskData.type_name} 操作人 设置无效`);
  1465. return;
  1466. }
  1467. this.doApply([taskData]);
  1468. }
  1469. doApplyMore(tableId) {
  1470. const that = this;
  1471. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1472. const taskDatas = [], errs = [];
  1473. trs.each(function(i, targetRow) {
  1474. const taskData = that.lineData($(targetRow));
  1475. if (!isNumeric(taskData.actual_invoice_amount)
  1476. || taskData.actual_invoice_amount === '0') {
  1477. return;
  1478. }
  1479. if (!isValidDate(taskData.invoice_date)) {
  1480. const err = `${taskData.type_name} 开票日期 设置错误`;
  1481. if (!err.includes(err)) {
  1482. err.push(err);
  1483. }
  1484. return;
  1485. }
  1486. if (taskData.operator === '') {
  1487. const err = `${taskData.type_name} 操作人 设置错误`;
  1488. if (!err.includes(err)) {
  1489. err.push(err);
  1490. }
  1491. return;
  1492. }
  1493. taskDatas.push(taskData);
  1494. });
  1495. if (errs.length > 0) {
  1496. showErr(errs.join('<br />'));
  1497. return;
  1498. }
  1499. if (taskDatas.length === 0) {
  1500. showErr('没有设置申请信息');
  1501. return;
  1502. }
  1503. this.doApply(taskDatas);
  1504. }
  1505. async doApply(invoiceUnit) {
  1506. const that = this;
  1507. let errsNormal = [];
  1508. await this.workflow.initializeGlobalTaskList();
  1509. const pendingTasks = this.workflow.getPendingTasksByApprover();
  1510. pendingTasks.forEach(taskItem => {
  1511. const currItems = taskItem.data.items || [];
  1512. currItems.forEach(currItem => {
  1513. const isPending = invoiceUnit.find(invoiceItem => {
  1514. return currItem.type === invoiceItem.type && currItem.type_id === invoiceItem.type_id;
  1515. });
  1516. if (isPending !== undefined) {
  1517. const err = `${currItem.type_name} 存在处理中的开票申请,审核后才能再次申请`;
  1518. if (!errsNormal.includes(err)) {
  1519. errsNormal.push(err);
  1520. }
  1521. }
  1522. });
  1523. });
  1524. if (errsNormal.length > 0) {
  1525. showErr(errsNormal.join('<br />'));
  1526. return;
  1527. }
  1528. const applyTrnasfer = () => {
  1529. const sortedInvoiceUnit = sortByName(invoiceUnit, 'type_name');
  1530. const title = that.type === 'mch' ? '机构名称' : '通道名称';
  1531. layui.table.render({
  1532. elem: '#tb_apply',
  1533. data: sortedInvoiceUnit,
  1534. limit: sortedInvoiceUnit.length,
  1535. cols: [[
  1536. {field: 'subject', title: '对应主体', width: 200},
  1537. {field: 'type_name', title: title, width: 200},
  1538. {field: 'actual_invoice_amount', title: '本次开票金额', width: 200},
  1539. {field: 'invoice_date', title: '开票日期', width: 200},
  1540. {field: 'operator', title: '操作人', width: 100},
  1541. {field: 'remark', title: '备注', width: 200},
  1542. ]],
  1543. done: function (res, curr, count) {
  1544. }
  1545. });
  1546. layer.open({
  1547. type: 1,
  1548. title: '开票确认',
  1549. area: ['1150px', '500px'],
  1550. content: $('#rechargeManual'),
  1551. btn: ['确定', '取消'],
  1552. success: function (layero) {
  1553. },
  1554. btn1: function () {
  1555. layer.closeAll();
  1556. const taskData = filterJsonFields(invoiceUnit, ["type", "subject", "type_id", "type_name", "amounts", "total_invoiced", "invoice_date", "available_invoice_amount", "actual_invoice_amount", "operator", "remark"]);
  1557. const applyData = {
  1558. items: taskData,
  1559. dv: that.dv
  1560. };
  1561. that.workflow.addTask(applyData, systemUserName, 'admin')
  1562. .then(succ => {
  1563. if (succ === true) {
  1564. showSuccess('已发起开票申请');
  1565. } else {
  1566. showErr('处理失败,请重试');
  1567. }
  1568. });
  1569. },
  1570. });
  1571. };
  1572. applyTrnasfer();
  1573. }
  1574. async doBatchInvoice() {
  1575. const that = this;
  1576. let sortedInvoiceUnit = [], worklist = [], invoiceUnit = [], paySum = 0, isCorrectVersion = true;
  1577. const loadinvoiceUnit = async () => {
  1578. await this.workflow.initializeGlobalTaskList();
  1579. worklist = this.workflow.getPendingTasksByApprover();
  1580. for (const task of worklist) {
  1581. if (Number(task.data.dv) !== that.dv) {
  1582. isCorrectVersion = false;
  1583. break;
  1584. }
  1585. }
  1586. invoiceUnit = this.workflow.getPendingTaskDetails();
  1587. sortedInvoiceUnit = sortByName(invoiceUnit, 'type_name');
  1588. };
  1589. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  1590. await loadinvoiceUnit();
  1591. if (isCorrectVersion === false) {
  1592. setTimeout(function() {
  1593. showErr('数据与当前程序版本不匹配,请作废当前数据后重新加款');
  1594. }, 500);
  1595. }
  1596. const title = that.type === 'mch' ? '机构名称' : '通道名称';
  1597. layui.table.render({
  1598. elem: '#tb_approve',
  1599. data: sortedInvoiceUnit,
  1600. limit: sortedInvoiceUnit.length,
  1601. cols: [[
  1602. {field: 'subject', title: '对应主体', width: 200},
  1603. {field: 'type_name', title: title, width: 200},
  1604. {field: 'actual_invoice_amount', title: '本次开票金额', width: 200},
  1605. {field: 'invoice_date', title: '开票日期', width: 200},
  1606. {field: 'operator', title: '操作人', width: 100},
  1607. {field: 'remark', title: '备注', width: 200},
  1608. {field: 'void_task', title: '', width: 100, templet: function(d){return '<button class="layui-btn layui-btn-sm layui-btn-primary task-void-btn" style="margin: 0" data-index="'+d.LAY_TABLE_INDEX+'">作废</button>';}}
  1609. ]],
  1610. done: function (res, curr, count) {
  1611. const tbRoot = $('#tb_approve');
  1612. const voidOneEvent = () => {
  1613. tbRoot.next('.layui-table-view').off('click', '.task-void-btn').on('click', '.task-void-btn', function () {
  1614. const index = $(this).data('index');
  1615. layer.confirm(`确认作废 ${sortedInvoiceUnit[index].type_name} 的开票申请吗?`, {
  1616. title: '提示',
  1617. btn: ['确定', '取消']
  1618. }, async (confirmIndex) => {
  1619. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  1620. await that.workflow.initializeGlobalTaskList();
  1621. const succ = await that.workflow.invalidateItem(that.type, sortedInvoiceUnit[index].type_id);
  1622. if (succ === true) {
  1623. await loadinvoiceUnit();
  1624. layui.table.reload('tb_approve', {
  1625. data: sortedInvoiceUnit
  1626. });
  1627. } else {
  1628. showErr('作废失败');
  1629. }
  1630. layer.close(loadIndex);
  1631. layer.close(confirmIndex);
  1632. });
  1633. });
  1634. };
  1635. voidOneEvent();
  1636. layer.close(loadIndex);
  1637. }
  1638. });
  1639. layer.open({
  1640. type: 1,
  1641. title: '开票审核',
  1642. area: ['1280px', '500px'],
  1643. content: $('#rechargeManualApprove'),
  1644. btn: ['批准', '作废'],
  1645. success: function (layero) {
  1646. },
  1647. btn1: async function () {
  1648. if (worklist.length === 0) {
  1649. showErr('没有待审核的开票申请');
  1650. return false;
  1651. }
  1652. if (isCorrectVersion === false) {
  1653. showErr('数据与当前程序版本不匹配,请作废当前数据后重新加款');
  1654. return false;
  1655. }
  1656. layer.load(2, {shade: [0.2, '#000']});
  1657. let typeData = [], typeField = '';
  1658. if (that.type === 'mch') {
  1659. await dataHelper.loadMerchant();
  1660. typeData = dataHelper.getMerchantList();
  1661. typeData.forEach(tItem => {
  1662. setEmptyFieldsToZero(tItem, ['total_invoiced', 'month_opened']);
  1663. });
  1664. typeField = 'mch_id';
  1665. } else {
  1666. await dataHelper.loadChannel();
  1667. typeData = dataHelper.getChannelList();
  1668. typeData.forEach(tItem => {
  1669. setEmptyFieldsToZero(tItem, ['total_invoiced', 'month_opened']);
  1670. });
  1671. typeField = 'store_id';
  1672. }
  1673. const companyData = dataHelper.getCompanyList();
  1674. for (const task of worklist) {
  1675. await that.workflow.executeTask(task.id, async () => {
  1676. const applyItems = task.data.items;
  1677. applyItems.forEach(aItem => {
  1678. if (aItem.type !== that.type) {
  1679. console.error('数据错误', that.type, aItem);
  1680. return;
  1681. }
  1682. const typeItem = typeData.find(tItem => tItem[typeField] === aItem.type_id);
  1683. const total_invoiced = parseFloat(typeItem.total_invoiced) + parseFloat(aItem.actual_invoice_amount);
  1684. const month_opened = parseFloat(typeItem.month_opened) + parseFloat(aItem.actual_invoice_amount);
  1685. typeItem.total_invoiced = total_invoiced.toString();
  1686. typeItem.last_invoice_date = aItem.invoice_date;
  1687. typeItem.month_opened = month_opened.toString();
  1688. const activeCompany = companyData.find(cItem => cItem.name === aItem.subject);
  1689. if (activeCompany !== undefined) {
  1690. const used_quota = parseFloat(activeCompany.used_quota) + parseFloat(aItem.actual_invoice_amount);
  1691. activeCompany.used_quota = used_quota.toString();
  1692. }
  1693. });
  1694. });
  1695. }
  1696. if (that.type === 'mch') {
  1697. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_MERCHANT, typeData);
  1698. await merchantTable.renderTable();
  1699. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_COMPANY, companyData);
  1700. companyTable.renderTable();
  1701. renderSummaryTables();
  1702. } else if (that.type === 'chan') {
  1703. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_CHANNEL, typeData);
  1704. await channelTable.renderTable();
  1705. renderSummaryTables();
  1706. }
  1707. layer.closeAll();
  1708. },
  1709. btn2: function () {
  1710. if (worklist.length === 0) {
  1711. showErr('没有可作废的开票申请');
  1712. return;
  1713. }
  1714. layer.confirm(`确认批量作废开票申请吗?`, {
  1715. title: '提示',
  1716. btn: ['确定', '取消']
  1717. }, async () => {
  1718. layer.load(2, {shade: [0.2, '#000']});
  1719. for (const task of worklist) {
  1720. await that.workflow.executeTask(task.id, async () => {});
  1721. }
  1722. layer.closeAll();
  1723. showSuccess('开票申请已作废');
  1724. });
  1725. return false;
  1726. }
  1727. });
  1728. }
  1729. }
  1730. class BatchCorrected {
  1731. constructor() {
  1732. this.workflow = new BatchWorkflow('company');
  1733. this.dv = 1; //数据版本,作用:由于需求变化导致存储的缓存数据格式发生变化,由该字段标记,审核的时候如果数据版本与当前dv版本不一致,需要手动作废审核重新操作。
  1734. }
  1735. lineData(targetRow) {
  1736. const name = targetRow.find('td[data-field="name"]').find('div').text().trim();
  1737. const corrected_used_quota = targetRow.find('td[data-field="corrected_used_quota"]').find('div').text().trim();
  1738. const operator = targetRow.find('td[data-field="operator"]').find('div').text().trim();
  1739. const remark = targetRow.find('td[data-field="remark"]').find('div').text().trim();
  1740. return {
  1741. name,
  1742. corrected_used_quota,
  1743. operator,
  1744. remark
  1745. };
  1746. }
  1747. doApplyOne(tableId, index) {
  1748. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1749. const targetRow = trs.eq(index);
  1750. const taskData = this.lineData(targetRow);
  1751. if (!isNumeric(taskData.corrected_used_quota)
  1752. || taskData.corrected_used_quota === '0') {
  1753. showErr(`${taskData.name} 矫正金额设置无效`);
  1754. return;
  1755. }
  1756. if (taskData.operator === '') {
  1757. showErr(`${taskData.name} 操作人 设置无效`);
  1758. return;
  1759. }
  1760. this.doApply([taskData]);
  1761. }
  1762. doApplyMore(tableId) {
  1763. const that = this;
  1764. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  1765. const taskDatas = [], errs = [];
  1766. trs.each(function(i, targetRow) {
  1767. const taskData = that.lineData($(targetRow));
  1768. if (!isNumeric(taskData.corrected_used_quota)
  1769. || taskData.corrected_used_quota === '0'
  1770. || Number(taskData.corrected_used_quota) < 0) {
  1771. return;
  1772. }
  1773. if (taskData.operator === '') {
  1774. const err = `${taskData.type_name} 操作人 设置错误`;
  1775. if (!err.includes(err)) {
  1776. err.push(err);
  1777. }
  1778. return;
  1779. }
  1780. taskDatas.push(taskData);
  1781. });
  1782. if (errs.length > 0) {
  1783. showErr(errs.join('<br />'));
  1784. return;
  1785. }
  1786. if (taskDatas.length === 0) {
  1787. showErr('没有设置矫正项');
  1788. return;
  1789. }
  1790. this.doApply(taskDatas);
  1791. }
  1792. async doApply(companyUnit) {
  1793. const that = this;
  1794. let errsNormal = [];
  1795. await this.workflow.initializeGlobalTaskList();
  1796. const pendingTasks = this.workflow.getPendingTasksByApprover();
  1797. pendingTasks.forEach(taskItem => {
  1798. const currItems = taskItem.data.items || [];
  1799. currItems.forEach(currItem => {
  1800. const isPending = companyUnit.find(cItem => {
  1801. return currItem.name === cItem.name;
  1802. });
  1803. if (isPending !== undefined) {
  1804. const err = `${currItem.type_name} 存在处理中的矫正申请,审核后才能再次申请`;
  1805. if (!errsNormal.includes(err)) {
  1806. errsNormal.push(err);
  1807. }
  1808. }
  1809. });
  1810. });
  1811. if (errsNormal.length > 0) {
  1812. showErr(errsNormal.join('<br />'));
  1813. return;
  1814. }
  1815. const applyTrnasfer = () => {
  1816. const sortedCompanyUnit = sortByName(companyUnit, 'name');
  1817. layui.table.render({
  1818. elem: '#tb_apply',
  1819. data: sortedCompanyUnit,
  1820. limit: sortedCompanyUnit.length,
  1821. cols: [[
  1822. {field: 'name', title: '对应主体', width: 200},
  1823. {field: 'corrected_used_quota', title: '矫正金额', width: 200},
  1824. {field: 'operator', title: '操作人', width: 100},
  1825. {field: 'remark', title: '备注', width: 200},
  1826. ]],
  1827. done: function (res, curr, count) {
  1828. }
  1829. });
  1830. layer.open({
  1831. type: 1,
  1832. title: '已用额度矫正',
  1833. area: ['1150px', '500px'],
  1834. content: $('#rechargeManual'),
  1835. btn: ['确定', '取消'],
  1836. success: function (layero) {
  1837. },
  1838. btn1: function () {
  1839. layer.closeAll();
  1840. const taskData = filterJsonFields(companyUnit, ["name", "corrected_used_quota", "operator", "remark"]);
  1841. const applyData = {
  1842. items: taskData,
  1843. dv: that.dv
  1844. };
  1845. that.workflow.addTask(applyData, systemUserName, 'admin')
  1846. .then(succ => {
  1847. if (succ === true) {
  1848. showSuccess('已发起已用额度矫正申请');
  1849. } else {
  1850. showErr('处理失败,请重试');
  1851. }
  1852. });
  1853. },
  1854. });
  1855. };
  1856. applyTrnasfer();
  1857. }
  1858. async doBatchCorrected() {
  1859. const that = this;
  1860. let sortedCompanyUnit = [], worklist = [], companyUnit = [], isCorrectVersion = true;
  1861. const loadCompanyUnit = async () => {
  1862. await this.workflow.initializeGlobalTaskList();
  1863. worklist = this.workflow.getPendingTasksByApprover();
  1864. for (const task of worklist) {
  1865. if (Number(task.data.dv) !== that.dv) {
  1866. isCorrectVersion = false;
  1867. break;
  1868. }
  1869. }
  1870. companyUnit = this.workflow.getPendingTaskDetails();
  1871. sortedCompanyUnit = sortByName(companyUnit, 'name');
  1872. };
  1873. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  1874. await loadCompanyUnit();
  1875. if (isCorrectVersion === false) {
  1876. setTimeout(function() {
  1877. showErr('数据与当前程序版本不匹配,请作废当前数据后重新加款');
  1878. }, 500);
  1879. }
  1880. layui.table.render({
  1881. elem: '#tb_approve',
  1882. data: sortedCompanyUnit,
  1883. limit: sortedCompanyUnit.length,
  1884. cols: [[
  1885. {field: 'name', title: '对应主体', width: 200},
  1886. {field: 'corrected_used_quota', title: '矫正金额', width: 200},
  1887. {field: 'operator', title: '操作人', width: 100},
  1888. {field: 'remark', title: '备注', width: 200},
  1889. {field: 'void_task', title: '', width: 100, templet: function(d){return '<button class="layui-btn layui-btn-sm layui-btn-primary task-void-btn" style="margin: 0" data-index="'+d.LAY_TABLE_INDEX+'">作废</button>';}}
  1890. ]],
  1891. done: function (res, curr, count) {
  1892. const tbRoot = $('#tb_approve');
  1893. const voidOneEvent = () => {
  1894. tbRoot.next('.layui-table-view').off('click', '.task-void-btn').on('click', '.task-void-btn', function () {
  1895. const index = $(this).data('index');
  1896. layer.confirm(`确认作废 ${sortedCompanyUnit[index].name} 的矫正申请吗?`, {
  1897. title: '提示',
  1898. btn: ['确定', '取消']
  1899. }, async (confirmIndex) => {
  1900. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  1901. await that.workflow.initializeGlobalTaskList();
  1902. const succ = await that.workflow.invalidateItem(sortedCompanyUnit[index].name);
  1903. if (succ === true) {
  1904. await loadCompanyUnit();
  1905. layui.table.reload('tb_approve', {
  1906. data: sortedCompanyUnit
  1907. });
  1908. } else {
  1909. showErr('作废失败');
  1910. }
  1911. layer.close(loadIndex);
  1912. layer.close(confirmIndex);
  1913. });
  1914. });
  1915. };
  1916. voidOneEvent();
  1917. layer.close(loadIndex);
  1918. }
  1919. });
  1920. layer.open({
  1921. type: 1,
  1922. title: '已用额度矫正审核',
  1923. area: ['1280px', '500px'],
  1924. content: $('#rechargeManualApprove'),
  1925. btn: ['批准', '作废'],
  1926. success: function (layero) {
  1927. },
  1928. btn1: async function () {
  1929. if (worklist.length === 0) {
  1930. showErr('没有待审核的矫正申请');
  1931. return false;
  1932. }
  1933. if (isCorrectVersion === false) {
  1934. showErr('数据与当前程序版本不匹配,请作废当前数据后重新加款');
  1935. return false;
  1936. }
  1937. layer.load(2, {shade: [0.2, '#000']});
  1938. await dataHelper.loadComapny();
  1939. const companyData = dataHelper.getCompanyList();
  1940. for (const task of worklist) {
  1941. await that.workflow.executeTask(task.id, async () => {
  1942. const applyItems = task.data.items;
  1943. applyItems.forEach(aItem => {
  1944. const activeCompany = companyData.find(cItem => cItem.name === aItem.name);
  1945. const used_quota = parseFloat(activeCompany.used_quota) + parseFloat(aItem.corrected_used_quota);
  1946. activeCompany.used_quota = used_quota.toString();
  1947. });
  1948. });
  1949. }
  1950. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_COMPANY, companyData);
  1951. companyTable.renderTable();
  1952. renderSummaryTables();
  1953. layer.closeAll();
  1954. },
  1955. btn2: function () {
  1956. if (worklist.length === 0) {
  1957. showErr('没有可作废的申请');
  1958. return;
  1959. }
  1960. layer.confirm(`确认批量作废 已用额度矫正 申请吗?`, {
  1961. title: '提示',
  1962. btn: ['确定', '取消']
  1963. }, async () => {
  1964. layer.load(2, {shade: [0.2, '#000']});
  1965. for (const task of worklist) {
  1966. await that.workflow.executeTask(task.id, async () => {});
  1967. }
  1968. layer.closeAll();
  1969. showSuccess('已用额度矫正 申请已作废');
  1970. });
  1971. return false;
  1972. }
  1973. });
  1974. }
  1975. }
  1976. function loadMsgBadge () {
  1977. const companyWorkflow = new BatchWorkflow('company');
  1978. const mchWorkflow = new BatchWorkflow('mch');
  1979. const chanWorkflow = new BatchWorkflow('chan');
  1980. const companyBadge = $('#badge-approve-company');
  1981. companyBadge.hide();
  1982. const mchBadge = $('#badge-approve-mch');
  1983. mchBadge.hide();
  1984. const chanBadge = $('#badge-approve-chan');
  1985. chanBadge.hide();
  1986. const refreshApprovalMessage = async () => {
  1987. await companyWorkflow.initializeGlobalTaskList();
  1988. const comMsg = companyWorkflow.getPendingTaskDetails();
  1989. const comNum = comMsg.length || 0;
  1990. companyBadge.html(comNum);
  1991. if (comNum === 0) {
  1992. companyBadge.hide();
  1993. } else {
  1994. companyBadge.show();
  1995. }
  1996. await mchWorkflow.initializeGlobalTaskList();
  1997. const mchMsg = mchWorkflow.getPendingTaskDetails();
  1998. const mchNum = mchMsg.length || 0;
  1999. mchBadge.html(mchNum);
  2000. if (mchNum === 0) {
  2001. mchBadge.hide();
  2002. } else {
  2003. mchBadge.show();
  2004. }
  2005. await chanWorkflow.initializeGlobalTaskList();
  2006. const chanMsg = chanWorkflow.getPendingTaskDetails();
  2007. const chanNum = chanMsg.length || 0;
  2008. chanBadge.html(chanNum);
  2009. if (chanNum === 0) {
  2010. chanBadge.hide();
  2011. } else {
  2012. chanBadge.show();
  2013. }
  2014. }
  2015. refreshApprovalMessage();
  2016. }
  2017. loadMsgBadge();
  2018. $('#btn_refresh_approve').on('click', function() {
  2019. if (systemUserName !== 'admin') {
  2020. showErr('您不是管理员,无审核权限');
  2021. return;
  2022. }
  2023. loadMsgBadge();
  2024. });
  2025. function setTableColVal(tableId, col, val) { //对整列设置值
  2026. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  2027. trs.each(function(i, tr) {
  2028. const td = $(tr).find('td[data-field="' + col + '"]');
  2029. if (td.length > 0) {
  2030. td.find('div').html(val);
  2031. }
  2032. });
  2033. }
  2034. async function conditionSet() {
  2035. const conditionList = dataHelper.getConditionList();
  2036. if (conditionList.length === 0) {
  2037. const month = getCurrentMonth();
  2038. const condition = {
  2039. month
  2040. };
  2041. await dataHelper.addOrUpdateData(CONSTANTS.KEY_QUOTA_CONDITION, condition, 0);
  2042. }
  2043. }
  2044. function getCurrMonthCondition() {
  2045. const conditionList = dataHelper.getConditionList();
  2046. const condition = conditionList[0];
  2047. return condition.month;
  2048. }
  2049. function renderSummaryTables() {
  2050. let $tables = $('#summary-tables');
  2051. $tables.html('');
  2052. const summarys = dataHelper.getSummaryList();
  2053. summarys.forEach(function(item, index) {
  2054. const subject = filterSubjectPrefix(item.subject);
  2055. $tables.append(`<div class="summary-tables-subject">${subject}</div>`);
  2056. const tableId = `tb-summary${item.subject}`;
  2057. $tables.append(`<table class="layui-hide" id="${tableId}"></table>`);
  2058. const summaryTable = new SummaryTable(tableId, item.subject);
  2059. summaryTable.renderTable();
  2060. });
  2061. }
  2062. async function initPage() {
  2063. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  2064. await dataHelper.loadComapny();
  2065. await dataHelper.loadMerchant();
  2066. await dataHelper.loadChannel();
  2067. await dataHelper.loadSummary();
  2068. await dataHelper.loadCondition();
  2069. await conditionSet();
  2070. const currMonth = getCurrMonthCondition();
  2071. $('#query_month').val(currMonth);
  2072. companyTable.renderTable();
  2073. await merchantTable.renderTable();
  2074. await channelTable.renderTable();
  2075. renderSummaryTables();
  2076. //UI回调事件
  2077. app.on('updateCompany', () => {
  2078. companyTable.renderTable();
  2079. renderSummaryTables();
  2080. });
  2081. app.on('updateMerchant', async () => {
  2082. await merchantTable.renderTable();
  2083. renderSummaryTables();
  2084. });
  2085. app.on('updateChannel', async () => {
  2086. await channelTable.renderTable();
  2087. renderSummaryTables();
  2088. });
  2089. app.on('updateSummary', async () => {
  2090. renderSummaryTables();
  2091. });
  2092. loadMsgBadge();
  2093. renderSummaryTables();
  2094. layer.close(loadIndex);
  2095. }
  2096. const batchMchInvoice = new BatchInvoice('mch');
  2097. const batchChanInvoice = new BatchInvoice('chan');
  2098. const batchCorrected = new BatchCorrected();
  2099. const companyTable = new CompanyTable();
  2100. const merchantTable = new MerchantTable();
  2101. const channelTable = new ChannelTable();
  2102. $('.ac-approve').on('click', function () {
  2103. if (systemUserName !== 'admin') {
  2104. showErr('您不是管理员,无审核权限');
  2105. return;
  2106. }
  2107. const tableId = $(this).data('table');
  2108. if (tableId === 'tb-merchant') {
  2109. batchMchInvoice.doBatchInvoice();
  2110. } else if (tableId === 'tb-channel') {
  2111. batchChanInvoice.doBatchInvoice();
  2112. } else if (tableId === 'tb-company') {
  2113. batchCorrected.doBatchCorrected();
  2114. }
  2115. });
  2116. $('.ac-batch-invoice').on('click', function () {
  2117. const tableId = $(this).data('table');
  2118. if (tableId === 'tb-merchant') {
  2119. batchMchInvoice.doApplyMore(tableId);
  2120. } else if (tableId === 'tb-channel') {
  2121. batchChanInvoice.doApplyMore(tableId);
  2122. } else if (tableId === 'tb-company') {
  2123. batchCorrected.doApplyMore(tableId);
  2124. }
  2125. });
  2126. $('.reset-col').on('click', async function () {
  2127. const loadIndex = layer.load(2, {shade: [0.2, '#000']});
  2128. const tableId = $(this).data('table');
  2129. const col = $(this).data('col');
  2130. setTableColVal(tableId, col, '0');
  2131. const activeData = () => {
  2132. const data = [];
  2133. const trs = $('#' + tableId).next('.layui-table-view').find('.layui-table-body tbody tr');
  2134. trs.each(function (i, tr) {
  2135. let typeIdField = '';
  2136. if (tableId === 'tb-merchant') {
  2137. typeIdField = 'mch_id';
  2138. } else if (tableId === 'tb-channel') {
  2139. typeIdField = 'store_id';
  2140. }
  2141. const type_id = $(tr).find('td[data-field="' + typeIdField + '"]').find('div').text();
  2142. data.push({
  2143. type_id
  2144. });
  2145. });
  2146. return data;
  2147. };
  2148. const updateMerchant = async (field) => {
  2149. const activeList = activeData();
  2150. const companyReduce = {};
  2151. const merchantList = dataHelper.getMerchantList();
  2152. merchantList.forEach(item => {
  2153. const ac = activeList.find(aItem => aItem.type_id === item.mch_id);
  2154. if (ac !== undefined) {
  2155. if (!companyReduce[item.subject]) {
  2156. companyReduce[item.subject] = 0;
  2157. }
  2158. companyReduce[item.subject] += parseFloat(item.month_opened);
  2159. item[field] = '0';
  2160. }
  2161. })
  2162. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_MERCHANT, merchantList);
  2163. if (field === 'month_opened') {
  2164. const companyList = dataHelper.getCompanyList();
  2165. companyList.forEach(item => {
  2166. if (companyReduce[item.name] !== undefined) {
  2167. const used_quota_up = parseFloat(item.used_quota) - companyReduce[item.name];
  2168. item.used_quota = used_quota_up.toString();
  2169. }
  2170. });
  2171. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_COMPANY, companyList);
  2172. }
  2173. await merchantTable.renderTable();
  2174. companyTable.renderTable();
  2175. renderSummaryTables();
  2176. };
  2177. const updateChannel = async (field) => {
  2178. const activeList = activeData();
  2179. const channelList = dataHelper.getChannelList();
  2180. channelList.forEach(item => {
  2181. const ac = activeList.find(aItem => aItem.type_id === item.store_id);
  2182. if (ac !== undefined) {
  2183. item[field] = '0';
  2184. }
  2185. })
  2186. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_CHANNEL, channelList);
  2187. await channelTable.renderTable();
  2188. renderSummaryTables();
  2189. };
  2190. if (col === 'actual_invoice_amount') {
  2191. layer.close(loadIndex);
  2192. return;
  2193. }
  2194. if (tableId === 'tb-merchant') {
  2195. await updateMerchant(col);
  2196. } else if (tableId === 'tb-channel') {
  2197. await updateChannel(col);
  2198. }
  2199. layer.close(loadIndex);
  2200. });
  2201. $('#btn-update-all').on('click', function (){
  2202. initPage();
  2203. });
  2204. if (isAdmin === false) {
  2205. $('.reset-bar button:first-child').hide();
  2206. $('.reset-bar button:nth-child(2)').hide();
  2207. $('.reset-bar button:nth-child(3)').css('margin-left', '750px');
  2208. $('.reset-bar button:nth-child(4)').css('margin-left', '150px');
  2209. $('.ac-approve').css('display', 'none');
  2210. } else {
  2211. $('.reset-bar button:first-child').css('margin-left', '745px');
  2212. $('.reset-bar button:nth-child(2)').css('margin-left', '150px');
  2213. $('.reset-bar button:nth-child(3)').css('margin-left', '300px');
  2214. $('.reset-bar button:nth-child(4)').css({
  2215. 'margin-left': '75px',
  2216. 'display': 'inline-block'
  2217. });
  2218. }
  2219. const tMonth = getCurrentMonth();
  2220. laydate.render({
  2221. elem: '#query_month',
  2222. type: 'month',
  2223. trigger: 'click',
  2224. max: tMonth,
  2225. done: async function (value, date, endDate) {
  2226. const condition = {
  2227. month: value
  2228. };
  2229. await dataHelper.updateAllData(CONSTANTS.KEY_QUOTA_CONDITION, [condition]);
  2230. await initPage();
  2231. }
  2232. });
  2233. initPage();
  2234. });
  2235. </script>