kaztbd_add.jsp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. <%@ page import="java.util.Map" %>
  2. <%@ page import="java.util.TreeMap" %>
  3. <%@ page language="java" pageEncoding="UTF-8" isELIgnored="false" %>
  4. <%@ taglib uri="/ssTag" prefix="ss"%>
  5. <% pageContext.setAttribute(ss.page.PageC.PAGE_objName,"kaztbd");%>
  6. <%pageContext.setAttribute("wdpageinformation","{'hastab':'0'}");%>
  7. <!DOCTYPE html>
  8. <html>
  9. <head>
  10. <%@ include file="/page/clip/header.jsp" %>
  11. <style>
  12. .table-container>tr>th{
  13. width:130px !important;
  14. }
  15. /* 把content-box的高度限制 从公共css 抽到具体有需要的页面 by xu 20251215 */
  16. .form-container .content-box {
  17. height: calc(100% - 80px) !important;
  18. }
  19. </style>
  20. </head>
  21. <body class="env-input-body">
  22. <form method="post" id="app" class="form-container">
  23. <div class="content-box fit-height-content">
  24. <div class="content-div" ssFith="true">
  25. <table class='form'>
  26. <tr>
  27. <th style="width: 120px">变动类别</th>
  28. <td>
  29. <%-- 功能说明:卡状态变动页table布局调整,变动类别独占一行 by xu 20260408 --%>
  30. <script>
  31. ss.dom.formElemConfig.kaztm={val:'',type:window.ss.dom.TYPE.ONOFFBTN};
  32. </script>
  33. <%
  34. Map<Integer,String > grczlbMap = (Map)(request.getAttribute("kaztMap"));
  35. for (Integer key : grczlbMap.keySet()) {
  36. pageContext.setAttribute("k",key);
  37. pageContext.setAttribute("v",grczlbMap.get(key));
  38. %>
  39. <ss-onoff
  40. v-model="kaztm"
  41. name="kaztm"
  42. label="${v}"
  43. value="${k}"
  44. :multiple="false"
  45. :null="false"
  46. placeholder="${v}"
  47. v-model="kaztm"
  48. :readonly="false"
  49. ></ss-onoff>
  50. <%
  51. }
  52. %>
  53. </td>
  54. </tr>
  55. <tr>
  56. <th>班级/亲属</th>
  57. <td style="display: flex;align-items: center;border: none;
  58. border-right: 1px solid #e2e4ec;">
  59. <script>
  60. ss.dom.formElemConfig.bjid={val:null,type:window.ss.dom.TYPE.OBJP};
  61. </script>
  62. <ss-objp
  63. :opt="bjidOption"
  64. :inp="true"
  65. url="<ss:serv name='loadObjpOpt' parm='{"objectpickerdropdown":"1"}' />"
  66. cb="bj"
  67. v-model="bjid"
  68. name="bjid"
  69. :readonly="false"
  70. width="200px"
  71. ></ss-objp>
  72. <script>
  73. ss.dom.formElemConfig.rylbm={val:'1100',type:window.ss.dom.TYPE.ONOFFBTN};
  74. </script>
  75. <ss-onoff
  76. v-model="rylbm"
  77. name="rylbm"
  78. label="职工亲属"
  79. value="1000"
  80. :multiple="true"
  81. :null="false"
  82. placeholder="职工亲属"
  83. v-model="rylbm"
  84. :readonly="false"
  85. ></ss-onoff>
  86. </td>
  87. </tr>
  88. <tr>
  89. <th>人员</th>
  90. <td style="width: 100%;">
  91. <%-- 功能说明:人员单独一行 by xu 20260408 --%>
  92. <input name="czryid" type="hidden" value='${sessionScope.ssUser.ryid}'/> <%-- 操作人员 ID。Lin --%>
  93. <input name="kaid" type="hidden"/> <%-- 卡 ID。Lin --%>
  94. <script>
  95. ss.dom.formElemConfig.cyryid={val:null,type:window.ss.dom.TYPE.OBJP};
  96. </script>
  97. <ss-objp
  98. :opt="cyryidOption"
  99. :inp="true"
  100. url="<ss:serv name='loadObjpOpt' parm='{"objectpickerdropdown":"1","objectpickerfilterField":"bjid,rylbm"}' />"
  101. cb="ryByBjOrRylb"
  102. v-model="cyryid"
  103. name="cyryid"
  104. :readonly="false"
  105. filterField="bjid,rylbm"
  106. onChange="selBaseInfoByRyid"
  107. ></ss-objp>
  108. <%-- 持有人员 ID.Lin --%>
  109. </td>
  110. </tr>
  111. <tr>
  112. <th>部门/班级</th>
  113. <td style="width: 100%;" id='bmbj'></td>
  114. </tr>
  115. <tr>
  116. <th>姓名</th>
  117. <td style="width: 100%;" id='xm'></td>
  118. </tr>
  119. <tr>
  120. <th>人员号</th>
  121. <td style="width: 100%;" id='ryh'></td>
  122. </tr>
  123. <tr>
  124. <th>卡号</th>
  125. <td style="width: 100%;" id='kah'></td>
  126. </tr>
  127. <tr>
  128. <th>卡状态</th>
  129. <td style="width: 100%;" id='kaztmc'></td>
  130. </tr>
  131. <tr>
  132. <th>消费余额</th>
  133. <td style="width: 100%;">
  134. <%-- 功能说明:添加消费余额字段 by xu 20260408 --%>
  135. <input name="xfye"/>
  136. </td>
  137. </tr>
  138. <tr>
  139. <th>描述</th>
  140. <td style="width: 100%;">
  141. <%-- 功能说明:描述单独一行 by xu 20260408 --%>
  142. <ss-inp v-model="ms" name="ms" placeholder="请输入描述"></ss-inp>
  143. </td>
  144. </tr>
  145. </table>
  146. </div>
  147. </div>
  148. <div class='bottom-div'>
  149. <ss-bottom-button
  150. id="saveAndCommit"
  151. text="保存并提交"
  152. onclick='submitGrczForm();'<%-- 功能说明:个人充值页提交前先校验"反向充值"金额必须为负数 by xu 20260323 --%>
  153. icon-class="bottom-div-save"
  154. ></ss-bottom-button>
  155. <ss-bottom-button
  156. text="关闭"
  157. onclick='ss.display.closeDialog();'
  158. icon-class="bottom-div-close"
  159. ></ss-bottom-button>
  160. </div>
  161. </div>
  162. <input name='wdComponentID' type='hidden' value='kaztbd_add'/></form>
  163. <script type="text/javascript">var wdRecordValue='${wdRecordValue}';</script>
  164. <script type="text/javascript" src="/ss/js/wdRecord.js"></script>
  165. <script type="text/javascript">(function(){wdRecord("kaztbd_add");})();</script>
  166. <script type="text/javascript" src="/ss/js/wdFitHeight.js"></script>
  167. <script type="text/javascript">initWdFitHeight(0)</script>
  168. <script type="text/javascript">initWdFitHeightFunction=function(){initWdFitHeight(0);};</script>
  169. <ss:equal val="${empty resizeComponent}" val2="false">
  170. <script>{var iframe=wd.display.getFrameOfWindow();
  171. if(iframe&&iframe.contentWindow==window)
  172. wd.display.resizeComponent(${resizeComponent.width}, ${resizeComponent.height}, ${empty resizeComponent.minHeight?'null':resizeComponent.minHeight}, ${empty resizeComponent.maxHeight?'null':resizeComponent.maxHeight});}</script>
  173. </ss:equal>
  174. <ss:help/>
  175. </body>
  176. <script type="text/javascript">
  177. try{wd.display.showMsgPopup('${msg}');
  178. }catch(err){console.error(err);}
  179. </script>
  180. <ss:equal val="${empty wdclosewindowparam}" val2="false">
  181. <script type="text/javascript">
  182. try{wd.display.setCloseWindowParam('${wdclosewindowparam}');
  183. }catch(err){console.error(err);}
  184. </script>
  185. </ss:equal>
  186. </html>
  187. <%@ include file="/page/clip/footer.jsp" %>
  188. <script>
  189. function getFormAppVm(){
  190. var appEl = document.getElementById("app");
  191. if (!appEl || !appEl.__vue_app__ || !appEl.__vue_app__._instance) {
  192. return null;
  193. }
  194. return appEl.__vue_app__._instance.proxy || null;
  195. }
  196. function normalizeRylbmValues(value){
  197. if (Array.isArray(value)) {
  198. return value.map(function(item){
  199. return item == null ? "" : item.toString();
  200. }).filter(Boolean);
  201. }
  202. if (value == null || value === "") {
  203. return [];
  204. }
  205. var cleanValue = value.toString().replace(/^,+/, "");
  206. if (!cleanValue) {
  207. return [];
  208. }
  209. return cleanValue.split(/[,|]/).filter(Boolean);
  210. }
  211. function hasRelativeRylbmValue(value){
  212. return normalizeRylbmValues(value).indexOf("1000") !== -1;
  213. }
  214. function clearRyDisplay(){
  215. var bmbjEl = document.getElementById('bmbj');
  216. var xmEl = document.getElementById('xm');
  217. var ryhEl = document.getElementById('ryh');
  218. if (bmbjEl) bmbjEl.innerHTML = "";
  219. if (xmEl) xmEl.innerHTML = "";
  220. if (ryhEl) ryhEl.innerHTML = "";
  221. }
  222. function clearRySelection(vm){
  223. if (!vm) {
  224. clearRyDisplay();
  225. return;
  226. }
  227. vm.ryid = "";
  228. clearRyDisplay();
  229. }
  230. function handleRylbmChange(groupValue){
  231. if (!hasRelativeRylbmValue(groupValue)) {
  232. return;
  233. }
  234. var vm = getFormAppVm();
  235. if (!vm) {
  236. clearRyDisplay();
  237. return;
  238. }
  239. vm.bjid = "";
  240. clearRySelection(vm);
  241. }
  242. function handleBjChange(value){
  243. if (value == null || value === "") {
  244. return;
  245. }
  246. var vm = getFormAppVm();
  247. if (!vm) {
  248. clearRyDisplay();
  249. return;
  250. }
  251. if (hasRelativeRylbmValue(vm.rylbm)) {
  252. vm.rylbm = "1100";
  253. }
  254. clearRySelection(vm);
  255. }
  256. function selBaseInfoByRyid(value){
  257. $.ajax({
  258. url:"<ss:serv name='kaztbd_selInfoByRyid'/>",
  259. type:"post",
  260. data:{
  261. ryid:value
  262. },
  263. dataType:"json",
  264. success:function(data){
  265. if (data.ssCode != 0) {
  266. alert(data.ssMsg);
  267. return;
  268. }
  269. var d = data.ssData;
  270. document.getElementById('xm').innerHTML = d.xm;
  271. document.getElementById('ryh').innerHTML = d.ryh;
  272. if (d.rylbm != 1100) { // 不是学员。Lin
  273. if (d.bmmc)
  274. document.getElementById('bmbj').innerHTML = d.bmmc;
  275. else
  276. document.getElementById('bmbj').innerHTML = "(无)";
  277. } else {
  278. if (d.bjmc)
  279. document.getElementById('bmbj').innerHTML = d.bjmc;
  280. else
  281. document.getElementById('bmbj').innerHTML = "(无)";
  282. }
  283. if (d.kah)
  284. document.getElementById('kah').innerHTML = d.kah;
  285. else
  286. document.getElementById('kah').innerHTML = "(无)";
  287. if (d.kaztmc)
  288. document.getElementById('kaztmc').innerHTML = d.kaztmc;
  289. else
  290. document.getElementById('kaztmc').innerHTML = "(无)";
  291. document.getElementsByName('kaid')[0].value = d.kaid;
  292. }
  293. });
  294. }
  295. </script>
  296. <script type="text/javascript" src="/js/validate/validator-rules.js"></script><%-- 功能说明:个人充值页接入桌面端校验规则,支持 SsInp 红线提示 by xu 20260323 --%>
  297. <script type="text/javascript" src="/js/validate/validation-manager.js"></script><%-- 功能说明:个人充值页接入桌面端校验管理器,支持 SsInp 红线提示 by xu 20260323 --%>
  298. <script>
  299. // 功能说明:维护个人充值页中需要强制输入负数的充值类别编码,供金额校验复用 by xu 20260323
  300. var NEGATIVE_ONLY_GRCZLBM_MAP = {
  301. "21": "反向充值"
  302. };
  303. // 功能说明:充值类别变化后延后一拍重跑金额校验,确保隐藏字段值更新后再清理红线状态 by xu 20260323
  304. function handleGrczlbmChange(groupValue, value, label){
  305. setTimeout(function(){
  306. if (window.ssVm && typeof window.ssVm.validateField === "function") {
  307. window.ssVm.validateField("je");
  308. return;
  309. }
  310. validateNegativeAmountByCategory(false);
  311. }, 0);
  312. }
  313. // 功能说明:初始化金额负数校验规则,接入 ssVm 统一红线与底部提示 by xu 20260323
  314. function initNegativeAmountValidation(){
  315. if (!window.ssVm || typeof window.ssVm.add !== "function" || window.ss.dom._grczNegativeAmountValidationInited) {
  316. return;
  317. }
  318. window.ss.dom._grczNegativeAmountValidationInited = true;
  319. window.ssVm.add("ss.commonValidator.custom", ["je"], {
  320. msgPrfx: "金额",
  321. relField: "grczlbm",
  322. validate: function(value, categoryValue){
  323. if (!isNegativeOnlyGrczlbm(categoryValue)) {
  324. return true;
  325. }
  326. if (value == null || value.toString().trim() === "") {
  327. return true;
  328. }
  329. if (isValidNegativeAmountText(value)) {
  330. return true;
  331. }
  332. return {
  333. valid: false,
  334. message: NEGATIVE_ONLY_GRCZLBM_MAP[categoryValue] + "金额只能输入负数"
  335. };
  336. }
  337. }, {
  338. je: window.ss.dom.formElemConfig.je ? window.ss.dom.formElemConfig.je.val : ""
  339. });
  340. }
  341. // 功能说明:根据充值类别判断当前金额是否必须为负数 by xu 20260323
  342. function isNegativeOnlyGrczlbm(categoryValue){
  343. var currentValue = categoryValue == null ? "" : categoryValue.toString();
  344. return !!NEGATIVE_ONLY_GRCZLBM_MAP[currentValue];
  345. }
  346. // 功能说明:统一判断金额文本是否为合法负数,供提交校验和 ssVm 规则复用 by xu 20260323
  347. function isValidNegativeAmountText(value){
  348. var amountText = value == null ? "" : value.toString().trim();
  349. if (!amountText) {
  350. return false;
  351. }
  352. var amountNumber = Number(amountText);
  353. return !isNaN(amountNumber) && amountNumber < 0;
  354. }
  355. // 功能说明:根据当前充值类别判断是否必须录入负数金额 by xu 20260323
  356. function getCurrentGrczlbmValue(){
  357. var vm = getFormAppVm();
  358. if (vm && vm.grczlbm != null && vm.grczlbm !== "") {
  359. return vm.grczlbm.toString();
  360. }
  361. var categoryElem = document.querySelector('[name="grczlbm"]');
  362. return categoryElem && categoryElem.value != null ? categoryElem.value.toString() : "";
  363. }
  364. // 功能说明:统一校验金额字段在指定充值类别下是否为负数 by xu 20260323
  365. function validateNegativeAmountByCategory(showMsg){
  366. var categoryValue = getCurrentGrczlbmValue();
  367. if (!isNegativeOnlyGrczlbm(categoryValue)) {
  368. return true;
  369. }
  370. var jeElem = document.querySelector('[name="je"]');
  371. if (!jeElem) {
  372. return true;
  373. }
  374. if (isValidNegativeAmountText(jeElem.value)) {
  375. return true;
  376. }
  377. if (showMsg !== false) {
  378. alert(NEGATIVE_ONLY_GRCZLBM_MAP[categoryValue] + "金额只能输入负数");
  379. jeElem.focus();
  380. }
  381. return false;
  382. }
  383. // 功能说明:个人充值页提交前先走 ssVm 全量校验,确保显示 SsInp 左侧红线与底部提示 by xu 20260323
  384. function submitGrczForm(){
  385. if (window.ssVm && window.ssVm.validations && window.ssVm.validations.size > 0) {
  386. var validateResult = window.ssVm.validateAll();
  387. if (!validateResult.valid) {
  388. return false;
  389. }
  390. } else if (!validateNegativeAmountByCategory(true)) {
  391. return false;
  392. }
  393. var formElem = document.querySelector("form");
  394. if (!formElem) {
  395. alert("表单不存在");
  396. return false;
  397. }
  398. formElem.action = "<ss:serv name='kaztbd_lr_tj' dest='addSure' parm='{thisViewObject:\"kaztbd\",dataType:\"update\"}'/>";
  399. ss.display.resizeComponent(881,361,515,515);
  400. formElem.submit();
  401. return true;
  402. }
  403. if (window.SS && typeof SS.ready === "function") {
  404. SS.ready(function(){
  405. // 功能说明:页面初始化后注册金额负数校验规则,保证 SsInp 输入时直接出现红线提示 by xu 20260323
  406. initNegativeAmountValidation();
  407. });
  408. }
  409. </script>