ext_lf_inp.jsp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462
  1. <%@ page language="java" pageEncoding="UTF-8" %>
  2. <%@ taglib uri="/ssTag" prefix="ss" %>
  3. <!DOCTYPE html>
  4. <html lang="en" style="font-size: 16px;">
  5. <head>
  6. <title>录入来访信息</title>
  7. <meta charset="UTF-8">
  8. <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  9. <link rel="stylesheet" href="/skin/easy/Main.css">
  10. <link rel="stylesheet" href="/skin/easy/mobiscroll.custom.css">
  11. <script type="text/javascript" src="/ss/jquery/jquery-1.7.2.min.js"></script>
  12. <script type="text/javascript" src="/ss/js/base.js"></script>
  13. <script type="text/javascript" src="/ss/js/common.js"></script>
  14. <script type="text/javascript" src="/ss/js/display.js"></script>
  15. <script type="text/javascript" src="/ss/js/edit.js"></script>
  16. <script type="text/javascript" src="/ss/js/mobiscroll.custom.js"></script>
  17. <script type="text/javascript" src="/ss/js/file.js"></script>
  18. <!-- <script type="text/javascript" src="/ss/js/objectPicker.js"></script> -->
  19. <style>
  20. th,
  21. td {
  22. border: 1px solid black;
  23. border-collapse: collapse;
  24. }
  25. table {
  26. table-layout: fixed;
  27. width: 100%;
  28. /* 确保表格占满容器宽度 */
  29. }
  30. .mobileForm table th {
  31. width: 8rem;
  32. }
  33. .mobileForm table td {
  34. font-size: 1rem;
  35. }
  36. .mobileDelete-button,
  37. .mobileAdd-button {
  38. margin-right: 5px;
  39. }
  40. .carNumberAdd {
  41. position: absolute;
  42. right: 0;
  43. top: 50%;
  44. transform: translateY(-50%);
  45. }
  46. .carNumberTd {
  47. padding: 5px !important;
  48. }
  49. .carNumberTd>div {
  50. display: flex;
  51. align-items: center;
  52. justify-content: space-between;
  53. }
  54. .carNumberTd>div>div {
  55. flex: 1;
  56. }
  57. .carNumberTd .mobileDelete-button {
  58. margin: 0 0 0 5px !important;
  59. }
  60. input[type='text'] {
  61. width: 100%;
  62. }
  63. .hidden {
  64. display: none;
  65. }
  66. </style>
  67. </head>
  68. <body>
  69. <%--
  70. 来访对象:<%=request.getAttribute("lf") %>
  71. 姓名:<%=((base.po.LfPo)(request.getAttribute("lf"))).getXm() %>
  72. 姓别码:${lf.xbm}
  73. --%>
  74. <!-- lfid - ${lf.lfid}
  75. 1. lflbm - ${lf.lflbm} // 来访类别
  76. 2. jfrxm - ${lf.jfrxm} // 受访人姓名
  77. 3. jfrgrdh - ${lf.jfrgrdh} // 个人电话
  78. 4. jfxiaoqid - ${lf.jfxiaoqid} // 到访校区
  79. 5. dwmc - ${lf.dwmc} // 来访人单位
  80. 6. jfbmid - ${lf.jfbmid} // 酒店名
  81. 7. rs - ${lf.rs} // 来访人数
  82. 8. yykssj - ${lf.yykssj} // 预约开始时间
  83. 9. yyjssj - ${lf.yyjssj} // 预约结束时间
  84. 10. jfryid - ${lf.jfryid} // 受访人ID
  85. xm - ${lf.xm}
  86. xbm - ${lf.xbm}
  87. sfzjlbm - ${lf.sfzjlbm}
  88. sfzh - ${lf.sfzh}
  89. grdh - ${lf.grdh}
  90. clh - ${lf.clh} -->
  91. <div style="height: calc(100% - 3.5rem); overflow: auto" class="mobileForm">
  92. <form action="/extRoot?type=3&token=${token}" method="post" id="myForm">
  93. <table>
  94. <tr>
  95. <th>来访类别</th>
  96. <td>
  97. <div class="ss-select-container" id="lflbm" value="${lf.lflbm}">
  98. <div class="ss-select">请选择</div>
  99. <div class="ss-options">
  100. </div>
  101. <input type="hidden" name="lflbm">
  102. </div>
  103. </td>
  104. </tr>
  105. </table>
  106. <table id="formSection2" class="hidden">
  107. <tr id="tr-jfrxm" class="hidden">
  108. <th>接访人姓名</th>
  109. <td>
  110. <input name="jfrxm" type="text" value="${lf.jfrxm}" />
  111. </td>
  112. </tr>
  113. <tr id="tr-jfrgrdh" class="hidden">
  114. <th>个人电话</th>
  115. <td>
  116. <input name="jfrgrdh" type="text" value="${lf.jfrgrdh}"/>
  117. </td>
  118. </tr>
  119. </table>
  120. <div class="mobileForm-title hidden">来访信息</div>
  121. <table id="formSection3" class="hidden">
  122. <tr id="tr-jfxiaoqid" class="hidden">
  123. <th>到访校区</th>
  124. <td>
  125. <div class="ss-select-container" id="jfxiaoqid" value="${lf.jfxiaoqid}">
  126. <div class="ss-select">请选择校区</div>
  127. <div class="ss-options">
  128. </div>
  129. <input type="hidden" name="jfxiaoqid">
  130. </div>
  131. </td>
  132. </tr>
  133. <tr id="tr-jfbmid" class="hidden">
  134. <th>酒店名</th>
  135. <td>
  136. <div class="ss-select-container" id="jfbmid" value="${lf.jfbmid}">
  137. <div class="ss-select">请选择</div>
  138. <div class="ss-options">
  139. </div>
  140. <input type="hidden" name="jfbmid">
  141. </div>
  142. </td>
  143. </tr>
  144. <tr id="tr-dwmc" class="hidden">
  145. <th>来访人单位</th>
  146. <td>
  147. <input name="dwmc" type="text" value="${lf.dwmc}"/>
  148. </td>
  149. </tr>
  150. <tr id="tr-sy" class="hidden">
  151. <th>事由</th>
  152. <td>
  153. <input name="sy" type="text" value="${lf.sy}"/>
  154. </td>
  155. </tr>
  156. <tr id="tr-rs" class="hidden">
  157. <th>来访人数</th>
  158. <td>
  159. <input name="rs" type="text" value="${lf.rs}"/>
  160. </td>
  161. </tr>
  162. <tr id="tr-yykssj" class="hidden">
  163. <th>预约日期</th>
  164. <td>
  165. <input name="yykssj" type="text" id="yykssj" value="${lf.yykssj}"/>
  166. </td>
  167. </tr>
  168. <tr id="tr-yyjssj" class="hidden" style="display: none;">
  169. <th>预约结束时间</th>
  170. <td>
  171. <input name="yyjssj" type="text" id="yyjssj" value="${lf.yyjssj}"/>
  172. </td>
  173. </tr>
  174. </table>
  175. <div class="mobileForm-title hidden">
  176. <span></span> <span class="mobileAdd-button" id="visitorAdd"></span>
  177. </div>
  178. <p style="margin: 1rem 0.5rem 0;">
  179. <span>申请入校免责声明</span>
  180. <br />
  181. <span>来访人员进校需申请报备,不得携带管制刀具、危化品、毒品等违法危险品进校,并如实声明所携带物品清单及合法性,若未如实告知,来访者和受访者需承担相关法律责任。</span>
  182. </p>
  183. <input type="hidden" id="sxry_num" name="sxry_num" value="" />
  184. <input type="hidden" name="lfsxry">
  185. <input type="hidden" name="jfryid" value="${lf.jfryid}">
  186. </form>
  187. </div>
  188. <div class="mobileBottom-div hidden">
  189. <div class="mobileBottom-down-div">
  190. <button class="mobileBottom-button" onclick="closePage()">取消</button>
  191. <button class="mobileBottom-button" onclick="submitForm()">
  192. 保存并提交
  193. </button>
  194. </div>
  195. </div>
  196. </body>
  197. <script type="text/javascript" src="/ss/validation/validation.js"></script>
  198. <script type="text/javascript" src="/ss/js/licensePlateNumInp.js"></script>
  199. <script type="text/javascript" src="/ss/validator/commonValidator.js"></script>
  200. <script>
  201. let carNumberInstances = {}; // 以随行人员编号为键,存储每个随行人员的车牌号实例数组
  202. let uniqueVisitorIdCounter = 1; // 用于生成唯一的随行人员 ID
  203. let visitorCount = 0; // 当前有效随行人员计数
  204. let sxry_num = [];
  205. let initSelectData; // 用于存储初始的 select 数据
  206. // 校验器
  207. var wdVm = window.wdVm || new ValidationManager();
  208. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  209. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  210. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  211. wdVm.add("wd.commonValidator.notNull", ["dwmc"], { msgPrfx: "单位名称", notBlank: true }, 1);
  212. // 通用的日期格式化函数
  213. function formatDateTime(date) {
  214. return (
  215. date.getFullYear() +
  216. "-" +
  217. ("0" + (date.getMonth() + 1)).slice(-2) +
  218. "-" +
  219. ("0" + date.getDate()).slice(-2)
  220. //" " +
  221. // ("0" + date.getHours()).slice(-2) +
  222. // ":" +
  223. // ("0" + date.getMinutes()).slice(-2) +
  224. // ":" +
  225. // ("0" + date.getSeconds()).slice(-2)
  226. );
  227. }
  228. // 带时间的日期格式化函数
  229. function formatDateTimeWithTime(date, withTime) {
  230. const datePart = date.getFullYear() +
  231. "-" +
  232. ("0" + (date.getMonth() + 1)).slice(-2) +
  233. "-" +
  234. ("0" + date.getDate()).slice(-2);
  235. if (withTime) {
  236. return datePart + " " +
  237. ("0" + date.getHours()).slice(-2) +
  238. ":" +
  239. ("0" + date.getMinutes()).slice(-2) +
  240. ":" +
  241. ("0" + date.getSeconds()).slice(-2);
  242. }
  243. return datePart;
  244. }
  245. // 创建分隔线和错误提示的函数
  246. function createValidation(container) {
  247. const parent = container.parentNode;
  248. // 生成分隔线
  249. let lineSpan = document.getElementById(container.id + 'Span');
  250. if (!lineSpan) {
  251. lineSpan = document.createElement('span'); // 创建线的 span
  252. lineSpan.id = container.id + 'Span'; // 使用指定格式的 id
  253. lineSpan.className = 'border-input-error vLine-leftWarning'; // 设置样式
  254. lineSpan.style.display = 'block'; // 初始状态隐藏分隔线
  255. parent.insertBefore(lineSpan, container.nextSibling); // 插入到 container 之后
  256. }
  257. // 生成错误提示
  258. let errorDiv = document.getElementById(container.id + 'ErrorDiv');
  259. if (!errorDiv) {
  260. errorDiv = document.createElement('div'); // 创建错误提示的 div
  261. errorDiv.id = container.id + 'ErrorDiv'; // 使用指定格式的 id
  262. errorDiv.className = 'error-message'; // 设置样式
  263. errorDiv.style.position = 'absolute';
  264. errorDiv.style.left = '0px';
  265. errorDiv.style.bottom = '0px';
  266. errorDiv.style.color = 'red';
  267. errorDiv.style.fontSize = '12px';
  268. errorDiv.style.width = '100%';
  269. errorDiv.style.textAlign = 'right';
  270. errorDiv.style.lineHeight = '18px';
  271. errorDiv.style.height = '18px';
  272. errorDiv.style.display = 'none'; // 初始状态隐藏
  273. parent.insertBefore(errorDiv, lineSpan ? lineSpan.nextSibling : container.nextSibling); // 插入到分隔线之后
  274. }
  275. }
  276. // 移除校验元素的函数
  277. function removeValidation(container) {
  278. const lineSpan = document.getElementById(container.id + 'Span');
  279. const errorDiv = document.getElementById(container.id + 'ErrorDiv');
  280. if (lineSpan) {
  281. lineSpan.remove(); // 删除分隔线
  282. }
  283. if (errorDiv) {
  284. errorDiv.remove(); // 删除错误提示
  285. }
  286. }
  287. // 更新错误提示信息的函数
  288. function updateMsg(container, msg) {
  289. let errorDiv = document.getElementById(container.id + 'ErrorDiv');
  290. // 如果未找到 errorDiv,先调用 createValidation 创建它
  291. if (!errorDiv) {
  292. createValidation(container);
  293. errorDiv = document.getElementById(container.id + 'ErrorDiv');
  294. }
  295. if (errorDiv) {
  296. errorDiv.textContent = msg; // 设置错误提示信息
  297. errorDiv.style.display = 'block'; // 显示错误提示
  298. }
  299. }
  300. let isValidStartTime = true;
  301. // let isValidEndTime = true;
  302. // 动态设置开始和结束时间
  303. function setInitialTime() {
  304. const yykssj = document.querySelector('#yykssj');
  305. const yyjssj = document.querySelector('#yyjssj');
  306. // 初始化开始时间
  307. var now = new Date();
  308. var oneHourLater = formatDateTime(new Date(now.getTime() + 3600 * 1000));
  309. // 设置结束时间为开始时间的 23:59:59
  310. var endDate = new Date(now.getTime() + 3600 * 1000);
  311. var endDateFormatted = endDate + ' 23:59:59';
  312. console.log('初始化的结束时间:',endDateFormatted)
  313. $("#yykssj")
  314. .mobiscroll()
  315. .datetime({
  316. display: "modal", // 弹出框显示
  317. dateFormat: "yy-mm-dd", // 日期格式:年-月-日
  318. dateOrder: "yyMMdd", // 设置为年-月-日顺序
  319. timeFormat: "", // 不显示时间选择器
  320. timeWheels: "", // 不显示时间滚轮
  321. lang: "zh", // 设置为中文
  322. onSelect:function(event,inst){
  323. console.log(event)
  324. // 解析 event 为 Date 对象
  325. // const selectedDate = new Date(event);
  326. // 设置时分秒为0:0:0
  327. // selectedDate.setHours(0, 0, 0, 0);
  328. removeValidation(yykssj);
  329. // isValidStartTime = true;
  330. yykssj.value = event;
  331. const endDate = event + ' 23:59:59';
  332. yyjssj.value = endDate;
  333. // 获取当前时间
  334. // const currentDate = new Date();
  335. // currentDate.setHours(0,0,0,0);
  336. // if (selectedDate.getTime() >= currentDate.getTime()) {
  337. // console.log('selectedDate:',selectedDate.getTime())
  338. // console.log('currentDate:',currentDate.getTime())
  339. // console.log('selectedDate.getTime() >= currentDate.getTime():',selectedDate.getTime() >= currentDate.getTime())
  340. // removeValidation(yykssj);
  341. // isValidStartTime = true;
  342. // // 获取结束时间
  343. // const endTime = new Date(yyjssj.value);
  344. // // 设置开始时间的值为不带时间的日期格式,用于显示
  345. // yykssj.value = formatDateTime(selectedDate);
  346. // // 设置结束时间为当天的 23:59:59
  347. // const endDate = selectedDate + ' 23:59:59';
  348. // yyjssj.value = endDate;
  349. // } else {
  350. // updateMsg(yykssj, "预约日期不能早于当前日期");
  351. // // yykssj.value = formatDateTime(new Date(now.getTime() + 3600 * 1000));
  352. // isValidStartTime = false;
  353. // }
  354. }
  355. }).val(oneHourLater);
  356. // 设置开始时间的显示格式(不带时间)
  357. yykssj.value = oneHourLater;
  358. // 设置结束时间的初始值为开始时间的 23:59:59
  359. yyjssj.value = endDateFormatted;
  360. }
  361. function closePage() {
  362. // 定义关闭页面的函数
  363. function closeWindow() {
  364. if (typeof WeixinJSBridge == "undefined") {
  365. // 监听WeixinJSBridgeReady事件
  366. document.addEventListener('WeixinJSBridgeReady', function () {
  367. WeixinJSBridge.call('closeWindow');
  368. }, false);
  369. } else {
  370. // 如果是微信浏览器,直接调用
  371. WeixinJSBridge.call('closeWindow');
  372. }
  373. }
  374. // 调用关闭页面函数
  375. closeWindow();
  376. // 如果不是微信浏览器,尝试使用window.close()关闭
  377. if (!/MicroMessenger/i.test(navigator.userAgent)) {
  378. window.close();
  379. window.history.back();
  380. }
  381. }
  382. var submitCount = 0;
  383. // 提交表单
  384. function submitForm() {
  385. // 处理开始时间,添加 00:00:00
  386. if(submitCount){
  387. alert('请勿重复提交')
  388. return false
  389. }
  390. const form = $("#myForm");
  391. const lflbm = $("input[name='lflbm']").val();
  392. let valid = false;
  393. const jfbmid = $("input[name='jfbmid']").val();
  394. const jfxiaoqid = $("input[name='jfxiaoqid']").val();
  395. const jfryid = $("input[name='jfryid']").val();
  396. const xbm = $("input[name='xbm']").val();
  397. const yykssj = document.querySelector('#yykssj');
  398. const yyjssj = document.querySelector('#yyjssj');
  399. if (!form[0].checkOnly(false)) { // 获取原生DOM元素并调用checkOnly
  400. // alert('原来的校验器,checkOnly不通过')
  401. valid = true;
  402. }
  403. // if (yykssj && yykssj.value) {
  404. // const newYykssj = yykssj.value + ' 00:00:00';
  405. // console.log('提交的时候一开始获取到的newYykssj:',newYykssj)
  406. // yykssj.value = newYykssj;
  407. // }
  408. //
  409. // 校验时间是否有效
  410. if (!isValidStartTime) {
  411. alert("预约日期不能早于当前日期")
  412. valid = true;
  413. }
  414. if (xbm === '') {
  415. valid = true;
  416. }
  417. if(((lflbm!='61')&&(lflbm!='161')&&(lflbm!='71'))&&jfryid === '' ) {
  418. valid = true;
  419. alert('未查询到该受访人信息,请重新输入!');
  420. }
  421. // 校验校区
  422. if (jfxiaoqid === '' ) {
  423. valid = true;
  424. }
  425. // 如果随行人员不为0
  426. if (sxry_num.length > 0) {
  427. $("input[name='sxry_num']").val(sxry_num.join(','));
  428. // 用来存储所有对象
  429. var dataArray = [];
  430. // 遍历数组
  431. sxry_num.forEach(function(num) {
  432. if($('input[name="xbm_' + num + '"]').val() === ''){
  433. valid = true;
  434. alert("请选择随行人员"+ num +"的性别")
  435. return false;
  436. }
  437. // 获取每个字段的值,如果为空则赋值为 ""
  438. var entry = {
  439. xbm: $('input[name="xbm_' + num + '"]').val() || "",
  440. sfzjlbm: $('input[name="sfzjlbm_' + num + '"]').val() || "",
  441. xm: $('input[name="xm_' + num + '"]').val() || "",
  442. sfzh: $('input[name="sfzh_' + num + '"]').val() || "",
  443. grdh: $('input[name="grdh_' + num + '"]').val() || "",
  444. clh: $('input[name="clh_' + num + '"]').val() || "", // 车辆号
  445. // syfjid: $('input[name="syfjid_' + num + '"]').val() || ""
  446. };
  447. // 将每个对象添加到数组中
  448. dataArray.push(entry);
  449. });
  450. $('input[name="lfsxry"]').val(JSON.stringify(dataArray));
  451. }
  452. if (valid){
  453. console.log('提交的校验不通过')
  454. return;
  455. }
  456. if (yykssj && yykssj.value) {
  457. const newYykssj = yykssj.value + ' 00:00:00';
  458. console.log('yykssj.value:',newYykssj)
  459. yykssj.value = newYykssj;
  460. }
  461. yyjssj.value = yykssj.value.replace(' 00:00:00', ' 23:59:59');
  462. console.log(yykssj.value,yyjssj.value)
  463. submitCount = 1;
  464. // alert('预约结束时间yyjssj:'+yyjssj.value);
  465. // return ;
  466. form.submit();
  467. }
  468. // 生成随行人员
  469. function addVisitor(visitorId, visitorNumber, title) {
  470. // console.log(`当前访客id是` + visitorId, `当前访客编号是` + visitorNumber);
  471. const inputNum = (visitorId === 1 ? '' : '_' + (visitorId - 1)) // 提交给后端的后缀,如果是第一个证明是访客 不用加后缀;第二个开始变随行人员,加后缀1开始
  472. // console.log(`当前随行人员编号是` + (!inputNum ? ':访客不需要编号' : '_' + (visitorId - 1)));
  473. carNumberInstances[visitorId] = []; // 初始化新随行人员的车牌号实例数组
  474. let newFormHtml = `
  475. <div class="mobileForm-container" data-visitor-id="` + visitorId + `">
  476. <div class="mobileForm-title">
  477. <span>` + (title ? title : '随行人员' + visitorNumber) + `</span>
  478. <span class="mobileDelete-button"></span>
  479. </div>
  480. <table>
  481. <tr>
  482. <th>姓名</th>
  483. <td><input name="xm`+ inputNum + `" value="" type="text"/></td>
  484. </tr>
  485. <tr>
  486. <th>性别</th>
  487. <td>
  488. <div class="ss-select-container" id="xbm`+ inputNum + `" value="">
  489. <div class="ss-select">请选择</div>
  490. <div class="ss-options">
  491. <div data-value="1">男</div>
  492. <div data-value="2">女</div>
  493. </div>
  494. <input type="hidden" name="xbm`+ inputNum + `" >
  495. </div>
  496. <%--
  497. <input name="xbmName" style="width:90px;" type="text" />
  498. <ss:objp name='xbm' inp='false' cb='xb'/>
  499. --%>
  500. </td>
  501. </tr>
  502. <tr>
  503. <th>证件类别</th>
  504. <td>
  505. <div class="ss-select-container" id="sfzjlbm`+ inputNum + `" value="1">
  506. <div class="ss-select">请选择</div>
  507. <div class="ss-options">
  508. <div data-value="1">身份证</div>
  509. </div>
  510. <input type="hidden" name="sfzjlbm`+ inputNum + `" >
  511. </div>
  512. </td>
  513. </tr>
  514. <tr>
  515. <th>证件号</th>
  516. <td><input name="sfzh`+ inputNum + `" value="" type="text"/></td>
  517. </tr>
  518. <tr>
  519. <th>个人电话</th>
  520. <td><input name="grdh`+ inputNum + `" type="text"/></td>
  521. </tr>`
  522. +
  523. (visitorNumber === 0 ? `<tr><th>附件</th><td><div id="sywjlp"></div></td></tr>`:``)
  524. +
  525. `
  526. <tr>
  527. <td colspan="2" style="text-align: center">
  528. 车辆号
  529. <!-- <span class="mobileAdd-button carNumberAdd"></span> -->
  530. </td>
  531. </tr>
  532. <tr>
  533. <td colspan="2" class="carNumberTd">
  534. <div>
  535. <div id="carNumberInput` + visitorId + `-1"></div>
  536. <span class="mobileDelete-button carNumberDelete" style="visibility: hidden"></span>
  537. </div>
  538. </td>
  539. </tr>
  540. </table>
  541. </div>
  542. `;
  543. // 如果是第一个随行人员,访客
  544. if (visitorNumber === 0) {
  545. newFormHtml = `
  546. <div class="mobileForm-container" data-visitor-id="` + visitorId + `">
  547. <div class="mobileForm-title">
  548. <span>` + (title ? title : '随行人员' + visitorNumber) + `</span>
  549. <span class="mobileDelete-button"></span>
  550. </div>
  551. <table>
  552. <tr>
  553. <th>姓名</th>
  554. <td><input name="xm" value="${lf.xm}" type="text"/></td>
  555. </tr>
  556. <tr>
  557. <th>性别</th>
  558. <td>
  559. <div class="ss-select-container" id="xbm" value="${lf.xbm}">
  560. <div class="ss-select">请选择</div>
  561. <div class="ss-options">
  562. <div data-value="1">男</div>
  563. <div data-value="2">女</div>
  564. </div>
  565. <input type="hidden" name="xbm" >
  566. </div>
  567. <%--
  568. <input name="xbmName" style="width:90px;" type="text" />
  569. <ss:objp name='xbm' inp='false' cb='xb'/>
  570. --%>
  571. </td>
  572. </tr>
  573. <tr>
  574. <th>证件类别</th>
  575. <td>
  576. <div class="ss-select-container" id="sfzjlbm" value="${lf.sfzjlbm}">
  577. <div class="ss-select">请选择</div>
  578. <div class="ss-options">
  579. <div data-value="1">身份证</div>
  580. </div>
  581. <input type="hidden" name="sfzjlbm" >
  582. </div>
  583. </td>
  584. </tr>
  585. <tr>
  586. <th>证件号</th>
  587. <td><input name="sfzh" value="${lf.sfzh}" type="text"/></td>
  588. </tr>
  589. <tr>
  590. <th>个人电话</th>
  591. <td><input name="grdh" value="${lf.grdh}" type="text"/></td>
  592. </tr>`
  593. +
  594. (visitorNumber === 0 ? `<tr><th>附件</th><td><div id="sywjlp"></div></td></tr>`:``)
  595. +
  596. `
  597. <tr>
  598. <td colspan="2" style="text-align: center">
  599. 车辆号
  600. <!-- <span class="mobileAdd-button carNumberAdd"></span> -->
  601. </td>
  602. </tr>
  603. <tr>
  604. <td colspan="2" class="carNumberTd">
  605. <div>
  606. <div id="carNumberInput1-1"></div>
  607. <span class="mobileDelete-button carNumberDelete" style="visibility: hidden"></span>
  608. </div>
  609. </td>
  610. </tr>
  611. </table>
  612. </div>
  613. `;
  614. newFormHtml = newFormHtml.replace(
  615. 'class="mobileDelete-button"',
  616. 'class="mobileDelete-button" style="visibility: hidden"'
  617. );
  618. $(".mobileForm .mobileForm-title").last().before(newFormHtml);
  619. const uploadUrl = '<ss:serv name="lf_uploadFile"/>';
  620. const loadUrl = "<ss:serv name='lf_loadFile'/>";
  621. // 选择并上传文件,并生成预览
  622. mobileFileUpload('sywjlp', {
  623. uploadUrl,
  624. loadUrl,
  625. maxSize: 1, //
  626. acceptedFileTypes: ['jpg', 'jpeg', 'png', 'gif', 'pdf','xlsx', 'docx', 'pptx', 'doc', 'ppt', 'xls','zip', 'rar', '7z'], // 限制文件类型
  627. maxFileSize: 20 * 1024 * 1024 // 单个文件最大为 5 MB
  628. });
  629. } else {
  630. // 新增随行人员时,追加到最后一个随行人员后面
  631. $(".mobileForm-container").last().after(newFormHtml);
  632. }
  633. // 初始化对应的随行人员的下拉信息
  634. const xbm = initSSSelect(`#xbm` + inputNum, initSelectData.XB, { text: 'mc', value: 'xbm' }, { enable: true });
  635. const sfzjlbm = initSSSelect('#sfzjlbm' + inputNum, initSelectData.SFZJLB, { text: 'mc', value: 'sfzjlbm' }, { enable: true });
  636. // 初始化对应的随行人员的校验
  637. wdVm.add("wd.commonValidator.notNull", [`xm` + inputNum], { msgPrfx: "姓名" }, 1);
  638. wdVm.add('wd.commonValidator.notNull', [`sfzjlbm` + inputNum], { 'msgPrfx': '身份证件类别' }, 1);
  639. // wdVm.add('wd.commonValidator.idCard',[`sfzh`+ inputNum],{'relField':`sfzh`+ inputNum+`,`+`sfzjlbm`+ inputNum,'msgPrfx':'身份证号'},1);
  640. wdVm.add("wd.commonValidator.idCard", ["sfzh" + inputNum], { msgPrfx: "证件号", notBlank: true, sfzjlbmName: `sfzjlbm` + inputNum }, 1);
  641. wdVm.add("wd.commonValidator.int", [`grdh` + inputNum], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  642. let carInput;
  643. // 处理第一个访客
  644. if (visitorId === 1) {
  645. carInput = new CarNumberInput('carNumberInput' + visitorId + '-1', 'clh', '粤')
  646. xbm.setValue('${lf.xbm}')
  647. sfzjlbm.setValue('${lf.sfzjlbm}')
  648. } else {
  649. carInput = new CarNumberInput('carNumberInput' + visitorId + '-1', 'clh' + inputNum, '粤')
  650. }
  651. carNumberInstances[visitorId].push(carInput);
  652. }
  653. /**
  654. * 初始化自定义下拉框,支持设置默认值、回调函数、自定义选项数组和校验功能
  655. * @param {string} containerSelector - 下拉框容器的CSS选择器
  656. * @param {Array} optionsArray - 包含选项的数组对象 [{...}](可选)
  657. * @param {object} mapping - 映射对象,定义选项中用于显示文本和作为值的字段名 {text: '字段名', value: '字段名'}(可选)
  658. * @param {object} validation - 校验对象,包含校验设置 {enable: true/false, message: '报错信息'}(可选)
  659. * @param {function|null} callback - 选中后的回调函数(可选)
  660. */
  661. function initSSSelect(containerSelector, optionsArray = [], mapping = { text: 'n', value: 'v' }, validation = { enable: false, message: '' }, callback = null) {
  662. const container = document.querySelector(containerSelector); // 获取容器
  663. if (!container) {
  664. console.error('容器未找到');
  665. return;
  666. }
  667. const ssSelect = container.querySelector('.ss-select'); // 获取显示区域
  668. const optionsContainer = container.querySelector('.ss-options'); // 获取选项容器
  669. const hiddenInput = container.querySelector('input[type="hidden"]'); // 隐藏的输入框
  670. // 获取容器的父级元素,以便插入错误提示
  671. const parent = container.parentNode;
  672. // 创建并插入分隔线 span
  673. let lineSpan = document.getElementById(containerSelector.replace(/[#.]/g, '') + 'Span');
  674. if (!lineSpan) {
  675. lineSpan = document.createElement('span'); // 创建线的 span
  676. lineSpan.id = containerSelector.replace(/[#.]/g, '') + 'Span'; // 使用指定格式的 id
  677. lineSpan.className = 'border-input-error vLine-leftWarning'; // 设置样式
  678. lineSpan.style.display = 'none'; // 显示分隔线
  679. parent.insertBefore(lineSpan, container.nextSibling); // 插入到 container 之后
  680. }
  681. if (validation.enable) {
  682. lineSpan.style.display = 'block'; // 显示分隔线
  683. }
  684. // 创建并插入错误提示的 div
  685. let errorDiv = document.getElementById(containerSelector.replace(/[#.]/g, '') + 'ErrorDiv');
  686. if (!errorDiv) {
  687. errorDiv = document.createElement('div'); // 创建错误提示的 div
  688. errorDiv.id = containerSelector.replace(/[#.]/g, '') + 'ErrorDiv'; // 使用指定格式的 id
  689. errorDiv.className = 'error-message'; // 设置样式
  690. errorDiv.style.position = 'absolute';
  691. errorDiv.style.left = '0px';
  692. errorDiv.style.bottom = '0px';
  693. errorDiv.style.color = 'red';
  694. errorDiv.style.fontSize = '12px';
  695. errorDiv.style.width = '100%';
  696. errorDiv.style.textAlign = 'right';
  697. errorDiv.style.lineHeight = '18px';
  698. errorDiv.style.height = '18px';
  699. errorDiv.style.display = 'none'; // 初始状态隐藏
  700. parent.insertBefore(errorDiv, lineSpan ? lineSpan.nextSibling : container.nextSibling); // 插入到分隔线之后
  701. }
  702. // 如果传入了选项数组,动态生成选项 DOM
  703. if (optionsArray.length > 0) {
  704. optionsContainer.innerHTML = ''; // 清空原有选项
  705. optionsArray.forEach(option => {
  706. const optionDiv = document.createElement('div');
  707. optionDiv.setAttribute('data-value', option[mapping.value]); // 使用映射的 value 作为选项值
  708. optionDiv.textContent = option[mapping.text]; // 使用映射的 text 作为显示文本
  709. optionsContainer.appendChild(optionDiv);
  710. });
  711. }else {
  712. optionsContainer.innerHTML = '<div class="padding">无选项</div>';
  713. }
  714. // 点击下拉框时,打开或关闭选项列表
  715. ssSelect.addEventListener('click', function (event) {
  716. // 关闭其他所有下拉框
  717. document.querySelectorAll('.ss-select-container').forEach(cont => {
  718. if (cont !== container) {
  719. cont.classList.remove('open');
  720. }
  721. });
  722. // 切换当前下拉框的状态
  723. container.classList.add('open');
  724. event.stopPropagation(); // 阻止事件冒泡,防止点击下拉框时触发 document 的点击事件
  725. // 如果启用了校验且没有选中内容,则显示错误提示
  726. if (validation.enable && (!hiddenInput.value || hiddenInput.value === "")) {
  727. errorDiv.textContent = validation.message || ''; // 设置错误提示文字
  728. errorDiv.style.display = 'block'; // 显示错误提示
  729. }
  730. });
  731. // 处理选项点击事件
  732. optionsContainer.querySelectorAll('div').forEach(option => {
  733. option.addEventListener('click', function () {
  734. const value = this.getAttribute('data-value'); // 获取选项的值
  735. const text = this.textContent; // 获取选项的文本
  736. // 设置下拉框显示文本和隐藏输入框的值
  737. ssSelect.textContent = text;
  738. hiddenInput.value = value;
  739. // 移除所有其他选项的选中状态
  740. optionsContainer.querySelectorAll('div').forEach(opt => opt.classList.remove('selected'));
  741. // 为当前选中的选项添加选中状态
  742. this.classList.add('selected');
  743. // 关闭下拉框
  744. container.classList.remove('open');
  745. // 隐藏错误提示
  746. errorDiv.style.display = 'none';
  747. // 隐藏分隔线
  748. lineSpan.style.display = 'none';
  749. // parent.style.borderBottom = 'none';
  750. // 如果有回调函数,调用并传递选中的值
  751. if (callback && typeof callback === 'function') {
  752. callback(value);
  753. }
  754. });
  755. });
  756. // 从容器的 value 属性获取默认值
  757. const defaultValue = container.getAttribute('value');
  758. // 设置默认选中值
  759. if (defaultValue !== null && defaultValue !== "") {
  760. const defaultOption = optionsContainer.querySelector(`div[data-value="`+defaultValue+`"]`);
  761. if (defaultOption) {
  762. console.log('defaultOption',defaultOption.textContent)
  763. ssSelect.textContent = defaultOption.textContent; // 设置下拉框的默认文本
  764. hiddenInput.value = defaultOption.getAttribute('data-value'); // 设置隐藏输入框的默认值
  765. defaultOption.classList.add('selected'); // 设置选中状态
  766. // 隐藏错误提示
  767. errorDiv.style.display = 'none';
  768. // 隐藏分隔线
  769. lineSpan.style.display = 'none';
  770. // 如果有回调函数,执行回调
  771. if (callback && typeof callback === 'function') {
  772. callback(defaultValue);
  773. }
  774. }
  775. }
  776. // 点击其他地方关闭所有下拉框
  777. document.addEventListener('click', function () {
  778. container.classList.remove('open');
  779. // 如果启用了校验功能且没有选中项,显示错误提示
  780. if (validation.enable && (!hiddenInput.value || hiddenInput.value === "")) {
  781. errorDiv.textContent = validation.message; // 设置错误提示文字
  782. errorDiv.style.display = 'block'; // 显示校验错误信息
  783. // parent.style.borderBottom = '1px solid red';
  784. }
  785. });
  786. // 防止点击容器内部时触发 document 的点击事件
  787. container.addEventListener('click', function (event) {
  788. event.stopPropagation();
  789. });
  790. // 如果启用了校验功能且没有默认选中项,显示错误提示
  791. // if (validation.enable && (!defaultValue || defaultValue === "")) {
  792. // errorDiv.textContent = validation.message; // 设置错误提示文字
  793. // errorDiv.style.display = 'block'; // 显示校验错误信息
  794. // }
  795. return {
  796. setValue: function(value) {
  797. if (!value) {
  798. // 恢复到初始状态
  799. ssSelect.textContent = '请选择';
  800. hiddenInput.value = '';
  801. // 移除所有选中状态
  802. optionsContainer.querySelectorAll('div').forEach(opt =>
  803. opt.classList.remove('selected')
  804. );
  805. // 如果启用了校验,显示错误提示和分隔线
  806. if (validation.enable) {
  807. errorDiv.textContent = validation.message || '';
  808. errorDiv.style.display = 'block';
  809. lineSpan.style.display = 'block';
  810. }
  811. return true;
  812. }
  813. const option = optionsContainer.querySelector(`div[data-value="${value}"]`);
  814. if (option) {
  815. // 更新显示文本和隐藏输入框的值
  816. ssSelect.textContent = option.textContent;
  817. hiddenInput.value = value;
  818. // 更新选中状态
  819. optionsContainer.querySelectorAll('div').forEach(opt => opt.classList.remove('selected'));
  820. option.classList.add('selected');
  821. // 隐藏错误提示和分隔线
  822. errorDiv.style.display = 'none';
  823. lineSpan.style.display = 'none';
  824. // 如果有回调函数,执行回调
  825. if (callback && typeof callback === 'function') {
  826. callback(value);
  827. }
  828. return true;
  829. }
  830. return false;
  831. }
  832. };
  833. }
  834. // 清除所有表单部分的显示
  835. function hideAllSections() {
  836. // 隐藏所有部分
  837. $('#formSection2, #formSection2 tr').addClass('hidden');
  838. $('#formSection3, #formSection3 tr').addClass('hidden');
  839. // 清第二部分校验
  840. wdVm.remove("wd.commonValidator.notNull", ["jfrxm"]);
  841. wdVm.remove("wd.commonValidator.int", ["jfrgrdh"]);
  842. wdVm.remove("wd.commonValidator.notNull", ["zy"]);
  843. wdVm.remove("wd.commonValidator.notNull", ["bj"]);
  844. wdVm.remove("wd.commonValidator.int", ["rs"]);
  845. wdVm.remove("wd.commonValidator.notNull", ["dwmc"]);
  846. wdVm.remove("wd.commonValidator.notNull", ["sy"]);
  847. }
  848. /**
  849. * 处理 "探访学生" 的表单显示
  850. * 受访人信息显示:姓名、专业、班级、个人电话
  851. * 来访信息显示:人数、预约开始时间、预约结束时间
  852. */
  853. function handleStudentVisit() {
  854. hideAllSections(); // 先隐藏所有部分
  855. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  856. $('#tr-jfrxm, #tr-zy, #tr-bj, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  857. // 加第二部分校验
  858. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  859. wdVm.add("wd.commonValidator.notNull", ["zy"], { msgPrfx: "专业" }, 1);
  860. wdVm.add("wd.commonValidator.notNull", ["bj"], { msgPrfx: "班级" }, 1);
  861. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  862. $('#formSection3').removeClass('hidden');
  863. $('#tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden');
  864. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  865. }
  866. /**
  867. * 处理 "探访教职工" 的表单显示
  868. * 受访人信息显示:姓名、个人电话
  869. * 来访信息显示:人数、预约开始时间、预约结束时间
  870. */
  871. function handleStaffVisit() {
  872. hideAllSections(); // 先隐藏所有部分
  873. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  874. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  875. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  876. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  877. $('#formSection3').removeClass('hidden');
  878. $('#tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden');
  879. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  880. }
  881. /**
  882. * 处理 "物流配送" 的表单显示
  883. * 受访人信息显示:姓名、个人电话
  884. * 来访信息显示:人数、预约开始时间、预约结束时间
  885. */
  886. function handleLogisticsVisit() {
  887. hideAllSections(); // 先隐藏所有部分
  888. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  889. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  890. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  891. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  892. $('#formSection3').removeClass('hidden');
  893. $('#tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden');
  894. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  895. }
  896. /**
  897. * 处理 "公务" 的表单显示
  898. * 受访人信息显示:姓名、个人电话
  899. * 来访信息显示:单位、人数、预约开始时间、预约结束时间
  900. */
  901. function handleOfficialVisit() {
  902. hideAllSections(); // 先隐藏所有部分
  903. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  904. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  905. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  906. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  907. $('#formSection3').removeClass('hidden'); // 显示表单部分3
  908. $('#tr-dwmc, #tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden'); // 显示公务相关字段
  909. wdVm.add("wd.commonValidator.notNull", ["dwmc"], { msgPrfx: "单位名称", notBlank: true }, 1);
  910. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  911. }
  912. /**
  913. * 处理 "工作学习" 的表单显示
  914. * 受访人信息显示:姓名、个人电话
  915. * 来访信息显示:人数、预约开始时间、预约结束时间
  916. */
  917. function handleWorkStudyVisit() {
  918. hideAllSections(); // 先隐藏所有部分
  919. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  920. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  921. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  922. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  923. $('#formSection3').removeClass('hidden');
  924. $('#tr-dwmc,#tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden');
  925. wdVm.add("wd.commonValidator.notNull", ["dwmc"], { msgPrfx: "单位名称", notBlank: true }, 1);
  926. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  927. }
  928. /**
  929. * 处理 "其他" 的表单显示
  930. * 受访人信息显示:姓名、个人电话
  931. * 来访信息显示:人数、预约开始时间、预约结束时间
  932. */
  933. function handleOtherVisit() {
  934. hideAllSections(); // 先隐藏所有部分
  935. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  936. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  937. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  938. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  939. $('#formSection3').removeClass('hidden');
  940. $('#tr-jfxiaoqid,#tr-rs, #tr-yykssj,#tr-sy, #tr-dwmc').removeClass('hidden');
  941. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  942. wdVm.add("wd.commonValidator.notNull", ["sy"], { msgPrfx: "事由", notBlank: true }, 1);
  943. wdVm.add("wd.commonValidator.notNull", ["dwmc"], { msgPrfx: "单位名称", notBlank: true }, 1);
  944. }
  945. /**
  946. * 处理 "酒店餐饮" 的表单显示
  947. * 受访人信息显示:无
  948. * 来访信息显示:酒店名【下拉】、人数、预约开始时间、预约结束时间
  949. */
  950. function handleHotelVisit() {
  951. hideAllSections(); // 先隐藏所有部分
  952. $('#formSection3').removeClass('hidden');
  953. $('#tr-jfbmid, #tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden'); // 显示酒店相关字段
  954. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  955. }
  956. /**
  957. * 处理 "培训会议" 的表单显示
  958. * 受访人信息显示:无
  959. * 来访信息显示:名称【下拉】、人数、预约开始时间、预约结束时间
  960. */
  961. function handleTrainingVisit() {
  962. hideAllSections(); // 先隐藏所有部分
  963. $('#formSection2').removeClass('hidden'); // 显示表单部分2
  964. $('#tr-jfrxm, #tr-jfrgrdh').removeClass('hidden'); // 显示相关字段
  965. wdVm.add("wd.commonValidator.notNull", ["jfrxm"], { msgPrfx: "受访人姓名" }, 1);
  966. wdVm.add("wd.commonValidator.int", ["jfrgrdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  967. $('#formSection3').removeClass('hidden');
  968. $('#tr-dwmc,#tr-jfxiaoqid,#tr-rs, #tr-yykssj').removeClass('hidden'); // 显示会议相关字段
  969. wdVm.add("wd.commonValidator.notNull", ["dwmc"], { msgPrfx: "单位名称", notBlank: true }, 1);
  970. wdVm.add("wd.commonValidator.int", ["rs"], { minLen: 1, maxLen: 10000, msgPrfx: "人数", notBlank: true }, 1);
  971. }
  972. let firstVisitor = true;
  973. let xqInstance ;
  974. let jfbmInstance ;
  975. // 选择类别后
  976. function selectLflbm(value) {
  977. // 初始化开始事件结束时间
  978. setInitialTime()
  979. // 清空已输入的数据
  980. function clearInput() {
  981. console.log('清除已输入的数据')
  982. $('input[name="jfrxm"]').val('')
  983. $('input[name="jfrgrdh"]').val('')
  984. $('input[name="jfryid"]').val('')
  985. $('input[name="jfxiaoqid"]').val('')
  986. $('#jfxiaoqid .ss-select').text('请选择校区');
  987. $("input[name='jfbmid']").val('')
  988. $('#jfbmid .ss-options div').remove();
  989. $('input[name="dwmc"]').val('')
  990. }
  991. clearInput()
  992. if (firstVisitor) {
  993. xqInstance = initSSSelect('#jfxiaoqid', initSelectData.XIAOQ, { text: 'mc', value: 'xiaoqid' }, { enable: true }, selectXq);// 初始化校区下拉
  994. console.log(xqInstance)
  995. // 初始化第一个随行人员
  996. addVisitor(uniqueVisitorIdCounter, visitorCount, '访客');
  997. const jfrxm = $("input[name='jfrxm']").val('${lf.jfrxm}')
  998. const jfrgrdh = $("input[name='jfrgrdh']").val('${lf.jfrgrdh}')
  999. const jfryid = $("input[name='jfryid']").val('${lf.jfryid}')
  1000. const dwmc = $("input[name='dwmc']").val('${lf.dwmc}')
  1001. // const xbm = $("input[name='xbm']").val(${lf.xbm});
  1002. // const sfzjlbm = $("input[name='sfzjlbm']").val(${lf.sfzjlbm});
  1003. const xm = $("input[name='xm']").val('${lf.xm}');
  1004. const sfzh = $("input[name='sfzh']").val('${lf.sfzh}');
  1005. const grdh = $("input[name='grdh']").val('${lf.grdh}');
  1006. carNumberInstances['1'][0].setCarNumber('${lf.clh}')
  1007. // wdVm.add("wd.commonValidator.notNull", ["xm"], { msgPrfx: "姓名" }, 1);
  1008. // wdVm.add("wd.commonValidator.idCard", ["sfzh"], { msgPrfx: "证件号", notBlank: true, chkCsrq: false, chkXb: false, chkCsdq: false }, 1);
  1009. // wdVm.add("wd.commonValidator.int", ["grdh"], { minLen: 11, maxLen: 11, msgPrfx: "个人电话", notBlank: true }, 1);
  1010. firstVisitor = false;
  1011. }else{
  1012. xqInstance.setValue()
  1013. $('#jfbmid .ss-select').text('请选择酒店');
  1014. }
  1015. switch (value) {
  1016. case '1': // 探访学生
  1017. handleStudentVisit();
  1018. break;
  1019. case '5': // 探访教职工
  1020. handleStaffVisit();
  1021. break;
  1022. case '11': // 公务
  1023. handleOfficialVisit();
  1024. break;
  1025. case '21': // 培训会议
  1026. handleTrainingVisit();
  1027. break;
  1028. case '31': // 工作学习
  1029. handleWorkStudyVisit();
  1030. break;
  1031. case '51': // 物流配送
  1032. handleLogisticsVisit();
  1033. break;
  1034. case '61': // 酒店餐饮
  1035. handleHotelVisit();
  1036. $('#tr-jfbmid th').text('酒店名');
  1037. break;
  1038. case '71': // 场地预约
  1039. handleHotelVisit();
  1040. $('#tr-jfbmid th').text('场地');
  1041. break;
  1042. case '91': // 其他
  1043. handleOtherVisit();
  1044. break;
  1045. case '99': // 测试
  1046. handleOfficialVisit();
  1047. break;
  1048. }
  1049. // 选择后出现标题和底部按钮
  1050. $('.mobileForm-title,.mobileBottom-div').removeClass('hidden');
  1051. }
  1052. function initBm(value){
  1053. const lflbm = $("input[name='lflbm']").val();
  1054. // 过滤得到 xiaoqid 等于传入值的酒店对象数组
  1055. let filteredData ;
  1056. if(lflbm==61){filteredData = initSelectData.JD.filter(hotel => hotel.xiaoqid == value);}
  1057. if(lflbm==71){filteredData = initSelectData.CGHD.filter(hotel => hotel.xiaoqid == value);}
  1058. // 打印过滤后的数据
  1059. jfbmInstance = initSSSelect('#jfbmid', filteredData, { text: 'mc', value: 'bmid' }, { enable: true });// 初始化酒店下拉
  1060. if('${lf.jfbmid}' == ''){
  1061. $('#jfbmid .ss-select').text('请选择');
  1062. console.log(jfbmInstance)
  1063. jfbmInstance.setValue()
  1064. }
  1065. }
  1066. // 选择了校区
  1067. function selectXq(value) {
  1068. const lflbm = $("input[name='lflbm']").val();
  1069. //如果是酒店餐饮,则根据校区初始选择酒店
  1070. initBm(value)
  1071. }
  1072. $(document).ready(function () {
  1073. const warnMsg = '${warnMsg}';
  1074. if (warnMsg) {
  1075. alert(warnMsg);
  1076. }
  1077. $.ajax({
  1078. type: 'post',
  1079. async: false,
  1080. url: "<ss:serv name='lf_initExtLfInp' parm='{"param1":"abc123"}'/>",
  1081. data: { param2: 'def456' },
  1082. success: function (result) {
  1083. initSelectData = result;
  1084. }
  1085. });
  1086. // 初始化自定义下拉框,传入回调函数
  1087. initSSSelect('#lflbm', initSelectData.LFLB, { text: 'mc', value: 'lflbm' }, { enable: true, message: '请选择来访类别!' }, selectLflbm);
  1088. // 绑定新增随行人员事件
  1089. $("#visitorAdd").click(function () {
  1090. visitorCount++; // 增加有效随行人员计数
  1091. // 把新增的随行人员ID存入数组
  1092. sxry_num.push(uniqueVisitorIdCounter);
  1093. console.log(sxry_num)
  1094. uniqueVisitorIdCounter++; // 增加唯一随行人员 ID
  1095. // 新增随行人员
  1096. addVisitor(uniqueVisitorIdCounter, visitorCount, '');
  1097. });
  1098. // 点击删除随行人员
  1099. $(document).on("click", ".mobileDelete-button", function () {
  1100. const currentVisitorId = $(this)
  1101. .closest(".mobileForm-container")
  1102. .data("visitor-id");
  1103. delete carNumberInstances[currentVisitorId];
  1104. // 从随行人员数组中删除对应ID
  1105. sxry_num = sxry_num.filter(item => item !== (currentVisitorId - 1));
  1106. console.log(sxry_num)
  1107. // 删除对应校验
  1108. wdVm.remove("wd.commonValidator.notNull", [`xm_` + (currentVisitorId - 1)]);
  1109. wdVm.remove("wd.commonValidator.idCard", [`sfzh_` + (currentVisitorId - 1)]);
  1110. wdVm.remove("wd.commonValidator.int", [`grdh_` + (currentVisitorId - 1)]);
  1111. wdVm.remove('wd.commonValidator.notNull', [`sfzjlbm_` + (currentVisitorId - 1)]);
  1112. // 删除元素
  1113. $(this).closest(".mobileForm-container").remove();
  1114. updateVisitorNumbers();
  1115. });
  1116. function updateVisitorNumbers() {
  1117. $(".mobileForm-container").each(function (index) {
  1118. const newVisitorNumber = index;
  1119. if (!index) {
  1120. $(this).find(".mobileForm-title span:first-child").text("访客");
  1121. } else {
  1122. $(this).find(".mobileForm-title span:first-child").text("随行人员" + newVisitorNumber);
  1123. }
  1124. });
  1125. visitorCount = $(".mobileForm-container").length - 1;//减1是为了不把访客算进去
  1126. console.log("删除后当前访客数量", visitorCount)
  1127. }
  1128. // 新增车牌号
  1129. $(document).on("click", ".carNumberAdd", function () {
  1130. const currentVisitorId = $(this)
  1131. .closest(".mobileForm-container")
  1132. .data("visitor-id");
  1133. console.log("当前随行人员的ID", currentVisitorId);
  1134. if (!carNumberInstances[currentVisitorId]) {
  1135. carNumberInstances[currentVisitorId] = []; // 初始化当前随行人员的实例数组
  1136. }
  1137. const currentCarNumberCounter =
  1138. carNumberInstances[currentVisitorId].length + 1;
  1139. const newId = `carNumberInput` + currentVisitorId + `-` + currentCarNumberCounter;
  1140. console.log("主动点击随行人员的车牌号", newId);
  1141. const newRow = `
  1142. <tr class="carNumberRow">
  1143. <td colspan="2" class="carNumberTd">
  1144. <div>
  1145. <div id="`+ newId + `"></div>
  1146. <span class="mobileDelete-button carNumberDelete"></span>
  1147. </div>
  1148. </td>
  1149. </tr>`;
  1150. $(this).closest("table").find("tr").last().after(newRow);
  1151. const carInput = new CarNumberInput(newId, 'clh', '粤');
  1152. carNumberInstances[currentVisitorId].push(carInput);
  1153. });
  1154. // 删除车牌号行
  1155. $(document).on("click", ".carNumberDelete", function () {
  1156. const currentVisitorId = $(this)
  1157. .closest(".mobileForm-container")
  1158. .data("visitor-id");
  1159. // 找到当前随行人员下的所有车牌号行(根据容器和行数查找)
  1160. const carNumberRows = $(this)
  1161. .closest(".mobileForm-container")
  1162. .find("tr.carNumberRow");
  1163. // 找到当前点击的删除按钮所在的tr元素
  1164. const currentRow = $(this).closest("tr.carNumberRow");
  1165. // 获取当前删除按钮对应的车牌号索引
  1166. const rowIndex = carNumberRows.index(currentRow) + 1;
  1167. // 确保carNumberRows和carNumberInstances数组的一致性
  1168. if (rowIndex !== -1 && carNumberInstances[currentVisitorId]) {
  1169. // 删除对应的实例
  1170. carNumberInstances[currentVisitorId].splice(rowIndex, 1);
  1171. console.log(
  1172. `删除随行人员${currentVisitorId}里面的第${rowIndex}个车牌号后,实例数组:`,
  1173. carNumberInstances[currentVisitorId]
  1174. );
  1175. }
  1176. // 删除DOM中的对应行
  1177. currentRow.remove();
  1178. });
  1179. });
  1180. </script>
  1181. <script>
  1182. // 定义监听的逻辑,添加防抖处理
  1183. var debounceTimer; // 用于防抖的定时器
  1184. function checkInputsAndSendRequest() {
  1185. // 清除之前的定时器,防止过于频繁地发起请求
  1186. clearTimeout(debounceTimer);
  1187. // 设置一个新的定时器,延迟执行校验
  1188. debounceTimer = setTimeout(function() {
  1189. var jfrxmValue = $('input[name="jfrxm"]').val(); // 获取 jfrxm 的值
  1190. var jfrgrdhValue = $('input[name="jfrgrdh"]').val(); // 获取 jfrgrdh 的值
  1191. var lflbm = $('input[name="lflbm"]').val(); // 获取 lflbm 的值
  1192. // 如果两个输入框都有值,再发起 AJAX 请求
  1193. if (jfrxmValue && jfrgrdhValue) {
  1194. // 发起 AJAX 请求
  1195. $.ajax({
  1196. type: 'post',
  1197. async: false,
  1198. url: "<ss:serv name='lf_loadRyidByXmGrdh'/>",
  1199. data: {
  1200. xm: jfrxmValue,
  1201. grdh: jfrgrdhValue,
  1202. lflbm: lflbm
  1203. },
  1204. success: function(result) {
  1205. // 如果有错误消息
  1206. if (result && result.msg) {
  1207. $('input[name="jfryid"]').val('');
  1208. showErrorMessages(result.msg); // 显示错误信息
  1209. } else if (result && result.ryid){
  1210. $('input[name="jfryid"]').val(result.ryid);
  1211. removeErrorMessages(); // 清除错误信息
  1212. }
  1213. <%--
  1214. // 如果有结果,赋值
  1215. if (result && result.length > 0) {
  1216. $('input[name="jfryid"]').val(result[0].ryid);
  1217. removeErrorMessages(); // 清除错误信息
  1218. } else {
  1219. $('input[name="jfryid"]').val('');
  1220. showErrorMessages(); // 显示错误信息
  1221. }
  1222. --%>
  1223. }
  1224. });
  1225. } else {
  1226. $('input[name="jfryid"]').val('');
  1227. // 如果输入不全,清除错误信息
  1228. removeErrorMessages();
  1229. }
  1230. }, 500); // 防抖延迟500ms
  1231. }
  1232. // 显示错误信息
  1233. function showErrorMessages(msg) {
  1234. var jfrxmTd = $('input[name="jfrxm"]').closest('td');
  1235. var jfrgrdhTd = $('input[name="jfrgrdh"]').closest('td');
  1236. // 检查是否已经存在错误提示
  1237. if (!jfrxmTd.find('.error-message').length) {
  1238. jfrxmTd.css("border-bottom", "1px solid red")
  1239. .append('<span class="border-input-error vLine-leftWarning jfrxmSpan"></span>')
  1240. .append('<div class="error-message" style="position: absolute; left: 0px; bottom: 0px; color: red; font-size: 12px; width: 100%; text-align: right; line-height: 18px; height: 18px;">'+msg+'</div>');
  1241. }
  1242. if (!jfrgrdhTd.find('.error-message').length) {
  1243. jfrgrdhTd.css("border-bottom", "1px solid red")
  1244. .append('<span class="border-input-error vLine-leftWarning jfrgrdhSpan"></span>')
  1245. .append('<div class="error-message" style="position: absolute; left: 0px; bottom: 0px; color: red; font-size: 12px; width: 100%; text-align: right; line-height: 18px; height: 18px;">'+msg+'</div>');
  1246. }
  1247. }
  1248. // 清除错误信息
  1249. function removeErrorMessages() {
  1250. var jfrxmTd = $('input[name="jfrxm"]').closest('td');
  1251. var jfrgrdhTd = $('input[name="jfrgrdh"]').closest('td');
  1252. jfrxmTd.css("border-bottom", ""); // 恢复边框样式
  1253. jfrgrdhTd.css("border-bottom", ""); // 恢复边框样式
  1254. jfrxmTd.find('.error-message').remove(); // 移除所有错误提示
  1255. jfrgrdhTd.find('.error-message').remove(); // 移除所有错误提示
  1256. jfrxmTd.find('.jfrxmSpan').remove(); // 移除所有错误提示
  1257. jfrgrdhTd.find('.jfrgrdhSpan').remove(); // 移除所有错误提示
  1258. }
  1259. // 监听两个 input 的输入事件
  1260. $('input[name="jfrxm"], input[name="jfrgrdh"]').on('input blur', function() {
  1261. checkInputsAndSendRequest();
  1262. });
  1263. if('${lf.jfrxm}' && '${lf.jfrgrdh}'){
  1264. checkInputsAndSendRequest();
  1265. }
  1266. </script>
  1267. <script>
  1268. // 使用事件委托绑定 td 的点击事件
  1269. $('table').on('click', 'td', function() {
  1270. console.log("td clicked");
  1271. focusTextInput($(this));
  1272. });
  1273. // 使用事件委托绑定 .error-message 的点击事件
  1274. $('body').on('click', '.error-message', function() {
  1275. focusTextInput($(this));
  1276. });
  1277. // 公共方法,用于查找并聚焦 input[type="text"]
  1278. function focusTextInput($element) {
  1279. const $input = $element.find('input[type="text"]').length
  1280. ? $element.find('input[type="text"]')
  1281. : $element.siblings('input[type="text"]');
  1282. if ($input.length) {
  1283. $input.focus();
  1284. }
  1285. }
  1286. </script>
  1287. </html>