index.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. import Week from "./func/week";
  2. import { Logger, Slide, GetDate, initialTasks } from "./func/utils";
  3. import initCalendar, {
  4. jump,
  5. getCurrentYM,
  6. whenChangeDate,
  7. renderCalendar,
  8. whenMulitSelect,
  9. whenSingleSelect,
  10. whenChooseArea,
  11. getCalendarDates,
  12. } from "./main.js";
  13. import {
  14. getPatientOnlineRecord,
  15. addPatientOnlineRecord,
  16. } from "../../pages/home/request";
  17. import tickleBehavior, {
  18. getTickleContext,
  19. } from "../../core/behavior/tickle.behavior";
  20. const slide = new Slide();
  21. const logger = new Logger();
  22. const getDate = new GetDate();
  23. // 获取上个月
  24. function getPrevMonth(year, month) {
  25. if (month === 1) {
  26. return { year: year - 1, month: 12 };
  27. }
  28. return { year, month: month - 1 };
  29. }
  30. // 获取下个月
  31. function getNextMonth(year, month) {
  32. if (month === 12) {
  33. return { year: year + 1, month: 1 };
  34. }
  35. return { year, month: month + 1 };
  36. }
  37. function pad(num) {
  38. return num < 10 ? "0" + num : "" + num;
  39. }
  40. Component({
  41. options: {
  42. styleIsolation: "apply-shared",
  43. multipleSlots: true, // 在组件定义时的选项中启用多slot支持
  44. },
  45. properties: {
  46. calendarConfig: {
  47. type: Object,
  48. value: {},
  49. },
  50. },
  51. behaviors: [tickleBehavior],
  52. data: {
  53. noClockIn: [],
  54. clockIn: [],
  55. id: "",
  56. handleMap: {
  57. prev_year: "chooseYear",
  58. prev_month: "chooseMonth",
  59. next_month: "chooseMonth",
  60. next_year: "chooseYear",
  61. },
  62. currentMonth: null,
  63. currentYear: null,
  64. firstDate: null,
  65. lastDate: null,
  66. dateArrType: 1,
  67. days: [],
  68. dayData: "",
  69. isFutureDate: false,
  70. },
  71. observers: {
  72. "calendar.days": function (newVal: any) {
  73. // 简化条件判断,只检查 newVal
  74. if (
  75. newVal &&
  76. newVal.length > 0 &&
  77. newVal[0] &&
  78. newVal[0].year &&
  79. newVal[0].month
  80. ) {
  81. this.setData({
  82. currentMonth: newVal[0].month,
  83. currentYear: newVal[0].year,
  84. });
  85. let firstDate = null;
  86. const empytGrids = this.data.calendar.empytGrids || [];
  87. const days = newVal || [];
  88. let prevData = null;
  89. if (empytGrids.length > 0) {
  90. // 有上月补齐格子,第一个就是上月的
  91. prevData = {
  92. year: getPrevMonth(days[0].year, days[0].month).year,
  93. month: getPrevMonth(days[0].year, days[0].month).month,
  94. day: empytGrids[0].day,
  95. };
  96. } else if (days.length > 0) {
  97. // 没有上月补齐格子,第一个就是本月1号
  98. prevData = {
  99. year: days[0].year,
  100. month: days[0].month,
  101. day: days[0].day,
  102. };
  103. }
  104. let lastDate = null;
  105. let nextData = null;
  106. const lastEmptyGrids = this.data.calendar.lastEmptyGrids || [];
  107. if (lastEmptyGrids.length > 0) {
  108. nextData = {
  109. year: getNextMonth(days[0].year, days[0].month).year,
  110. month: getNextMonth(days[0].year, days[0].month).month,
  111. day: lastEmptyGrids[lastEmptyGrids.length - 1].day,
  112. };
  113. } else if (days.length > 0) {
  114. nextData = {
  115. year: days[days.length - 1].year,
  116. month: days[days.length - 1].month,
  117. day: days[days.length - 1].day,
  118. };
  119. }
  120. lastDate =
  121. nextData.year + "-" + pad(nextData.month) + "-" + pad(nextData.day);
  122. firstDate =
  123. prevData.year + "-" + pad(prevData.month) + "-" + pad(prevData.day);
  124. this.setData({
  125. firstDate,
  126. lastDate,
  127. });
  128. this.setData({
  129. id: wx.getStorageSync("recordId") || "",
  130. });
  131. if (this.data.id) {
  132. this.getCaRecord(this.data.id, firstDate, lastDate);
  133. } else {
  134. setTimeout(() => {
  135. this.getCaRecord(this.data.id, firstDate, lastDate);
  136. }, 2000);
  137. }
  138. }
  139. },
  140. },
  141. lifetimes: {
  142. attached: async function () {
  143. this.initComp();
  144. },
  145. detached: function () {
  146. initialTasks.flag = "finished";
  147. initialTasks.tasks.length = 0;
  148. },
  149. },
  150. methods: {
  151. // 补卡
  152. async onPatchCard(e: any) {
  153. try {
  154. const cardId = e.currentTarget.dataset.id;
  155. await addPatientOnlineRecord(cardId);
  156. wx.showToast({
  157. title: "补卡成功",
  158. icon: "success",
  159. duration: 1500,
  160. });
  161. await this.getCaRecord(
  162. this.data.id,
  163. this.data.firstDate,
  164. this.data.lastDate
  165. );
  166. } catch (error: any) {
  167. getTickleContext.call(this).showWarnMessage(error.errMsg);
  168. }
  169. },
  170. async getCaRecord(id: string | number, startDate: string, endDate: string) {
  171. try {
  172. const res = await getPatientOnlineRecord(id, startDate, endDate);
  173. const { currentYear, currentMonth } = this.data;
  174. if (res && res.length > 0) {
  175. // 1. 先筛选出本月的数据
  176. const monthData = (res || []).filter(
  177. (item: any) =>
  178. item.arrangeYear == currentYear && item.arrangeMon == currentMonth
  179. );
  180. // 2. 遍历本月 days,赋值
  181. (this.data.calendar.days || []).forEach((dayItem: any) => {
  182. // 只处理本月的格子
  183. if (dayItem.year == currentYear && dayItem.month == currentMonth) {
  184. // 只给当前日期及之前的日期赋值
  185. const currentDate = new Date();
  186. const itemDate = new Date(
  187. dayItem.year,
  188. dayItem.month - 1,
  189. dayItem.day
  190. );
  191. // 如果日期是今天或之前,才进行赋值
  192. if (itemDate <= currentDate) {
  193. const match = monthData.find(
  194. (d: any) => d.arrangeDay == dayItem.day
  195. );
  196. if (match) {
  197. dayItem.clockIn = [...match.clockIn];
  198. dayItem.noClockIn = [...match.noClockIn];
  199. dayItem.type = match.type;
  200. }
  201. } else {
  202. // 未来日期设置空的打卡数据,确保不显示打卡和补卡功能
  203. dayItem.clockIn = [];
  204. dayItem.noClockIn = [];
  205. dayItem.type = null;
  206. }
  207. }
  208. });
  209. const matchData = monthData.filter(
  210. (d: any) => d.arrangeDay == this.data.dayData
  211. );
  212. if (matchData.length > 0) {
  213. this.setData({
  214. noClockIn: matchData[0].noClockIn,
  215. clockIn: matchData[0].clockIn,
  216. });
  217. }
  218. this.setData({
  219. days: this.data.calendar.days,
  220. });
  221. if (this.data.dateArrType == 1) {
  222. const currentDay = this.data.days.find(
  223. (item: any) => item.lunar.isToday
  224. );
  225. if (currentDay) {
  226. // 检查当前日期是否为未来日期
  227. const currentDate = new Date();
  228. const itemDate = new Date(
  229. currentDay.year,
  230. currentDay.month - 1,
  231. currentDay.day
  232. );
  233. const isCurrentDayFuture = itemDate > currentDate;
  234. if (!isCurrentDayFuture) {
  235. this.setData({
  236. noClockIn: currentDay.noClockIn,
  237. clockIn: currentDay.clockIn,
  238. isFutureDate: false,
  239. });
  240. } else {
  241. this.setData({
  242. noClockIn: [],
  243. clockIn: [],
  244. isFutureDate: true,
  245. });
  246. }
  247. }
  248. }
  249. }
  250. } catch (error) {
  251. getTickleContext.call(this).showWarnMessage(error.errMsg);
  252. }
  253. },
  254. initComp() {
  255. const calendarConfig = this.setDefaultDisableDate();
  256. this.setConfig(calendarConfig);
  257. },
  258. setDefaultDisableDate() {
  259. const calendarConfig = this.properties.calendarConfig || {};
  260. if (calendarConfig.disableMode && !calendarConfig.disableMode.date) {
  261. calendarConfig.disableMode.date = getDate.toTimeStr(
  262. getDate.todayDate()
  263. );
  264. }
  265. return calendarConfig;
  266. },
  267. setConfig(config) {
  268. if (config.markToday && typeof config.markToday === "string") {
  269. config.highlightToday = true;
  270. }
  271. config.theme = config.theme || "default";
  272. this.weekMode = config.weekMode;
  273. this.setData(
  274. {
  275. calendarConfig: config,
  276. },
  277. () => {
  278. initCalendar(this, config);
  279. }
  280. );
  281. },
  282. chooseDate(e) {
  283. const { type } = e.currentTarget.dataset;
  284. if (!type) return;
  285. const methodName = this.data.handleMap[type];
  286. this[methodName](type);
  287. },
  288. chooseYear(type) {
  289. const { curYear, curMonth } = this.data.calendar;
  290. if (!curYear || !curMonth) return logger.warn("异常:未获取到当前年月");
  291. if (this.weekMode) {
  292. return console.warn("周视图下不支持点击切换年月");
  293. }
  294. let newYear = +curYear;
  295. let newMonth = +curMonth;
  296. if (type === "prev_year") {
  297. newYear -= 1;
  298. } else if (type === "next_year") {
  299. newYear += 1;
  300. }
  301. this.render(curYear, curMonth, newYear, newMonth);
  302. },
  303. chooseMonth(type) {
  304. const { curYear, curMonth } = this.data.calendar;
  305. if (!curYear || !curMonth) return logger.warn("异常:未获取到当前年月");
  306. if (this.weekMode) return console.warn("周视图下不支持点击切换年月");
  307. let newYear = +curYear;
  308. let newMonth = +curMonth;
  309. if (type === "prev_month") {
  310. newMonth = newMonth - 1;
  311. if (newMonth < 1) {
  312. newYear -= 1;
  313. newMonth = 12;
  314. }
  315. } else if (type === "next_month") {
  316. newMonth += 1;
  317. if (newMonth > 12) {
  318. newYear += 1;
  319. newMonth = 1;
  320. }
  321. }
  322. this.render(curYear, curMonth, newYear, newMonth);
  323. },
  324. render(curYear, curMonth, newYear, newMonth) {
  325. whenChangeDate.call(this, {
  326. curYear,
  327. curMonth,
  328. newYear,
  329. newMonth,
  330. });
  331. this.setData({
  332. "calendar.curYear": newYear,
  333. "calendar.curMonth": newMonth,
  334. });
  335. renderCalendar.call(this, newYear, newMonth);
  336. },
  337. /**
  338. * 日期点击事件
  339. * @param {!object} e 事件对象
  340. */
  341. tapDayItem(e) {
  342. this.setData({
  343. dateArrType: 2,
  344. });
  345. const { idx, date = {} } = e.currentTarget.dataset;
  346. const selectedDate = `${date.year} ${date.month}.${date.day}`;
  347. this.triggerEvent("onSelect", {
  348. selectedDate,
  349. });
  350. const { day, disable, clockIn, noClockIn, type } = date;
  351. // 检查是否为未来日期
  352. const currentDate = new Date();
  353. const itemDate = new Date(date.year, date.month - 1, date.day);
  354. const isFutureDate = itemDate > currentDate;
  355. // 如果是未来日期,设置空的打卡数据,但仍然可以点击
  356. if (isFutureDate) {
  357. this.setData({
  358. noClockIn: [],
  359. clockIn: [],
  360. dayData: day,
  361. isFutureDate: true,
  362. });
  363. } else {
  364. this.setData({
  365. noClockIn: noClockIn || [],
  366. clockIn: clockIn || [],
  367. dayData: day,
  368. isFutureDate: false,
  369. });
  370. }
  371. if (disable || !day) return;
  372. const config = this.data.calendarConfig || this.config || {};
  373. const { multi, chooseAreaMode } = config;
  374. if (multi) {
  375. whenMulitSelect.call(this, idx);
  376. } else if (chooseAreaMode) {
  377. whenChooseArea.call(this, idx);
  378. } else {
  379. whenSingleSelect.call(this, idx);
  380. }
  381. this.setData({
  382. "calendar.noDefault": false,
  383. });
  384. },
  385. doubleClickToToday() {
  386. if (this.config.multi || this.weekMode) return;
  387. if (this.count === undefined) {
  388. this.count = 1;
  389. } else {
  390. this.count += 1;
  391. }
  392. if (this.lastClick) {
  393. const difference = new Date().getTime() - this.lastClick;
  394. if (difference < 500 && this.count >= 2) {
  395. jump.call(this);
  396. }
  397. this.count = undefined;
  398. this.lastClick = undefined;
  399. } else {
  400. this.lastClick = new Date().getTime();
  401. }
  402. },
  403. /**
  404. * 日历滑动开始
  405. * @param {object} e
  406. */
  407. calendarTouchstart(e) {
  408. const t = e.touches[0];
  409. const startX = t.clientX;
  410. const startY = t.clientY;
  411. this.slideLock = true; // 滑动事件加锁
  412. this.setData({
  413. "gesture.startX": startX,
  414. "gesture.startY": startY,
  415. });
  416. },
  417. /**
  418. * 日历滑动中
  419. * @param {object} e
  420. */
  421. calendarTouchmove(e) {
  422. const { gesture } = this.data;
  423. const { preventSwipe } = this.properties.calendarConfig;
  424. if (!this.slideLock || preventSwipe) return;
  425. if (slide.isLeft(gesture, e.touches[0])) {
  426. this.handleSwipe("left");
  427. this.slideLock = false;
  428. }
  429. if (slide.isRight(gesture, e.touches[0])) {
  430. this.handleSwipe("right");
  431. this.slideLock = false;
  432. }
  433. },
  434. calendarTouchend(e) {
  435. this.setData({
  436. "calendar.leftSwipe": 0,
  437. "calendar.rightSwipe": 0,
  438. });
  439. },
  440. handleSwipe(direction) {
  441. let swipeKey = "calendar.leftSwipe";
  442. let swipeCalendarType = "next_month";
  443. let weekChangeType = "next_week";
  444. if (direction === "right") {
  445. swipeKey = "calendar.rightSwipe";
  446. swipeCalendarType = "prev_month";
  447. weekChangeType = "prev_week";
  448. }
  449. this.setData({
  450. [swipeKey]: 1,
  451. });
  452. this.currentYM = getCurrentYM();
  453. if (this.weekMode) {
  454. this.slideLock = false;
  455. this.currentDates = getCalendarDates();
  456. if (weekChangeType === "prev_week") {
  457. Week(this).calculatePrevWeekDays();
  458. } else if (weekChangeType === "next_week") {
  459. Week(this).calculateNextWeekDays();
  460. }
  461. this.onSwipeCalendar(weekChangeType);
  462. this.onWeekChange(weekChangeType);
  463. return;
  464. }
  465. this.chooseMonth(swipeCalendarType);
  466. this.onSwipeCalendar(swipeCalendarType);
  467. },
  468. onSwipeCalendar(direction) {
  469. this.triggerEvent("onSwipe", {
  470. directionType: direction,
  471. currentYM: this.currentYM,
  472. });
  473. },
  474. onWeekChange(direction) {
  475. this.triggerEvent("whenChangeWeek", {
  476. current: {
  477. currentYM: this.currentYM,
  478. dates: [...this.currentDates],
  479. },
  480. next: {
  481. currentYM: getCurrentYM(),
  482. dates: getCalendarDates(),
  483. },
  484. directionType: direction,
  485. });
  486. this.currentDates = null;
  487. this.currentYM = null;
  488. },
  489. },
  490. });