kaztbd_add.ss.jsp 10 KB

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