rcjhRc_monthZbAdd.ss.jsp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  1. <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>日历拖拽</title>
  7. <css.ss file="/ss/fullcalendar/main_.css"/>
  8. <css.ss file="/ss/fullcalendar/fullcalendar.css"/>
  9. <css.ss file="/ss/fullcalendar/jquery-ui.css"/>
  10. <%-- 必须去掉,会导致下拉列表出不来(变成录入框)。Lin
  11. 与编译时加入的 /ss/jquery/jquery.js 版本为 v1.11.2
  12. /ss/fullcalendar/jquery.js 版本为 v1.9.1
  13. <js@ss file="/ss/fullcalendar/jquery.js"/>
  14. --%>
  15. <js.ss file="/ss/fullcalendar/jquery-ui.js"/>
  16. <js.ss file="/ss/fullcalendar/fullcalendar.js"/>
  17. <style type="text/css">
  18. /* 原main.css部分,无需理会 */
  19. .icon-doc {
  20. width: 22px;
  21. height: 40px;
  22. display: inline-block;
  23. vertical-align: middle;
  24. background: url(/skin/easy/image/list-icon.png) center center no-repeat;
  25. float: left;
  26. margin-right: 6px;
  27. }
  28. .box {
  29. border: 1px solid #a9c5e1;
  30. box-sizing: border-box;
  31. border-radius: 3px;
  32. font-size: 18px;
  33. color: #4c4c4c;
  34. }
  35. .dragList-div {
  36. overflow: hidden;
  37. }
  38. .dragList-div .box {
  39. overflow: hidden;
  40. width: 48.5%;
  41. box-sizing: border-box;
  42. }
  43. .dragList-div .box:first-child {
  44. float: left;
  45. margin-left: 7px;
  46. }
  47. .dragList-div .box:last-child {
  48. float: right;
  49. margin-right: 7px;
  50. }
  51. .list-div {
  52. position: relative;
  53. overflow: auto;
  54. box-sizing: border-box;
  55. }
  56. .list {
  57. font-size: 14px;
  58. color: #000;
  59. }
  60. .list:nth-child(odd) {
  61. background-color: #ffffff;
  62. }
  63. .list:nth-child(even) {
  64. background-color: #fafafa;
  65. }
  66. span.list:hover {
  67. background-color: #c7e3fc;
  68. }
  69. div.list:hover {
  70. background-color: #c7e3fc;
  71. }
  72. .list a {
  73. color: #000;
  74. }
  75. table.list {
  76. width: calc(100% - 60px) !important;
  77. height: auto;
  78. border-collapse: separate;
  79. border-top-left-radius: 5px;
  80. border-top-right-radius: 5px;
  81. border-spacing: 0px;
  82. overflow: hidden;
  83. box-sizing: border-box;
  84. border: 1px solid #e0e0e0;
  85. margin-left: 30px;
  86. }
  87. .list tr {
  88. height: 40px;
  89. }
  90. .list tr:nth-child(odd) {
  91. background-color: #ffffff;
  92. }
  93. .list tr:nth-child(even) {
  94. background-color: #fafafa;
  95. }
  96. .list th {
  97. background-color: #6c9ed7;
  98. font-size: 14px;
  99. height: 40px;
  100. padding: 0px 30px 0px 12px;
  101. color: #fff;
  102. min-width: 50px;
  103. max-width: 250px;
  104. text-align: left;
  105. border-right: 1px solid #f2f2f2;
  106. box-sizing: border-box;
  107. word-break: break-word;
  108. vertical-align: middle;
  109. position: relative;
  110. }
  111. .list th:last-child {
  112. border-right: none;
  113. }
  114. .list tr td {
  115. font-size: 14px;
  116. color: #747474;
  117. box-sizing: border-box;
  118. word-break: break-word;
  119. position: relative;
  120. line-height: 42px;
  121. overflow: hidden;
  122. font-weight: normal;
  123. white-space: nowrap;
  124. text-overflow: ellipsis;
  125. padding: 0px 30px 0px 12px;
  126. border-right: 1px solid #f2f2f2;
  127. vertical-align: middle;
  128. max-width: 370px;
  129. }
  130. .list tr td:last-child {
  131. border-right: none;
  132. }
  133. /*闭合文件夹样式*/
  134. .list-highlight {
  135. color: #2b368f;
  136. font-size: 14px;
  137. }
  138. /* 次要的(待办列表灰色时间) */
  139. .list-smallDim {
  140. color: #969696;
  141. font-size: 12px;
  142. display: inline-block;
  143. vertical-align: middle;
  144. box-sizing: border-box;
  145. height: 40px;
  146. cursor: url(image/cur.ico), default !important;
  147. }
  148. .label {
  149. margin: 0;
  150. background-color: #6c9ddb;
  151. text-indent: 15px;
  152. height: 42px;
  153. text-overflow: ellipsis;
  154. box-sizing: border-box;
  155. overflow: hidden;
  156. white-space: nowrap;
  157. vertical-align: middle;
  158. font-weight: bold;
  159. color: #fff;
  160. line-height: 42px;
  161. font-size: 16px;
  162. position: relative;
  163. }
  164. /* 原main.css部分结束,无需理会 */
  165. .container{
  166. width: 100%;
  167. height: 100%;
  168. display: flex;
  169. gap: 20px;
  170. justify-content: center;
  171. align-items: center;
  172. }
  173. #calendar {
  174. width: 960px;
  175. margin-top: 20px;
  176. /* margin: 20px auto 10px auto; */
  177. float: left;
  178. }
  179. .fancy {
  180. width: 450px;
  181. height: auto
  182. }
  183. .fancy h3 {
  184. height: 30px;
  185. line-height: 30px;
  186. border-bottom: 1px solid #d3d3d3;
  187. font-size: 14px
  188. }
  189. .fancy form {
  190. padding: 10px
  191. }
  192. .fancy p {
  193. height: 28px;
  194. line-height: 28px;
  195. padding: 4px;
  196. color: #999
  197. }
  198. .input {
  199. height: 20px;
  200. line-height: 20px;
  201. padding: 2px;
  202. border: 1px solid #d3d3d3;
  203. width: 100px
  204. }
  205. .btn {
  206. -webkit-border-radius: 3px;
  207. -moz-border-radius: 3px;
  208. padding: 5px 12px;
  209. cursor: pointer
  210. }
  211. .btn_ok {
  212. background: #360;
  213. border: 1px solid #390;
  214. color: #fff
  215. }
  216. .btn_cancel {
  217. background: #f0f0f0;
  218. border: 1px solid #d3d3d3;
  219. color: #666
  220. }
  221. .btn_del {
  222. background: #f90;
  223. border: 1px solid #f80;
  224. color: #fff
  225. }
  226. .sub_btn {
  227. height: 32px;
  228. line-height: 32px;
  229. padding-top: 6px;
  230. border-top: 1px solid #f0f0f0;
  231. text-align: right;
  232. position: relative
  233. }
  234. .sub_btn .del {
  235. position: absolute;
  236. left: 2px
  237. }
  238. #menu {
  239. position: absolute;
  240. height: auto;
  241. display: none;
  242. z-index:99999999999;
  243. padding: 5px 5px;
  244. overflow: auto hidden;
  245. outline: none;
  246. box-shadow: 4px 4px 9px rgba(0, 0, 0, .13);
  247. box-sizing: border-box;
  248. background-color: #fff;
  249. border-left: 1px solid #e1e1e1;
  250. border-right: 1px solid #e1e1e1;
  251. border-bottom: 1px solid #e1e1e1;
  252. }
  253. .popList{
  254. width: 60px;
  255. height: 100%;
  256. }
  257. .active:hover{
  258. background: rgba(107, 159, 211);
  259. color: #fff;
  260. }
  261. /* 拖拽时的样式 */
  262. .drag-helper {
  263. padding: 5px 10px;
  264. background: #4a90e2;
  265. color: white;
  266. border-radius: 3px;
  267. z-index: 9999;
  268. position: fixed;
  269. pointer-events: none;
  270. }
  271. /* 日历事件样式 */
  272. .fc-event {
  273. background-color: #4a90e2 !important;
  274. border: none !important;
  275. color: white !important;
  276. padding: 2px 5px !important;
  277. border-radius: 3px !important;
  278. margin: 1px 2px !important;
  279. }
  280. /* 日期单元格高亮样式 */
  281. .fc-highlight {
  282. background: #e8f0fe !important;
  283. }
  284. /* 拖拽项样式 */
  285. .staff-list li {
  286. cursor: move;
  287. }
  288. /* 保存按钮样式 */
  289. .save-button {
  290. /* position: fixed;
  291. bottom: 20px;
  292. right: 20px; */
  293. margin: 0 10px;
  294. padding: 10px 20px;
  295. background-color: #4a90e2;
  296. color: white;
  297. border: none;
  298. border-radius: 4px;
  299. cursor: pointer;
  300. font-size: 16px;
  301. box-shadow: 0 2px 4px rgba(0,0,0,0.2);
  302. transition: all 0.3s ease;
  303. }
  304. .save-button:hover {
  305. background-color: #357abd;
  306. box-shadow: 0 4px 8px rgba(0,0,0,0.2);
  307. }
  308. /* 事件悬停样式 */
  309. .fc-event {
  310. position: relative;
  311. }
  312. .delete-btn {
  313. display: none;
  314. position: absolute;
  315. right: 2px;
  316. top: 50%;
  317. transform: translateY(-50%);
  318. color: #fff;
  319. width: 16px;
  320. height: 16px;
  321. line-height: 16px;
  322. text-align: center;
  323. cursor: pointer;
  324. font-size: 14px;
  325. transition: all 0.2s;
  326. z-index: 10;
  327. }
  328. .fc-event:hover .delete-btn {
  329. display: block;
  330. }
  331. .fc-event:hover .delete-btn:hover {
  332. color: #e74c3c;
  333. transform: translateY(-50%) scale(1.2);
  334. }
  335. /* 删除确认弹窗样式 */
  336. .delete-confirm {
  337. position: fixed;
  338. top: 50%;
  339. left: 50%;
  340. transform: translate(-50%, -50%);
  341. background: white;
  342. padding: 20px;
  343. border-radius: 8px;
  344. box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  345. z-index: 1000;
  346. display: none;
  347. }
  348. .delete-confirm .buttons {
  349. margin-top: 15px;
  350. text-align: right;
  351. }
  352. .delete-confirm button {
  353. padding: 5px 15px;
  354. margin-left: 10px;
  355. border-radius: 4px;
  356. cursor: pointer;
  357. border: none;
  358. }
  359. .delete-confirm .confirm {
  360. background: #e74c3c;
  361. color: white;
  362. }
  363. .delete-confirm .cancel {
  364. background: #f0f0f0;
  365. color: #333;
  366. }
  367. </style>
  368. </head>
  369. <body>
  370. <div class="container">
  371. <div id="calendar" >
  372. <menu id="menu">
  373. <ul class="popList">
  374. </ul>
  375. </menu>
  376. </div>
  377. <div id="datass" style="display: none;">
  378. </div>
  379. <div style="display: flex;flex-direction: column;gap: 20px;">
  380. <div class="dragList-div">
  381. <%-- Start 来自 rcjhRc_ddpZbAdd.ss.jsp。Lin
  382. 去掉 wsbf.js 里的 searchBm(this),直接用 findbm()
  383. wsbf.js 里的 searchBm(this):
  384. findbm();
  385. selectedClass(_obj, bmSelectButton); --%>
  386. <div style="float:right;">
  387. <%-- 增加,增加群组。Lin --%>
  388. <input id="qzid" name="qzid" type="hidden" value="${bmid}" onchange="findQz()"/>
  389. <input name="qzName" type="text" placeholder="群组" style="width: 118px"/>
  390. <objp.ss name="qz" cb="qz" inp="true"/>
  391. <%-- --%>
  392. <input type="hidden" id="data" name="" value="${dataType}">
  393. <input id="bmid" name="bmid" type="hidden" value="${bmid}" onchange="findbm()"/> <%-- ="searchBm(this)"。Lin --%>
  394. <input name="bmName" type="text" placeholder="部门" style="width: 118px"/>
  395. <objp.ss name="bm" cb="bm" inp="true"/>
  396. </div>
  397. <%-- End 来自 rcjhRc_ddpZbAdd.ss.jsp。Lin --%>
  398. <div class="box" style="width: 300px;">
  399. <p class="label">可选人员</p>
  400. <div class="list-body" style="position: relative;overflow-x: hidden;width: 100%;height: 380px;">
  401. <div id="ddpOption" class="scrollbar" style="height: 100%; overflow-y: auto; outline: none;" tabindex="2">
  402. <%-- 去掉,改为动态插入。Lin
  403. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  404. <span class="icon-doc"></span>
  405. <div data-id="1" class="list"><span>陈明宝</span></div>
  406. </div>
  407. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  408. <span class="icon-doc"></span>
  409. <div data-id="2" class="list"><span>尤国君</span></div>
  410. </div>
  411. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  412. <span class="icon-doc"></span>
  413. <div data-id="3" class="list"><span>郑华姐</span></div>
  414. </div>
  415. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  416. <span class="icon-doc"></span>
  417. <div data-id="4" class="list"><span>张仕完</span></div>
  418. </div>
  419. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  420. <span class="icon-doc"></span>
  421. <div data-id="5" class="list"><span>郑锦通</span></div>
  422. </div>
  423. <div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">
  424. <span class="icon-doc"></span>
  425. <div data-id="6" class="list"><span>林晓东</span></div>
  426. </div>
  427. --%>
  428. </div>
  429. </div>
  430. </div>
  431. <button class="save-button" onclick="saveSchedule()">保存排班表</button>
  432. </div>
  433. </div>
  434. </div>
  435. <!-- 删除确认弹窗 -->
  436. <div class="delete-confirm">
  437. <p>确定要删除这天的排班吗?</p>
  438. <div class="buttons">
  439. <button class="cancel" onclick="cancelDelete()">取消</button>
  440. <button class="confirm" onclick="confirmDelete()">确定</button>
  441. </div>
  442. </div>
  443. </body>
  444. <script>
  445. // 查询群组。Lin
  446. // 抄自 findbm()
  447. function findQz() {
  448. // initColumn(); // 去掉,没有了。不用先选中。Lin
  449. // var xm = $("#xm").val(); // 再去掉,没有 <input id=xm。Lin
  450. var qzid = $("#qzid").val();
  451. // var ryid=$("#ryid").val(); // 再去掉,没用到了 -- 去掉人员下拉选择了。Lin
  452. // console.info("xm:" + xm); //"bfsb_cx" // 再去掉,没有 <input id=xm。Lin
  453. $.ajax({
  454. url: "<serv.ss name='rcjhRc_selRyOptByQzid'/>",
  455. type: "post",
  456. data: {
  457. qzid: qzid
  458. /* 再去掉,没用到了 -- 去掉人员下拉选择了。Lin
  459. mc: xm,
  460. type: "bm",
  461. ryid: ryid
  462. */
  463. },
  464. dataType: "json",
  465. async: false,
  466. success: function (data) {
  467. insOptList(data.ryList);
  468. }
  469. })
  470. }
  471. // 抄自 rcjhRc_ddpZbAdd.ss.jsp 里的 findbm()。Lin
  472. //"查询部门"
  473. function findbm() {
  474. // initColumn(); // 去掉,没有了。不用先选中。Lin
  475. // var xm = $("#xm").val(); // 再去掉,没有 <input id=xm。Lin
  476. var bmid = $("#bmid").val();
  477. // var ryid=$("#ryid").val(); // 再去掉,没用到了 -- 去掉人员下拉选择了。Lin
  478. // console.info("xm:" + xm); //"bfsb_cx" // 再去掉,没有 <input id=xm。Lin
  479. $.ajax({
  480. url: "<serv.ss name='rcjhRc_selRyOptByBmid'/>", // :"pb_bd_zbap_findBm"。Lin
  481. type: "post",
  482. data: {
  483. bmid: bmid
  484. /* 再去掉,没用到了 -- 去掉人员下拉选择了。Lin
  485. mc: xm,
  486. type: "bm",
  487. ryid:ryid
  488. */
  489. },
  490. dataType: "json",
  491. async: false,
  492. success: function(data) {
  493. /* 去掉,抽取到 insOptList(,与 findQz( 共用。Lin
  494. /// * 改,适配月排班。Lin
  495. // console.info("ok<<<");
  496. // console.info("ld:" + data.ryList.length);
  497. // //console.info("come in");
  498. // //console.info("ryids长度:"+ryids.length);
  499. // $("#ryList").remove();
  500. // var box = '<div class="column" style="width:210px;height:75%;overflow:auto" id="ryList" tdname="1"><p class="label">可选</p></div>';
  501. // $("#thirth").append(box);
  502. // var divbox = ""
  503. // for(var j = 0; j < data.ryList.length; j++) {
  504. // divbox += '<div class="item" style="min-height: 41px;line-height: 41px;width: 100%;margin:auto;box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" name="bfsb" onMouseDown="pd(this);" onmousemove="mouse(this)"><span class="icon-unchecked icons" style="display: inline-block; width: 28px; height: 40px; float: left;"></span><span class="icon-doc"></span><h3>' + data.ryList[j].xm + '</h3><input type="hidden" value="' + data.ryList[j].ryid + '"/></div>';
  505. // }
  506. // console.log(divbox);
  507. // $("#ryList").append(divbox);
  508. /// *
  509. var divbox = ""
  510. for(var j = 0; j < data.ryList.length; j++) {
  511. divbox += '<div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">'+
  512. '<span class="icon-doc"></span>'+
  513. '<div data-id="'+ data.ryList[j].ryid +'" class="list"><span>'+ data.ryList[j].xm +'</span></div></div>';
  514. }
  515. $("#ddpOption").append(divbox);
  516. ///// 增加,从外面移进来 -- 改为动态加载了。Lin
  517. // 初始化人员列表的拖拽
  518. $('.list-background').each(function() {
  519. /// 再增加,解决跨月保存问题。Lin
  520. // 设置data属性,这些会被FullCalendar用来创建事件
  521. var staffId = $(this).find(".list").data("id");
  522. var staffName = $(this).find(".list span").text();
  523. $(this).data({
  524. event: {
  525. title: staffName,
  526. staffId: staffId,
  527. allDay: true,
  528. stick: true, // 保持事件在视图切换时不消失
  529. color: "#4a90e2",
  530. },
  531. });
  532. ///
  533. $(this).draggable({
  534. zIndex: 999,
  535. revert: true,
  536. revertDuration: 0,
  537. helper: function(event) {
  538. /// * 再改,解决跨月保存问题。Lin
  539. // var name = $(this).find('.list span').text();
  540. // return $('<div>')
  541. // .text(name)
  542. /// *
  543. return $('<div>').text(staffName)
  544. .css({
  545. 'background': '#4a90e2',
  546. 'color': 'white',
  547. 'padding': '5px 10px',
  548. 'border-radius': '3px',
  549. 'position': 'absolute',
  550. 'width': 'auto',
  551. 'height': 'auto',
  552. 'line-height': 'normal',
  553. 'font-size': '14px',
  554. 'white-space': 'nowrap'
  555. });
  556. },
  557. appendTo: 'body',
  558. cursor: 'move',
  559. cursorAt: { left: 20, top: 15 },
  560. start: function(e, ui) {
  561. $(ui.helper).css('z-index', 9999);
  562. }
  563. });
  564. });
  565. /// 再增加,解决跨月保存问题。Lin
  566. // 处理日历单元格的拖放
  567. $(".fc-day").droppable({
  568. drop: function (event, ui) {
  569. console.log("cell drop");
  570. // 保存拖放的目标日期到拖拽源元素
  571. var date = $(this).data("date");
  572. $(ui.draggable).data("drop-date", date);
  573. },
  574. });
  575. ///
  576. /////
  577. */ insOptList(data.ryList);
  578. }
  579. })
  580. }
  581. // 增加,从 findbm() 里抽取出来 -- 与 findQz() 共用。Lin
  582. function insOptList(ryList) {
  583. /* 改,适配月排班。Lin
  584. console.info("ok<<<");
  585. console.info("ld:" + data.ryList.length);
  586. //console.info("come in");
  587. //console.info("ryids长度:"+ryids.length);
  588. $("#ryList").remove();
  589. var box = '<div class="column" style="width:210px;height:75%;overflow:auto" id="ryList" tdname="1"><p class="label">可选</p></div>';
  590. $("#thirth").append(box);
  591. var divbox = ""
  592. for(var j = 0; j < data.ryList.length; j++) {
  593. divbox += '<div class="item" style="min-height: 41px;line-height: 41px;width: 100%;margin:auto;box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;" name="bfsb" onMouseDown="pd(this);" onmousemove="mouse(this)"><span class="icon-unchecked icons" style="display: inline-block; width: 28px; height: 40px; float: left;"></span><span class="icon-doc"></span><h3>' + data.ryList[j].xm + '</h3><input type="hidden" value="' + data.ryList[j].ryid + '"/></div>';
  594. }
  595. console.log(divbox);
  596. $("#ryList").append(divbox);
  597. */
  598. var divbox = ""
  599. for(var j = 0; j < ryList.length; j++) { // < data.ryList.。Lin
  600. divbox += '<div class="list-background list" style="min-height: 41px;line-height: 41px;width: calc(100% - 4px);box-sizing: border-box;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;">'+
  601. '<span class="icon-doc"></span>'+
  602. '<div data-id="'+ ryList[j].ryid +'" class="list"><span>'+ ryList[j].xm +'</span></div></div>'; // + data.ryList[j].。Lin
  603. }
  604. $("#ddpOption").append(divbox);
  605. ///// 增加,从外面移进来 -- 改为动态加载了。Lin
  606. // 初始化人员列表的拖拽
  607. $('.list-background').each(function() {
  608. /// 再增加,解决跨月保存问题。Lin
  609. // 设置data属性,这些会被FullCalendar用来创建事件
  610. var staffId = $(this).find(".list").data("id");
  611. var staffName = $(this).find(".list span").text();
  612. $(this).data({
  613. event: {
  614. title: staffName,
  615. staffId: staffId,
  616. allDay: true,
  617. stick: true, // 保持事件在视图切换时不消失
  618. color: "#4a90e2",
  619. },
  620. });
  621. ///
  622. $(this).draggable({
  623. zIndex: 999,
  624. revert: true,
  625. revertDuration: 0,
  626. helper: function(event) {
  627. /* 再改,解决跨月保存问题。Lin
  628. var name = $(this).find('.list span').text();
  629. return $('<div>')
  630. .text(name)
  631. */ return $('<div>').text(staffName)
  632. .css({
  633. 'background': '#4a90e2',
  634. 'color': 'white',
  635. 'padding': '5px 10px',
  636. 'border-radius': '3px',
  637. 'position': 'absolute',
  638. 'width': 'auto',
  639. 'height': 'auto',
  640. 'line-height': 'normal',
  641. 'font-size': '14px',
  642. 'white-space': 'nowrap'
  643. });
  644. },
  645. appendTo: 'body',
  646. cursor: 'move',
  647. cursorAt: { left: 20, top: 15 },
  648. start: function(e, ui) {
  649. $(ui.helper).css('z-index', 9999);
  650. }
  651. });
  652. });
  653. /// 再增加,解决跨月保存问题。Lin
  654. // 处理日历单元格的拖放
  655. $(".fc-day").droppable({
  656. drop: function (event, ui) {
  657. console.log("cell drop");
  658. // 保存拖放的目标日期到拖拽源元素
  659. var date = $(this).data("date");
  660. $(ui.draggable).data("drop-date", date);
  661. },
  662. });
  663. ///
  664. /////
  665. }
  666. // 模拟接口数据
  667. /* 改。Lin
  668. * date 改为 rq,staffId 改为 fzryid,staffName 改为 xm
  669. const mockScheduleData = [
  670. { date: '2025-05-15', staffId: '1', staffName: '陈明宝' },
  671. { date: '2025-06-20', staffId: '2', staffName: '尤国君' },
  672. { date: '2025-07-05', staffId: '3', staffName: '郑华姐' },
  673. { date: '2025-05-10', staffId: '4', staffName: '张仕完' },
  674. { date: '2025-05-20', staffId: '6', staffName: '林晓东' },
  675. { date: '2025-06-15', staffId: '6', staffName: '林晓东' },
  676. { date: '2025-06-25', staffId: '6', staffName: '林晓东' },
  677. { date: '2025-07-10', staffId: '6', staffName: '林晓东' },
  678. { date: '2025-07-15', staffId: '6', staffName: '林晓东' },
  679. { date: '2025-07-20', staffId: '6', staffName: '林晓东' },
  680. { date: '2025-07-25', staffId: '6', staffName: '林晓东' },
  681. { date: '2025-08-05', staffId: '6', staffName: '林晓东' },
  682. ]; */
  683. /* 再去掉,直接赋值到新加的 historySchedules -- 解决跨月保存问题。Lin
  684. var mockScheduleData = $@{zbapList};
  685. */
  686. // "调整了:存储所有历史数据的变量"(小许)。增加,解决跨月保存问题。Lin
  687. let historySchedules = ${zbapList}; // = []。Lin
  688. // 模拟API调用
  689. /* 再去掉,直接赋值到 historySchedules 了。Lin
  690. * 原调用 fetchScheduleData() 后,赋值到 historySchedules
  691. function fetchScheduleData(startDate, endDate) {
  692. return new Promise((resolve) => {
  693. setTimeout(() => {
  694. // 过滤出指定日期范围内的数据
  695. const filteredData = mockScheduleData.filter(schedule => {
  696. const scheduleDate = new Date(schedule.rq); // (schedule.date)。Lin
  697. return scheduleDate >= startDate && scheduleDate <= endDate;
  698. });
  699. resolve(filteredData);
  700. }, 300); // 模拟网络延迟
  701. });
  702. }
  703. */
  704. $(function() {
  705. // 初始化日历
  706. var calendar = $('#calendar').fullCalendar({
  707. header: {
  708. left: 'prev,next today',
  709. center: 'title',
  710. right: 'month'
  711. },
  712. height: window.innerHeight - 50,
  713. // 调整3:启用事件编辑,允许拖拽已有排班
  714. editable: true,
  715. droppable: true,
  716. firstDay: 0,
  717. // 视图渲染完成后的回调
  718. viewRender: function(view) {
  719. // 获取当前视图的开始和结束日期
  720. var start = view.start;
  721. var end = view.end;
  722. // 清除当前视图的所有事件
  723. $('#calendar').fullCalendar('removeEvents');
  724. // 加载该月份的数据
  725. /* 再改,解决跨月保存问题。Lin
  726. * 去掉 fetchScheduleData(startDate, endDate),直接赋值到新加的 historySchedules
  727. * 原在 fetchScheduleData(startDate, endDate) 过滤出当前月数据,现改为在这过滤
  728. fetchScheduleData(new Date(start), new Date(end)).then(scheduleData => {
  729. scheduleData.forEach(schedule => {
  730. */
  731. historySchedules.forEach(schedule => {
  732. // 直接使用日期字符串创建 Date 对象
  733. var scheduleDate = new Date(schedule.rq);
  734. // 在日历组件内部根据视图范围过滤数据
  735. if (scheduleDate >= start && scheduleDate < end) {
  736. $('#calendar').fullCalendar('renderEvent', {
  737. title: schedule.xm, // .staffName,。Lin
  738. start: schedule.rq, // .date,。Lin
  739. allDay: true,
  740. staffId: schedule.fzryid, // .staffId,。Lin
  741. color: '#4a90e2'
  742. }, true);
  743. }
  744. });
  745. // }); // 去掉 fetchScheduleData(new Date(start), new Date(end)).then(scheduleData => { 了。Lin
  746. },
  747. /// 再增加,支持月历内拖放。Lin
  748. // 调整3:处理事件拖拽,更新historySchedules
  749. eventDrop: function(event, delta, revertFunc) {
  750. console.log('事件被拖拽到:', event.start);
  751. // 格式化新的日期
  752. var newDate = event.start;
  753. var formattedDate = newDate.getFullYear() + '-' +
  754. String(newDate.getMonth() + 1).padStart(2, '0') + '-' +
  755. String(newDate.getDate()).padStart(2, '0');
  756. // 从historySchedules中找到并更新对应的记录
  757. var oldValue = formattedDate.replace(/-/g, '') + '-' + event.staffId;
  758. // 更新historySchedules
  759. historySchedules = historySchedules.map(item => {
  760. var itemDate = new Date(item.rq); // .date)。Lin
  761. var eventDate = new Date(event._oldDate); // 保存的原始日期
  762. /// 再增加,解决 new Date(item.rq) 与 new Date(event._oldDate) 不一致问题。Lin
  763. // new Date(item.rq) 转为 08:00:00,new Date(event._oldDate) 转为 00:00:00
  764. // event._oldDate = event.start.toISOString()
  765. itemDate.setHours(0, 0, 0, 0);
  766. eventDate.setHours(0, 0, 0, 0);
  767. ///
  768. // 如果找到匹配的记录,更新日期
  769. if (itemDate.getTime() === eventDate.getTime() && // .getTime()。Lin
  770. item.fzryid === event.staffId) { // .staffId ===。Lin
  771. return {
  772. ...item,
  773. rq: formattedDate, // date:。Lin
  774. value: oldValue
  775. };
  776. }
  777. return item;
  778. });
  779. console.log('更新后的historySchedules:', historySchedules);
  780. },
  781. ///
  782. // 拖拽事件
  783. drop: function(date) {
  784. var $this = $(this);
  785. var targetDate = date;
  786. // 移除当天已有的事件
  787. $('#calendar').fullCalendar('removeEvents', function(event) {
  788. var eventDate = new Date(event.start);
  789. var dropDate = new Date(targetDate);
  790. return eventDate.getDate() === dropDate.getDate() &&
  791. eventDate.getMonth() === dropDate.getMonth() &&
  792. eventDate.getFullYear() === dropDate.getFullYear();
  793. });
  794. /// 再增加,解决跨月保存问题。Lin
  795. // 获取员工信息
  796. var staffId = $this.find(".list").data("id");
  797. var staffName = $this.find(".list span").text();
  798. // 格式化日期为 YYYY-MM-DD
  799. var formattedDate =
  800. targetDate.getFullYear() +
  801. "-" +
  802. String(targetDate.getMonth() + 1).padStart(2, "0") +
  803. "-" +
  804. String(targetDate.getDate()).padStart(2, "0");
  805. // 更新 historySchedules
  806. // 删除同一天的旧数据(如果存在)
  807. historySchedules = historySchedules.filter(
  808. (item) => item.rq !== formattedDate // .date !==。Lin
  809. );
  810. // 添加新数据
  811. var newSchedule = {
  812. rq: formattedDate, // date:。Lin
  813. fzryid: staffId, // staffId:。Lin
  814. xm: staffName, // staffName:。Lin
  815. value: formattedDate.replace(/-/g, "") + "-" + staffId, // 去掉,没用到。再不能去掉,有用到 "首先将历史数据放入 Map,使用 value 作为键"。Lin
  816. };
  817. historySchedules.push(newSchedule);
  818. console.log("更新后的historySchedules:", historySchedules);
  819. ///
  820. // 添加新事件
  821. $('#calendar').fullCalendar('renderEvent', {
  822. /* 再改,解决跨月保存问题。Lin
  823. title: $this.find('.list span').text(),
  824. */ title: staffName,
  825. start: targetDate,
  826. allDay: true,
  827. /* 再改,解决跨月保存问题。Lin
  828. staffId: $this.find('.list').data('id'),
  829. */ staffId: staffId,
  830. color: '#4a90e2'
  831. }, true);
  832. },
  833. // 调整3:在事件渲染时保存原始日期,用于后续比较和更新
  834. // 拖放时的视觉反馈
  835. eventRender: function(event, element) {
  836. /// 再增加,支持月历内拖放。Lin
  837. // 保存事件的原始日期
  838. event._oldDate = event.start.toISOString();
  839. ///
  840. element.css({
  841. 'background-color': '#4a90e2',
  842. 'border': 'none',
  843. 'color': 'white',
  844. 'padding': '2px 5px',
  845. 'border-radius': '3px',
  846. 'margin': '1px 2px'
  847. });
  848. // 添加删除按钮
  849. var deleteBtn = $('<span class="delete-btn" style="cursor:pointer;margin-left:5px;position:absolute;right:2px;top:50%;transform:translateY(-50%);">×</span>');
  850. element.append(deleteBtn);
  851. // 为删除按钮添加点击事件
  852. deleteBtn.on('click', function(e) {
  853. e.preventDefault();
  854. e.stopPropagation();
  855. window.eventToDelete = event;
  856. $('.delete-confirm').fadeIn(200);
  857. });
  858. },
  859. // 移除原来的 eventClick 处理器
  860. eventClick: function(event, jsEvent, view) {
  861. // 如果需要其他点击事件处理,可以在这里添加
  862. }
  863. });
  864. // 初始化人员列表的拖拽
  865. /* 去掉,移到 findBm() 里 -- 改为动态加载。Lin
  866. $('.list-background').each(function() {
  867. $(this).draggable({
  868. zIndex: 999,
  869. revert: true,
  870. revertDuration: 0,
  871. helper: function(event) {
  872. var name = $(this).find('.list span').text();
  873. return $('<div>')
  874. .text(name)
  875. .css({
  876. 'background': '#4a90e2',
  877. 'color': 'white',
  878. 'padding': '5px 10px',
  879. 'border-radius': '3px',
  880. 'position': 'absolute',
  881. 'width': 'auto',
  882. 'height': 'auto',
  883. 'line-height': 'normal',
  884. 'font-size': '14px',
  885. 'white-space': 'nowrap'
  886. });
  887. },
  888. appendTo: 'body',
  889. cursor: 'move',
  890. cursorAt: { left: 20, top: 15 },
  891. start: function(e, ui) {
  892. $(ui.helper).css('z-index', 9999);
  893. }
  894. });
  895. });
  896. */
  897. });
  898. // 保存排班表 > 调整2:保存排班表时更新historySchedules
  899. // 再改,解决跨月保存问题。Lin
  900. function saveSchedule() {
  901. // 获取所有事件
  902. var events = $('#calendar').fullCalendar('clientEvents');
  903. var scheduleArray = [];
  904. /// 增加,解决跨月保存问题。Lin
  905. // 创建一个 Map 来存储所有排班,键为日期
  906. var scheduleMap = new Map();
  907. // 首先将历史数据放入 Map,使用 value 作为键
  908. historySchedules.forEach(function(schedule) {
  909. scheduleMap.set(schedule.value, schedule);
  910. });
  911. // 获取当前视图的日期范围
  912. var view = $('#calendar').fullCalendar('getView');
  913. var viewStart = new Date(view.start);
  914. var viewEnd = new Date(view.end);
  915. ///
  916. // 处理当前视图中的事件,更新或添加到 Map 中
  917. events.forEach(function(event) {
  918. // 格式化日期为 YYYY-MM-DD
  919. var date = new Date(event.start);
  920. /* 改,把 20250624 改为 2025-06-24 -- 转为原来的。Lin
  921. var formattedDate = date.getFullYear() + '' +
  922. String(date.getMonth() + 1).padStart(2, '0') + '' +
  923. String(date.getDate()).padStart(2, '0');
  924. */ var formattedDate = date.getFullYear() + '-' +
  925. String(date.getMonth() + 1).padStart(2, '0') + '-' +
  926. String(date.getDate()).padStart(2, '0');
  927. // 创建排班记录
  928. var schedule = {
  929. rq: formattedDate, // date:。Lin
  930. fzryid: Number(event.staffId), // staffId:。Lin
  931. xm: event.title, // staffName:。Lin
  932. value:formattedDate.replace(/-/g, "") + '-' + event.staffId // 去掉,没用到。再不能去掉,有用到 "首先将历史数据放入 Map,使用 value 作为键"。Lin
  933. };
  934. /* 再改,解决跨月保存问题。Lin
  935. scheduleArray.push(schedule);
  936. */ scheduleMap.set(schedule.value, schedule); // 更新 Map 中的数据
  937. });
  938. /// 再增加,解决跨月保存问题。Lin
  939. // 删除当前视图范围内但不在 events 中的数据
  940. /* 再去掉,不能删除 -- 解决跨月保存问题。Lin
  941. historySchedules.forEach(function(schedule) {
  942. var scheduleDate = new Date(schedule.date);
  943. // 如果日期在当前视图范围内,但不在 events 中,则删除
  944. if (scheduleDate >= viewStart && scheduleDate < viewEnd) {
  945. var found = events.some(function(event) {
  946. var eventDate = new Date(event.start);
  947. return eventDate.getTime() === scheduleDate.getTime();
  948. });
  949. if (!found) {
  950. scheduleMap.delete(schedule.value);
  951. }
  952. }
  953. });
  954. */
  955. // 将 Map 转换回数组
  956. scheduleArray = Array.from(scheduleMap.values());
  957. ///
  958. // 按日期排序
  959. scheduleArray.sort((a, b) => a.rq.localeCompare(b.rq)); // => a.date.,(b.date))。Lin
  960. /// 再增加,解决跨月保存问题。Lin
  961. //调整2:更新历史数据
  962. historySchedules = scheduleArray;
  963. ///
  964. /// 增加,转为原来的 ,2025-06-24|2025-06-24|13:30:00^13:32:00^111121$undefined$* -- 抄自 rcjhRc_ddpZbAdd.ss.jsp 里的 savebfap()。Lin
  965. var zstr = "";
  966. scheduleArray.forEach(schedule => {
  967. zstr += ","+ schedule.rq +"|"+ schedule.rq +"|"+
  968. "00:00:00^23:59:59^"+
  969. schedule.fzryid +"$undefined$*";
  970. });
  971. //保存
  972. $.ajax({
  973. url: "<serv.ss name='rcjhRc_saveZbAdd'/>", // :"pb_bd_zbap_pbaobc"。Lin
  974. type: "post",
  975. data: {
  976. rcjhid: "${rcjhid}",
  977. rqsjstr: zstr
  978. },
  979. dataType: "json",
  980. success: function(data) {
  981. console.info(data.statu);
  982. if(data.statu == 1) {
  983. window.location = "<serv.ss dest='info' parm='{msg:"保存成功"}'/>";
  984. } else {
  985. window.location = "<serv.ss dest='info' parm='{msg:"保存失败"}'/>";
  986. }
  987. }
  988. })
  989. ///
  990. // alert('共'+scheduleArray.length+'条排班数据\n'+JSON.stringify(scheduleArray)); // 去掉,完成使命了。Lin
  991. }
  992. // 取消删除
  993. function cancelDelete() {
  994. $('.delete-confirm').fadeOut(200);
  995. window.eventToDelete = null;
  996. }
  997. // 确认删除
  998. function confirmDelete() {
  999. if (window.eventToDelete) {
  1000. /* 再改,解决跨月保存问题。Lin
  1001. $('#calendar').fullCalendar('removeEvents', window.eventToDelete._id);
  1002. */
  1003. var date = window.eventToDelete.start;
  1004. var staffId = window.eventToDelete.staffId;
  1005. // 调用deleteSchedule函数
  1006. deleteSchedule(date, staffId);
  1007. // 关闭确认框
  1008. $('.delete-confirm').fadeOut(200);
  1009. window.eventToDelete = null;
  1010. }
  1011. }
  1012. /// 再增加,解决跨月保存问题。Lin
  1013. // 调整2:删除排班时更新historySchedules
  1014. function deleteSchedule(date, staffId) {
  1015. console.log("删除排班:", date, staffId);
  1016. // 直接从historySchedules中删除对应的数据
  1017. historySchedules = historySchedules.filter((item) => {
  1018. var itemDate = new Date(item.rq); // .date)。Lin
  1019. var targetDate = new Date(date);
  1020. return (
  1021. itemDate.getTime() !== targetDate.getTime() ||
  1022. item.fzryid !== staffId // .staffId !==。Lin
  1023. );
  1024. });
  1025. // 重新渲染当前视图
  1026. var view = $("#calendar").fullCalendar("getView");
  1027. var start = view.start;
  1028. var end = view.end;
  1029. // 清除当前视图的所有事件
  1030. $("#calendar").fullCalendar("removeEvents");
  1031. // 重新渲染数据
  1032. historySchedules.forEach((schedule) => {
  1033. var scheduleDate = new Date(schedule.rq); // .date)。Lin
  1034. if (scheduleDate >= start && scheduleDate < end) {
  1035. $("#calendar").fullCalendar(
  1036. "renderEvent",
  1037. {
  1038. title: schedule.xm, // .staffName,。Lin
  1039. start: scheduleDate,
  1040. allDay: true,
  1041. staffId: schedule.fzryid, // .staffId,。Lin
  1042. color: "#4a90e2",
  1043. },
  1044. true
  1045. );
  1046. }
  1047. });
  1048. }
  1049. ///
  1050. </script>
  1051. </html>