index.ts 14 KB

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